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 $
27 * @(#) $DragonFly: src/sys/netproto/atm/uni/uniarp_input.c,v 1.8 2006/12/20 18:14:43 dillon Exp $
31 * ATM Forum UNI Support
32 * ---------------------
34 * UNI ATMARP support (RFC1577) - Input packet processing
38 #include <netproto/atm/kern_include.h>
40 #include <netproto/atm/ipatm/ipatm_var.h>
41 #include <netproto/atm/ipatm/ipatm_serv.h>
42 #include "uniip_var.h"
47 static void proc_arp_req (struct ipvcc *, KBuffer *);
48 static void proc_arp_rsp (struct ipvcc *, KBuffer *);
49 static void proc_arp_nak (struct ipvcc *, KBuffer *);
50 static void proc_inarp_req (struct ipvcc *, KBuffer *);
51 static void proc_inarp_rsp (struct ipvcc *, KBuffer *);
58 static Atm_addr satmsub;
60 static Atm_addr tatmsub;
61 static struct in_addr sip;
62 static struct in_addr tip;
66 * Process ATMARP Input Data
69 * tok uniarp connection token (pointer to ipvcc)
70 * m pointer to input packet buffer chain
77 uniarp_cpcs_data(void *tok, KBuffer *m)
79 struct ipvcc *ivp = tok;
80 struct atmarp_hdr *ahp;
82 int len, plen = sizeof(struct atmarp_hdr);
86 uniarp_pdu_print(ivp, m, "receive");
90 * Verify IP's VCC state
92 if (ivp->iv_state != IPVCC_ACTIVE) {
97 * Get the fixed fields together
99 if (KB_LEN(m) < sizeof(struct atmarp_hdr)) {
100 KB_PULLUP(m, sizeof(struct atmarp_hdr), m);
105 KB_DATASTART(m, ahp, struct atmarp_hdr *);
108 * Initial packet verification
110 if ((ahp->ah_hrd != htons(ARP_ATMFORUM)) ||
111 (ahp->ah_pro != htons(ETHERTYPE_IP)))
115 * Verify/gather source address fields
117 if ((len = (ahp->ah_shtl & ARP_TL_LMASK)) != 0) {
118 if (ahp->ah_shtl & ARP_TL_E164) {
119 if (len > sizeof(struct atm_addr_e164))
121 satm.address_format = T_ATM_E164_ADDR;
123 if (len != sizeof(struct atm_addr_nsap))
125 satm.address_format = T_ATM_ENDSYS_ADDR;
127 satm.address_length = len;
128 if (KB_COPYDATA(m, plen, len, (caddr_t)satm.address))
132 satm.address_format = T_ATM_ABSENT;
133 satm.address_length = 0;
136 if ((len = (ahp->ah_sstl & ARP_TL_LMASK)) != 0) {
137 if (((ahp->ah_sstl & ARP_TL_TMASK) != ARP_TL_NSAPA) ||
138 (len != sizeof(struct atm_addr_nsap)))
140 satmsub.address_format = T_ATM_ENDSYS_ADDR;
141 satmsub.address_length = len;
142 if (KB_COPYDATA(m, plen, len, (caddr_t)satmsub.address))
146 satmsub.address_format = T_ATM_ABSENT;
147 satmsub.address_length = 0;
150 if ((len = ahp->ah_spln) != 0) {
151 if (len != sizeof(struct in_addr))
153 if (KB_COPYDATA(m, plen, len, (caddr_t)&sip))
161 * Verify/gather target address fields
163 if ((len = (ahp->ah_thtl & ARP_TL_LMASK)) != 0) {
164 if (ahp->ah_thtl & ARP_TL_E164) {
165 if (len > sizeof(struct atm_addr_e164))
167 tatm.address_format = T_ATM_E164_ADDR;
169 if (len != sizeof(struct atm_addr_nsap))
171 tatm.address_format = T_ATM_ENDSYS_ADDR;
173 tatm.address_length = len;
174 if (KB_COPYDATA(m, plen, len, (caddr_t)tatm.address))
178 tatm.address_format = T_ATM_ABSENT;
179 tatm.address_length = 0;
182 if ((len = (ahp->ah_tstl & ARP_TL_LMASK)) != 0) {
183 if (((ahp->ah_tstl & ARP_TL_TMASK) != ARP_TL_NSAPA) ||
184 (len != sizeof(struct atm_addr_nsap)))
186 tatmsub.address_format = T_ATM_ENDSYS_ADDR;
187 tatmsub.address_length = len;
188 if (KB_COPYDATA(m, plen, len, (caddr_t)tatmsub.address))
192 tatmsub.address_format = T_ATM_ABSENT;
193 tatmsub.address_length = 0;
196 if ((len = ahp->ah_tpln) != 0) {
197 if (len != sizeof(struct in_addr))
199 if (KB_COPYDATA(m, plen, len, (caddr_t)&tip))
207 * Verify packet length
209 for (len = 0, n = m; n; n = KB_NEXT(n))
215 * Now finish with packet-specific processing
217 switch (ntohs(ahp->ah_op)) {
219 proc_arp_req(ivp, m);
223 proc_arp_rsp(ivp, m);
227 proc_inarp_req(ivp, m);
231 proc_inarp_rsp(ivp, m);
235 proc_arp_nak(ivp, m);
245 uniarp_stat.uas_rcvdrop++;
252 * Process an ATMARP request packet
255 * ivp pointer to input VCC's IPVCC control block
256 * m pointer to input packet buffer chain
263 proc_arp_req(struct ipvcc *ivp, KBuffer *m)
274 * Only an arp server should receive these
278 uip = (struct uniip *)inp->inf_isintf;
280 (uip->uip_arpstate != UIAS_SERVER_ACTIVE))
284 * These should be sent only on SVCs
286 if ((ivp->iv_flags & IVF_SVC) == 0)
290 * Locate our addresses
292 sgp = nip->nif_pif->pif_siginst;
293 myip.s_addr = IA_SIN(inp->inf_addr)->sin_addr.s_addr;
296 * Target IP address must be present
302 * Drop packet if both Source addresses aren't present
304 if ((sip.s_addr == 0) || (satm.address_format == T_ATM_ABSENT))
308 * Source addresses can't be ours
310 if (ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &satm) &&
311 ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel, &satmsub)) {
312 struct vccb *vcp = ivp->iv_conn->co_connvc->cvc_vcc;
315 "uniarp: vcc=(%d,%d) reports our ATM address\n",
316 vcp->vc_vpi, vcp->vc_vci);
319 if (sip.s_addr == myip.s_addr) {
320 struct vccb *vcp = ivp->iv_conn->co_connvc->cvc_vcc;
323 "uniarp: vcc=(%d,%d) reports our IP address\n",
324 vcp->vc_vpi, vcp->vc_vci);
329 * Validate Source IP address
331 if (uniarp_validate_ip(uip, &sip, UAO_REGISTER) != 0)
335 * If the source and target IP addresses are the same, then this
336 * must be a client registration request (RFC-2225). Otherwise,
337 * try to accomodate old clients (per RFC-2225 8.4.4).
339 if (sip.s_addr == tip.s_addr)
340 uniarp_cache_svc(uip, &sip, &satm, &satmsub, UAO_REGISTER);
342 uap = (struct uniarp *)ivp->iv_arpent;
343 if ((uap == NULL) || (uap->ua_origin < UAO_REGISTER))
344 uniarp_cache_svc(uip, &sip, &satm, &satmsub,
349 * Lookup the target IP address in the cache (and also check if
350 * the query is for our address).
352 UNIARP_LOOKUP(tip.s_addr, uap);
353 if (uap && (uap->ua_flags & UAF_VALID)) {
355 * We've found a valid mapping
357 uniarp_arp_rsp(uip, &uap->ua_arpmap, &sip, &satm,
360 } else if (tip.s_addr == myip.s_addr) {
362 * We're the target, so respond accordingly
364 uniarp_arp_rsp(uip, &uip->uip_arpsvrmap, &sip, &satm,
369 * We don't know who the target is, so NAK the query
371 uniarp_arp_nak(uip, m, ivp);
384 * Process an ATMARP reply packet
387 * ivp pointer to input VCC's IPVCC control block
388 * m pointer to input packet buffer chain
395 proc_arp_rsp(struct ipvcc *ivp, KBuffer *m)
406 * Only the arp server should send these
410 uip = (struct uniip *)inp->inf_isintf;
412 (uip->uip_arpsvrvcc != ivp))
416 * Locate our addresses
418 sgp = nip->nif_pif->pif_siginst;
419 myip.s_addr = IA_SIN(inp->inf_addr)->sin_addr.s_addr;
422 * Target addresses must be ours
424 if ((tip.s_addr != myip.s_addr) ||
425 !ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &tatm) ||
426 !ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel, &tatmsub))
430 * Drop packet if both Source addresses aren't present
432 if ((sip.s_addr == 0) || (satm.address_format == T_ATM_ABSENT))
436 * If the Source addresses are ours, this is an arp server
437 * registration response
439 if (ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &satm) &&
440 ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel, &satmsub)) {
441 if (sip.s_addr == myip.s_addr) {
443 * Registration response - update our state and
444 * set a registration refresh timer
446 if (uip->uip_arpstate == UIAS_CLIENT_REGISTER)
447 uip->uip_arpstate = UIAS_CLIENT_ACTIVE;
449 if (uip->uip_arpstate == UIAS_CLIENT_ACTIVE) {
450 UNIIP_ARP_CANCEL(uip);
451 UNIIP_ARP_TIMER(uip, UNIARP_REGIS_REFRESH);
455 * If the cache entry for the server VCC isn't valid
456 * yet, then send an Inverse ATMARP request to solicit
457 * the server's IP address
459 uap = (struct uniarp *)ivp->iv_arpent;
460 if ((uap->ua_flags & UAF_VALID) == 0) {
461 uniarp_inarp_req(uip, &uap->ua_dstatm,
462 &uap->ua_dstatmsub, ivp);
467 "uniarp: arpserver has our IP address wrong\n");
470 } else if (sip.s_addr == myip.s_addr) {
472 "uniarp: arpserver has our ATM address wrong\n");
477 * Validate the Source IP address
479 if (uniarp_validate_ip(uip, &sip, UAO_LOOKUP) != 0)
483 * Now we believe this packet contains an authoritative mapping,
484 * which we probably need to setup an outgoing SVC connection
486 uniarp_cache_svc(uip, &sip, &satm, &satmsub, UAO_LOOKUP);
496 * Process an ATMARP negative ack packet
499 * ivp pointer to input VCC's IPVCC control block
500 * m pointer to input packet buffer chain
507 proc_arp_nak(struct ipvcc *ivp, KBuffer *m)
519 * Only the arp server should send these
523 uip = (struct uniip *)inp->inf_isintf;
525 (uip->uip_arpsvrvcc != ivp))
529 * Locate our addresses
531 sgp = nip->nif_pif->pif_siginst;
532 myip.s_addr = IA_SIN(inp->inf_addr)->sin_addr.s_addr;
535 * Source addresses must be ours
537 if ((sip.s_addr != myip.s_addr) ||
538 !ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &satm) ||
539 !ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel, &satmsub))
543 * Drop packet if the Target IP address isn't there or if this
544 * is a registration response, indicating an old or flakey server
546 if ((tip.s_addr == 0) || (tip.s_addr == myip.s_addr))
550 * Otherwise, see who we were looking for
552 UNIARP_LOOKUP(tip.s_addr, uap);
557 * This entry isn't valid any longer, so notify all VCCs using this
558 * entry that they must finish up. The last notify should cause
559 * this entry to be freed by the vcclose() function.
561 uap->ua_flags &= ~UAF_VALID;
562 for (ivp = uap->ua_ivp; ivp; ivp = inext) {
563 inext = ivp->iv_arpnext;
564 (*inp->inf_arpnotify)(ivp, MAP_FAILED);
575 * Process an InATMARP request packet
578 * ivp pointer to input VCC's IPVCC control block
579 * m pointer to input packet buffer chain
586 proc_inarp_req(struct ipvcc *ivp, KBuffer *m)
597 * Get interface pointers
601 uip = (struct uniip *)inp->inf_isintf;
606 * Locate our addresses
608 sgp = nip->nif_pif->pif_siginst;
609 myip.s_addr = IA_SIN(inp->inf_addr)->sin_addr.s_addr;
612 * Packet must have a Source IP address and, if it was received
613 * over an SVC, a Source ATM address too.
615 if ((sip.s_addr == 0) ||
616 ((ivp->iv_flags & IVF_SVC) && (satm.address_format == T_ATM_ABSENT)))
620 * Validate Source ATM address
623 if (satm.address_format != T_ATM_ABSENT) {
624 if (ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &satm) &&
625 ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel,
631 * Validate Source IP address
633 if ((sip.s_addr == myip.s_addr) ||
634 (uniarp_validate_ip(uip, &sip, UAO_PEER_REQ) != 0))
638 * The Target ATM address is required for a packet received over
639 * an SVC, optional for a PVC. If one is present, it must be our
642 if ((ivp->iv_flags & IVF_SVC) && (tatm.address_format == T_ATM_ABSENT))
644 if ((tatm.address_format != T_ATM_ABSENT) &&
645 (!ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &tatm) ||
646 !ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel, &tatmsub)))
650 * See where this packet is from
652 if (ivp->iv_flags & IVF_PVC) {
654 * Process the PVC arp data, although we don't really
655 * update the arp cache with this information
657 uniarp_cache_pvc(ivp, &sip, &satm, &satmsub);
659 } else if (uip->uip_arpsvrvcc == ivp) {
661 * Packet is from the arp server, so we've received a
662 * registration/refresh request (1577 version).
664 * Therefore, update cache with authoritative data.
666 uniarp_cache_svc(uip, &sip, &satm, &satmsub, UAO_LOOKUP);
669 * Make sure the cache update didn't kill the server VCC
671 if (uip->uip_arpsvrvcc != ivp)
675 * Update the server state and set the
676 * registration refresh timer
678 uip->uip_arpstate = UIAS_CLIENT_ACTIVE;
679 UNIIP_ARP_CANCEL(uip);
680 UNIIP_ARP_TIMER(uip, UNIARP_REGIS_REFRESH);
683 * Otherwise, we consider this source mapping data as
684 * non-authoritative and update the cache appropriately
686 if (uniarp_cache_svc(uip, &sip, &satm, &satmsub, UAO_PEER_REQ))
691 * Send an InATMARP response back to originator
693 uniarp_inarp_rsp(uip, &sip, &satm, &satmsub, ivp);
703 * Process an InATMARP response packet
706 * ivp pointer to input VCC's IPVCC control block
707 * m pointer to input packet buffer chain
714 proc_inarp_rsp(struct ipvcc *ivp, KBuffer *m)
725 * Get interface pointers
729 uip = (struct uniip *)inp->inf_isintf;
734 * Locate our addresses
736 sgp = nip->nif_pif->pif_siginst;
737 myip.s_addr = IA_SIN(inp->inf_addr)->sin_addr.s_addr;
740 * Packet must have a Source IP address and, if it was received
741 * over an SVC, a Source ATM address too.
743 if ((sip.s_addr == 0) ||
744 ((ivp->iv_flags & IVF_SVC) && (satm.address_format == T_ATM_ABSENT)))
748 * Validate Source ATM address
751 if (satm.address_format != T_ATM_ABSENT) {
752 if (ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &satm) &&
753 ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel,
759 * Validate Source IP address
760 * - must be in our LIS
762 * - can't be broadcast
763 * - can't be multicast
765 if ((sip.s_addr == myip.s_addr) ||
766 (uniarp_validate_ip(uip, &sip, UAO_PEER_RSP) != 0))
770 * The Target ATM address is required for a packet received over
771 * an SVC, optional for a PVC. If one is present, it must be our
774 if ((ivp->iv_flags & IVF_SVC) && (tatm.address_format == T_ATM_ABSENT))
776 if ((tatm.address_format != T_ATM_ABSENT) &&
777 (!ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &tatm) ||
778 !ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel, &tatmsub)))
782 * See where this packet is from
784 if (ivp->iv_flags & IVF_PVC) {
786 * Process the PVC arp data, although we don't really
787 * update the arp cache with this information
789 uniarp_cache_pvc(ivp, &sip, &satm, &satmsub);
793 * Can't tell the difference between an RFC-1577 registration
794 * and a data connection from a client of another arpserver
795 * on our LIS (using SCSP) - so we'll update the cache now
796 * with what we've got. Our clients will get "registered"
797 * when (if) they query us with an arp request.
799 uniarp_cache_svc(uip, &sip, &satm, &satmsub,
811 * Print an ATMARP PDU
814 * ivp pointer to input VCC control block
815 * m pointer to pdu buffer chain
816 * msg pointer to message string
823 uniarp_pdu_print(struct ipvcc *ivp, KBuffer *m, char *msg)
828 vcp = ivp->iv_conn->co_connvc->cvc_vcc;
829 ksnprintf(buf, sizeof(buf),
830 "uniarp %s: vcc=(%d,%d)\n", msg, vcp->vc_vpi, vcp->vc_vci);
831 atm_pdu_print(m, buf);