bpf: Use bpf global token instead mplock to protect bpf stuffs
[dragonfly.git] / sys / netproto / atm / uni / uniarp.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.c,v 1.8 2000/01/15 20:46:07 mks Exp $
27  *      @(#) $DragonFly: src/sys/netproto/atm/uni/uniarp.c,v 1.8 2006/01/14 13:36:39 swildner Exp $
28  */
29
30 /*
31  * ATM Forum UNI Support
32  * ---------------------
33  *
34  * UNI ATMARP support (RFC1577)
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 "unisig_var.h"
43 #include "uniip_var.h"
44
45 /*
46  * Global variables
47  */
48 struct uniarp           *uniarp_arptab[UNIARP_HASHSIZ] = {NULL};
49 struct uniarp           *uniarp_nomaptab = NULL;
50 struct uniarp           *uniarp_pvctab = NULL;
51 struct atm_time         uniarp_timer = {0, 0};          /* Aging timer */
52 struct uniarp_stat      uniarp_stat = {0};
53 int                     uniarp_print = 0;
54
55 Atm_endpoint    uniarp_endpt = {
56         NULL,
57         ENDPT_ATMARP,
58         uniarp_ioctl,
59         uniarp_getname,
60         uniarp_connected,
61         uniarp_cleared,
62         NULL,
63         NULL,
64         NULL,
65         NULL,
66         uniarp_cpcs_data,
67         NULL,
68         NULL,
69         NULL,
70         NULL
71 };
72
73 struct sp_info  uniarp_pool = {
74         "uni arp pool",                 /* si_name */
75         sizeof(struct uniarp),          /* si_blksiz */
76         10,                             /* si_blkcnt */
77         200                             /* si_maxallow */
78 };
79
80
81 /*
82  * Local variables
83  */
84 static void     uniarp_server_mode (struct uniip *);
85 static void     uniarp_client_mode (struct uniip *, Atm_addr *);
86
87
88 /*
89  * Process module loading notification
90  * 
91  * Called whenever the uni module is initializing.
92  *
93  * Arguments:
94  *      none
95  *
96  * Returns:
97  *      0       initialization successful
98  *      errno   initialization failed - reason indicated
99  *
100  */
101 int
102 uniarp_start(void)
103 {
104         int     err;
105
106         /*
107          * Register our endpoint
108          */
109         err = atm_endpoint_register(&uniarp_endpt);
110
111         return (err);
112 }
113
114
115 /*
116  * Process module unloading notification
117  * 
118  * Called whenever the uni module is about to be unloaded.  All signalling
119  * instances will have been previously detached.  All uniarp resources 
120  * must be freed now.
121  *
122  * Arguments:
123  *      none
124  *
125  * Returns:
126  *      none
127  *
128  */
129 void
130 uniarp_stop(void)
131 {
132         int     i;
133
134         /* 
135          * Make sure the arp table is empty
136          */
137         for (i = 0; i < UNIARP_HASHSIZ; i++) {
138                 if (uniarp_arptab[i] != NULL)
139                         panic("uniarp_stop: arp table not empty");
140         }
141
142         /*
143          * Cancel timers
144          */
145         atm_untimeout(&uniarp_timer);
146
147         /*
148          * De-register ourselves
149          */
150         atm_endpoint_deregister(&uniarp_endpt);
151
152         /*
153          * Free our storage pools
154          */
155         atm_release_pool(&uniarp_pool);
156 }
157
158
159 /*
160  * Process IP Network Interface Activation
161  * 
162  * Called whenever an IP network interface becomes active.
163  *
164  * Called at splnet.
165  *
166  * Arguments:
167  *      uip     pointer to UNI IP interface
168  *
169  * Returns:
170  *      none
171  *
172  */
173 void
174 uniarp_ipact(struct uniip *uip)
175 {
176         struct unisig           *usp;
177
178         ATM_DEBUG1("uniarp_ipact: uip=%p\n", uip);
179
180         /*
181          * Set initial state
182          */
183         uip->uip_arpstate = UIAS_NOTCONF;
184         uip->uip_arpsvratm.address_format = T_ATM_ABSENT;
185         uip->uip_arpsvratm.address_length = 0;
186         uip->uip_arpsvrsub.address_format = T_ATM_ABSENT;
187         uip->uip_arpsvrsub.address_length = 0;
188
189         usp = (struct unisig *)uip->uip_ipnif->inf_nif->nif_pif->pif_siginst;
190         if (usp->us_addr.address_format != T_ATM_ABSENT)
191                 uip->uip_flags |= UIF_IFADDR;
192
193         /*
194          * Make sure aging timer is running
195          */
196         if ((uniarp_timer.ti_flag & TIF_QUEUED) == 0)
197                 atm_timeout(&uniarp_timer, UNIARP_AGING, uniarp_aging);
198
199         return;
200 }
201
202
203 /*
204  * Process IP Network Interface Deactivation
205  * 
206  * Called whenever an IP network interface becomes inactive.  All VCCs
207  * for this interface should already have been closed.
208  *
209  * Called at splnet.
210  *
211  * Arguments:
212  *      uip     pointer to UNI IP interface
213  *
214  * Returns:
215  *      none
216  *
217  */
218 void
219 uniarp_ipdact(struct uniip *uip)
220 {
221         struct uniarp           *uap, *unext;
222         int     i;
223
224         ATM_DEBUG1("uniarp_ipdact: uip=%p\n", uip);
225
226         /* 
227          * Delete all interface entries
228          */
229         for (i = 0; i < UNIARP_HASHSIZ; i++) {
230                 for (uap = uniarp_arptab[i]; uap; uap = unext) {
231                         unext = uap->ua_next;
232
233                         if (uap->ua_intf != uip)
234                                 continue;
235
236                         /*
237                          * All VCCs should (better) be gone by now
238                          */
239                         if (uap->ua_ivp)
240                                 panic("uniarp_ipdact: entry not empty");
241
242                         /*
243                          * Clean up any loose ends
244                          */
245                         UNIARP_CANCEL(uap);
246
247                         /*
248                          * Delete entry from arp table and free entry
249                          */
250                         UNIARP_DELETE(uap);
251                         atm_free((caddr_t)uap);
252                 }
253         }
254
255         /*
256          * Clean up 'nomap' table
257          */
258         for (uap = uniarp_nomaptab; uap; uap = unext) {
259                 unext = uap->ua_next;
260
261                 if (uap->ua_intf != uip)
262                         continue;
263
264                 /*
265                  * All VCCs should (better) be gone by now
266                  */
267                 if (uap->ua_ivp)
268                         panic("uniarp_ipdact: entry not empty");
269
270                 /*
271                  * Clean up any loose ends
272                  */
273                 UNIARP_CANCEL(uap);
274
275                 /*
276                  * Delete entry from 'no map' table and free entry
277                  */
278                 UNLINK(uap, struct uniarp, uniarp_nomaptab, ua_next);
279                 atm_free((caddr_t)uap);
280         }
281
282         /*
283          * Also clean up pvc table
284          */
285         for (uap = uniarp_pvctab; uap; uap = unext) {
286                 unext = uap->ua_next;
287
288                 if (uap->ua_intf != uip)
289                         continue;
290
291                 /*
292                  * All PVCs should (better) be gone by now
293                  */
294                 panic("uniarp_ipdact: pvc table not empty");
295         }
296
297         /*
298          * Cancel arp interface timer
299          */
300         UNIIP_ARP_CANCEL(uip);
301
302         /*
303          * Stop aging timer if this is the last active interface
304          */
305         if (uniip_head == uip && uip->uip_next == NULL)
306                 atm_untimeout(&uniarp_timer);
307 }
308
309
310 /*
311  * Process Interface ATM Address Change
312  * 
313  * This function is called whenever the ATM address for a physical
314  * interface is set/changed.
315  *
316  * Called at splnet.
317  *
318  * Arguments:
319  *      sip     pointer to interface's UNI signalling instance
320  *
321  * Returns:
322  *      none
323  *
324  */
325 void
326 uniarp_ifaddr(struct siginst *sip)
327 {
328         struct atm_nif          *nip;
329         struct uniip            *uip;
330
331         ATM_DEBUG1("uniarp_ifaddr: sip=%p\n", sip);
332
333         /*
334          * We've got to handle this for every network interface
335          */
336         for (nip = sip->si_pif->pif_nif; nip; nip = nip->nif_pnext) {
337
338                 /*
339                  * Find our control blocks
340                  */
341                 for (uip = uniip_head; uip; uip = uip->uip_next) {
342                         if (uip->uip_ipnif->inf_nif == nip)
343                                 break;
344                 }
345                 if (uip == NULL)
346                         continue;
347
348                 /*
349                  * We don't support changing prefix (yet)
350                  */
351                 if (uip->uip_flags & UIF_IFADDR) {
352                         log(LOG_ERR, "uniarp_ifaddr: change not supported\n");
353                         continue;
354                 }
355
356                 /*
357                  * Note that address has been set and figure out what
358                  * to do next
359                  */
360                 uip->uip_flags |= UIF_IFADDR;
361
362                 if (uip->uip_arpstate == UIAS_CLIENT_PADDR) {
363                         /*
364                          * This is what we're waiting for
365                          */
366                         uniarp_client_mode(uip, NULL);
367                 } else if (uip->uip_arpstate == UIAS_SERVER_ACTIVE) {
368                         /*
369                          * Set new local arpserver atm address
370                          */
371                         ATM_ADDR_SEL_COPY(&sip->si_addr, nip->nif_sel,
372                                                 &uip->uip_arpsvratm);
373                 }
374         }
375
376         return;
377 }
378
379
380 /*
381  * Set ATMARP Server Mode
382  * 
383  * This function is called to configure the local node to become the 
384  * ATMARP server for the specified LIS.
385  *
386  * Called at splnet.
387  *
388  * Arguments:
389  *      uip     pointer to UNI IP interface
390  *
391  * Returns:
392  *      none
393  *
394  */
395 static void
396 uniarp_server_mode(struct uniip *uip)
397 {
398         struct ip_nif   *inp;
399         struct atm_nif  *nip;
400         struct siginst  *sgp;
401         struct ipvcc    *ivp, *inext;
402         struct uniarp   *uap, *unext;
403         int             i;
404
405         ATM_DEBUG1("uniarp_server_mode: uip=%p\n", uip);
406
407         /*
408          * Handle client/server mode changes first
409          */
410         switch (uip->uip_arpstate) {
411
412         case UIAS_NOTCONF:
413         case UIAS_SERVER_ACTIVE:
414         case UIAS_CLIENT_PADDR:
415                 /*
416                  * Nothing to undo
417                  */
418                 break;
419
420         case UIAS_CLIENT_POPEN:
421                 /*
422                  * We're becoming the server, so kill the pending connection
423                  */
424                 UNIIP_ARP_CANCEL(uip);
425                 if ((ivp = uip->uip_arpsvrvcc) != NULL) {
426                         ivp->iv_flags &= ~IVF_NOIDLE;
427                         uip->uip_arpsvrvcc = NULL;
428                         (*ivp->iv_ipnif->inf_arpnotify)(ivp, MAP_FAILED);
429                 }
430                 break;
431
432         case UIAS_CLIENT_REGISTER:
433         case UIAS_CLIENT_ACTIVE:
434                 /*
435                  * We're becoming the server, but leave existing VCC as a
436                  * "normal" IP VCC
437                  */
438                 UNIIP_ARP_CANCEL(uip);
439                 ivp = uip->uip_arpsvrvcc;
440                 ivp->iv_flags &= ~IVF_NOIDLE;
441                 uip->uip_arpsvrvcc = NULL;
442                 break;
443         }
444
445         /*
446          * Revalidate status for all arp entries on this interface
447          */
448         for (i = 0; i < UNIARP_HASHSIZ; i++) {
449                 for (uap = uniarp_arptab[i]; uap; uap = unext) {
450                         unext = uap->ua_next;
451
452                         if (uap->ua_intf != uip)
453                                 continue;
454
455                         if (uap->ua_origin >= UAO_PERM)
456                                 continue;
457
458                         if (uap->ua_origin >= UAO_SCSP) {
459                                 if (uniarp_validate_ip(uip, &uap->ua_dstip,
460                                                         uap->ua_origin) == 0)
461                                         continue;
462                         }
463
464                         if (uap->ua_ivp == NULL) {
465                                 UNIARP_CANCEL(uap);
466                                 UNIARP_DELETE(uap);
467                                 atm_free((caddr_t)uap);
468                                 continue;
469                         }
470
471                         if (uap->ua_flags & UAF_VALID) {
472                                 uap->ua_flags |= UAF_LOCKED;
473                                 for (ivp = uap->ua_ivp; ivp; ivp = inext) {
474                                         inext = ivp->iv_arpnext;
475                                         (*ivp->iv_ipnif->inf_arpnotify)
476                                                         (ivp, MAP_INVALID);
477                                 }
478                                 uap->ua_flags &= ~(UAF_LOCKED | UAF_VALID);
479                         }
480                         uap->ua_aging = 1;
481                         uap->ua_origin = 0;
482                 }
483         }
484
485         /*
486          * OK, now let's make ourselves the server
487          */
488         inp = uip->uip_ipnif;
489         nip = inp->inf_nif;
490         sgp = nip->nif_pif->pif_siginst;
491         ATM_ADDR_SEL_COPY(&sgp->si_addr, nip->nif_sel, &uip->uip_arpsvratm);
492         uip->uip_arpsvrip = IA_SIN(inp->inf_addr)->sin_addr;
493         uip->uip_arpstate = UIAS_SERVER_ACTIVE;
494         return;
495 }
496
497
498 /*
499  * Set ATMARP Client Mode
500  * 
501  * This function is called to configure the local node to be an ATMARP 
502  * client on the specified LIS using the specified ATMARP server.
503  *
504  * Called at splnet.
505  *
506  * Arguments:
507  *      uip     pointer to UNI IP interface
508  *      aap     pointer to the ATMARP server's ATM address
509  *
510  * Returns:
511  *      none
512  *
513  */
514 static void
515 uniarp_client_mode(struct uniip *uip, Atm_addr *aap)
516 {
517         struct ip_nif           *inp = uip->uip_ipnif;
518         struct uniarp           *uap, *unext;
519         struct ipvcc            *ivp, *inext;
520         int                     i;
521
522         ATM_DEBUG2("uniarp_client_mode: uip=%p, atm=(%s,-)\n",
523                 uip, aap ? unisig_addr_print(aap): "-");
524
525         /*
526          * Handle client/server mode changes first
527          */
528         switch (uip->uip_arpstate) {
529
530         case UIAS_NOTCONF:
531         case UIAS_CLIENT_PADDR:
532                 /*
533                  * Nothing to undo
534                  */
535                 break;
536
537         case UIAS_CLIENT_POPEN:
538                 /*
539                  * If this is this a timeout retry, just go do it
540                  */
541                 if (aap == NULL)
542                         break;
543
544                 /*
545                  * If this isn't really a different arpserver, we're done
546                  */
547                 if (ATM_ADDR_EQUAL(aap, &uip->uip_arpsvratm))
548                         return;
549
550                 /*
551                  * We're changing servers, so kill the pending connection
552                  */
553                 UNIIP_ARP_CANCEL(uip);
554                 if ((ivp = uip->uip_arpsvrvcc) != NULL) {
555                         ivp->iv_flags &= ~IVF_NOIDLE;
556                         uip->uip_arpsvrvcc = NULL;
557                         (*ivp->iv_ipnif->inf_arpnotify)(ivp, MAP_FAILED);
558                 }
559                 break;
560
561         case UIAS_CLIENT_REGISTER:
562         case UIAS_CLIENT_ACTIVE:
563                 /*
564                  * If this isn't really a different arpserver, we're done
565                  */
566                 if (ATM_ADDR_EQUAL(aap, &uip->uip_arpsvratm))
567                         return;
568
569                 /*
570                  * We're changing servers, but leave existing VCC as a
571                  * "normal" IP VCC
572                  */
573                 UNIIP_ARP_CANCEL(uip);
574                 ivp = uip->uip_arpsvrvcc;
575                 ivp->iv_flags &= ~IVF_NOIDLE;
576                 uip->uip_arpsvrvcc = NULL;
577                 break;
578
579         case UIAS_SERVER_ACTIVE:
580                 /*
581                  * We're changing from server mode, so...
582                  *
583                  * Reset valid/authoritative status for all arp entries
584                  * on this interface
585                  */
586                 for (i = 0; i < UNIARP_HASHSIZ; i++) {
587                         for (uap = uniarp_arptab[i]; uap; uap = unext) {
588                                 unext = uap->ua_next;
589
590                                 if (uap->ua_intf != uip)
591                                         continue;
592
593                                 if (uap->ua_origin >= UAO_PERM)
594                                         continue;
595
596                                 if (uap->ua_ivp == NULL) {
597                                         UNIARP_CANCEL(uap);
598                                         UNIARP_DELETE(uap);
599                                         atm_free((caddr_t)uap);
600                                         continue;
601                                 }
602
603                                 if (uap->ua_flags & UAF_VALID) {
604                                         uap->ua_flags |= UAF_LOCKED;
605                                         for (ivp = uap->ua_ivp; ivp;
606                                                                 ivp = inext) {
607                                                 inext = ivp->iv_arpnext;
608                                                 (*ivp->iv_ipnif->inf_arpnotify)
609                                                         (ivp, MAP_INVALID);
610                                         }
611                                         uap->ua_flags &=
612                                                 ~(UAF_LOCKED | UAF_VALID);
613                                 }
614                                 uap->ua_aging = 1;
615                                 uap->ua_origin = 0;
616                         }
617                 }
618                 uip->uip_arpsvratm.address_format = T_ATM_ABSENT;
619                 uip->uip_arpsvratm.address_length = 0;
620                 uip->uip_arpsvrsub.address_format = T_ATM_ABSENT;
621                 uip->uip_arpsvrsub.address_length = 0;
622                 uip->uip_arpsvrip.s_addr = 0;
623                 break;
624         }
625
626         /*
627          * Save the arp server address, if supplied now
628          */
629         if (aap)
630                 ATM_ADDR_COPY(aap, &uip->uip_arpsvratm);
631
632         /*
633          * If the interface's ATM address isn't set yet, then we
634          * can't do much until it is
635          */
636         if ((uip->uip_flags & UIF_IFADDR) == 0) {
637                 uip->uip_arpstate = UIAS_CLIENT_PADDR;
638                 return;
639         }
640
641         /*
642          * Just to keep things simple, if we already have (or are trying to
643          * setup) any SVCs to our new server, kill the connections so we can
644          * open a "fresh" SVC for the arpserver connection.
645          */
646         for (i = 0; i < UNIARP_HASHSIZ; i++) {
647                 for (uap = uniarp_arptab[i]; uap; uap = unext) {
648                         unext = uap->ua_next;
649
650                         if (ATM_ADDR_EQUAL(&uip->uip_arpsvratm,
651                                                         &uap->ua_dstatm) &&
652                             ATM_ADDR_EQUAL(&uip->uip_arpsvrsub,
653                                                         &uap->ua_dstatmsub)) {
654                                 uap->ua_flags &= ~UAF_VALID;
655                                 for (ivp = uap->ua_ivp; ivp; ivp = inext) {
656                                         inext = ivp->iv_arpnext;
657                                         (*inp->inf_arpnotify)(ivp, MAP_FAILED);
658                                 }
659                         }
660                 }
661         }
662         for (uap = uniarp_nomaptab; uap; uap = unext) {
663                 unext = uap->ua_next;
664
665                 if (ATM_ADDR_EQUAL(&uip->uip_arpsvratm, &uap->ua_dstatm) &&
666                     ATM_ADDR_EQUAL(&uip->uip_arpsvrsub, &uap->ua_dstatmsub)) {
667                         uap->ua_flags &= ~UAF_VALID;
668                         for (ivp = uap->ua_ivp; ivp; ivp = inext) {
669                                 inext = ivp->iv_arpnext;
670                                 (*inp->inf_arpnotify)(ivp, MAP_FAILED);
671                         }
672                 }
673         }
674
675         /*
676          * Now, get an arp entry for the server connection
677          */
678         uip->uip_arpstate = UIAS_CLIENT_POPEN;
679         uap = (struct uniarp *)atm_allocate(&uniarp_pool);
680         if (uap == NULL) {
681                 UNIIP_ARP_TIMER(uip, 1 * ATM_HZ);
682                 return;
683         }
684
685         /*
686          * Next, initiate an SVC to the server
687          */
688         if ((*inp->inf_createsvc)(&inp->inf_nif->nif_if, AF_ATM,
689                         (caddr_t)&uip->uip_arpsvratm, &ivp)) {
690                 atm_free((caddr_t)uap);
691                 UNIIP_ARP_TIMER(uip, 1 * ATM_HZ);
692                 return;
693         }
694
695         /*
696          * Finally, get everything set up and wait for the SVC
697          * connection to complete
698          */
699         uip->uip_arpsvrvcc = ivp;
700         ivp->iv_flags |= IVF_NOIDLE;
701
702         ATM_ADDR_COPY(&uip->uip_arpsvratm, &uap->ua_dstatm);
703         ATM_ADDR_COPY(&uip->uip_arpsvrsub, &uap->ua_dstatmsub);
704         uap->ua_intf = uip;
705
706         LINK2TAIL(ivp, struct ipvcc, uap->ua_ivp, iv_arpnext);
707         ivp->iv_arpent = (struct arpmap *)uap;
708
709         LINK2TAIL(uap, struct uniarp, uniarp_nomaptab, ua_next);
710
711         return;
712 }
713
714
715 /*
716  * Process a UNI ARP interface timeout
717  * 
718  * Called when a previously scheduled uniip arp interface timer expires.
719  * Processing will be based on the current uniip arp state.
720  *
721  * Called at splnet.
722  *
723  * Arguments:
724  *      tip     pointer to uniip arp timer control block
725  *
726  * Returns:
727  *      none
728  *
729  */
730 void
731 uniarp_iftimeout(struct atm_time *tip)
732 {
733         struct ip_nif   *inp;
734         struct uniip    *uip;
735
736
737         /*
738          * Back-off to uniip control block
739          */
740         uip = (struct uniip *)
741                 ((caddr_t)tip - (int)(&((struct uniip *)0)->uip_arptime));
742
743         ATM_DEBUG2("uniarp_iftimeout: uip=%p, state=%d\n", uip, 
744                 uip->uip_arpstate);
745
746         /*
747          * Process timeout based on protocol state
748          */
749         switch (uip->uip_arpstate) {
750
751         case UIAS_CLIENT_POPEN:
752                 /*
753                  * Retry opening arp server connection
754                  */
755                 uniarp_client_mode(uip, NULL);
756                 break;
757
758         case UIAS_CLIENT_REGISTER:
759                 /*
760                  * Resend registration request
761                  */
762                 inp = uip->uip_ipnif;
763                 uniarp_arp_req(uip, &(IA_SIN(inp->inf_addr)->sin_addr));
764
765                 /*
766                  * Restart timer
767                  */
768                 UNIIP_ARP_TIMER(uip, 2 * ATM_HZ);
769
770                 break;
771
772         case UIAS_CLIENT_ACTIVE:
773                 /*
774                  * Refresh our registration
775                  */
776                 inp = uip->uip_ipnif;
777                 uniarp_arp_req(uip, &(IA_SIN(inp->inf_addr)->sin_addr));
778
779                 /*
780                  * Restart timer
781                  */
782                 UNIIP_ARP_TIMER(uip, UNIARP_REGIS_RETRY);
783
784                 break;
785
786         default:
787                 log(LOG_ERR, "uniarp_iftimeout: invalid state %d\n",
788                         uip->uip_arpstate);
789         }
790 }
791
792
793 /*
794  * UNI ARP IOCTL support
795  *
796  * Function will be called at splnet.
797  *
798  * Arguments:
799  *      code    PF_ATM sub-operation code
800  *      data    pointer to code specific parameter data area
801  *      arg1    pointer to code specific argument
802  *
803  * Returns:
804  *      0       request procesed
805  *      errno   error processing request - reason indicated
806  *
807  */
808 int
809 uniarp_ioctl(int code, caddr_t data, caddr_t arg1)
810 {
811         struct atmaddreq        *aap;
812         struct atmdelreq        *adp;
813         struct atmsetreq        *asp;
814         struct atminfreq        *aip;
815         struct air_arp_rsp      aar;
816         struct air_asrv_rsp     asr;
817         struct atm_pif          *pip;
818         struct atm_nif          *nip;
819         struct ipvcc            *ivp, *inext;
820         struct uniip            *uip;
821         struct uniarp           *uap;
822         struct unisig           *usp;
823         struct in_addr          ip;
824         Atm_addr                atmsub;
825         u_long                  dst;
826         int                     err = 0, i, buf_len;
827         caddr_t                 buf_addr;
828
829         switch (code) {
830
831         case AIOCS_ADD_ARP:
832                 /*
833                  * Add a permanent ARP mapping
834                  */
835                 aap = (struct atmaddreq *)data;
836                 uip = (struct uniip *)arg1;
837                 if (aap->aar_arp_addr.address_format != T_ATM_ENDSYS_ADDR) {
838                         err = EINVAL;
839                         break;
840                 }
841                 atmsub.address_format = T_ATM_ABSENT;
842                 atmsub.address_length = 0;
843                 ip = SATOSIN(&aap->aar_arp_dst)->sin_addr;
844
845                 /*
846                  * Validate IP address
847                  */
848                 if (uniarp_validate_ip(uip, &ip, aap->aar_arp_origin) != 0) {
849                         err = EADDRNOTAVAIL;
850                         break;
851                 }
852
853                 /*
854                  * Add an entry to the cache
855                  */
856                 err = uniarp_cache_svc(uip, &ip, &aap->aar_arp_addr,
857                                 &atmsub, aap->aar_arp_origin);
858                 break;
859
860         case AIOCS_DEL_ARP:
861                 /*
862                  * Delete an ARP mapping
863                  */
864                 adp = (struct atmdelreq *)data;
865                 uip = (struct uniip *)arg1;
866                 ip = SATOSIN(&adp->adr_arp_dst)->sin_addr;
867
868                 /*
869                  * Now find the entry to be deleted
870                  */
871                 UNIARP_LOOKUP(ip.s_addr, uap);
872                 if (uap == NULL) {
873                         err = ENOENT;
874                         break;
875                 }
876
877                 /*
878                  * Notify all VCCs using this entry that they must finish
879                  * up now.  
880                  */
881                 uap->ua_flags |= UAF_LOCKED;
882                 for (ivp = uap->ua_ivp; ivp; ivp = inext) {
883                         inext = ivp->iv_arpnext;
884                         (*ivp->iv_ipnif->inf_arpnotify)(ivp, MAP_FAILED);
885                 }
886
887                 /*
888                  * Now free up the entry
889                  */
890                 UNIARP_CANCEL(uap);
891                 UNIARP_DELETE(uap);
892                 atm_free((caddr_t)uap);
893                 break;
894
895         case AIOCS_SET_ASV:
896                 /*
897                  * Set interface ARP server address
898                  */
899                 asp = (struct atmsetreq *)data;
900                 for (uip = uniip_head; uip; uip = uip->uip_next) {
901                         if (uip->uip_ipnif->inf_nif == (struct atm_nif *)arg1)
902                                 break;
903                 }
904                 if (uip == NULL) {
905                         err = ENOPROTOOPT;
906                         break;
907                 }
908
909                 /*
910                  * Check for our own address
911                  */
912                 usp = (struct unisig *)
913                                 uip->uip_ipnif->inf_nif->nif_pif->pif_siginst;
914                 if (ATM_ADDR_EQUAL(&asp->asr_arp_addr, &usp->us_addr)) {
915                         asp->asr_arp_addr.address_format = T_ATM_ABSENT;
916                 }
917
918                 /*
919                  * If we're going into server mode, make sure we can get 
920                  * the memory for the prefix list before continuing
921                  */
922                 if (asp->asr_arp_addr.address_format == T_ATM_ABSENT) {
923                         i = asp->asr_arp_plen / sizeof(struct uniarp_prf);
924                         if (i <= 0) {
925                                 err = EINVAL;
926                                 break;
927                         }
928                         buf_len = i * sizeof(struct uniarp_prf);
929                         buf_addr = KM_ALLOC(buf_len, M_DEVBUF, 
930                                                 M_INTWAIT | M_NULLOK);
931                         if (buf_addr == NULL) {
932                                 err = ENOMEM;
933                                 break;
934                         }
935                         err = copyin(asp->asr_arp_pbuf, buf_addr, buf_len);
936                         if (err) {
937                                 KM_FREE(buf_addr, buf_len, M_DEVBUF);
938                                 break;
939                         }
940                 } else {
941                         /* Silence the compiler */
942                         i = 0;
943                         buf_addr = NULL;
944                 }
945
946                 /*
947                  * Free any existing prefix address list
948                  */
949                 if (uip->uip_prefix != NULL) {
950                         KM_FREE(uip->uip_prefix, 
951                                 uip->uip_nprefix * sizeof(struct uniarp_prf),
952                                 M_DEVBUF);
953                         uip->uip_prefix = NULL;
954                         uip->uip_nprefix = 0;
955                 }
956
957                 if (asp->asr_arp_addr.address_format == T_ATM_ABSENT) {
958                         /*
959                          * Set ATMARP server mode
960                          */
961                         uip->uip_prefix = (struct uniarp_prf *)buf_addr;
962                         uip->uip_nprefix = i;
963                         uniarp_server_mode(uip);
964                 } else
965                         /*
966                          * Set ATMARP client mode
967                          */
968                         uniarp_client_mode(uip, &asp->asr_arp_addr);
969                 break;
970
971         case AIOCS_INF_ARP:
972                 /*
973                  * Get ARP table information
974                  */
975                 aip = (struct atminfreq *)data;
976
977                 if (aip->air_arp_addr.sa_family != AF_INET)
978                         break;
979                 dst = SATOSIN(&aip->air_arp_addr)->sin_addr.s_addr;
980
981                 buf_addr = aip->air_buf_addr;
982                 buf_len = aip->air_buf_len;
983
984                 pip = ((struct siginst *)arg1)->si_pif;
985
986                 /*
987                  * Run through entire arp table
988                  */
989                 for (i = 0; i < UNIARP_HASHSIZ; i++) {
990                         for (uap = uniarp_arptab[i]; uap; uap = uap->ua_next) {
991                                 /*
992                                  * We only want valid entries learned
993                                  * from the supplied interface.
994                                  */
995                                 nip = uap->ua_intf->uip_ipnif->inf_nif;
996                                 if (nip->nif_pif != pip)
997                                         continue;
998                                 if ((dst != INADDR_ANY) &&
999                                     (dst != uap->ua_dstip.s_addr))
1000                                         continue;
1001
1002                                 /*
1003                                  * Make sure there's room in the user's buffer
1004                                  */
1005                                 if (buf_len < sizeof(aar)) {
1006                                         err = ENOSPC;
1007                                         break;
1008                                 }
1009
1010                                 /*
1011                                  * Fill in info to be returned
1012                                  */
1013                                 SATOSIN(&aar.aap_arp_addr)->sin_family =
1014                                         AF_INET;
1015                                 SATOSIN(&aar.aap_arp_addr)->sin_addr.s_addr =
1016                                         uap->ua_dstip.s_addr;
1017                                 strlcpy(aar.aap_intf,
1018                                     nip->nif_if.if_xname,
1019                                     sizeof(aar.aap_intf));
1020                                 aar.aap_flags = uap->ua_flags;
1021                                 aar.aap_origin = uap->ua_origin;
1022                                 if (uap->ua_flags & UAF_VALID)
1023                                         aar.aap_age = uap->ua_aging + 
1024                                             uap->ua_retry * UNIARP_RETRY_AGE;
1025                                 else
1026                                         aar.aap_age = 0;
1027                                 ATM_ADDR_COPY(&uap->ua_dstatm, &aar.aap_addr);
1028                                 ATM_ADDR_COPY(&uap->ua_dstatmsub,
1029                                         &aar.aap_subaddr);
1030
1031                                 /*
1032                                  * Copy the response into the user's buffer
1033                                  */
1034                                 if ((err = copyout((caddr_t)&aar, buf_addr, 
1035                                                         sizeof(aar))) != 0)
1036                                         break;
1037                                 buf_addr += sizeof(aar);
1038                                 buf_len -= sizeof(aar);
1039                         }
1040                         if (err)
1041                                 break;
1042                 }
1043
1044                 /*
1045                  * Now go through the 'nomap' table
1046                  */
1047                 if (err || (dst != INADDR_ANY))
1048                         goto updbuf;
1049                 for (uap = uniarp_nomaptab; uap; uap = uap->ua_next) {
1050                         /*
1051                          * We only want valid entries learned
1052                          * from the supplied interface.
1053                          */
1054                         nip = uap->ua_intf->uip_ipnif->inf_nif;
1055                         if (nip->nif_pif != pip)
1056                                 continue;
1057
1058                         /*
1059                          * Make sure there's room in the user's buffer
1060                          */
1061                         if (buf_len < sizeof(aar)) {
1062                                 err = ENOSPC;
1063                                 break;
1064                         }
1065
1066                         /*
1067                          * Fill in info to be returned
1068                          */
1069                         SATOSIN(&aar.aap_arp_addr)->sin_family = AF_INET;
1070                         SATOSIN(&aar.aap_arp_addr)->sin_addr.s_addr = 0;
1071                         strlcpy(aar.aap_intf,
1072                             nip->nif_if.if_xname,
1073                             sizeof(aar.aap_intf));
1074                         aar.aap_flags = 0;
1075                         aar.aap_origin = uap->ua_origin;
1076                         aar.aap_age = 0;
1077                         ATM_ADDR_COPY(&uap->ua_dstatm, &aar.aap_addr);
1078                         ATM_ADDR_COPY(&uap->ua_dstatmsub,
1079                                 &aar.aap_subaddr);
1080
1081                         /*
1082                          * Copy the response into the user's buffer
1083                          */
1084                         if ((err = copyout((caddr_t)&aar, buf_addr, 
1085                                                 sizeof(aar))) != 0)
1086                                 break;
1087                         buf_addr += sizeof(aar);
1088                         buf_len -= sizeof(aar);
1089                 }
1090
1091 updbuf:
1092                 /*
1093                  * Update the buffer pointer and length
1094                  */
1095                 aip->air_buf_addr = buf_addr;
1096                 aip->air_buf_len = buf_len;
1097
1098                 /*
1099                  * If the user wants the refresh status reset and no 
1100                  * errors have been encountered, then do the reset
1101                  */
1102                 if ((err == 0) && (aip->air_arp_flags & ARP_RESET_REF)) {
1103                         for (i = 0; i < UNIARP_HASHSIZ; i++) {
1104                                 for (uap = uniarp_arptab[i]; uap; 
1105                                                         uap = uap->ua_next) {
1106                                         /*
1107                                          * We only want valid entries learned
1108                                          * from the supplied interface.
1109                                          */
1110                                         nip = uap->ua_intf->uip_ipnif->inf_nif;
1111                                         if (nip->nif_pif != pip)
1112                                                 continue;
1113                                         if ((dst != INADDR_ANY) &&
1114                                             (dst != uap->ua_dstip.s_addr))
1115                                                 continue;
1116
1117                                         /*
1118                                          * Reset refresh flag
1119                                          */
1120                                         uap->ua_flags &= ~UAF_REFRESH;
1121                                 }
1122                         }
1123                 }
1124                 break;
1125
1126         case AIOCS_INF_ASV:
1127                 /*
1128                  * Get ARP server information
1129                  */
1130                 aip = (struct atminfreq *)data;
1131                 nip = (struct atm_nif *)arg1;
1132
1133                 buf_addr = aip->air_buf_addr;
1134                 buf_len = aip->air_buf_len;
1135
1136                 for (uip = uniip_head; uip; uip = uip->uip_next) {
1137
1138                         if (uip->uip_ipnif->inf_nif != nip)
1139                                 continue;
1140
1141                         /*
1142                          * Make sure there's room in the user's buffer
1143                          */
1144                         if (buf_len < sizeof(asr)) {
1145                                 err = ENOSPC;
1146                                 break;
1147                         }
1148
1149                         /*
1150                          * Fill in info to be returned
1151                          */
1152                         strlcpy(asr.asp_intf,
1153                             nip->nif_if.if_xname,
1154                             sizeof(asr.asp_intf));
1155                         asr.asp_state = uip->uip_arpstate;
1156                         if (uip->uip_arpstate == UIAS_SERVER_ACTIVE) {
1157                                 asr.asp_addr.address_format = T_ATM_ABSENT;
1158                                 asr.asp_addr.address_length = 0;
1159                         } else {
1160                                 ATM_ADDR_COPY(&uip->uip_arpsvratm,
1161                                                 &asr.asp_addr);
1162                         }
1163                         asr.asp_subaddr.address_format = T_ATM_ABSENT;
1164                         asr.asp_subaddr.address_length = 0;
1165                         asr.asp_nprefix = uip->uip_nprefix;
1166
1167                         /*
1168                          * Copy the response into the user's buffer
1169                          */
1170                         if ((err = copyout((caddr_t)&asr, buf_addr, sizeof(asr))) != 0)
1171                                 break;
1172                         buf_addr += sizeof(asr);
1173                         buf_len -= sizeof(asr);
1174
1175                         /*
1176                          * Copy the prefix list into the user's buffer
1177                          */
1178                         if (uip->uip_nprefix) {
1179                                 i = uip->uip_nprefix 
1180                                                 * sizeof(struct uniarp_prf);
1181                                 if (buf_len < i) {
1182                                         err = ENOSPC;
1183                                         break;
1184                                 }
1185                                 if ((err = copyout(uip->uip_prefix, buf_addr, i)) != 0)
1186                                         break;
1187                                 buf_addr += i;
1188                                 buf_len -= i;
1189                         }
1190                 }
1191
1192                 /*
1193                  * Update the buffer pointer and length
1194                  */
1195                 aip->air_buf_addr = buf_addr;
1196                 aip->air_buf_len = buf_len;
1197                 break;
1198
1199         default:
1200                 err = EOPNOTSUPP;
1201         }
1202
1203         return (err);
1204 }
1205
1206
1207 /*
1208  * Get Connection's Application/Owner Name
1209  * 
1210  * Arguments:
1211  *      tok     uniarp connection token (pointer to ipvcc)
1212  *
1213  * Returns:
1214  *      addr    pointer to string containing our name
1215  *
1216  */
1217 caddr_t
1218 uniarp_getname(void *tok)
1219 {
1220         return ("ATMARP");
1221 }
1222