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