fetch.9: Minor fixes.
[dragonfly.git] / sys / netproto / atm / uni / uniarp.c
blob1ebe9b6db4e9848653c032d19bf9c8e83145bb0c
1 /*
3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
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.
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.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
26 * @(#) $FreeBSD: src/sys/netatm/uni/uniarp.c,v 1.8 2000/01/15 20:46:07 mks Exp $
27 * @(#) $DragonFly: src/sys/netproto/atm/uni/uniarp.c,v 1.8 2006/01/14 13:36:39 swildner Exp $
31 * ATM Forum UNI Support
32 * ---------------------
34 * UNI ATMARP support (RFC1577)
38 #include <netproto/atm/kern_include.h>
40 #include <netproto/atm/ipatm/ipatm_var.h>
41 #include <netproto/atm/ipatm/ipatm_serv.h>
42 #include "unisig_var.h"
43 #include "uniip_var.h"
46 * Global variables
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;
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
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 */
82 * Local variables
84 static void uniarp_server_mode (struct uniip *);
85 static void uniarp_client_mode (struct uniip *, Atm_addr *);
89 * Process module loading notification
91 * Called whenever the uni module is initializing.
93 * Arguments:
94 * none
96 * Returns:
97 * 0 initialization successful
98 * errno initialization failed - reason indicated
102 uniarp_start(void)
104 int err;
107 * Register our endpoint
109 err = atm_endpoint_register(&uniarp_endpt);
111 return (err);
116 * Process module unloading notification
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.
122 * Arguments:
123 * none
125 * Returns:
126 * none
129 void
130 uniarp_stop(void)
132 int i;
135 * Make sure the arp table is empty
137 for (i = 0; i < UNIARP_HASHSIZ; i++) {
138 if (uniarp_arptab[i] != NULL)
139 panic("uniarp_stop: arp table not empty");
143 * Cancel timers
145 atm_untimeout(&uniarp_timer);
148 * De-register ourselves
150 atm_endpoint_deregister(&uniarp_endpt);
153 * Free our storage pools
155 atm_release_pool(&uniarp_pool);
160 * Process IP Network Interface Activation
162 * Called whenever an IP network interface becomes active.
164 * Called at splnet.
166 * Arguments:
167 * uip pointer to UNI IP interface
169 * Returns:
170 * none
173 void
174 uniarp_ipact(struct uniip *uip)
176 struct unisig *usp;
178 ATM_DEBUG1("uniarp_ipact: uip=%p\n", uip);
181 * Set initial state
183 uip->uip_arpstate = UIAS_NOTCONF;
184 uip->uip_arpsvratm.address_format = T_ATM_ABSENT;
185 uip->uip_arpsvratm.address_length = 0;
186 uip->uip_arpsvrsub.address_format = T_ATM_ABSENT;
187 uip->uip_arpsvrsub.address_length = 0;
189 usp = (struct unisig *)uip->uip_ipnif->inf_nif->nif_pif->pif_siginst;
190 if (usp->us_addr.address_format != T_ATM_ABSENT)
191 uip->uip_flags |= UIF_IFADDR;
194 * Make sure aging timer is running
196 if ((uniarp_timer.ti_flag & TIF_QUEUED) == 0)
197 atm_timeout(&uniarp_timer, UNIARP_AGING, uniarp_aging);
199 return;
204 * Process IP Network Interface Deactivation
206 * Called whenever an IP network interface becomes inactive. All VCCs
207 * for this interface should already have been closed.
209 * Called at splnet.
211 * Arguments:
212 * uip pointer to UNI IP interface
214 * Returns:
215 * none
218 void
219 uniarp_ipdact(struct uniip *uip)
221 struct uniarp *uap, *unext;
222 int i;
224 ATM_DEBUG1("uniarp_ipdact: uip=%p\n", uip);
227 * Delete all interface entries
229 for (i = 0; i < UNIARP_HASHSIZ; i++) {
230 for (uap = uniarp_arptab[i]; uap; uap = unext) {
231 unext = uap->ua_next;
233 if (uap->ua_intf != uip)
234 continue;
237 * All VCCs should (better) be gone by now
239 if (uap->ua_ivp)
240 panic("uniarp_ipdact: entry not empty");
243 * Clean up any loose ends
245 UNIARP_CANCEL(uap);
248 * Delete entry from arp table and free entry
250 UNIARP_DELETE(uap);
251 atm_free((caddr_t)uap);
256 * Clean up 'nomap' table
258 for (uap = uniarp_nomaptab; uap; uap = unext) {
259 unext = uap->ua_next;
261 if (uap->ua_intf != uip)
262 continue;
265 * All VCCs should (better) be gone by now
267 if (uap->ua_ivp)
268 panic("uniarp_ipdact: entry not empty");
271 * Clean up any loose ends
273 UNIARP_CANCEL(uap);
276 * Delete entry from 'no map' table and free entry
278 UNLINK(uap, struct uniarp, uniarp_nomaptab, ua_next);
279 atm_free((caddr_t)uap);
283 * Also clean up pvc table
285 for (uap = uniarp_pvctab; uap; uap = unext) {
286 unext = uap->ua_next;
288 if (uap->ua_intf != uip)
289 continue;
292 * All PVCs should (better) be gone by now
294 panic("uniarp_ipdact: pvc table not empty");
298 * Cancel arp interface timer
300 UNIIP_ARP_CANCEL(uip);
303 * Stop aging timer if this is the last active interface
305 if (uniip_head == uip && uip->uip_next == NULL)
306 atm_untimeout(&uniarp_timer);
311 * Process Interface ATM Address Change
313 * This function is called whenever the ATM address for a physical
314 * interface is set/changed.
316 * Called at splnet.
318 * Arguments:
319 * sip pointer to interface's UNI signalling instance
321 * Returns:
322 * none
325 void
326 uniarp_ifaddr(struct siginst *sip)
328 struct atm_nif *nip;
329 struct uniip *uip;
331 ATM_DEBUG1("uniarp_ifaddr: sip=%p\n", sip);
334 * We've got to handle this for every network interface
336 for (nip = sip->si_pif->pif_nif; nip; nip = nip->nif_pnext) {
339 * Find our control blocks
341 for (uip = uniip_head; uip; uip = uip->uip_next) {
342 if (uip->uip_ipnif->inf_nif == nip)
343 break;
345 if (uip == NULL)
346 continue;
349 * We don't support changing prefix (yet)
351 if (uip->uip_flags & UIF_IFADDR) {
352 log(LOG_ERR, "uniarp_ifaddr: change not supported\n");
353 continue;
357 * Note that address has been set and figure out what
358 * to do next
360 uip->uip_flags |= UIF_IFADDR;
362 if (uip->uip_arpstate == UIAS_CLIENT_PADDR) {
364 * This is what we're waiting for
366 uniarp_client_mode(uip, NULL);
367 } else if (uip->uip_arpstate == UIAS_SERVER_ACTIVE) {
369 * Set new local arpserver atm address
371 ATM_ADDR_SEL_COPY(&sip->si_addr, nip->nif_sel,
372 &uip->uip_arpsvratm);
376 return;
381 * Set ATMARP Server Mode
383 * This function is called to configure the local node to become the
384 * ATMARP server for the specified LIS.
386 * Called at splnet.
388 * Arguments:
389 * uip pointer to UNI IP interface
391 * Returns:
392 * none
395 static void
396 uniarp_server_mode(struct uniip *uip)
398 struct ip_nif *inp;
399 struct atm_nif *nip;
400 struct siginst *sgp;
401 struct ipvcc *ivp, *inext;
402 struct uniarp *uap, *unext;
403 int i;
405 ATM_DEBUG1("uniarp_server_mode: uip=%p\n", uip);
408 * Handle client/server mode changes first
410 switch (uip->uip_arpstate) {
412 case UIAS_NOTCONF:
413 case UIAS_SERVER_ACTIVE:
414 case UIAS_CLIENT_PADDR:
416 * Nothing to undo
418 break;
420 case UIAS_CLIENT_POPEN:
422 * We're becoming the server, so kill the pending connection
424 UNIIP_ARP_CANCEL(uip);
425 if ((ivp = uip->uip_arpsvrvcc) != NULL) {
426 ivp->iv_flags &= ~IVF_NOIDLE;
427 uip->uip_arpsvrvcc = NULL;
428 (*ivp->iv_ipnif->inf_arpnotify)(ivp, MAP_FAILED);
430 break;
432 case UIAS_CLIENT_REGISTER:
433 case UIAS_CLIENT_ACTIVE:
435 * We're becoming the server, but leave existing VCC as a
436 * "normal" IP VCC
438 UNIIP_ARP_CANCEL(uip);
439 ivp = uip->uip_arpsvrvcc;
440 ivp->iv_flags &= ~IVF_NOIDLE;
441 uip->uip_arpsvrvcc = NULL;
442 break;
446 * Revalidate status for all arp entries on this interface
448 for (i = 0; i < UNIARP_HASHSIZ; i++) {
449 for (uap = uniarp_arptab[i]; uap; uap = unext) {
450 unext = uap->ua_next;
452 if (uap->ua_intf != uip)
453 continue;
455 if (uap->ua_origin >= UAO_PERM)
456 continue;
458 if (uap->ua_origin >= UAO_SCSP) {
459 if (uniarp_validate_ip(uip, &uap->ua_dstip,
460 uap->ua_origin) == 0)
461 continue;
464 if (uap->ua_ivp == NULL) {
465 UNIARP_CANCEL(uap);
466 UNIARP_DELETE(uap);
467 atm_free((caddr_t)uap);
468 continue;
471 if (uap->ua_flags & UAF_VALID) {
472 uap->ua_flags |= UAF_LOCKED;
473 for (ivp = uap->ua_ivp; ivp; ivp = inext) {
474 inext = ivp->iv_arpnext;
475 (*ivp->iv_ipnif->inf_arpnotify)
476 (ivp, MAP_INVALID);
478 uap->ua_flags &= ~(UAF_LOCKED | UAF_VALID);
480 uap->ua_aging = 1;
481 uap->ua_origin = 0;
486 * OK, now let's make ourselves the server
488 inp = uip->uip_ipnif;
489 nip = inp->inf_nif;
490 sgp = nip->nif_pif->pif_siginst;
491 ATM_ADDR_SEL_COPY(&sgp->si_addr, nip->nif_sel, &uip->uip_arpsvratm);
492 uip->uip_arpsvrip = IA_SIN(inp->inf_addr)->sin_addr;
493 uip->uip_arpstate = UIAS_SERVER_ACTIVE;
494 return;
499 * Set ATMARP Client Mode
501 * This function is called to configure the local node to be an ATMARP
502 * client on the specified LIS using the specified ATMARP server.
504 * Called at splnet.
506 * Arguments:
507 * uip pointer to UNI IP interface
508 * aap pointer to the ATMARP server's ATM address
510 * Returns:
511 * none
514 static void
515 uniarp_client_mode(struct uniip *uip, Atm_addr *aap)
517 struct ip_nif *inp = uip->uip_ipnif;
518 struct uniarp *uap, *unext;
519 struct ipvcc *ivp, *inext;
520 int i;
522 ATM_DEBUG2("uniarp_client_mode: uip=%p, atm=(%s,-)\n",
523 uip, aap ? unisig_addr_print(aap): "-");
526 * Handle client/server mode changes first
528 switch (uip->uip_arpstate) {
530 case UIAS_NOTCONF:
531 case UIAS_CLIENT_PADDR:
533 * Nothing to undo
535 break;
537 case UIAS_CLIENT_POPEN:
539 * If this is this a timeout retry, just go do it
541 if (aap == NULL)
542 break;
545 * If this isn't really a different arpserver, we're done
547 if (ATM_ADDR_EQUAL(aap, &uip->uip_arpsvratm))
548 return;
551 * We're changing servers, so kill the pending connection
553 UNIIP_ARP_CANCEL(uip);
554 if ((ivp = uip->uip_arpsvrvcc) != NULL) {
555 ivp->iv_flags &= ~IVF_NOIDLE;
556 uip->uip_arpsvrvcc = NULL;
557 (*ivp->iv_ipnif->inf_arpnotify)(ivp, MAP_FAILED);
559 break;
561 case UIAS_CLIENT_REGISTER:
562 case UIAS_CLIENT_ACTIVE:
564 * If this isn't really a different arpserver, we're done
566 if (ATM_ADDR_EQUAL(aap, &uip->uip_arpsvratm))
567 return;
570 * We're changing servers, but leave existing VCC as a
571 * "normal" IP VCC
573 UNIIP_ARP_CANCEL(uip);
574 ivp = uip->uip_arpsvrvcc;
575 ivp->iv_flags &= ~IVF_NOIDLE;
576 uip->uip_arpsvrvcc = NULL;
577 break;
579 case UIAS_SERVER_ACTIVE:
581 * We're changing from server mode, so...
583 * Reset valid/authoritative status for all arp entries
584 * on this interface
586 for (i = 0; i < UNIARP_HASHSIZ; i++) {
587 for (uap = uniarp_arptab[i]; uap; uap = unext) {
588 unext = uap->ua_next;
590 if (uap->ua_intf != uip)
591 continue;
593 if (uap->ua_origin >= UAO_PERM)
594 continue;
596 if (uap->ua_ivp == NULL) {
597 UNIARP_CANCEL(uap);
598 UNIARP_DELETE(uap);
599 atm_free((caddr_t)uap);
600 continue;
603 if (uap->ua_flags & UAF_VALID) {
604 uap->ua_flags |= UAF_LOCKED;
605 for (ivp = uap->ua_ivp; ivp;
606 ivp = inext) {
607 inext = ivp->iv_arpnext;
608 (*ivp->iv_ipnif->inf_arpnotify)
609 (ivp, MAP_INVALID);
611 uap->ua_flags &=
612 ~(UAF_LOCKED | UAF_VALID);
614 uap->ua_aging = 1;
615 uap->ua_origin = 0;
618 uip->uip_arpsvratm.address_format = T_ATM_ABSENT;
619 uip->uip_arpsvratm.address_length = 0;
620 uip->uip_arpsvrsub.address_format = T_ATM_ABSENT;
621 uip->uip_arpsvrsub.address_length = 0;
622 uip->uip_arpsvrip.s_addr = 0;
623 break;
627 * Save the arp server address, if supplied now
629 if (aap)
630 ATM_ADDR_COPY(aap, &uip->uip_arpsvratm);
633 * If the interface's ATM address isn't set yet, then we
634 * can't do much until it is
636 if ((uip->uip_flags & UIF_IFADDR) == 0) {
637 uip->uip_arpstate = UIAS_CLIENT_PADDR;
638 return;
642 * Just to keep things simple, if we already have (or are trying to
643 * setup) any SVCs to our new server, kill the connections so we can
644 * open a "fresh" SVC for the arpserver connection.
646 for (i = 0; i < UNIARP_HASHSIZ; i++) {
647 for (uap = uniarp_arptab[i]; uap; uap = unext) {
648 unext = uap->ua_next;
650 if (ATM_ADDR_EQUAL(&uip->uip_arpsvratm,
651 &uap->ua_dstatm) &&
652 ATM_ADDR_EQUAL(&uip->uip_arpsvrsub,
653 &uap->ua_dstatmsub)) {
654 uap->ua_flags &= ~UAF_VALID;
655 for (ivp = uap->ua_ivp; ivp; ivp = inext) {
656 inext = ivp->iv_arpnext;
657 (*inp->inf_arpnotify)(ivp, MAP_FAILED);
662 for (uap = uniarp_nomaptab; uap; uap = unext) {
663 unext = uap->ua_next;
665 if (ATM_ADDR_EQUAL(&uip->uip_arpsvratm, &uap->ua_dstatm) &&
666 ATM_ADDR_EQUAL(&uip->uip_arpsvrsub, &uap->ua_dstatmsub)) {
667 uap->ua_flags &= ~UAF_VALID;
668 for (ivp = uap->ua_ivp; ivp; ivp = inext) {
669 inext = ivp->iv_arpnext;
670 (*inp->inf_arpnotify)(ivp, MAP_FAILED);
676 * Now, get an arp entry for the server connection
678 uip->uip_arpstate = UIAS_CLIENT_POPEN;
679 uap = (struct uniarp *)atm_allocate(&uniarp_pool);
680 if (uap == NULL) {
681 UNIIP_ARP_TIMER(uip, 1 * ATM_HZ);
682 return;
686 * Next, initiate an SVC to the server
688 if ((*inp->inf_createsvc)(&inp->inf_nif->nif_if, AF_ATM,
689 (caddr_t)&uip->uip_arpsvratm, &ivp)) {
690 atm_free((caddr_t)uap);
691 UNIIP_ARP_TIMER(uip, 1 * ATM_HZ);
692 return;
696 * Finally, get everything set up and wait for the SVC
697 * connection to complete
699 uip->uip_arpsvrvcc = ivp;
700 ivp->iv_flags |= IVF_NOIDLE;
702 ATM_ADDR_COPY(&uip->uip_arpsvratm, &uap->ua_dstatm);
703 ATM_ADDR_COPY(&uip->uip_arpsvrsub, &uap->ua_dstatmsub);
704 uap->ua_intf = uip;
706 LINK2TAIL(ivp, struct ipvcc, uap->ua_ivp, iv_arpnext);
707 ivp->iv_arpent = (struct arpmap *)uap;
709 LINK2TAIL(uap, struct uniarp, uniarp_nomaptab, ua_next);
711 return;
716 * Process a UNI ARP interface timeout
718 * Called when a previously scheduled uniip arp interface timer expires.
719 * Processing will be based on the current uniip arp state.
721 * Called at splnet.
723 * Arguments:
724 * tip pointer to uniip arp timer control block
726 * Returns:
727 * none
730 void
731 uniarp_iftimeout(struct atm_time *tip)
733 struct ip_nif *inp;
734 struct uniip *uip;
738 * Back-off to uniip control block
740 uip = (struct uniip *)
741 ((caddr_t)tip - (int)(&((struct uniip *)0)->uip_arptime));
743 ATM_DEBUG2("uniarp_iftimeout: uip=%p, state=%d\n", uip,
744 uip->uip_arpstate);
747 * Process timeout based on protocol state
749 switch (uip->uip_arpstate) {
751 case UIAS_CLIENT_POPEN:
753 * Retry opening arp server connection
755 uniarp_client_mode(uip, NULL);
756 break;
758 case UIAS_CLIENT_REGISTER:
760 * Resend registration request
762 inp = uip->uip_ipnif;
763 uniarp_arp_req(uip, &(IA_SIN(inp->inf_addr)->sin_addr));
766 * Restart timer
768 UNIIP_ARP_TIMER(uip, 2 * ATM_HZ);
770 break;
772 case UIAS_CLIENT_ACTIVE:
774 * Refresh our registration
776 inp = uip->uip_ipnif;
777 uniarp_arp_req(uip, &(IA_SIN(inp->inf_addr)->sin_addr));
780 * Restart timer
782 UNIIP_ARP_TIMER(uip, UNIARP_REGIS_RETRY);
784 break;
786 default:
787 log(LOG_ERR, "uniarp_iftimeout: invalid state %d\n",
788 uip->uip_arpstate);
794 * UNI ARP IOCTL support
796 * Function will be called at splnet.
798 * Arguments:
799 * code PF_ATM sub-operation code
800 * data pointer to code specific parameter data area
801 * arg1 pointer to code specific argument
803 * Returns:
804 * 0 request procesed
805 * errno error processing request - reason indicated
809 uniarp_ioctl(int code, caddr_t data, caddr_t arg1)
811 struct atmaddreq *aap;
812 struct atmdelreq *adp;
813 struct atmsetreq *asp;
814 struct atminfreq *aip;
815 struct air_arp_rsp aar;
816 struct air_asrv_rsp asr;
817 struct atm_pif *pip;
818 struct atm_nif *nip;
819 struct ipvcc *ivp, *inext;
820 struct uniip *uip;
821 struct uniarp *uap;
822 struct unisig *usp;
823 struct in_addr ip;
824 Atm_addr atmsub;
825 u_long dst;
826 int err = 0, i, buf_len;
827 caddr_t buf_addr;
829 switch (code) {
831 case AIOCS_ADD_ARP:
833 * Add a permanent ARP mapping
835 aap = (struct atmaddreq *)data;
836 uip = (struct uniip *)arg1;
837 if (aap->aar_arp_addr.address_format != T_ATM_ENDSYS_ADDR) {
838 err = EINVAL;
839 break;
841 atmsub.address_format = T_ATM_ABSENT;
842 atmsub.address_length = 0;
843 ip = SATOSIN(&aap->aar_arp_dst)->sin_addr;
846 * Validate IP address
848 if (uniarp_validate_ip(uip, &ip, aap->aar_arp_origin) != 0) {
849 err = EADDRNOTAVAIL;
850 break;
854 * Add an entry to the cache
856 err = uniarp_cache_svc(uip, &ip, &aap->aar_arp_addr,
857 &atmsub, aap->aar_arp_origin);
858 break;
860 case AIOCS_DEL_ARP:
862 * Delete an ARP mapping
864 adp = (struct atmdelreq *)data;
865 uip = (struct uniip *)arg1;
866 ip = SATOSIN(&adp->adr_arp_dst)->sin_addr;
869 * Now find the entry to be deleted
871 UNIARP_LOOKUP(ip.s_addr, uap);
872 if (uap == NULL) {
873 err = ENOENT;
874 break;
878 * Notify all VCCs using this entry that they must finish
879 * up now.
881 uap->ua_flags |= UAF_LOCKED;
882 for (ivp = uap->ua_ivp; ivp; ivp = inext) {
883 inext = ivp->iv_arpnext;
884 (*ivp->iv_ipnif->inf_arpnotify)(ivp, MAP_FAILED);
888 * Now free up the entry
890 UNIARP_CANCEL(uap);
891 UNIARP_DELETE(uap);
892 atm_free((caddr_t)uap);
893 break;
895 case AIOCS_SET_ASV:
897 * Set interface ARP server address
899 asp = (struct atmsetreq *)data;
900 for (uip = uniip_head; uip; uip = uip->uip_next) {
901 if (uip->uip_ipnif->inf_nif == (struct atm_nif *)arg1)
902 break;
904 if (uip == NULL) {
905 err = ENOPROTOOPT;
906 break;
910 * Check for our own address
912 usp = (struct unisig *)
913 uip->uip_ipnif->inf_nif->nif_pif->pif_siginst;
914 if (ATM_ADDR_EQUAL(&asp->asr_arp_addr, &usp->us_addr)) {
915 asp->asr_arp_addr.address_format = T_ATM_ABSENT;
919 * If we're going into server mode, make sure we can get
920 * the memory for the prefix list before continuing
922 if (asp->asr_arp_addr.address_format == T_ATM_ABSENT) {
923 i = asp->asr_arp_plen / sizeof(struct uniarp_prf);
924 if (i <= 0) {
925 err = EINVAL;
926 break;
928 buf_len = i * sizeof(struct uniarp_prf);
929 buf_addr = KM_ALLOC(buf_len, M_DEVBUF,
930 M_INTWAIT | M_NULLOK);
931 if (buf_addr == NULL) {
932 err = ENOMEM;
933 break;
935 err = copyin(asp->asr_arp_pbuf, buf_addr, buf_len);
936 if (err) {
937 KM_FREE(buf_addr, buf_len, M_DEVBUF);
938 break;
940 } else {
941 /* Silence the compiler */
942 i = 0;
943 buf_addr = NULL;
947 * Free any existing prefix address list
949 if (uip->uip_prefix != NULL) {
950 KM_FREE(uip->uip_prefix,
951 uip->uip_nprefix * sizeof(struct uniarp_prf),
952 M_DEVBUF);
953 uip->uip_prefix = NULL;
954 uip->uip_nprefix = 0;
957 if (asp->asr_arp_addr.address_format == T_ATM_ABSENT) {
959 * Set ATMARP server mode
961 uip->uip_prefix = (struct uniarp_prf *)buf_addr;
962 uip->uip_nprefix = i;
963 uniarp_server_mode(uip);
964 } else
966 * Set ATMARP client mode
968 uniarp_client_mode(uip, &asp->asr_arp_addr);
969 break;
971 case AIOCS_INF_ARP:
973 * Get ARP table information
975 aip = (struct atminfreq *)data;
977 if (aip->air_arp_addr.sa_family != AF_INET)
978 break;
979 dst = SATOSIN(&aip->air_arp_addr)->sin_addr.s_addr;
981 buf_addr = aip->air_buf_addr;
982 buf_len = aip->air_buf_len;
984 pip = ((struct siginst *)arg1)->si_pif;
987 * Run through entire arp table
989 for (i = 0; i < UNIARP_HASHSIZ; i++) {
990 for (uap = uniarp_arptab[i]; uap; uap = uap->ua_next) {
992 * We only want valid entries learned
993 * from the supplied interface.
995 nip = uap->ua_intf->uip_ipnif->inf_nif;
996 if (nip->nif_pif != pip)
997 continue;
998 if ((dst != INADDR_ANY) &&
999 (dst != uap->ua_dstip.s_addr))
1000 continue;
1003 * Make sure there's room in the user's buffer
1005 if (buf_len < sizeof(aar)) {
1006 err = ENOSPC;
1007 break;
1011 * Fill in info to be returned
1013 SATOSIN(&aar.aap_arp_addr)->sin_family =
1014 AF_INET;
1015 SATOSIN(&aar.aap_arp_addr)->sin_addr.s_addr =
1016 uap->ua_dstip.s_addr;
1017 strlcpy(aar.aap_intf,
1018 nip->nif_if.if_xname,
1019 sizeof(aar.aap_intf));
1020 aar.aap_flags = uap->ua_flags;
1021 aar.aap_origin = uap->ua_origin;
1022 if (uap->ua_flags & UAF_VALID)
1023 aar.aap_age = uap->ua_aging +
1024 uap->ua_retry * UNIARP_RETRY_AGE;
1025 else
1026 aar.aap_age = 0;
1027 ATM_ADDR_COPY(&uap->ua_dstatm, &aar.aap_addr);
1028 ATM_ADDR_COPY(&uap->ua_dstatmsub,
1029 &aar.aap_subaddr);
1032 * Copy the response into the user's buffer
1034 if ((err = copyout((caddr_t)&aar, buf_addr,
1035 sizeof(aar))) != 0)
1036 break;
1037 buf_addr += sizeof(aar);
1038 buf_len -= sizeof(aar);
1040 if (err)
1041 break;
1045 * Now go through the 'nomap' table
1047 if (err || (dst != INADDR_ANY))
1048 goto updbuf;
1049 for (uap = uniarp_nomaptab; uap; uap = uap->ua_next) {
1051 * We only want valid entries learned
1052 * from the supplied interface.
1054 nip = uap->ua_intf->uip_ipnif->inf_nif;
1055 if (nip->nif_pif != pip)
1056 continue;
1059 * Make sure there's room in the user's buffer
1061 if (buf_len < sizeof(aar)) {
1062 err = ENOSPC;
1063 break;
1067 * Fill in info to be returned
1069 SATOSIN(&aar.aap_arp_addr)->sin_family = AF_INET;
1070 SATOSIN(&aar.aap_arp_addr)->sin_addr.s_addr = 0;
1071 strlcpy(aar.aap_intf,
1072 nip->nif_if.if_xname,
1073 sizeof(aar.aap_intf));
1074 aar.aap_flags = 0;
1075 aar.aap_origin = uap->ua_origin;
1076 aar.aap_age = 0;
1077 ATM_ADDR_COPY(&uap->ua_dstatm, &aar.aap_addr);
1078 ATM_ADDR_COPY(&uap->ua_dstatmsub,
1079 &aar.aap_subaddr);
1082 * Copy the response into the user's buffer
1084 if ((err = copyout((caddr_t)&aar, buf_addr,
1085 sizeof(aar))) != 0)
1086 break;
1087 buf_addr += sizeof(aar);
1088 buf_len -= sizeof(aar);
1091 updbuf:
1093 * Update the buffer pointer and length
1095 aip->air_buf_addr = buf_addr;
1096 aip->air_buf_len = buf_len;
1099 * If the user wants the refresh status reset and no
1100 * errors have been encountered, then do the reset
1102 if ((err == 0) && (aip->air_arp_flags & ARP_RESET_REF)) {
1103 for (i = 0; i < UNIARP_HASHSIZ; i++) {
1104 for (uap = uniarp_arptab[i]; uap;
1105 uap = uap->ua_next) {
1107 * We only want valid entries learned
1108 * from the supplied interface.
1110 nip = uap->ua_intf->uip_ipnif->inf_nif;
1111 if (nip->nif_pif != pip)
1112 continue;
1113 if ((dst != INADDR_ANY) &&
1114 (dst != uap->ua_dstip.s_addr))
1115 continue;
1118 * Reset refresh flag
1120 uap->ua_flags &= ~UAF_REFRESH;
1124 break;
1126 case AIOCS_INF_ASV:
1128 * Get ARP server information
1130 aip = (struct atminfreq *)data;
1131 nip = (struct atm_nif *)arg1;
1133 buf_addr = aip->air_buf_addr;
1134 buf_len = aip->air_buf_len;
1136 for (uip = uniip_head; uip; uip = uip->uip_next) {
1138 if (uip->uip_ipnif->inf_nif != nip)
1139 continue;
1142 * Make sure there's room in the user's buffer
1144 if (buf_len < sizeof(asr)) {
1145 err = ENOSPC;
1146 break;
1150 * Fill in info to be returned
1152 strlcpy(asr.asp_intf,
1153 nip->nif_if.if_xname,
1154 sizeof(asr.asp_intf));
1155 asr.asp_state = uip->uip_arpstate;
1156 if (uip->uip_arpstate == UIAS_SERVER_ACTIVE) {
1157 asr.asp_addr.address_format = T_ATM_ABSENT;
1158 asr.asp_addr.address_length = 0;
1159 } else {
1160 ATM_ADDR_COPY(&uip->uip_arpsvratm,
1161 &asr.asp_addr);
1163 asr.asp_subaddr.address_format = T_ATM_ABSENT;
1164 asr.asp_subaddr.address_length = 0;
1165 asr.asp_nprefix = uip->uip_nprefix;
1168 * Copy the response into the user's buffer
1170 if ((err = copyout((caddr_t)&asr, buf_addr, sizeof(asr))) != 0)
1171 break;
1172 buf_addr += sizeof(asr);
1173 buf_len -= sizeof(asr);
1176 * Copy the prefix list into the user's buffer
1178 if (uip->uip_nprefix) {
1179 i = uip->uip_nprefix
1180 * sizeof(struct uniarp_prf);
1181 if (buf_len < i) {
1182 err = ENOSPC;
1183 break;
1185 if ((err = copyout(uip->uip_prefix, buf_addr, i)) != 0)
1186 break;
1187 buf_addr += i;
1188 buf_len -= i;
1193 * Update the buffer pointer and length
1195 aip->air_buf_addr = buf_addr;
1196 aip->air_buf_len = buf_len;
1197 break;
1199 default:
1200 err = EOPNOTSUPP;
1203 return (err);
1208 * Get Connection's Application/Owner Name
1210 * Arguments:
1211 * tok uniarp connection token (pointer to ipvcc)
1213 * Returns:
1214 * addr pointer to string containing our name
1217 caddr_t
1218 uniarp_getname(void *tok)
1220 return ("ATMARP");