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