]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - 6/sys/netatm/uni/uniarp_input.c
merge fix for boot-time hang on centos' xen
[FreeBSD/FreeBSD.git] / 6 / sys / netatm / uni / uniarp_input.c
1 /*-
2  * ===================================
3  * HARP  |  Host ATM Research Platform
4  * ===================================
5  *
6  *
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.
11  *
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.
19  *
20  * Copyright 1994-1998 Network Computing Services, Inc.
21  *
22  * Copies of this Software may be made, however, the above copyright
23  * notice must be reproduced on all copies.
24  */
25
26 /*
27  * ATM Forum UNI Support
28  * ---------------------
29  *
30  * UNI ATMARP support (RFC1577) - Input packet processing
31  */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35
36 #include <sys/param.h>
37 #include <sys/types.h>
38 #include <sys/systm.h>
39 #include <sys/time.h>
40 #include <sys/socket.h>
41 #include <sys/socketvar.h>
42 #include <sys/syslog.h>
43 #include <net/if.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>
60
61 #include <netatm/ipatm/ipatm_var.h>
62 #include <netatm/ipatm/ipatm_serv.h>
63 #include <netatm/uni/uniip_var.h>
64
65 /*
66  * Local functions
67  */
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 *);
73
74
75 /*
76  * Local variables
77  */
78 static Atm_addr satm;
79 static Atm_addr satmsub;
80 static Atm_addr tatm;
81 static Atm_addr tatmsub;
82 static struct in_addr   sip;
83 static struct in_addr   tip;
84
85
86 /*
87  * Process ATMARP Input Data
88  * 
89  * Arguments:
90  *      tok     uniarp connection token (pointer to ipvcc)
91  *      m       pointer to input packet buffer chain
92  *
93  * Returns:
94  *      none
95  *
96  */
97 void
98 uniarp_cpcs_data(tok, m)
99         void            *tok;
100         KBuffer         *m;
101 {
102         struct ipvcc    *ivp = tok;
103         struct atmarp_hdr       *ahp;
104         KBuffer         *n;
105         int             len, plen = sizeof(struct atmarp_hdr);
106
107         if (uniarp_print)
108                 uniarp_pdu_print(ivp, m, "receive");
109
110         /*
111          * Verify IP's VCC state
112          */
113         if (ivp->iv_state != IPVCC_ACTIVE) {
114                 goto bad;
115         }
116
117         /*
118          * Get the fixed fields together
119          */
120         if (KB_LEN(m) < sizeof(struct atmarp_hdr)) {
121                 KB_PULLUP(m, sizeof(struct atmarp_hdr), m);
122                 if (m == NULL)
123                         goto bad;
124         }
125
126         KB_DATASTART(m, ahp, struct atmarp_hdr *);
127
128         /*
129          * Initial packet verification
130          */
131         if ((ahp->ah_hrd != htons(ARP_ATMFORUM)) ||
132             (ahp->ah_pro != htons(ETHERTYPE_IP)))
133                 goto bad;
134
135         /*
136          * Verify/gather source address fields
137          */
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))
141                                 goto bad;
142                         satm.address_format = T_ATM_E164_ADDR;
143                 } else {
144                         if (len != sizeof(struct atm_addr_nsap))
145                                 goto bad;
146                         satm.address_format = T_ATM_ENDSYS_ADDR;
147                 }
148                 satm.address_length = len;
149                 if (KB_COPYDATA(m, plen, len, (caddr_t)satm.address))
150                         goto bad;
151                 plen += len;
152         } else {
153                 satm.address_format = T_ATM_ABSENT;
154                 satm.address_length = 0;
155         }
156
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)))
160                         goto bad;
161                 satmsub.address_format = T_ATM_ENDSYS_ADDR;
162                 satmsub.address_length = len;
163                 if (KB_COPYDATA(m, plen, len, (caddr_t)satmsub.address))
164                         goto bad;
165                 plen += len;
166         } else {
167                 satmsub.address_format = T_ATM_ABSENT;
168                 satmsub.address_length = 0;
169         }
170
171         if ((len = ahp->ah_spln) != 0) {
172                 if (len != sizeof(struct in_addr))
173                         goto bad;
174                 if (KB_COPYDATA(m, plen, len, (caddr_t)&sip))
175                         goto bad;
176                 plen += len;
177         } else {
178                 sip.s_addr = 0;
179         }
180
181         /*
182          * Verify/gather target address fields
183          */
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))
187                                 goto bad;
188                         tatm.address_format = T_ATM_E164_ADDR;
189                 } else {
190                         if (len != sizeof(struct atm_addr_nsap))
191                                 goto bad;
192                         tatm.address_format = T_ATM_ENDSYS_ADDR;
193                 }
194                 tatm.address_length = len;
195                 if (KB_COPYDATA(m, plen, len, (caddr_t)tatm.address))
196                         goto bad;
197                 plen += len;
198         } else {
199                 tatm.address_format = T_ATM_ABSENT;
200                 tatm.address_length = 0;
201         }
202
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)))
206                         goto bad;
207                 tatmsub.address_format = T_ATM_ENDSYS_ADDR;
208                 tatmsub.address_length = len;
209                 if (KB_COPYDATA(m, plen, len, (caddr_t)tatmsub.address))
210                         goto bad;
211                 plen += len;
212         } else {
213                 tatmsub.address_format = T_ATM_ABSENT;
214                 tatmsub.address_length = 0;
215         }
216
217         if ((len = ahp->ah_tpln) != 0) {
218                 if (len != sizeof(struct in_addr))
219                         goto bad;
220                 if (KB_COPYDATA(m, plen, len, (caddr_t)&tip))
221                         goto bad;
222                 plen += len;
223         } else {
224                 tip.s_addr = 0;
225         }
226
227         /*
228          * Verify packet length
229          */
230         for (len = 0, n = m; n; n = KB_NEXT(n))
231                 len += KB_LEN(n);
232         if (len != plen)
233                 goto bad;
234
235         /*
236          * Now finish with packet-specific processing
237          */
238         switch (ntohs(ahp->ah_op)) {
239         case ARP_REQUEST:
240                 proc_arp_req(ivp, m);
241                 break;
242
243         case ARP_REPLY:
244                 proc_arp_rsp(ivp, m);
245                 break;
246
247         case INARP_REQUEST:
248                 proc_inarp_req(ivp, m);
249                 break;
250
251         case INARP_REPLY:
252                 proc_inarp_rsp(ivp, m);
253                 break;
254
255         case ARP_NAK:
256                 proc_arp_nak(ivp, m);
257                 break;
258
259         default:
260                 goto bad;
261         }
262
263         return;
264
265 bad:
266         uniarp_stat.uas_rcvdrop++;
267         if (m)
268                 KB_FREEALL(m);
269 }
270
271
272 /*
273  * Process an ATMARP request packet
274  * 
275  * Arguments:
276  *      ivp     pointer to input VCC's IPVCC control block
277  *      m       pointer to input packet buffer chain
278  *
279  * Returns:
280  *      none
281  *
282  */
283 static void
284 proc_arp_req(ivp, m)
285         struct ipvcc    *ivp;
286         KBuffer         *m;
287 {
288         struct ip_nif   *inp;
289         struct atm_nif  *nip;
290         struct siginst  *sgp;
291         struct uniip    *uip;
292         struct uniarp   *uap;
293         struct in_addr  myip;
294         int             s = splnet();
295
296         /*
297          * Only an arp server should receive these
298          */
299         inp = ivp->iv_ipnif;
300         nip = inp->inf_nif;
301         uip = (struct uniip *)inp->inf_isintf;
302         if ((uip == NULL) ||
303             (uip->uip_arpstate != UIAS_SERVER_ACTIVE))
304                 goto drop;
305
306         /*
307          * These should be sent only on SVCs
308          */
309         if ((ivp->iv_flags & IVF_SVC) == 0)
310                 goto drop;
311
312         /*
313          * Locate our addresses
314          */
315         sgp = nip->nif_pif->pif_siginst;
316         myip.s_addr = IA_SIN(inp->inf_addr)->sin_addr.s_addr;
317
318         /*
319          * Target IP address must be present
320          */
321         if (tip.s_addr == 0)
322                 goto drop;
323
324         /*
325          * Drop packet if both Source addresses aren't present
326          */
327         if ((sip.s_addr == 0) || (satm.address_format == T_ATM_ABSENT))
328                 goto drop;
329
330         /*
331          * Source addresses can't be ours
332          */
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;
336
337                 log(LOG_WARNING,
338                         "uniarp: vcc=(%d,%d) reports our ATM address\n",
339                         vcp->vc_vpi, vcp->vc_vci);
340                 goto drop;
341         }
342         if (sip.s_addr == myip.s_addr) {
343                 struct vccb     *vcp = ivp->iv_conn->co_connvc->cvc_vcc;
344
345                 log(LOG_WARNING,
346                         "uniarp: vcc=(%d,%d) reports our IP address\n",
347                         vcp->vc_vpi, vcp->vc_vci);
348                 goto drop;
349         }
350
351         /*
352          * Validate Source IP address
353          */
354         if (uniarp_validate_ip(uip, &sip, UAO_REGISTER) != 0)
355                 goto drop;
356
357         /*
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).
361          */
362         if (sip.s_addr == tip.s_addr)
363                 (void) uniarp_cache_svc(uip, &sip, &satm, &satmsub,
364                                 UAO_REGISTER);
365         else {
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,
369                                         UAO_REGISTER);
370         }
371
372         /*
373          * Lookup the target IP address in the cache (and also check if
374          * the query is for our address).
375          */
376         UNIARP_LOOKUP(tip.s_addr, uap);
377         if (uap && (uap->ua_flags & UAF_VALID)) {
378                 /*
379                  * We've found a valid mapping
380                  */
381                 (void) uniarp_arp_rsp(uip, &uap->ua_arpmap, &sip, &satm,
382                                         &satmsub, ivp);
383
384         } else if (tip.s_addr == myip.s_addr) {
385                 /*
386                  * We're the target, so respond accordingly
387                  */
388                 (void) uniarp_arp_rsp(uip, &uip->uip_arpsvrmap, &sip, &satm,
389                                         &satmsub, ivp);
390
391         } else {
392                 /*
393                  * We don't know who the target is, so NAK the query
394                  */
395                 (void) uniarp_arp_nak(uip, m, ivp);
396                 m = NULL;
397         }
398
399 drop:
400         (void) splx(s);
401         if (m)
402                 KB_FREEALL(m);
403         return;
404 }
405
406
407 /*
408  * Process an ATMARP reply packet
409  * 
410  * Arguments:
411  *      ivp     pointer to input VCC's IPVCC control block
412  *      m       pointer to input packet buffer chain
413  *
414  * Returns:
415  *      none
416  *
417  */
418 static void
419 proc_arp_rsp(ivp, m)
420         struct ipvcc    *ivp;
421         KBuffer         *m;
422 {
423         struct ip_nif   *inp;
424         struct atm_nif  *nip;
425         struct siginst  *sgp;
426         struct uniip    *uip;
427         struct uniarp   *uap;
428         struct in_addr  myip;
429         int             s = splnet();
430
431         /*
432          * Only the arp server should send these
433          */
434         inp = ivp->iv_ipnif;
435         nip = inp->inf_nif;
436         uip = (struct uniip *)inp->inf_isintf;
437         if ((uip == NULL) ||
438             (uip->uip_arpsvrvcc != ivp))
439                 goto drop;
440
441         /*
442          * Locate our addresses
443          */
444         sgp = nip->nif_pif->pif_siginst;
445         myip.s_addr = IA_SIN(inp->inf_addr)->sin_addr.s_addr;
446
447         /*
448          * Target addresses must be ours
449          */
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))
453                 goto drop;
454
455         /*
456          * Drop packet if both Source addresses aren't present
457          */
458         if ((sip.s_addr == 0) || (satm.address_format == T_ATM_ABSENT))
459                 goto drop;
460
461         /*
462          * If the Source addresses are ours, this is an arp server
463          * registration response
464          */
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) {
468                         /*
469                          * Registration response - update our state and
470                          * set a registration refresh timer
471                          */
472                         if (uip->uip_arpstate == UIAS_CLIENT_REGISTER)
473                                 uip->uip_arpstate = UIAS_CLIENT_ACTIVE;
474
475                         if (uip->uip_arpstate == UIAS_CLIENT_ACTIVE) {
476                                 UNIIP_ARP_CANCEL(uip);
477                                 UNIIP_ARP_TIMER(uip, UNIARP_REGIS_REFRESH);
478                         }
479
480                         /*
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
484                          */
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);
489                         }
490                         goto drop;
491                 } else {
492                         log(LOG_WARNING,
493                                 "uniarp: arpserver has our IP address wrong\n");
494                         goto drop;
495                 }
496         } else if (sip.s_addr == myip.s_addr) {
497                 log(LOG_WARNING,
498                         "uniarp: arpserver has our ATM address wrong\n");
499                 goto drop;
500         }
501
502         /*
503          * Validate the Source IP address
504          */
505         if (uniarp_validate_ip(uip, &sip, UAO_LOOKUP) != 0)
506                 goto drop;
507
508         /*
509          * Now we believe this packet contains an authoritative mapping,
510          * which we probably need to setup an outgoing SVC connection
511          */
512         (void) uniarp_cache_svc(uip, &sip, &satm, &satmsub, UAO_LOOKUP);
513
514 drop:
515         (void) splx(s);
516         KB_FREEALL(m);
517         return;
518 }
519
520
521 /*
522  * Process an ATMARP negative ack packet
523  * 
524  * Arguments:
525  *      ivp     pointer to input VCC's IPVCC control block
526  *      m       pointer to input packet buffer chain
527  *
528  * Returns:
529  *      none
530  *
531  */
532 static void
533 proc_arp_nak(ivp, m)
534         struct ipvcc    *ivp;
535         KBuffer         *m;
536 {
537         struct ip_nif   *inp;
538         struct atm_nif  *nip;
539         struct siginst  *sgp;
540         struct uniip    *uip;
541         struct uniarp   *uap;
542         struct in_addr  myip;
543         struct ipvcc    *inext;
544         int             s = splnet();
545
546         /*
547          * Only the arp server should send these
548          */
549         inp = ivp->iv_ipnif;
550         nip = inp->inf_nif;
551         uip = (struct uniip *)inp->inf_isintf;
552         if ((uip == NULL) ||
553             (uip->uip_arpsvrvcc != ivp))
554                 goto drop;
555
556         /*
557          * Locate our addresses
558          */
559         sgp = nip->nif_pif->pif_siginst;
560         myip.s_addr = IA_SIN(inp->inf_addr)->sin_addr.s_addr;
561
562         /*
563          * Source addresses must be ours
564          */
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))
568                 goto drop;
569
570         /*
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
573          */
574         if ((tip.s_addr == 0) || (tip.s_addr == myip.s_addr))
575                 goto drop;
576
577         /*
578          * Otherwise, see who we were looking for
579          */
580         UNIARP_LOOKUP(tip.s_addr, uap);
581         if (uap == NULL)
582                 goto drop;
583
584         /*
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.
588          */
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);
593         }
594
595 drop:
596         (void) splx(s);
597         KB_FREEALL(m);
598         return;
599 }
600
601
602 /*
603  * Process an InATMARP request packet
604  * 
605  * Arguments:
606  *      ivp     pointer to input VCC's IPVCC control block
607  *      m       pointer to input packet buffer chain
608  *
609  * Returns:
610  *      none
611  *
612  */
613 static void
614 proc_inarp_req(ivp, m)
615         struct ipvcc    *ivp;
616         KBuffer         *m;
617 {
618         struct ip_nif   *inp;
619         struct atm_nif  *nip;
620         struct siginst  *sgp;
621         struct uniip    *uip;
622         struct in_addr  myip;
623         int             s = splnet();
624
625         /*
626          * Get interface pointers
627          */
628         inp = ivp->iv_ipnif;
629         nip = inp->inf_nif;
630         uip = (struct uniip *)inp->inf_isintf;
631         if (uip == NULL)
632                 goto drop;
633
634         /*
635          * Locate our addresses
636          */
637         sgp = nip->nif_pif->pif_siginst;
638         myip.s_addr = IA_SIN(inp->inf_addr)->sin_addr.s_addr;
639
640         /*
641          * Packet must have a Source IP address and, if it was received
642          * over an SVC, a Source ATM address too.
643          */
644         if ((sip.s_addr == 0) ||
645             ((ivp->iv_flags & IVF_SVC) && (satm.address_format == T_ATM_ABSENT)))
646                 goto drop;
647
648         /*
649          * Validate Source ATM address
650          *      - can't be me
651          */
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,
655                                                 &satmsub))
656                         goto drop;
657         }
658
659         /*
660          * Validate Source IP address
661          */
662         if ((sip.s_addr == myip.s_addr) ||
663             (uniarp_validate_ip(uip, &sip, UAO_PEER_REQ) != 0))
664                 goto drop;
665
666         /*
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
669          * address.
670          */
671         if ((ivp->iv_flags & IVF_SVC) && (tatm.address_format == T_ATM_ABSENT))
672                 goto drop;
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)))
676                 goto drop;
677
678         /*
679          * See where this packet is from
680          */
681         if (ivp->iv_flags & IVF_PVC) {
682                 /*
683                  * Process the PVC arp data, although we don't really 
684                  * update the arp cache with this information
685                  */
686                 uniarp_cache_pvc(ivp, &sip, &satm, &satmsub);
687
688         } else if (uip->uip_arpsvrvcc == ivp) {
689                 /*
690                  * Packet is from the arp server, so we've received a
691                  * registration/refresh request (1577 version).
692                  *
693                  * Therefore, update cache with authoritative data.
694                  */
695                 (void) uniarp_cache_svc(uip, &sip, &satm, &satmsub, UAO_LOOKUP);
696
697                 /*
698                  * Make sure the cache update didn't kill the server VCC
699                  */
700                 if (uip->uip_arpsvrvcc != ivp)
701                         goto drop;
702
703                 /*
704                  * Update the server state and set the
705                  * registration refresh timer
706                  */
707                 uip->uip_arpstate = UIAS_CLIENT_ACTIVE;
708                 UNIIP_ARP_CANCEL(uip);
709                 UNIIP_ARP_TIMER(uip, UNIARP_REGIS_REFRESH);
710         } else {
711                 /*
712                  * Otherwise, we consider this source mapping data as
713                  * non-authoritative and update the cache appropriately
714                  */
715                 if (uniarp_cache_svc(uip, &sip, &satm, &satmsub, UAO_PEER_REQ))
716                         goto drop;
717         }
718
719         /*
720          * Send an InATMARP response back to originator
721          */
722         (void) uniarp_inarp_rsp(uip, &sip, &satm, &satmsub, ivp);
723
724 drop:
725         (void) splx(s);
726         KB_FREEALL(m);
727         return;
728 }
729
730
731 /*
732  * Process an InATMARP response packet
733  * 
734  * Arguments:
735  *      ivp     pointer to input VCC's IPVCC control block
736  *      m       pointer to input packet buffer chain
737  *
738  * Returns:
739  *      none
740  *
741  */
742 static void
743 proc_inarp_rsp(ivp, m)
744         struct ipvcc    *ivp;
745         KBuffer         *m;
746 {
747         struct ip_nif   *inp;
748         struct atm_nif  *nip;
749         struct siginst  *sgp;
750         struct uniip    *uip;
751         struct in_addr  myip;
752         int             s = splnet();
753
754         /*
755          * Get interface pointers
756          */
757         inp = ivp->iv_ipnif;
758         nip = inp->inf_nif;
759         uip = (struct uniip *)inp->inf_isintf;
760         if (uip == NULL)
761                 goto drop;
762
763         /*
764          * Locate our addresses
765          */
766         sgp = nip->nif_pif->pif_siginst;
767         myip.s_addr = IA_SIN(inp->inf_addr)->sin_addr.s_addr;
768
769         /*
770          * Packet must have a Source IP address and, if it was received
771          * over an SVC, a Source ATM address too.
772          */
773         if ((sip.s_addr == 0) ||
774             ((ivp->iv_flags & IVF_SVC) && (satm.address_format == T_ATM_ABSENT)))
775                 goto drop;
776
777         /*
778          * Validate Source ATM address
779          *      - can't be me
780          */
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,
784                                                 &satmsub))
785                         goto drop;
786         }
787
788         /*
789          * Validate Source IP address
790          *      - must be in our LIS
791          *      - can't be me
792          *      - can't be broadcast
793          *      - can't be multicast
794          */
795         if ((sip.s_addr == myip.s_addr) ||
796             (uniarp_validate_ip(uip, &sip, UAO_PEER_RSP) != 0))
797                 goto drop;
798
799         /*
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
802          * address.
803          */
804         if ((ivp->iv_flags & IVF_SVC) && (tatm.address_format == T_ATM_ABSENT))
805                 goto drop;
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)))
809                 goto drop;
810
811         /*
812          * See where this packet is from
813          */
814         if (ivp->iv_flags & IVF_PVC) {
815                 /*
816                  * Process the PVC arp data, although we don't really 
817                  * update the arp cache with this information
818                  */
819                 uniarp_cache_pvc(ivp, &sip, &satm, &satmsub);
820
821         } else {
822                 /*
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.
828                  */
829                 (void) uniarp_cache_svc(uip, &sip, &satm, &satmsub,
830                                 UAO_PEER_RSP);
831         }
832
833 drop:
834         (void) splx(s);
835         KB_FREEALL(m);
836         return;
837 }
838
839
840 /*
841  * Print an ATMARP PDU
842  * 
843  * Arguments:
844  *      ivp     pointer to input VCC control block
845  *      m       pointer to pdu buffer chain
846  *      msg     pointer to message string
847  *
848  * Returns:
849  *      none
850  *
851  */
852 void
853 uniarp_pdu_print(const struct ipvcc *ivp, const KBuffer *m, const char *msg)
854 {
855         char            buf[128];
856         struct vccb     *vcp;
857
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);
862 }