fetch.9: Minor fixes.
[dragonfly.git] / sys / netproto / atm / spans / spans_arp.c
blob0f41d3eebbd9e893f0660bf64d3e9789b2c469b4
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/spans/spans_arp.c,v 1.7 2000/01/15 20:34:55 mks Exp $
27 * @(#) $DragonFly: src/sys/netproto/atm/spans/spans_arp.c,v 1.9 2006/01/14 13:36:39 swildner Exp $
31 * SPANS Signalling Manager
32 * ---------------------------
34 * SPANS CLS - ARP support
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 "spans_xdr.h"
43 #include "spans_var.h"
44 #include "spans_cls.h"
47 * Global variables
49 struct spansarp *spansarp_arptab[SPANSARP_HASHSIZ] = {NULL};
53 * Local functions
55 static int spansarp_request (struct spansarp *);
56 static void spansarp_aging (struct atm_time *);
57 static void spansarp_retry (struct atm_time *);
60 * Local variables
62 static struct atm_time spansarp_timer = {0, 0}; /* Aging timer */
63 static struct atm_time spansarp_rtimer = {0, 0}; /* Retry timer */
65 static struct spansarp *spansarp_retry_head = NULL; /* Retry chain */
67 static struct sp_info spansarp_pool = {
68 "spans arp pool", /* si_name */
69 sizeof(struct spansarp), /* si_blksiz */
70 10, /* si_blkcnt */
71 100 /* si_maxallow */
76 * Process a new outgoing SVC requiring SPANS ARP support
78 * This function is called by an endpoint wishing to resolve a destination
79 * IP address to an ATM address in order to open an SVC to that destination.
80 * If a valid mapping is already in our cache, then we just tell the caller
81 * about it and that's that. Otherwise, we have to allocate a new arp entry
82 * and issue a query for the mapping.
84 * Arguments:
85 * ivp pointer to SVC's IPVCC control block
86 * dst pointer to destination IP address
88 * Returns:
89 * MAP_VALID - Got the answer, returned via iv_arpent field.
90 * MAP_PROCEEDING - OK so far, querying for peer's mapping
91 * MAP_FAILED - error, unable to allocate resources
94 int
95 spansarp_svcout(struct ipvcc *ivp, struct in_addr *dst)
97 struct spanscls *clp;
98 struct spansarp *sap;
100 ivp->iv_arpent = NULL;
103 * Lookup destination address
105 crit_enter();
106 SPANSARP_LOOKUP(dst->s_addr, sap);
108 if (sap) {
110 * Link this vcc to entry queue
112 LINK2TAIL(ivp, struct ipvcc, sap->sa_ivp, iv_arpnext);
115 * If entry is valid, we're done
117 if (sap->sa_flags & SAF_VALID) {
118 ivp->iv_arpent = (struct arpmap *)sap;
119 crit_exit();
120 return (MAP_VALID);
124 * We're already looking for this address
126 crit_exit();
127 return (MAP_PROCEEDING);
131 * Need a new arp entry - first, find the cls instance
132 * corresponding to the requestor's IP interface.
134 for (clp = spanscls_head; clp; clp = clp->cls_next) {
135 if (clp->cls_ipnif == ivp->iv_ipnif)
136 break;
138 if (clp == NULL) {
139 crit_exit();
140 return (MAP_FAILED);
144 * Now get the new arp entry
146 sap = (struct spansarp *)atm_allocate(&spansarp_pool);
147 if (sap == NULL) {
148 crit_exit();
149 return (MAP_FAILED);
153 * Get entry set up
155 sap->sa_dstip.s_addr = dst->s_addr;
156 sap->sa_dstatm.address_format = T_ATM_ABSENT;
157 sap->sa_dstatm.address_length = 0;
158 sap->sa_dstatmsub.address_format = T_ATM_ABSENT;
159 sap->sa_dstatmsub.address_length = 0;
160 sap->sa_cls = clp;
161 sap->sa_origin = SAO_LOOKUP;
164 * Link ipvcc to arp entry for later notification
166 LINK2TAIL(ivp, struct ipvcc, sap->sa_ivp, iv_arpnext);
169 * Add arp entry to table
171 SPANSARP_ADD(sap);
174 * Add arp entry to retry list and start retry timer if needed
176 LINK2TAIL(sap, struct spansarp, spansarp_retry_head, sa_rnext);
177 if ((spansarp_rtimer.ti_flag & TIF_QUEUED) == 0)
178 atm_timeout(&spansarp_rtimer, SPANSARP_RETRY, spansarp_retry);
181 * Issue arp request for this address
183 spansarp_request(sap);
185 crit_exit();
186 return (MAP_PROCEEDING);
191 * Process a new incoming SVC requiring SPANS ARP support
193 * This function is called by an endpoint wishing to resolve a destination
194 * ATM address to its IP address for an incoming call in order to allow a
195 * bi-directional flow of IP packets on the SVC.
197 * SPANS ARP does not provide reverse mapping facilities and only supports
198 * uni-directional SVCs. Thus, we lie a little to IP and always return a
199 * MAP_PROCEEDING indication, but we will never later notify IP of a
200 * MAP_VALID condition.
202 * Arguments:
203 * ivp pointer to SVC's IPVCC control block
204 * dst pointer to destination ATM address
205 * dstsub pointer to destination ATM subaddress
207 * Returns:
208 * MAP_VALID - Got the answer, returned via iv_arpent field.
209 * MAP_PROCEEDING - OK so far, querying for peer's mapping
210 * MAP_FAILED - error, unable to allocate resources
214 spansarp_svcin(struct ipvcc *ivp, Atm_addr *dst, Atm_addr *dstsub)
217 * Clear ARP entry field
219 ivp->iv_arpent = NULL;
221 return (MAP_PROCEEDING);
226 * SPANS ARP SVC activation notification
228 * This function is called when a previously opened SVC has successfully
229 * been connected.
231 * Arguments:
232 * ivp pointer to SVC's IPVCC control block
234 * Returns:
235 * 0 activation processing successful
236 * errno activation failed - reason indicated
240 spansarp_svcactive(struct ipvcc *ivp)
242 struct spansarp *sap;
244 crit_enter();
246 * Find an entry for the destination address
248 SPANSARP_LOOKUP(ivp->iv_dst.s_addr, sap);
249 if (sap) {
251 * IP is finished with entry, so remove IP VCC from chain
253 UNLINK(ivp, struct ipvcc, sap->sa_ivp, iv_arpnext);
254 ivp->iv_arpent = NULL;
257 * This seems like a reasonable reason to refresh the entry
259 sap->sa_reftime = 0;
261 crit_exit();
262 return (0);
267 * SPANS ARP supported VCC is closing
269 * This function is called just prior to a user closing a VCC which
270 * supports SPANS ARP. We'll sever our links to the VCC and then
271 * figure out how much more cleanup we need to do for now.
273 * Arguments:
274 * ivp pointer to VCC's IPVCC control block
276 * Returns:
277 * none
280 void
281 spansarp_vcclose(struct ipvcc *ivp)
283 struct spansarp *sap;
285 crit_enter();
287 * Get spansarp entry
289 SPANSARP_LOOKUP(ivp->iv_dst.s_addr, sap);
290 if (sap == NULL) {
291 crit_exit();
292 return;
296 * Remove IP VCC from chain
298 UNLINK(ivp, struct ipvcc, sap->sa_ivp, iv_arpnext);
299 ivp->iv_arpent = NULL;
302 * If entry is currently valid or in use, not much else for us to do
304 if ((sap->sa_flags & (SAF_VALID | SAF_LOCKED)) ||
305 (sap->sa_origin >= SAO_PERM)) {
306 crit_exit();
307 return;
311 * If there are still other VCCs waiting, exit
313 if (sap->sa_ivp) {
314 crit_exit();
315 return;
319 * Noone else waiting, so remove entry from the retry chain
321 UNLINK(sap, struct spansarp, spansarp_retry_head, sa_rnext);
324 * Free entry
326 SPANSARP_DELETE(sap);
327 atm_free((caddr_t)sap);
328 crit_exit();
333 * Process module unloading notification
335 * Called whenever the spans module is about to be unloaded. All signalling
336 * instances will have been previously detached. All spansarp resources
337 * must be freed now.
339 * Arguments:
340 * none
342 * Returns:
343 * none
346 void
347 spansarp_stop(void)
349 int i;
352 * Make sure the arp table is empty
354 for (i = 0; i < SPANSARP_HASHSIZ; i++) {
355 if (spansarp_arptab[i] != NULL)
356 panic("spansarp_stop: arp table not empty");
360 * Cancel timers
362 atm_untimeout(&spansarp_timer);
363 atm_untimeout(&spansarp_rtimer);
366 * Free our storage pools
368 atm_release_pool(&spansarp_pool);
373 * Process IP Network Interface Activation
375 * Called whenever an IP network interface becomes active.
377 * Called from a critical section.
379 * Arguments:
380 * clp pointer to CLS interface
382 * Returns:
383 * none
386 void
387 spansarp_ipact(struct spanscls *clp)
390 * Make sure aging timer is running
392 if ((spansarp_timer.ti_flag & TIF_QUEUED) == 0)
393 atm_timeout(&spansarp_timer, SPANSARP_AGING, spansarp_aging);
398 * Process IP Network Interface Deactivation
400 * Called whenever an IP network interface becomes inactive.
402 * Called from a critical section.
404 * Arguments:
405 * clp pointer to CLS interface
407 * Returns:
408 * none
411 void
412 spansarp_ipdact(struct spanscls *clp)
414 struct spanscls *clp2;
415 struct spansarp *sap, *snext;
416 int i;
419 * Delete all interface entries
421 for (i = 0; i < SPANSARP_HASHSIZ; i++) {
422 for (sap = spansarp_arptab[i]; sap; sap = snext) {
423 snext = sap->sa_next;
426 * Clean up entries for this interface
428 if (sap->sa_cls != clp)
429 continue;
432 * All VCCs better be gone by now
434 if (sap->sa_ivp)
435 panic("spansarp_ipdact: entry not empty");
438 * Remove entry from the retry chain
440 UNLINK(sap, struct spansarp,
441 spansarp_retry_head, sa_rnext);
444 * Delete entry from arp table
446 SPANSARP_DELETE(sap);
447 atm_free((caddr_t)sap);
452 * Stop aging timer if this is the last active interface
454 for (clp2 = spanscls_head; clp2; clp2 = clp2->cls_next) {
455 if ((clp != clp2) && (clp2->cls_ipnif))
456 break;
458 if (clp2 == NULL)
459 atm_untimeout(&spansarp_timer);
464 * Issue a SPANS ARP request packet
466 * Arguments:
467 * sap pointer to arp table entry
469 * Returns:
470 * 0 packet was successfully sent
471 * else unable to send packet
474 static int
475 spansarp_request(struct spansarp *sap)
477 struct spanscls *clp;
478 struct spans *spp;
479 struct spanscls_hdr *chp;
480 struct spansarp_hdr *ahp;
481 KBuffer *m;
482 struct ip_nif *inp;
483 int err;
485 clp = sap->sa_cls;
486 spp = clp->cls_spans;
487 inp = clp->cls_ipnif;
490 * Make sure CLS VCC is open and that we know our addresses
492 if (clp->cls_state != CLS_OPEN)
493 return (1);
494 if (spp->sp_addr.address_format != T_ATM_SPANS_ADDR)
495 return (1);
496 if (inp == NULL)
497 return (1);
500 * Get a buffer for pdu
502 KB_ALLOCPKT(m, ARP_PACKET_LEN, KB_F_NOWAIT, KB_T_DATA);
503 if (m == NULL)
504 return (1);
507 * Place pdu at end of buffer
509 KB_PLENSET(m, ARP_PACKET_LEN);
510 KB_TAILALIGN(m, ARP_PACKET_LEN);
511 KB_DATASTART(m, chp, struct spanscls_hdr *);
512 ahp = (struct spansarp_hdr *)(chp + 1);
515 * Build headers
517 spans_addr_copy(&spans_bcastaddr, &chp->ch_dst);
518 spans_addr_copy(spp->sp_addr.address, &chp->ch_src);
519 *(u_int *)&chp->ch_proto = *(u_int *)&spanscls_hdr.ch_proto;
520 *(u_int *)&chp->ch_dsap = *(u_int *)&spanscls_hdr.ch_dsap;
521 *(u_short *)&chp->ch_oui[1] = *(u_short *)&spanscls_hdr.ch_oui[1];
522 chp->ch_pid = htons(ETHERTYPE_ARP);
526 * Build ARP packet
528 ahp->ah_hrd = htons(ARP_SPANS);
529 ahp->ah_pro = htons(ETHERTYPE_IP);
530 ahp->ah_hln = sizeof(spans_addr);
531 ahp->ah_pln = sizeof(struct in_addr);
532 ahp->ah_op = htons(ARP_REQUEST);
533 spans_addr_copy(spp->sp_addr.address, &ahp->ah_sha);
534 KM_COPY(&(IA_SIN(inp->inf_addr)->sin_addr), ahp->ah_spa,
535 sizeof(struct in_addr));
536 KM_COPY(&sap->sa_dstip, ahp->ah_tpa, sizeof(struct in_addr));
539 * Now, send the pdu via the CLS service
541 err = atm_cm_cpcs_data(clp->cls_conn, m);
542 if (err) {
543 KB_FREEALL(m);
544 return (1);
547 return (0);
552 * Process a SPANS ARP input packet
554 * Arguments:
555 * clp pointer to interface CLS control block
556 * m pointer to input packet buffer chain
558 * Returns:
559 * none
562 void
563 spansarp_input(struct spanscls *clp, KBuffer *m)
565 struct spans *spp = clp->cls_spans;
566 struct spanscls_hdr *chp;
567 struct spansarp_hdr *ahp;
568 struct spansarp *sap;
569 struct ip_nif *inp = clp->cls_ipnif;
570 struct in_addr in_me, in_src, in_targ;
571 int err;
574 * Make sure IP interface has been activated
576 if (inp == NULL)
577 goto free;
580 * Get the packet together
582 if (KB_LEN(m) < ARP_PACKET_LEN) {
583 KB_PULLUP(m, ARP_PACKET_LEN, m);
584 if (m == 0)
585 return;
587 KB_DATASTART(m, chp, struct spanscls_hdr *);
588 ahp = (struct spansarp_hdr *)(chp + 1);
590 KM_COPY(ahp->ah_spa, &in_src, sizeof(struct in_addr));
591 KM_COPY(ahp->ah_tpa, &in_targ, sizeof(struct in_addr));
592 KM_COPY(&(IA_SIN(inp->inf_addr)->sin_addr), &in_me,
593 sizeof(struct in_addr));
596 * Initial packet verification
598 if ((ahp->ah_hrd != htons(ARP_SPANS)) ||
599 (ahp->ah_pro != htons(ETHERTYPE_IP)))
600 goto free;
603 * Validate source addresses
604 * can't be from hardware broadcast
605 * can't be from me
607 if (!spans_addr_cmp(&ahp->ah_sha, &spans_bcastaddr))
608 goto free;
609 if (!spans_addr_cmp(&ahp->ah_sha, spp->sp_addr.address))
610 goto free;
611 if (in_src.s_addr == in_me.s_addr) {
612 log(LOG_ERR,
613 "duplicate IP address sent from spans address %s\n",
614 spans_addr_print(&ahp->ah_sha));
615 in_targ = in_me;
616 goto chkop;
620 * If source IP address is from unspecified or broadcast addresses,
621 * don't bother updating arp table, but answer possible requests
623 if (in_broadcast(in_src, &inp->inf_nif->nif_if))
624 goto chkop;
627 * Update arp table with source address info
629 crit_enter();
630 SPANSARP_LOOKUP(in_src.s_addr, sap);
631 if (sap) {
633 * Found an entry for the source, but don't
634 * update permanent entries
636 if (sap->sa_origin != SAO_PERM) {
639 * Update the entry
641 sap->sa_dstatm.address_format = T_ATM_SPANS_ADDR;
642 sap->sa_dstatm.address_length = sizeof(spans_addr);
643 spans_addr_copy(&ahp->ah_sha, sap->sa_dstatm.address);
644 sap->sa_cls = clp;
645 sap->sa_reftime = 0;
646 if ((sap->sa_flags & SAF_VALID) == 0) {
648 * Newly valid entry, notify waiting users
650 struct ipvcc *ivp, *inext;
652 sap->sa_flags |= SAF_VALID;
653 for (ivp = sap->sa_ivp; ivp; ivp = inext) {
654 inext = ivp->iv_arpnext;
656 ivp->iv_arpent = (struct arpmap *)sap;
657 (*inp->inf_arpnotify)(ivp, MAP_VALID);
661 * Remove ourselves from the retry chain
663 UNLINK(sap, struct spansarp,
664 spansarp_retry_head, sa_rnext);
668 } else if (in_targ.s_addr == in_me.s_addr) {
670 * Source unknown and we're the target - add new entry
672 sap = (struct spansarp *)atm_allocate(&spansarp_pool);
673 if (sap) {
674 sap->sa_dstip.s_addr = in_src.s_addr;
675 sap->sa_dstatm.address_format = T_ATM_SPANS_ADDR;
676 sap->sa_dstatm.address_length = sizeof(spans_addr);
677 spans_addr_copy(&ahp->ah_sha, sap->sa_dstatm.address);
678 sap->sa_dstatmsub.address_format = T_ATM_ABSENT;
679 sap->sa_dstatmsub.address_length = 0;
680 sap->sa_cls = clp;
681 sap->sa_flags = SAF_VALID;
682 sap->sa_origin = SAO_LOOKUP;
683 SPANSARP_ADD(sap);
686 crit_exit();
688 chkop:
690 * If this is a request for our address, send a reply
692 if (ntohs(ahp->ah_op) != ARP_REQUEST)
693 goto free;
694 if (in_targ.s_addr != in_me.s_addr)
695 goto free;
697 spans_addr_copy(&chp->ch_src, &chp->ch_dst);
698 spans_addr_copy(spp->sp_addr.address, &chp->ch_src);
699 ahp->ah_op = htons(ARP_REPLY);
700 spans_addr_copy(&ahp->ah_sha, &ahp->ah_tha);
701 spans_addr_copy(spp->sp_addr.address, &ahp->ah_sha);
702 KM_COPY(ahp->ah_spa, ahp->ah_tpa, sizeof(struct in_addr));
703 KM_COPY(&in_me, ahp->ah_spa, sizeof(struct in_addr));
705 err = atm_cm_cpcs_data(clp->cls_conn, m);
706 if (err)
707 goto free;
708 return;
710 free:
711 KB_FREEALL(m);
716 * Process a SPANS ARP aging timer tick
718 * This function is called every SPANSARP_AGING seconds, in order to age
719 * all the arp table entries.
721 * Called from a critical section.
723 * Arguments:
724 * tip pointer to spansarp aging timer control block
726 * Returns:
727 * none
730 static void
731 spansarp_aging(struct atm_time *tip)
733 struct spansarp *sap, *snext;
734 struct ipvcc *ivp, *inext;
735 int i;
739 * Schedule next timeout
741 atm_timeout(&spansarp_timer, SPANSARP_AGING, spansarp_aging);
744 * Run through arp table bumping each entry's aging timer.
746 for (i = 0; i < SPANSARP_HASHSIZ; i++) {
747 for (sap = spansarp_arptab[i]; sap; sap = snext) {
748 snext = sap->sa_next;
751 * Permanent (manually installed) entries aren't aged
753 if (sap->sa_origin == SAO_PERM)
754 continue;
757 * See if entry is valid and over-aged
759 if ((sap->sa_flags & SAF_VALID) == 0)
760 continue;
761 if (++sap->sa_reftime < SPANSARP_MAXAGE)
762 continue;
765 * Entry is now invalid, tell IP/ATM about it
767 sap->sa_flags |= SAF_LOCKED;
768 for (ivp = sap->sa_ivp; ivp; ivp = inext) {
769 inext = ivp->iv_arpnext;
770 (*ivp->iv_ipnif->inf_arpnotify)
771 (ivp, MAP_INVALID);
773 sap->sa_flags &= ~(SAF_LOCKED | SAF_VALID);
775 if (sap->sa_ivp != NULL) {
777 * Somebody still cares, so add the arp
778 * entry to the retry list.
780 LINK2TAIL(sap, struct spansarp,
781 spansarp_retry_head, sa_rnext);
782 if ((spansarp_rtimer.ti_flag & TIF_QUEUED) == 0)
783 atm_timeout(&spansarp_rtimer,
784 SPANSARP_RETRY, spansarp_retry);
787 * Issue arp request for this address
789 spansarp_request(sap);
791 } else {
793 * Delete unused entry
795 SPANSARP_DELETE(sap);
796 atm_free((caddr_t)sap);
804 * Process a SPANS ARP retry timer tick
806 * This function is called every SPANSARP_RETRY seconds, in order to retry
807 * awaiting arp resolution requests. We will retry requests indefinitely,
808 * assuming that IP will set a timeout to close the VCC(s) requesting the
809 * failing address resolution.
811 * Called from a critical section.
813 * Arguments:
814 * tip pointer to spansarp retry timer control block
816 * Returns:
817 * none
820 static void
821 spansarp_retry(struct atm_time *tip)
823 struct spansarp *sap;
827 * See if there's work to do
829 if (spansarp_retry_head == NULL) {
830 return;
834 * Schedule next timeout
836 atm_timeout(&spansarp_rtimer, SPANSARP_RETRY, spansarp_retry);
839 * Run through retry chain, (re)issuing arp requests.
841 for (sap = spansarp_retry_head; sap; sap = sap->sa_next) {
844 * Send another arp request
846 spansarp_request(sap);
852 * SPANS ARP IOCTL support
854 * Function will be called from a critical section.
856 * Arguments:
857 * code PF_ATM sub-operation code
858 * data pointer to code specific parameter data area
859 * arg1 pointer to code specific argument
861 * Returns:
862 * 0 request procesed
863 * errno error processing request - reason indicated
867 spansarp_ioctl(int code, caddr_t data, caddr_t arg1)
869 struct atmaddreq *aap;
870 struct atmdelreq *adp;
871 struct atminfreq *aip;
872 struct spans *spp;
873 struct spanscls *clp;
874 struct spansarp *sap;
875 struct air_arp_rsp aar;
876 struct ip_nif *inp;
877 struct ipvcc *ivp, *inext;
878 struct in_addr ip;
879 u_long dst;
880 int err = 0, i, buf_len;
881 caddr_t buf_addr;
884 switch (code) {
886 case AIOCS_ADD_ARP:
888 * Add a permanent ARP mapping
890 aap = (struct atmaddreq *)data;
891 clp = (struct spanscls *)arg1;
892 inp = clp->cls_ipnif;
893 if ((aap->aar_arp_addr.address_format != T_ATM_SPANS_ADDR) ||
894 (aap->aar_arp_origin != ARP_ORIG_PERM)) {
895 err = EINVAL;
896 break;
898 ip = SATOSIN(&aap->aar_arp_dst)->sin_addr;
901 * See if we already have an entry for this IP address
903 SPANSARP_LOOKUP(ip.s_addr, sap);
904 if (sap == NULL) {
906 * No, get a new arp entry
908 sap = (struct spansarp *)atm_allocate(&spansarp_pool);
909 if (sap == NULL) {
910 err = ENOMEM;
911 break;
915 * Get entry set up
917 sap->sa_dstip = ip;
918 ATM_ADDR_COPY(&aap->aar_arp_addr, &sap->sa_dstatm);
919 sap->sa_dstatmsub.address_format = T_ATM_ABSENT;
920 sap->sa_dstatmsub.address_length = 0;
921 sap->sa_cls = clp;
922 sap->sa_flags |= SAF_VALID;
923 sap->sa_origin = SAO_PERM;
926 * Add entry to table
928 SPANSARP_ADD(sap);
929 break;
934 * See if we're attempting to change the ATM address for
935 * this cached entry
937 if ((sap->sa_dstatm.address_format != T_ATM_ABSENT) &&
938 (!ATM_ADDR_EQUAL(&aap->aar_arp_addr, &sap->sa_dstatm) ||
939 (clp != sap->sa_cls))) {
942 * Yes, notify IP/ATM that a mapping change has
943 * occurred. IP/ATM will close any VCC's which
944 * aren't waiting for this map.
946 sap->sa_flags |= SAF_LOCKED;
947 for (ivp = sap->sa_ivp; ivp; ivp = inext) {
948 inext = ivp->iv_arpnext;
949 (*inp->inf_arpnotify)(ivp, MAP_CHANGED);
951 sap->sa_flags &= ~SAF_LOCKED;
955 * Update the cached entry with the new data
957 ATM_ADDR_COPY(&aap->aar_arp_addr, &sap->sa_dstatm);
958 sap->sa_cls = clp;
961 * If this entry isn't valid, notify anyone who might
962 * be interested
964 if ((sap->sa_flags & SAF_VALID) == 0) {
966 sap->sa_flags |= SAF_LOCKED;
967 for (ivp = sap->sa_ivp; ivp; ivp = inext) {
968 inext = ivp->iv_arpnext;
969 (*inp->inf_arpnotify)(ivp, MAP_VALID);
971 sap->sa_flags &= ~SAF_LOCKED;
975 * Remove this entry from the retry chain
977 UNLINK(sap, struct spansarp, spansarp_retry_head, sa_rnext);
980 * Mark the entry as permanent
982 sap->sa_flags |= SAF_VALID;
983 sap->sa_origin = SAO_PERM;
984 break;
986 case AIOCS_DEL_ARP:
988 * Delete an ARP mapping
990 adp = (struct atmdelreq *)data;
991 clp = (struct spanscls *)arg1;
992 ip = SATOSIN(&adp->adr_arp_dst)->sin_addr;
995 * Now find the entry to be deleted
997 SPANSARP_LOOKUP(ip.s_addr, sap);
998 if (sap == NULL) {
999 err = ENOENT;
1000 break;
1004 * Notify all VCCs using this entry that they must finish
1005 * up now.
1007 sap->sa_flags |= SAF_LOCKED;
1008 for (ivp = sap->sa_ivp; ivp; ivp = inext) {
1009 inext = ivp->iv_arpnext;
1010 (*ivp->iv_ipnif->inf_arpnotify)(ivp, MAP_FAILED);
1014 * Now free up the entry
1016 UNLINK(sap, struct spansarp, spansarp_retry_head, sa_rnext);
1017 SPANSARP_DELETE(sap);
1018 atm_free((caddr_t)sap);
1019 break;
1021 case AIOCS_INF_ARP:
1023 * Get ARP table information
1025 aip = (struct atminfreq *)data;
1026 spp = (struct spans *)arg1;
1028 if (aip->air_arp_addr.sa_family != AF_INET)
1029 break;
1030 dst = SATOSIN(&aip->air_arp_addr)->sin_addr.s_addr;
1032 buf_addr = aip->air_buf_addr;
1033 buf_len = aip->air_buf_len;
1035 if ((clp = spp->sp_cls) == NULL)
1036 break;
1039 * Run through entire arp table
1041 for (i = 0; i < SPANSARP_HASHSIZ; i++) {
1042 for (sap = spansarp_arptab[i]; sap;
1043 sap = sap->sa_next) {
1045 * We only want entries learned
1046 * from the supplied interface.
1048 if (sap->sa_cls != clp)
1049 continue;
1050 if ((dst != INADDR_ANY) &&
1051 (dst != sap->sa_dstip.s_addr))
1052 continue;
1055 * Make sure there's room in the user's buffer
1057 if (buf_len < sizeof(aar)) {
1058 err = ENOSPC;
1059 break;
1063 * Fill in info to be returned
1065 SATOSIN(&aar.aap_arp_addr)->sin_family =
1066 AF_INET;
1067 SATOSIN(&aar.aap_arp_addr)->sin_addr.s_addr =
1068 sap->sa_dstip.s_addr;
1069 strlcpy(aar.aap_intf,
1070 clp->cls_ipnif->inf_nif->nif_if.if_xname,
1071 sizeof(aar.aap_intf));
1072 aar.aap_flags = sap->sa_flags;
1073 aar.aap_origin = sap->sa_origin;
1074 if (sap->sa_flags & SAF_VALID)
1075 aar.aap_age = SPANSARP_MAXAGE -
1076 sap->sa_reftime;
1077 else
1078 aar.aap_age = 0;
1079 ATM_ADDR_COPY(&sap->sa_dstatm, &aar.aap_addr);
1080 ATM_ADDR_COPY(&sap->sa_dstatmsub,
1081 &aar.aap_subaddr);
1084 * Copy the response into the user's buffer
1086 if ((err = copyout((caddr_t)&aar, buf_addr,
1087 sizeof(aar))) != 0)
1088 break;
1089 buf_addr += sizeof(aar);
1090 buf_len -= sizeof(aar);
1092 if (err)
1093 break;
1097 * Update the buffer pointer and length
1099 aip->air_buf_addr = buf_addr;
1100 aip->air_buf_len = buf_len;
1101 break;
1103 case AIOCS_INF_ASV:
1105 * Get ARP server information
1107 /* SPANS doesn't have an ARP server */
1108 break;
1110 default:
1111 err = EOPNOTSUPP;
1114 return (err);