3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
8 * This Host ATM Research Platform ("HARP") file (the "Software") is
9 * made available by Network Computing Services, Inc. ("NetworkCS")
10 * "AS IS". NetworkCS does not provide maintenance, improvements or
11 * support of any kind.
13 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17 * In no event shall NetworkCS be responsible for any damages, including
18 * but not limited to consequential damages, arising from or relating to
19 * any use of the Software or related support.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
26 * @(#) $FreeBSD: src/sys/netatm/uni/uniarp_input.c,v 1.6 2000/01/17 20:49:55 mks Exp $
31 * ATM Forum UNI Support
32 * ---------------------
34 * UNI ATMARP support (RFC1577) - Input packet processing
38 #include <netatm/kern_include.h>
40 #include <netatm/ipatm/ipatm_var.h>
41 #include <netatm/ipatm/ipatm_serv.h>
42 #include <netatm/uni/uniip_var.h>
45 __RCSID("@(#) $FreeBSD: src/sys/netatm/uni/uniarp_input.c,v 1.6 2000/01/17 20:49:55 mks Exp $");
52 static void proc_arp_req __P((struct ipvcc *, KBuffer *));
53 static void proc_arp_rsp __P((struct ipvcc *, KBuffer *));
54 static void proc_arp_nak __P((struct ipvcc *, KBuffer *));
55 static void proc_inarp_req __P((struct ipvcc *, KBuffer *));
56 static void proc_inarp_rsp __P((struct ipvcc *, KBuffer *));
63 static Atm_addr satmsub;
65 static Atm_addr tatmsub;
66 static struct in_addr sip;
67 static struct in_addr tip;
71 * Process ATMARP Input Data
74 * tok uniarp connection token (pointer to ipvcc)
75 * m pointer to input packet buffer chain
82 uniarp_cpcs_data(tok, m)
86 struct ipvcc *ivp = tok;
87 struct atmarp_hdr *ahp;
89 int len, plen = sizeof(struct atmarp_hdr);
93 uniarp_pdu_print(ivp, m, "receive");
97 * Verify IP's VCC state
99 if (ivp->iv_state != IPVCC_ACTIVE) {
104 * Get the fixed fields together
106 if (KB_LEN(m) < sizeof(struct atmarp_hdr)) {
107 KB_PULLUP(m, sizeof(struct atmarp_hdr), m);
112 KB_DATASTART(m, ahp, struct atmarp_hdr *);
115 * Initial packet verification
117 if ((ahp->ah_hrd != htons(ARP_ATMFORUM)) ||
118 (ahp->ah_pro != htons(ETHERTYPE_IP)))
122 * Verify/gather source address fields
124 if ((len = (ahp->ah_shtl & ARP_TL_LMASK)) != 0) {
125 if (ahp->ah_shtl & ARP_TL_E164) {
126 if (len > sizeof(struct atm_addr_e164))
128 satm.address_format = T_ATM_E164_ADDR;
130 if (len != sizeof(struct atm_addr_nsap))
132 satm.address_format = T_ATM_ENDSYS_ADDR;
134 satm.address_length = len;
135 if (KB_COPYDATA(m, plen, len, (caddr_t)satm.address))
139 satm.address_format = T_ATM_ABSENT;
140 satm.address_length = 0;
143 if ((len = (ahp->ah_sstl & ARP_TL_LMASK)) != 0) {
144 if (((ahp->ah_sstl & ARP_TL_TMASK) != ARP_TL_NSAPA) ||
145 (len != sizeof(struct atm_addr_nsap)))
147 satmsub.address_format = T_ATM_ENDSYS_ADDR;
148 satmsub.address_length = len;
149 if (KB_COPYDATA(m, plen, len, (caddr_t)satmsub.address))
153 satmsub.address_format = T_ATM_ABSENT;
154 satmsub.address_length = 0;
157 if ((len = ahp->ah_spln) != 0) {
158 if (len != sizeof(struct in_addr))
160 if (KB_COPYDATA(m, plen, len, (caddr_t)&sip))
168 * Verify/gather target address fields
170 if ((len = (ahp->ah_thtl & ARP_TL_LMASK)) != 0) {
171 if (ahp->ah_thtl & ARP_TL_E164) {
172 if (len > sizeof(struct atm_addr_e164))
174 tatm.address_format = T_ATM_E164_ADDR;
176 if (len != sizeof(struct atm_addr_nsap))
178 tatm.address_format = T_ATM_ENDSYS_ADDR;
180 tatm.address_length = len;
181 if (KB_COPYDATA(m, plen, len, (caddr_t)tatm.address))
185 tatm.address_format = T_ATM_ABSENT;
186 tatm.address_length = 0;
189 if ((len = (ahp->ah_tstl & ARP_TL_LMASK)) != 0) {
190 if (((ahp->ah_tstl & ARP_TL_TMASK) != ARP_TL_NSAPA) ||
191 (len != sizeof(struct atm_addr_nsap)))
193 tatmsub.address_format = T_ATM_ENDSYS_ADDR;
194 tatmsub.address_length = len;
195 if (KB_COPYDATA(m, plen, len, (caddr_t)tatmsub.address))
199 tatmsub.address_format = T_ATM_ABSENT;
200 tatmsub.address_length = 0;
203 if ((len = ahp->ah_tpln) != 0) {
204 if (len != sizeof(struct in_addr))
206 if (KB_COPYDATA(m, plen, len, (caddr_t)&tip))
214 * Verify packet length
216 for (len = 0, n = m; n; n = KB_NEXT(n))
222 * Now finish with packet-specific processing
224 switch (ntohs(ahp->ah_op)) {
226 proc_arp_req(ivp, m);
230 proc_arp_rsp(ivp, m);
234 proc_inarp_req(ivp, m);
238 proc_inarp_rsp(ivp, m);
242 proc_arp_nak(ivp, m);
252 uniarp_stat.uas_rcvdrop++;
259 * Process an ATMARP request packet
262 * ivp pointer to input VCC's IPVCC control block
263 * m pointer to input packet buffer chain
283 * Only an arp server should receive these
287 uip = (struct uniip *)inp->inf_isintf;
289 (uip->uip_arpstate != UIAS_SERVER_ACTIVE))
293 * These should be sent only on SVCs
295 if ((ivp->iv_flags & IVF_SVC) == 0)
299 * Locate our addresses
301 sgp = nip->nif_pif->pif_siginst;
302 myip.s_addr = IA_SIN(inp->inf_addr)->sin_addr.s_addr;
305 * Target IP address must be present
311 * Drop packet if both Source addresses aren't present
313 if ((sip.s_addr == 0) || (satm.address_format == T_ATM_ABSENT))
317 * Source addresses can't be ours
319 if (ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &satm) &&
320 ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel, &satmsub)) {
321 struct vccb *vcp = ivp->iv_conn->co_connvc->cvc_vcc;
324 "uniarp: vcc=(%d,%d) reports our ATM address\n",
325 vcp->vc_vpi, vcp->vc_vci);
328 if (sip.s_addr == myip.s_addr) {
329 struct vccb *vcp = ivp->iv_conn->co_connvc->cvc_vcc;
332 "uniarp: vcc=(%d,%d) reports our IP address\n",
333 vcp->vc_vpi, vcp->vc_vci);
338 * Validate Source IP address
340 if (uniarp_validate_ip(uip, &sip, UAO_REGISTER) != 0)
344 * If the source and target IP addresses are the same, then this
345 * must be a client registration request (RFC-2225). Otherwise,
346 * try to accomodate old clients (per RFC-2225 8.4.4).
348 if (sip.s_addr == tip.s_addr)
349 (void) uniarp_cache_svc(uip, &sip, &satm, &satmsub,
352 uap = (struct uniarp *)ivp->iv_arpent;
353 if ((uap == NULL) || (uap->ua_origin < UAO_REGISTER))
354 (void) uniarp_cache_svc(uip, &sip, &satm, &satmsub,
359 * Lookup the target IP address in the cache (and also check if
360 * the query is for our address).
362 UNIARP_LOOKUP(tip.s_addr, uap);
363 if (uap && (uap->ua_flags & UAF_VALID)) {
365 * We've found a valid mapping
367 (void) uniarp_arp_rsp(uip, &uap->ua_arpmap, &sip, &satm,
370 } else if (tip.s_addr == myip.s_addr) {
372 * We're the target, so respond accordingly
374 (void) uniarp_arp_rsp(uip, &uip->uip_arpsvrmap, &sip, &satm,
379 * We don't know who the target is, so NAK the query
381 (void) uniarp_arp_nak(uip, m, ivp);
394 * Process an ATMARP reply packet
397 * ivp pointer to input VCC's IPVCC control block
398 * m pointer to input packet buffer chain
418 * Only the arp server should send these
422 uip = (struct uniip *)inp->inf_isintf;
424 (uip->uip_arpsvrvcc != ivp))
428 * Locate our addresses
430 sgp = nip->nif_pif->pif_siginst;
431 myip.s_addr = IA_SIN(inp->inf_addr)->sin_addr.s_addr;
434 * Target addresses must be ours
436 if ((tip.s_addr != myip.s_addr) ||
437 !ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &tatm) ||
438 !ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel, &tatmsub))
442 * Drop packet if both Source addresses aren't present
444 if ((sip.s_addr == 0) || (satm.address_format == T_ATM_ABSENT))
448 * If the Source addresses are ours, this is an arp server
449 * registration response
451 if (ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &satm) &&
452 ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel, &satmsub)) {
453 if (sip.s_addr == myip.s_addr) {
455 * Registration response - update our state and
456 * set a registration refresh timer
458 if (uip->uip_arpstate == UIAS_CLIENT_REGISTER)
459 uip->uip_arpstate = UIAS_CLIENT_ACTIVE;
461 if (uip->uip_arpstate == UIAS_CLIENT_ACTIVE) {
462 UNIIP_ARP_CANCEL(uip);
463 UNIIP_ARP_TIMER(uip, UNIARP_REGIS_REFRESH);
467 * If the cache entry for the server VCC isn't valid
468 * yet, then send an Inverse ATMARP request to solicit
469 * the server's IP address
471 uap = (struct uniarp *)ivp->iv_arpent;
472 if ((uap->ua_flags & UAF_VALID) == 0) {
473 (void) uniarp_inarp_req(uip, &uap->ua_dstatm,
474 &uap->ua_dstatmsub, ivp);
479 "uniarp: arpserver has our IP address wrong\n");
482 } else if (sip.s_addr == myip.s_addr) {
484 "uniarp: arpserver has our ATM address wrong\n");
489 * Validate the Source IP address
491 if (uniarp_validate_ip(uip, &sip, UAO_LOOKUP) != 0)
495 * Now we believe this packet contains an authoritative mapping,
496 * which we probably need to setup an outgoing SVC connection
498 (void) uniarp_cache_svc(uip, &sip, &satm, &satmsub, UAO_LOOKUP);
508 * Process an ATMARP negative ack packet
511 * ivp pointer to input VCC's IPVCC control block
512 * m pointer to input packet buffer chain
533 * Only the arp server should send these
537 uip = (struct uniip *)inp->inf_isintf;
539 (uip->uip_arpsvrvcc != ivp))
543 * Locate our addresses
545 sgp = nip->nif_pif->pif_siginst;
546 myip.s_addr = IA_SIN(inp->inf_addr)->sin_addr.s_addr;
549 * Source addresses must be ours
551 if ((sip.s_addr != myip.s_addr) ||
552 !ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &satm) ||
553 !ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel, &satmsub))
557 * Drop packet if the Target IP address isn't there or if this
558 * is a registration response, indicating an old or flakey server
560 if ((tip.s_addr == 0) || (tip.s_addr == myip.s_addr))
564 * Otherwise, see who we were looking for
566 UNIARP_LOOKUP(tip.s_addr, uap);
571 * This entry isn't valid any longer, so notify all VCCs using this
572 * entry that they must finish up. The last notify should cause
573 * this entry to be freed by the vcclose() function.
575 uap->ua_flags &= ~UAF_VALID;
576 for (ivp = uap->ua_ivp; ivp; ivp = inext) {
577 inext = ivp->iv_arpnext;
578 (*inp->inf_arpnotify)(ivp, MAP_FAILED);
589 * Process an InATMARP request packet
592 * ivp pointer to input VCC's IPVCC control block
593 * m pointer to input packet buffer chain
600 proc_inarp_req(ivp, m)
612 * Get interface pointers
616 uip = (struct uniip *)inp->inf_isintf;
621 * Locate our addresses
623 sgp = nip->nif_pif->pif_siginst;
624 myip.s_addr = IA_SIN(inp->inf_addr)->sin_addr.s_addr;
627 * Packet must have a Source IP address and, if it was received
628 * over an SVC, a Source ATM address too.
630 if ((sip.s_addr == 0) ||
631 ((ivp->iv_flags & IVF_SVC) && (satm.address_format == T_ATM_ABSENT)))
635 * Validate Source ATM address
638 if (satm.address_format != T_ATM_ABSENT) {
639 if (ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &satm) &&
640 ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel,
646 * Validate Source IP address
648 if ((sip.s_addr == myip.s_addr) ||
649 (uniarp_validate_ip(uip, &sip, UAO_PEER_REQ) != 0))
653 * The Target ATM address is required for a packet received over
654 * an SVC, optional for a PVC. If one is present, it must be our
657 if ((ivp->iv_flags & IVF_SVC) && (tatm.address_format == T_ATM_ABSENT))
659 if ((tatm.address_format != T_ATM_ABSENT) &&
660 (!ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &tatm) ||
661 !ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel, &tatmsub)))
665 * See where this packet is from
667 if (ivp->iv_flags & IVF_PVC) {
669 * Process the PVC arp data, although we don't really
670 * update the arp cache with this information
672 uniarp_cache_pvc(ivp, &sip, &satm, &satmsub);
674 } else if (uip->uip_arpsvrvcc == ivp) {
676 * Packet is from the arp server, so we've received a
677 * registration/refresh request (1577 version).
679 * Therefore, update cache with authoritative data.
681 (void) uniarp_cache_svc(uip, &sip, &satm, &satmsub, UAO_LOOKUP);
684 * Make sure the cache update didn't kill the server VCC
686 if (uip->uip_arpsvrvcc != ivp)
690 * Update the server state and set the
691 * registration refresh timer
693 uip->uip_arpstate = UIAS_CLIENT_ACTIVE;
694 UNIIP_ARP_CANCEL(uip);
695 UNIIP_ARP_TIMER(uip, UNIARP_REGIS_REFRESH);
698 * Otherwise, we consider this source mapping data as
699 * non-authoritative and update the cache appropriately
701 if (uniarp_cache_svc(uip, &sip, &satm, &satmsub, UAO_PEER_REQ))
706 * Send an InATMARP response back to originator
708 (void) uniarp_inarp_rsp(uip, &sip, &satm, &satmsub, ivp);
718 * Process an InATMARP response packet
721 * ivp pointer to input VCC's IPVCC control block
722 * m pointer to input packet buffer chain
729 proc_inarp_rsp(ivp, m)
741 * Get interface pointers
745 uip = (struct uniip *)inp->inf_isintf;
750 * Locate our addresses
752 sgp = nip->nif_pif->pif_siginst;
753 myip.s_addr = IA_SIN(inp->inf_addr)->sin_addr.s_addr;
756 * Packet must have a Source IP address and, if it was received
757 * over an SVC, a Source ATM address too.
759 if ((sip.s_addr == 0) ||
760 ((ivp->iv_flags & IVF_SVC) && (satm.address_format == T_ATM_ABSENT)))
764 * Validate Source ATM address
767 if (satm.address_format != T_ATM_ABSENT) {
768 if (ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &satm) &&
769 ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel,
775 * Validate Source IP address
776 * - must be in our LIS
778 * - can't be broadcast
779 * - can't be multicast
781 if ((sip.s_addr == myip.s_addr) ||
782 (uniarp_validate_ip(uip, &sip, UAO_PEER_RSP) != 0))
786 * The Target ATM address is required for a packet received over
787 * an SVC, optional for a PVC. If one is present, it must be our
790 if ((ivp->iv_flags & IVF_SVC) && (tatm.address_format == T_ATM_ABSENT))
792 if ((tatm.address_format != T_ATM_ABSENT) &&
793 (!ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &tatm) ||
794 !ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel, &tatmsub)))
798 * See where this packet is from
800 if (ivp->iv_flags & IVF_PVC) {
802 * Process the PVC arp data, although we don't really
803 * update the arp cache with this information
805 uniarp_cache_pvc(ivp, &sip, &satm, &satmsub);
809 * Can't tell the difference between an RFC-1577 registration
810 * and a data connection from a client of another arpserver
811 * on our LIS (using SCSP) - so we'll update the cache now
812 * with what we've got. Our clients will get "registered"
813 * when (if) they query us with an arp request.
815 (void) uniarp_cache_svc(uip, &sip, &satm, &satmsub,
827 * Print an ATMARP PDU
830 * ivp pointer to input VCC control block
831 * m pointer to pdu buffer chain
832 * msg pointer to message string
839 uniarp_pdu_print(ivp, m, msg)
847 vcp = ivp->iv_conn->co_connvc->cvc_vcc;
848 snprintf(buf, sizeof(buf),
849 "uniarp %s: vcc=(%d,%d)\n", msg, vcp->vc_vpi, vcp->vc_vci);
850 atm_pdu_print(m, buf);