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"
49 struct spansarp
*spansarp_arptab
[SPANSARP_HASHSIZ
] = {NULL
};
55 static int spansarp_request (struct spansarp
*);
56 static void spansarp_aging (struct atm_time
*);
57 static void spansarp_retry (struct atm_time
*);
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 */
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.
85 * ivp pointer to SVC's IPVCC control block
86 * dst pointer to destination IP address
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
95 spansarp_svcout(struct ipvcc
*ivp
, struct in_addr
*dst
)
100 ivp
->iv_arpent
= NULL
;
103 * Lookup destination address
106 SPANSARP_LOOKUP(dst
->s_addr
, 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
;
124 * We're already looking for this address
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
)
144 * Now get the new arp entry
146 sap
= (struct spansarp
*)atm_allocate(&spansarp_pool
);
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;
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
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
);
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.
203 * ivp pointer to SVC's IPVCC control block
204 * dst pointer to destination ATM address
205 * dstsub pointer to destination ATM subaddress
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
232 * ivp pointer to SVC's IPVCC control block
235 * 0 activation processing successful
236 * errno activation failed - reason indicated
240 spansarp_svcactive(struct ipvcc
*ivp
)
242 struct spansarp
*sap
;
246 * Find an entry for the destination address
248 SPANSARP_LOOKUP(ivp
->iv_dst
.s_addr
, 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
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.
274 * ivp pointer to VCC's IPVCC control block
281 spansarp_vcclose(struct ipvcc
*ivp
)
283 struct spansarp
*sap
;
289 SPANSARP_LOOKUP(ivp
->iv_dst
.s_addr
, sap
);
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
)) {
311 * If there are still other VCCs waiting, exit
319 * Noone else waiting, so remove entry from the retry chain
321 UNLINK(sap
, struct spansarp
, spansarp_retry_head
, sa_rnext
);
326 SPANSARP_DELETE(sap
);
327 atm_free((caddr_t
)sap
);
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
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");
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.
380 * clp pointer to CLS interface
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.
405 * clp pointer to CLS interface
412 spansarp_ipdact(struct spanscls
*clp
)
414 struct spanscls
*clp2
;
415 struct spansarp
*sap
, *snext
;
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
)
432 * All VCCs better be gone by now
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
))
459 atm_untimeout(&spansarp_timer
);
464 * Issue a SPANS ARP request packet
467 * sap pointer to arp table entry
470 * 0 packet was successfully sent
471 * else unable to send packet
475 spansarp_request(struct spansarp
*sap
)
477 struct spanscls
*clp
;
479 struct spanscls_hdr
*chp
;
480 struct spansarp_hdr
*ahp
;
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
)
494 if (spp
->sp_addr
.address_format
!= T_ATM_SPANS_ADDR
)
500 * Get a buffer for pdu
502 KB_ALLOCPKT(m
, ARP_PACKET_LEN
, KB_F_NOWAIT
, KB_T_DATA
);
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);
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
);
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
);
552 * Process a SPANS ARP input packet
555 * clp pointer to interface CLS control block
556 * m pointer to input packet buffer chain
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
;
574 * Make sure IP interface has been activated
580 * Get the packet together
582 if (KB_LEN(m
) < ARP_PACKET_LEN
) {
583 KB_PULLUP(m
, ARP_PACKET_LEN
, m
);
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
)))
603 * Validate source addresses
604 * can't be from hardware broadcast
607 if (!spans_addr_cmp(&ahp
->ah_sha
, &spans_bcastaddr
))
609 if (!spans_addr_cmp(&ahp
->ah_sha
, spp
->sp_addr
.address
))
611 if (in_src
.s_addr
== in_me
.s_addr
) {
613 "duplicate IP address sent from spans address %s\n",
614 spans_addr_print(&ahp
->ah_sha
));
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
))
627 * Update arp table with source address info
630 SPANSARP_LOOKUP(in_src
.s_addr
, sap
);
633 * Found an entry for the source, but don't
634 * update permanent entries
636 if (sap
->sa_origin
!= SAO_PERM
) {
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
);
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
);
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;
681 sap
->sa_flags
= SAF_VALID
;
682 sap
->sa_origin
= SAO_LOOKUP
;
690 * If this is a request for our address, send a reply
692 if (ntohs(ahp
->ah_op
) != ARP_REQUEST
)
694 if (in_targ
.s_addr
!= in_me
.s_addr
)
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
);
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.
724 * tip pointer to spansarp aging timer control block
731 spansarp_aging(struct atm_time
*tip
)
733 struct spansarp
*sap
, *snext
;
734 struct ipvcc
*ivp
, *inext
;
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
)
757 * See if entry is valid and over-aged
759 if ((sap
->sa_flags
& SAF_VALID
) == 0)
761 if (++sap
->sa_reftime
< SPANSARP_MAXAGE
)
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
)
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
);
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.
814 * tip pointer to spansarp retry timer control block
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
) {
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.
857 * code PF_ATM sub-operation code
858 * data pointer to code specific parameter data area
859 * arg1 pointer to code specific argument
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
;
873 struct spanscls
*clp
;
874 struct spansarp
*sap
;
875 struct air_arp_rsp aar
;
877 struct ipvcc
*ivp
, *inext
;
880 int err
= 0, i
, buf_len
;
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
)) {
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
);
906 * No, get a new arp entry
908 sap
= (struct spansarp
*)atm_allocate(&spansarp_pool
);
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;
922 sap
->sa_flags
|= SAF_VALID
;
923 sap
->sa_origin
= SAO_PERM
;
934 * See if we're attempting to change the ATM address for
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
);
961 * If this entry isn't valid, notify anyone who might
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
;
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
);
1004 * Notify all VCCs using this entry that they must finish
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
);
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
)
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
)
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
)
1050 if ((dst
!= INADDR_ANY
) &&
1051 (dst
!= sap
->sa_dstip
.s_addr
))
1055 * Make sure there's room in the user's buffer
1057 if (buf_len
< sizeof(aar
)) {
1063 * Fill in info to be returned
1065 SATOSIN(&aar
.aap_arp_addr
)->sin_family
=
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
-
1079 ATM_ADDR_COPY(&sap
->sa_dstatm
, &aar
.aap_addr
);
1080 ATM_ADDR_COPY(&sap
->sa_dstatmsub
,
1084 * Copy the response into the user's buffer
1086 if ((err
= copyout((caddr_t
)&aar
, buf_addr
,
1089 buf_addr
+= sizeof(aar
);
1090 buf_len
-= sizeof(aar
);
1097 * Update the buffer pointer and length
1099 aip
->air_buf_addr
= buf_addr
;
1100 aip
->air_buf_len
= buf_len
;
1105 * Get ARP server information
1107 /* SPANS doesn't have an ARP server */