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