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.5 2003/08/23 10:06:22 rob 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(tok, m)
81 struct ipvcc *ivp = tok;
82 struct atmarp_hdr *ahp;
84 int len, plen = sizeof(struct atmarp_hdr);
88 uniarp_pdu_print(ivp, m, "receive");
92 * Verify IP's VCC state
94 if (ivp->iv_state != IPVCC_ACTIVE) {
99 * Get the fixed fields together
101 if (KB_LEN(m) < sizeof(struct atmarp_hdr)) {
102 KB_PULLUP(m, sizeof(struct atmarp_hdr), m);
107 KB_DATASTART(m, ahp, struct atmarp_hdr *);
110 * Initial packet verification
112 if ((ahp->ah_hrd != htons(ARP_ATMFORUM)) ||
113 (ahp->ah_pro != htons(ETHERTYPE_IP)))
117 * Verify/gather source address fields
119 if ((len = (ahp->ah_shtl & ARP_TL_LMASK)) != 0) {
120 if (ahp->ah_shtl & ARP_TL_E164) {
121 if (len > sizeof(struct atm_addr_e164))
123 satm.address_format = T_ATM_E164_ADDR;
125 if (len != sizeof(struct atm_addr_nsap))
127 satm.address_format = T_ATM_ENDSYS_ADDR;
129 satm.address_length = len;
130 if (KB_COPYDATA(m, plen, len, (caddr_t)satm.address))
134 satm.address_format = T_ATM_ABSENT;
135 satm.address_length = 0;
138 if ((len = (ahp->ah_sstl & ARP_TL_LMASK)) != 0) {
139 if (((ahp->ah_sstl & ARP_TL_TMASK) != ARP_TL_NSAPA) ||
140 (len != sizeof(struct atm_addr_nsap)))
142 satmsub.address_format = T_ATM_ENDSYS_ADDR;
143 satmsub.address_length = len;
144 if (KB_COPYDATA(m, plen, len, (caddr_t)satmsub.address))
148 satmsub.address_format = T_ATM_ABSENT;
149 satmsub.address_length = 0;
152 if ((len = ahp->ah_spln) != 0) {
153 if (len != sizeof(struct in_addr))
155 if (KB_COPYDATA(m, plen, len, (caddr_t)&sip))
163 * Verify/gather target address fields
165 if ((len = (ahp->ah_thtl & ARP_TL_LMASK)) != 0) {
166 if (ahp->ah_thtl & ARP_TL_E164) {
167 if (len > sizeof(struct atm_addr_e164))
169 tatm.address_format = T_ATM_E164_ADDR;
171 if (len != sizeof(struct atm_addr_nsap))
173 tatm.address_format = T_ATM_ENDSYS_ADDR;
175 tatm.address_length = len;
176 if (KB_COPYDATA(m, plen, len, (caddr_t)tatm.address))
180 tatm.address_format = T_ATM_ABSENT;
181 tatm.address_length = 0;
184 if ((len = (ahp->ah_tstl & ARP_TL_LMASK)) != 0) {
185 if (((ahp->ah_tstl & ARP_TL_TMASK) != ARP_TL_NSAPA) ||
186 (len != sizeof(struct atm_addr_nsap)))
188 tatmsub.address_format = T_ATM_ENDSYS_ADDR;
189 tatmsub.address_length = len;
190 if (KB_COPYDATA(m, plen, len, (caddr_t)tatmsub.address))
194 tatmsub.address_format = T_ATM_ABSENT;
195 tatmsub.address_length = 0;
198 if ((len = ahp->ah_tpln) != 0) {
199 if (len != sizeof(struct in_addr))
201 if (KB_COPYDATA(m, plen, len, (caddr_t)&tip))
209 * Verify packet length
211 for (len = 0, n = m; n; n = KB_NEXT(n))
217 * Now finish with packet-specific processing
219 switch (ntohs(ahp->ah_op)) {
221 proc_arp_req(ivp, m);
225 proc_arp_rsp(ivp, m);
229 proc_inarp_req(ivp, m);
233 proc_inarp_rsp(ivp, m);
237 proc_arp_nak(ivp, m);
247 uniarp_stat.uas_rcvdrop++;
254 * Process an ATMARP request packet
257 * ivp pointer to input VCC's IPVCC control block
258 * m pointer to input packet buffer chain
278 * Only an arp server should receive these
282 uip = (struct uniip *)inp->inf_isintf;
284 (uip->uip_arpstate != UIAS_SERVER_ACTIVE))
288 * These should be sent only on SVCs
290 if ((ivp->iv_flags & IVF_SVC) == 0)
294 * Locate our addresses
296 sgp = nip->nif_pif->pif_siginst;
297 myip.s_addr = IA_SIN(inp->inf_addr)->sin_addr.s_addr;
300 * Target IP address must be present
306 * Drop packet if both Source addresses aren't present
308 if ((sip.s_addr == 0) || (satm.address_format == T_ATM_ABSENT))
312 * Source addresses can't be ours
314 if (ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &satm) &&
315 ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel, &satmsub)) {
316 struct vccb *vcp = ivp->iv_conn->co_connvc->cvc_vcc;
319 "uniarp: vcc=(%d,%d) reports our ATM address\n",
320 vcp->vc_vpi, vcp->vc_vci);
323 if (sip.s_addr == myip.s_addr) {
324 struct vccb *vcp = ivp->iv_conn->co_connvc->cvc_vcc;
327 "uniarp: vcc=(%d,%d) reports our IP address\n",
328 vcp->vc_vpi, vcp->vc_vci);
333 * Validate Source IP address
335 if (uniarp_validate_ip(uip, &sip, UAO_REGISTER) != 0)
339 * If the source and target IP addresses are the same, then this
340 * must be a client registration request (RFC-2225). Otherwise,
341 * try to accomodate old clients (per RFC-2225 8.4.4).
343 if (sip.s_addr == tip.s_addr)
344 (void) uniarp_cache_svc(uip, &sip, &satm, &satmsub,
347 uap = (struct uniarp *)ivp->iv_arpent;
348 if ((uap == NULL) || (uap->ua_origin < UAO_REGISTER))
349 (void) uniarp_cache_svc(uip, &sip, &satm, &satmsub,
354 * Lookup the target IP address in the cache (and also check if
355 * the query is for our address).
357 UNIARP_LOOKUP(tip.s_addr, uap);
358 if (uap && (uap->ua_flags & UAF_VALID)) {
360 * We've found a valid mapping
362 (void) uniarp_arp_rsp(uip, &uap->ua_arpmap, &sip, &satm,
365 } else if (tip.s_addr == myip.s_addr) {
367 * We're the target, so respond accordingly
369 (void) uniarp_arp_rsp(uip, &uip->uip_arpsvrmap, &sip, &satm,
374 * We don't know who the target is, so NAK the query
376 (void) uniarp_arp_nak(uip, m, ivp);
389 * Process an ATMARP reply packet
392 * ivp pointer to input VCC's IPVCC control block
393 * m pointer to input packet buffer chain
413 * Only the arp server should send these
417 uip = (struct uniip *)inp->inf_isintf;
419 (uip->uip_arpsvrvcc != ivp))
423 * Locate our addresses
425 sgp = nip->nif_pif->pif_siginst;
426 myip.s_addr = IA_SIN(inp->inf_addr)->sin_addr.s_addr;
429 * Target addresses must be ours
431 if ((tip.s_addr != myip.s_addr) ||
432 !ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &tatm) ||
433 !ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel, &tatmsub))
437 * Drop packet if both Source addresses aren't present
439 if ((sip.s_addr == 0) || (satm.address_format == T_ATM_ABSENT))
443 * If the Source addresses are ours, this is an arp server
444 * registration response
446 if (ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &satm) &&
447 ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel, &satmsub)) {
448 if (sip.s_addr == myip.s_addr) {
450 * Registration response - update our state and
451 * set a registration refresh timer
453 if (uip->uip_arpstate == UIAS_CLIENT_REGISTER)
454 uip->uip_arpstate = UIAS_CLIENT_ACTIVE;
456 if (uip->uip_arpstate == UIAS_CLIENT_ACTIVE) {
457 UNIIP_ARP_CANCEL(uip);
458 UNIIP_ARP_TIMER(uip, UNIARP_REGIS_REFRESH);
462 * If the cache entry for the server VCC isn't valid
463 * yet, then send an Inverse ATMARP request to solicit
464 * the server's IP address
466 uap = (struct uniarp *)ivp->iv_arpent;
467 if ((uap->ua_flags & UAF_VALID) == 0) {
468 (void) uniarp_inarp_req(uip, &uap->ua_dstatm,
469 &uap->ua_dstatmsub, ivp);
474 "uniarp: arpserver has our IP address wrong\n");
477 } else if (sip.s_addr == myip.s_addr) {
479 "uniarp: arpserver has our ATM address wrong\n");
484 * Validate the Source IP address
486 if (uniarp_validate_ip(uip, &sip, UAO_LOOKUP) != 0)
490 * Now we believe this packet contains an authoritative mapping,
491 * which we probably need to setup an outgoing SVC connection
493 (void) uniarp_cache_svc(uip, &sip, &satm, &satmsub, UAO_LOOKUP);
503 * Process an ATMARP negative ack packet
506 * ivp pointer to input VCC's IPVCC control block
507 * m pointer to input packet buffer chain
528 * Only the arp server should send these
532 uip = (struct uniip *)inp->inf_isintf;
534 (uip->uip_arpsvrvcc != ivp))
538 * Locate our addresses
540 sgp = nip->nif_pif->pif_siginst;
541 myip.s_addr = IA_SIN(inp->inf_addr)->sin_addr.s_addr;
544 * Source addresses must be ours
546 if ((sip.s_addr != myip.s_addr) ||
547 !ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &satm) ||
548 !ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel, &satmsub))
552 * Drop packet if the Target IP address isn't there or if this
553 * is a registration response, indicating an old or flakey server
555 if ((tip.s_addr == 0) || (tip.s_addr == myip.s_addr))
559 * Otherwise, see who we were looking for
561 UNIARP_LOOKUP(tip.s_addr, uap);
566 * This entry isn't valid any longer, so notify all VCCs using this
567 * entry that they must finish up. The last notify should cause
568 * this entry to be freed by the vcclose() function.
570 uap->ua_flags &= ~UAF_VALID;
571 for (ivp = uap->ua_ivp; ivp; ivp = inext) {
572 inext = ivp->iv_arpnext;
573 (*inp->inf_arpnotify)(ivp, MAP_FAILED);
584 * Process an InATMARP request packet
587 * ivp pointer to input VCC's IPVCC control block
588 * m pointer to input packet buffer chain
595 proc_inarp_req(ivp, m)
607 * Get interface pointers
611 uip = (struct uniip *)inp->inf_isintf;
616 * Locate our addresses
618 sgp = nip->nif_pif->pif_siginst;
619 myip.s_addr = IA_SIN(inp->inf_addr)->sin_addr.s_addr;
622 * Packet must have a Source IP address and, if it was received
623 * over an SVC, a Source ATM address too.
625 if ((sip.s_addr == 0) ||
626 ((ivp->iv_flags & IVF_SVC) && (satm.address_format == T_ATM_ABSENT)))
630 * Validate Source ATM address
633 if (satm.address_format != T_ATM_ABSENT) {
634 if (ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &satm) &&
635 ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel,
641 * Validate Source IP address
643 if ((sip.s_addr == myip.s_addr) ||
644 (uniarp_validate_ip(uip, &sip, UAO_PEER_REQ) != 0))
648 * The Target ATM address is required for a packet received over
649 * an SVC, optional for a PVC. If one is present, it must be our
652 if ((ivp->iv_flags & IVF_SVC) && (tatm.address_format == T_ATM_ABSENT))
654 if ((tatm.address_format != T_ATM_ABSENT) &&
655 (!ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &tatm) ||
656 !ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel, &tatmsub)))
660 * See where this packet is from
662 if (ivp->iv_flags & IVF_PVC) {
664 * Process the PVC arp data, although we don't really
665 * update the arp cache with this information
667 uniarp_cache_pvc(ivp, &sip, &satm, &satmsub);
669 } else if (uip->uip_arpsvrvcc == ivp) {
671 * Packet is from the arp server, so we've received a
672 * registration/refresh request (1577 version).
674 * Therefore, update cache with authoritative data.
676 (void) uniarp_cache_svc(uip, &sip, &satm, &satmsub, UAO_LOOKUP);
679 * Make sure the cache update didn't kill the server VCC
681 if (uip->uip_arpsvrvcc != ivp)
685 * Update the server state and set the
686 * registration refresh timer
688 uip->uip_arpstate = UIAS_CLIENT_ACTIVE;
689 UNIIP_ARP_CANCEL(uip);
690 UNIIP_ARP_TIMER(uip, UNIARP_REGIS_REFRESH);
693 * Otherwise, we consider this source mapping data as
694 * non-authoritative and update the cache appropriately
696 if (uniarp_cache_svc(uip, &sip, &satm, &satmsub, UAO_PEER_REQ))
701 * Send an InATMARP response back to originator
703 (void) uniarp_inarp_rsp(uip, &sip, &satm, &satmsub, ivp);
713 * Process an InATMARP response packet
716 * ivp pointer to input VCC's IPVCC control block
717 * m pointer to input packet buffer chain
724 proc_inarp_rsp(ivp, m)
736 * Get interface pointers
740 uip = (struct uniip *)inp->inf_isintf;
745 * Locate our addresses
747 sgp = nip->nif_pif->pif_siginst;
748 myip.s_addr = IA_SIN(inp->inf_addr)->sin_addr.s_addr;
751 * Packet must have a Source IP address and, if it was received
752 * over an SVC, a Source ATM address too.
754 if ((sip.s_addr == 0) ||
755 ((ivp->iv_flags & IVF_SVC) && (satm.address_format == T_ATM_ABSENT)))
759 * Validate Source ATM address
762 if (satm.address_format != T_ATM_ABSENT) {
763 if (ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &satm) &&
764 ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel,
770 * Validate Source IP address
771 * - must be in our LIS
773 * - can't be broadcast
774 * - can't be multicast
776 if ((sip.s_addr == myip.s_addr) ||
777 (uniarp_validate_ip(uip, &sip, UAO_PEER_RSP) != 0))
781 * The Target ATM address is required for a packet received over
782 * an SVC, optional for a PVC. If one is present, it must be our
785 if ((ivp->iv_flags & IVF_SVC) && (tatm.address_format == T_ATM_ABSENT))
787 if ((tatm.address_format != T_ATM_ABSENT) &&
788 (!ATM_ADDR_SEL_EQUAL(&sgp->si_addr, nip->nif_sel, &tatm) ||
789 !ATM_ADDR_SEL_EQUAL(&sgp->si_subaddr, nip->nif_sel, &tatmsub)))
793 * See where this packet is from
795 if (ivp->iv_flags & IVF_PVC) {
797 * Process the PVC arp data, although we don't really
798 * update the arp cache with this information
800 uniarp_cache_pvc(ivp, &sip, &satm, &satmsub);
804 * Can't tell the difference between an RFC-1577 registration
805 * and a data connection from a client of another arpserver
806 * on our LIS (using SCSP) - so we'll update the cache now
807 * with what we've got. Our clients will get "registered"
808 * when (if) they query us with an arp request.
810 (void) uniarp_cache_svc(uip, &sip, &satm, &satmsub,
822 * Print an ATMARP PDU
825 * ivp pointer to input VCC control block
826 * m pointer to pdu buffer chain
827 * msg pointer to message string
834 uniarp_pdu_print(ivp, m, msg)
842 vcp = ivp->iv_conn->co_connvc->cvc_vcc;
843 snprintf(buf, sizeof(buf),
844 "uniarp %s: vcc=(%d,%d)\n", msg, vcp->vc_vpi, vcp->vc_vci);
845 atm_pdu_print(m, buf);