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