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