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