2 * ===================================
3 * HARP | Host ATM Research Platform
4 * ===================================
7 * This Host ATM Research Platform ("HARP") file (the "Software") is
8 * made available by Network Computing Services, Inc. ("NetworkCS")
9 * "AS IS". NetworkCS does not provide maintenance, improvements or
10 * support of any kind.
12 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
13 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
14 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
15 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
16 * In no event shall NetworkCS be responsible for any damages, including
17 * but not limited to consequential damages, arising from or relating to
18 * any use of the Software or related support.
20 * Copyright 1994-1998 Network Computing Services, Inc.
22 * Copies of this Software may be made, however, the above copyright
23 * notice must be reproduced on all copies.
27 * ATM Forum UNI Support
28 * ---------------------
30 * UNI ATMARP support (RFC1577) - Input packet processing
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
36 #include <sys/param.h>
37 #include <sys/types.h>
38 #include <sys/systm.h>
40 #include <sys/socket.h>
41 #include <sys/socketvar.h>
42 #include <sys/syslog.h>
44 #include <netinet/in.h>
45 #include <netinet/in_var.h>
46 #include <netinet/if_ether.h>
47 #include <netatm/port.h>
48 #include <netatm/queue.h>
49 #include <netatm/atm.h>
50 #include <netatm/atm_sys.h>
51 #include <netatm/atm_sap.h>
52 #include <netatm/atm_cm.h>
53 #include <netatm/atm_if.h>
54 #include <netatm/atm_vc.h>
55 #include <netatm/atm_ioctl.h>
56 #include <netatm/atm_sigmgr.h>
57 #include <netatm/atm_stack.h>
58 #include <netatm/atm_pcb.h>
59 #include <netatm/atm_var.h>
61 #include <netatm/ipatm/ipatm_var.h>
62 #include <netatm/ipatm/ipatm_serv.h>
63 #include <netatm/uni/uniip_var.h>
68 static void proc_arp_req(struct ipvcc *, KBuffer *);
69 static void proc_arp_rsp(struct ipvcc *, KBuffer *);
70 static void proc_arp_nak(struct ipvcc *, KBuffer *);
71 static void proc_inarp_req(struct ipvcc *, KBuffer *);
72 static void proc_inarp_rsp(struct ipvcc *, KBuffer *);
79 static Atm_addr satmsub;
81 static Atm_addr tatmsub;
82 static struct in_addr sip;
83 static struct in_addr tip;
87 * Process ATMARP Input Data
90 * tok uniarp connection token (pointer to ipvcc)
91 * m pointer to input packet buffer chain
98 uniarp_cpcs_data(tok, m)
102 struct ipvcc *ivp = tok;
103 struct atmarp_hdr *ahp;
105 int len, plen = sizeof(struct atmarp_hdr);
108 uniarp_pdu_print(ivp, m, "receive");
111 * Verify IP's VCC state
113 if (ivp->iv_state != IPVCC_ACTIVE) {
118 * Get the fixed fields together
120 if (KB_LEN(m) < sizeof(struct atmarp_hdr)) {
121 KB_PULLUP(m, sizeof(struct atmarp_hdr), m);
126 KB_DATASTART(m, ahp, struct atmarp_hdr *);
129 * Initial packet verification
131 if ((ahp->ah_hrd != htons(ARP_ATMFORUM)) ||
132 (ahp->ah_pro != htons(ETHERTYPE_IP)))
136 * Verify/gather source address fields
138 if ((len = (ahp->ah_shtl & ARP_TL_LMASK)) != 0) {
139 if (ahp->ah_shtl & ARP_TL_E164) {
140 if (len > sizeof(struct atm_addr_e164))
142 satm.address_format = T_ATM_E164_ADDR;
144 if (len != sizeof(struct atm_addr_nsap))
146 satm.address_format = T_ATM_ENDSYS_ADDR;
148 satm.address_length = len;
149 if (KB_COPYDATA(m, plen, len, (caddr_t)satm.address))
153 satm.address_format = T_ATM_ABSENT;
154 satm.address_length = 0;
157 if ((len = (ahp->ah_sstl & ARP_TL_LMASK)) != 0) {
158 if (((ahp->ah_sstl & ARP_TL_TMASK) != ARP_TL_NSAPA) ||
159 (len != sizeof(struct atm_addr_nsap)))
161 satmsub.address_format = T_ATM_ENDSYS_ADDR;
162 satmsub.address_length = len;
163 if (KB_COPYDATA(m, plen, len, (caddr_t)satmsub.address))
167 satmsub.address_format = T_ATM_ABSENT;
168 satmsub.address_length = 0;
171 if ((len = ahp->ah_spln) != 0) {
172 if (len != sizeof(struct in_addr))
174 if (KB_COPYDATA(m, plen, len, (caddr_t)&sip))
182 * Verify/gather target address fields
184 if ((len = (ahp->ah_thtl & ARP_TL_LMASK)) != 0) {
185 if (ahp->ah_thtl & ARP_TL_E164) {
186 if (len > sizeof(struct atm_addr_e164))
188 tatm.address_format = T_ATM_E164_ADDR;
190 if (len != sizeof(struct atm_addr_nsap))
192 tatm.address_format = T_ATM_ENDSYS_ADDR;
194 tatm.address_length = len;
195 if (KB_COPYDATA(m, plen, len, (caddr_t)tatm.address))
199 tatm.address_format = T_ATM_ABSENT;
200 tatm.address_length = 0;
203 if ((len = (ahp->ah_tstl & ARP_TL_LMASK)) != 0) {
204 if (((ahp->ah_tstl & ARP_TL_TMASK) != ARP_TL_NSAPA) ||
205 (len != sizeof(struct atm_addr_nsap)))
207 tatmsub.address_format = T_ATM_ENDSYS_ADDR;
208 tatmsub.address_length = len;
209 if (KB_COPYDATA(m, plen, len, (caddr_t)tatmsub.address))
213 tatmsub.address_format = T_ATM_ABSENT;
214 tatmsub.address_length = 0;
217 if ((len = ahp->ah_tpln) != 0) {
218 if (len != sizeof(struct in_addr))
220 if (KB_COPYDATA(m, plen, len, (caddr_t)&tip))
228 * Verify packet length
230 for (len = 0, n = m; n; n = KB_NEXT(n))
236 * Now finish with packet-specific processing
238 switch (ntohs(ahp->ah_op)) {
240 proc_arp_req(ivp, m);
244 proc_arp_rsp(ivp, m);
248 proc_inarp_req(ivp, m);
252 proc_inarp_rsp(ivp, m);
256 proc_arp_nak(ivp, m);
266 uniarp_stat.uas_rcvdrop++;
273 * Process an ATMARP request packet
276 * ivp pointer to input VCC's IPVCC control block
277 * m pointer to input packet buffer chain
297 * Only an arp server should receive these
301 uip = (struct uniip *)inp->inf_isintf;
303 (uip->uip_arpstate != UIAS_SERVER_ACTIVE))
307 * These should be sent only on SVCs
309 if ((ivp->iv_flags & IVF_SVC) == 0)
313 * Locate our addresses
315 sgp = nip->nif_pif->pif_siginst;
316 myip.s_addr = IA_SIN(inp->inf_addr)->sin_addr.s_addr;
319 * Target IP address must be present
325 * Drop packet if both Source addresses aren't present
327 if ((sip.s_addr == 0) || (satm.address_format == T_ATM_ABSENT))
331 * Source addresses can't be ours
333 if (ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &satm) &&
334 ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel, &satmsub)) {
335 struct vccb *vcp = ivp->iv_conn->co_connvc->cvc_vcc;
338 "uniarp: vcc=(%d,%d) reports our ATM address\n",
339 vcp->vc_vpi, vcp->vc_vci);
342 if (sip.s_addr == myip.s_addr) {
343 struct vccb *vcp = ivp->iv_conn->co_connvc->cvc_vcc;
346 "uniarp: vcc=(%d,%d) reports our IP address\n",
347 vcp->vc_vpi, vcp->vc_vci);
352 * Validate Source IP address
354 if (uniarp_validate_ip(uip, &sip, UAO_REGISTER) != 0)
358 * If the source and target IP addresses are the same, then this
359 * must be a client registration request (RFC-2225). Otherwise,
360 * try to accomodate old clients (per RFC-2225 8.4.4).
362 if (sip.s_addr == tip.s_addr)
363 (void) uniarp_cache_svc(uip, &sip, &satm, &satmsub,
366 uap = (struct uniarp *)ivp->iv_arpent;
367 if ((uap == NULL) || (uap->ua_origin < UAO_REGISTER))
368 (void) uniarp_cache_svc(uip, &sip, &satm, &satmsub,
373 * Lookup the target IP address in the cache (and also check if
374 * the query is for our address).
376 UNIARP_LOOKUP(tip.s_addr, uap);
377 if (uap && (uap->ua_flags & UAF_VALID)) {
379 * We've found a valid mapping
381 (void) uniarp_arp_rsp(uip, &uap->ua_arpmap, &sip, &satm,
384 } else if (tip.s_addr == myip.s_addr) {
386 * We're the target, so respond accordingly
388 (void) uniarp_arp_rsp(uip, &uip->uip_arpsvrmap, &sip, &satm,
393 * We don't know who the target is, so NAK the query
395 (void) uniarp_arp_nak(uip, m, ivp);
408 * Process an ATMARP reply packet
411 * ivp pointer to input VCC's IPVCC control block
412 * m pointer to input packet buffer chain
432 * Only the arp server should send these
436 uip = (struct uniip *)inp->inf_isintf;
438 (uip->uip_arpsvrvcc != ivp))
442 * Locate our addresses
444 sgp = nip->nif_pif->pif_siginst;
445 myip.s_addr = IA_SIN(inp->inf_addr)->sin_addr.s_addr;
448 * Target addresses must be ours
450 if ((tip.s_addr != myip.s_addr) ||
451 !ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &tatm) ||
452 !ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel, &tatmsub))
456 * Drop packet if both Source addresses aren't present
458 if ((sip.s_addr == 0) || (satm.address_format == T_ATM_ABSENT))
462 * If the Source addresses are ours, this is an arp server
463 * registration response
465 if (ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &satm) &&
466 ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel, &satmsub)) {
467 if (sip.s_addr == myip.s_addr) {
469 * Registration response - update our state and
470 * set a registration refresh timer
472 if (uip->uip_arpstate == UIAS_CLIENT_REGISTER)
473 uip->uip_arpstate = UIAS_CLIENT_ACTIVE;
475 if (uip->uip_arpstate == UIAS_CLIENT_ACTIVE) {
476 UNIIP_ARP_CANCEL(uip);
477 UNIIP_ARP_TIMER(uip, UNIARP_REGIS_REFRESH);
481 * If the cache entry for the server VCC isn't valid
482 * yet, then send an Inverse ATMARP request to solicit
483 * the server's IP address
485 uap = (struct uniarp *)ivp->iv_arpent;
486 if ((uap->ua_flags & UAF_VALID) == 0) {
487 (void) uniarp_inarp_req(uip, &uap->ua_dstatm,
488 &uap->ua_dstatmsub, ivp);
493 "uniarp: arpserver has our IP address wrong\n");
496 } else if (sip.s_addr == myip.s_addr) {
498 "uniarp: arpserver has our ATM address wrong\n");
503 * Validate the Source IP address
505 if (uniarp_validate_ip(uip, &sip, UAO_LOOKUP) != 0)
509 * Now we believe this packet contains an authoritative mapping,
510 * which we probably need to setup an outgoing SVC connection
512 (void) uniarp_cache_svc(uip, &sip, &satm, &satmsub, UAO_LOOKUP);
522 * Process an ATMARP negative ack packet
525 * ivp pointer to input VCC's IPVCC control block
526 * m pointer to input packet buffer chain
547 * Only the arp server should send these
551 uip = (struct uniip *)inp->inf_isintf;
553 (uip->uip_arpsvrvcc != ivp))
557 * Locate our addresses
559 sgp = nip->nif_pif->pif_siginst;
560 myip.s_addr = IA_SIN(inp->inf_addr)->sin_addr.s_addr;
563 * Source addresses must be ours
565 if ((sip.s_addr != myip.s_addr) ||
566 !ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &satm) ||
567 !ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel, &satmsub))
571 * Drop packet if the Target IP address isn't there or if this
572 * is a registration response, indicating an old or flakey server
574 if ((tip.s_addr == 0) || (tip.s_addr == myip.s_addr))
578 * Otherwise, see who we were looking for
580 UNIARP_LOOKUP(tip.s_addr, uap);
585 * This entry isn't valid any longer, so notify all VCCs using this
586 * entry that they must finish up. The last notify should cause
587 * this entry to be freed by the vcclose() function.
589 uap->ua_flags &= ~UAF_VALID;
590 for (ivp = uap->ua_ivp; ivp; ivp = inext) {
591 inext = ivp->iv_arpnext;
592 (*inp->inf_arpnotify)(ivp, MAP_FAILED);
603 * Process an InATMARP request packet
606 * ivp pointer to input VCC's IPVCC control block
607 * m pointer to input packet buffer chain
614 proc_inarp_req(ivp, m)
626 * Get interface pointers
630 uip = (struct uniip *)inp->inf_isintf;
635 * Locate our addresses
637 sgp = nip->nif_pif->pif_siginst;
638 myip.s_addr = IA_SIN(inp->inf_addr)->sin_addr.s_addr;
641 * Packet must have a Source IP address and, if it was received
642 * over an SVC, a Source ATM address too.
644 if ((sip.s_addr == 0) ||
645 ((ivp->iv_flags & IVF_SVC) && (satm.address_format == T_ATM_ABSENT)))
649 * Validate Source ATM address
652 if (satm.address_format != T_ATM_ABSENT) {
653 if (ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &satm) &&
654 ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel,
660 * Validate Source IP address
662 if ((sip.s_addr == myip.s_addr) ||
663 (uniarp_validate_ip(uip, &sip, UAO_PEER_REQ) != 0))
667 * The Target ATM address is required for a packet received over
668 * an SVC, optional for a PVC. If one is present, it must be our
671 if ((ivp->iv_flags & IVF_SVC) && (tatm.address_format == T_ATM_ABSENT))
673 if ((tatm.address_format != T_ATM_ABSENT) &&
674 (!ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &tatm) ||
675 !ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel, &tatmsub)))
679 * See where this packet is from
681 if (ivp->iv_flags & IVF_PVC) {
683 * Process the PVC arp data, although we don't really
684 * update the arp cache with this information
686 uniarp_cache_pvc(ivp, &sip, &satm, &satmsub);
688 } else if (uip->uip_arpsvrvcc == ivp) {
690 * Packet is from the arp server, so we've received a
691 * registration/refresh request (1577 version).
693 * Therefore, update cache with authoritative data.
695 (void) uniarp_cache_svc(uip, &sip, &satm, &satmsub, UAO_LOOKUP);
698 * Make sure the cache update didn't kill the server VCC
700 if (uip->uip_arpsvrvcc != ivp)
704 * Update the server state and set the
705 * registration refresh timer
707 uip->uip_arpstate = UIAS_CLIENT_ACTIVE;
708 UNIIP_ARP_CANCEL(uip);
709 UNIIP_ARP_TIMER(uip, UNIARP_REGIS_REFRESH);
712 * Otherwise, we consider this source mapping data as
713 * non-authoritative and update the cache appropriately
715 if (uniarp_cache_svc(uip, &sip, &satm, &satmsub, UAO_PEER_REQ))
720 * Send an InATMARP response back to originator
722 (void) uniarp_inarp_rsp(uip, &sip, &satm, &satmsub, ivp);
732 * Process an InATMARP response packet
735 * ivp pointer to input VCC's IPVCC control block
736 * m pointer to input packet buffer chain
743 proc_inarp_rsp(ivp, m)
755 * Get interface pointers
759 uip = (struct uniip *)inp->inf_isintf;
764 * Locate our addresses
766 sgp = nip->nif_pif->pif_siginst;
767 myip.s_addr = IA_SIN(inp->inf_addr)->sin_addr.s_addr;
770 * Packet must have a Source IP address and, if it was received
771 * over an SVC, a Source ATM address too.
773 if ((sip.s_addr == 0) ||
774 ((ivp->iv_flags & IVF_SVC) && (satm.address_format == T_ATM_ABSENT)))
778 * Validate Source ATM address
781 if (satm.address_format != T_ATM_ABSENT) {
782 if (ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &satm) &&
783 ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel,
789 * Validate Source IP address
790 * - must be in our LIS
792 * - can't be broadcast
793 * - can't be multicast
795 if ((sip.s_addr == myip.s_addr) ||
796 (uniarp_validate_ip(uip, &sip, UAO_PEER_RSP) != 0))
800 * The Target ATM address is required for a packet received over
801 * an SVC, optional for a PVC. If one is present, it must be our
804 if ((ivp->iv_flags & IVF_SVC) && (tatm.address_format == T_ATM_ABSENT))
806 if ((tatm.address_format != T_ATM_ABSENT) &&
807 (!ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &tatm) ||
808 !ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel, &tatmsub)))
812 * See where this packet is from
814 if (ivp->iv_flags & IVF_PVC) {
816 * Process the PVC arp data, although we don't really
817 * update the arp cache with this information
819 uniarp_cache_pvc(ivp, &sip, &satm, &satmsub);
823 * Can't tell the difference between an RFC-1577 registration
824 * and a data connection from a client of another arpserver
825 * on our LIS (using SCSP) - so we'll update the cache now
826 * with what we've got. Our clients will get "registered"
827 * when (if) they query us with an arp request.
829 (void) uniarp_cache_svc(uip, &sip, &satm, &satmsub,
841 * Print an ATMARP PDU
844 * ivp pointer to input VCC control block
845 * m pointer to pdu buffer chain
846 * msg pointer to message string
853 uniarp_pdu_print(const struct ipvcc *ivp, const KBuffer *m, const char *msg)
858 vcp = ivp->iv_conn->co_connvc->cvc_vcc;
859 snprintf(buf, sizeof(buf),
860 "uniarp %s: vcc=(%d,%d)\n", msg, vcp->vc_vpi, vcp->vc_vci);
861 atm_pdu_print(m, buf);