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/usr.sbin/atm/atmarpd/atmarp_subr.c,v 1.3 1999/08/28 01:15:30 peter Exp $
27 * @(#) $DragonFly: src/usr.sbin/atm/atmarpd/atmarp_subr.c,v 1.4 2004/12/18 22:48:02 swildner Exp $
32 * Server Cache Synchronization Protocol (SCSP) Support
33 * ----------------------------------------------------
35 * SCSP-ATMARP server interface: misc. subroutines
39 #include <sys/types.h>
40 #include <sys/param.h>
41 #include <sys/socket.h>
42 #include <sys/sockio.h>
44 #include <netinet/in.h>
45 #include <arpa/inet.h>
46 #include <netatm/port.h>
47 #include <netatm/queue.h>
48 #include <netatm/atm.h>
49 #include <netatm/atm_if.h>
50 #include <netatm/atm_sap.h>
51 #include <netatm/atm_sigmgr.h>
52 #include <netatm/atm_sys.h>
53 #include <netatm/atm_ioctl.h>
54 #include <netatm/uni/unisig_var.h>
55 #include <netatm/uni/uniip_var.h>
65 #include "../scspd/scsp_msg.h"
66 #include "../scspd/scsp_if.h"
67 #include "../scspd/scsp_var.h"
68 #include "atmarp_var.h"
71 * Find an ATMARP interface, given its socket number
74 * sd socket descriptor
78 * else pointer to interface associated with socket
82 atmarp_find_intf_sock(int sd
)
87 * Loop through the list of interfaces
89 for (aip
= atmarp_intf_head
; aip
; aip
= aip
->ai_next
) {
90 if (aip
->ai_scsp_sock
== sd
)
99 * Find an ATMARP interface, given its name
102 * name pointer to network interface name
106 * else pointer to interface associated with name
110 atmarp_find_intf_name(char *name
)
115 * Loop through the list of interfaces
117 for (aip
= atmarp_intf_head
; aip
; aip
= aip
->ai_next
) {
118 if (strcmp(name
, aip
->ai_intf
) == 0)
127 * Clear the mark field on all ATMARP cache entries
137 atmarp_clear_marks(void)
144 * Loop through list of interfaces
146 for (aip
= atmarp_intf_head
; aip
; aip
= aip
->ai_next
) {
148 * Clear mark on every entry in the interface's cache
150 for (i
= 0; i
< ATMARP_HASHSIZ
; i
++ ) {
151 for (aap
= aip
->ai_arptbl
[i
]; aap
;
152 aap
= aap
->aa_next
) {
161 * Check whether the host system is an ATMARP server for
162 * the LIS associated with a given interface
165 * aip pointer to an ATMARP interface control block
169 * 0 host is not a server
173 atmarp_is_server(Atmarp_intf
*aip
)
176 int buf_len
= sizeof(struct air_asrv_rsp
);
177 struct atminfreq air
;
178 struct air_asrv_rsp
*asrv_info
;
181 * Get interface information from the kernel
183 strcpy(air
.air_int_intf
, aip
->ai_intf
);
184 air
.air_opcode
= AIOCS_INF_ASV
;
185 buf_len
= do_info_ioctl(&air
, buf_len
);
190 * Check the interface's ATMARP server address
192 asrv_info
= (struct air_asrv_rsp
*) air
.air_buf_addr
;
193 rc
= (asrv_info
->asp_addr
.address_format
== T_ATM_ABSENT
) &&
194 (asrv_info
->asp_subaddr
.address_format
==
202 * Check whether an interface is up and ready for service
205 * aip pointer to network interface block
208 * 0 interface not ready, errno has reason
209 * 1 interface is ready to go (interface block is updated)
213 atmarp_if_ready(Atmarp_intf
*aip
)
215 int i
, len
, mtu
, rc
, sel
;
217 struct atminfreq air
;
218 struct air_netif_rsp
*netif_rsp
= NULL
;
219 struct air_int_rsp
*intf_rsp
= NULL
;
220 struct sockaddr_in
*ip_addr
;
221 struct sockaddr_in subnet_mask
;
225 * Get the IP address and physical interface name
226 * associated with the network interface
228 UM_ZERO(&air
, sizeof(struct atminfreq
));
229 air
.air_opcode
= AIOCS_INF_NIF
;
230 strcpy(air
.air_netif_intf
, aip
->ai_intf
);
231 len
= do_info_ioctl(&air
, sizeof(struct air_netif_rsp
));
235 netif_rsp
= (struct air_netif_rsp
*)air
.air_buf_addr
;
237 ip_addr
= (struct sockaddr_in
*)&netif_rsp
->anp_proto_addr
;
238 if (ip_addr
->sin_family
!= AF_INET
||
239 ip_addr
->sin_addr
.s_addr
== 0) {
240 errno
= EAFNOSUPPORT
;
245 * Get the MTU for the network interface
247 mtu
= get_mtu(aip
->ai_intf
);
254 * Get the subnet mask associated with the
257 rc
= get_subnet_mask(aip
->ai_intf
, &subnet_mask
);
258 if (rc
|| subnet_mask
.sin_family
!= AF_INET
) {
263 * Get physical interface information
265 UM_ZERO(&air
, sizeof(struct atminfreq
));
266 air
.air_opcode
= AIOCS_INF_INT
;
267 strcpy(air
.air_int_intf
, netif_rsp
->anp_phy_intf
);
268 len
= do_info_ioctl(&air
, sizeof(struct air_int_rsp
));
272 intf_rsp
= (struct air_int_rsp
*)air
.air_buf_addr
;
275 * Check the signalling manager
277 if (intf_rsp
->anp_sig_proto
!= ATM_SIG_UNI30
&&
278 intf_rsp
->anp_sig_proto
!= ATM_SIG_UNI31
&&
279 intf_rsp
->anp_sig_proto
!= ATM_SIG_UNI40
) {
285 * Check the interface state
287 if (intf_rsp
->anp_sig_state
!= UNISIG_ACTIVE
) {
293 * Check the address format
295 if (intf_rsp
->anp_addr
.address_format
!= T_ATM_ENDSYS_ADDR
&&
296 !(intf_rsp
->anp_addr
.address_format
==
298 intf_rsp
->anp_subaddr
.address_format
==
299 T_ATM_ENDSYS_ADDR
)) {
305 * Find the selector byte value for the interface
307 for (i
=0; i
<strlen(aip
->ai_intf
); i
++) {
308 if (aip
->ai_intf
[i
] >= '0' &&
309 aip
->ai_intf
[i
] <= '9')
312 sel
= atoi(&aip
->ai_intf
[i
]);
315 * Make sure we're the server for this interface's LIS
317 if (!atmarp_is_server(aip
)) {
323 * If we already have the interface active and the address
324 * hasn't changed, return
326 if (aip
->ai_state
!= AI_STATE_NULL
&&
327 bcmp((caddr_t
) &((struct sockaddr_in
*)
328 &netif_rsp
->anp_proto_addr
)->sin_addr
,
329 (caddr_t
)&aip
->ai_ip_addr
,
330 sizeof(aip
->ai_ip_addr
)) == 0 &&
331 ATM_ADDR_EQUAL(&intf_rsp
->anp_addr
,
332 &aip
->ai_atm_addr
) &&
333 ATM_ADDR_EQUAL(&intf_rsp
->anp_subaddr
,
334 &aip
->ai_atm_subaddr
)) {
339 * Delete any existing ATMARP cache entry for this interface
341 ATMARP_LOOKUP(aip
, aip
->ai_ip_addr
.s_addr
, aap
);
343 ATMARP_DELETE(aip
, aap
);
348 * Update the interface entry
350 aip
->ai_ip_addr
= ((struct sockaddr_in
*)
351 &netif_rsp
->anp_proto_addr
)->sin_addr
;
352 aip
->ai_subnet_mask
= subnet_mask
.sin_addr
;
353 aip
->ai_mtu
= mtu
+ 8;
354 ATM_ADDR_COPY(&intf_rsp
->anp_addr
,
356 ATM_ADDR_COPY(&intf_rsp
->anp_subaddr
,
357 &aip
->ai_atm_subaddr
);
358 anp
= (Atm_addr_nsap
*)aip
->ai_atm_addr
.address
;
359 if (aip
->ai_atm_addr
.address_format
== T_ATM_ENDSYS_ADDR
) {
361 } else if (aip
->ai_atm_addr
.address_format
==
363 aip
->ai_atm_subaddr
.address_format
==
369 * Get a new ATMARP cache for the interface
371 aap
= (Atmarp
*)UM_ALLOC(sizeof(Atmarp
));
373 atmarp_mem_err("atmarp_if_ready: sizeof(Atmarp)");
375 UM_ZERO(aap
, sizeof(Atmarp
));
380 aap
->aa_dstip
= aip
->ai_ip_addr
;
381 ATM_ADDR_COPY(&intf_rsp
->anp_addr
, &aap
->aa_dstatm
);
382 ATM_ADDR_COPY(&intf_rsp
->anp_subaddr
,
384 aap
->aa_key
.key_len
= SCSP_ATMARP_KEY_LEN
;
385 scsp_cache_key(&aap
->aa_dstatm
, &aap
->aa_dstip
,
386 SCSP_ATMARP_KEY_LEN
, aap
->aa_key
.key
);
387 aap
->aa_oid
.id_len
= SCSP_ATMARP_ID_LEN
;
388 aap
->aa_seq
= SCSP_CSA_SEQ_MIN
;
389 UM_COPY(&aap
->aa_dstip
.s_addr
, aap
->aa_oid
.id
,
392 aap
->aa_flags
= AAF_SERVER
;
393 aap
->aa_origin
= UAO_LOCAL
;
396 * Add the entry to the cache
398 ATMARP_ADD(aip
, aap
);
419 * Copy an ATMARP cache entry from kernel format into an entry
420 * suitable for our cache
423 * cp pointer to kernel entry
426 * pointer to a new cache entry
431 atmarp_copy_cache_entry(struct air_arp_rsp
*cp
)
433 struct sockaddr_in
*ipp
;
442 aip
= atmarp_find_intf_name(cp
->aap_intf
);
447 * Get a new cache entry
449 aap
= (Atmarp
*)UM_ALLOC(sizeof(Atmarp
));
454 UM_ZERO(aap
, sizeof(Atmarp
));
458 * Copy fields from the kernel entry to the new entry
460 ipp
= (struct sockaddr_in
*)&cp
->aap_arp_addr
;
461 UM_COPY(&ipp
->sin_addr
.s_addr
, &aap
->aa_dstip
.s_addr
,
462 sizeof(aap
->aa_dstip
.s_addr
));
463 ATM_ADDR_COPY(&cp
->aap_addr
, &aap
->aa_dstatm
);
464 ATM_ADDR_COPY(&cp
->aap_subaddr
, &aap
->aa_dstatmsub
);
465 if (cp
->aap_origin
== UAO_PERM
)
466 aap
->aa_flags
|= AAF_PERM
;
467 aap
->aa_origin
= cp
->aap_origin
;
470 * Set up fields for SCSP
472 aap
->aa_key
.key_len
= SCSP_ATMARP_KEY_LEN
;
473 scsp_cache_key(&cp
->aap_addr
, &aap
->aa_dstip
,
474 SCSP_ATMARP_KEY_LEN
, (char *)aap
->aa_key
.key
);
475 aap
->aa_oid
.id_len
= SCSP_ATMARP_ID_LEN
;
476 UM_COPY(&aip
->ai_ip_addr
.s_addr
, aap
->aa_oid
.id
,
478 aap
->aa_seq
= SCSP_CSA_SEQ_MIN
;
485 * Send an updated ATMARP cache entry to the kernel
488 * aap pointer to updated entry
492 * errno reason for failure
496 atmarp_update_kernel(Atmarp
*aap
)
499 struct atmaddreq aar
;
500 struct sockaddr_in
*ipp
;
503 * Build ioctl request
505 UM_ZERO(&aar
, sizeof(aar
));
506 aar
.aar_opcode
= AIOCS_ADD_ARP
;
507 strncpy(aar
.aar_arp_intf
, aap
->aa_intf
->ai_intf
,
508 sizeof(aar
.aar_arp_intf
));
509 aar
.aar_arp_origin
= UAO_SCSP
;
510 ATM_ADDR_COPY(&aap
->aa_dstatm
, &aar
.aar_arp_addr
);
511 ipp
= (struct sockaddr_in
*)&aar
.aar_arp_dst
;
512 ipp
->sin_family
= AF_INET
;
513 #if (defined(BSD) && (BSD >= 199103))
514 ipp
->sin_len
= sizeof(struct sockaddr_in
);
516 ipp
->sin_addr
= aap
->aa_dstip
;
519 * Pass the new mapping to the kernel
521 sd
= socket(AF_ATM
, SOCK_DGRAM
, 0);
525 if (ioctl(sd
, AIOCADD
, (caddr_t
)&aar
) < 0) {
535 * Read the ATMARP cache from the kernel and scan it, processing
546 atmarp_get_updated_cache(void)
549 struct atminfreq air
;
550 struct air_arp_rsp
*cp
;
551 struct sockaddr_in
*ipp
;
558 air
.air_opcode
= AIOCS_INF_ARP
;
559 air
.air_arp_flags
= ARP_RESET_REF
;
560 ipp
= (struct sockaddr_in
*)&air
.air_arp_addr
;
561 #if (defined(BSD) && (BSD >= 199103))
562 ipp
->sin_len
= sizeof(struct sockaddr_in
);
564 ipp
->sin_family
= AF_INET
;
565 ipp
->sin_addr
.s_addr
= INADDR_ANY
;
568 * Issue an ATMARP information request IOCTL
570 len
= do_info_ioctl(&air
, sizeof(struct air_arp_rsp
) * 200);
576 * Clear marks on all our cache entries
578 atmarp_clear_marks();
581 * Loop through the cache, processing each entry
583 for (cp
= (struct air_arp_rsp
*) air
.air_buf_addr
;
585 cp
++, len
-= sizeof(struct air_arp_rsp
)) {
586 atmarp_process_cache_entry(cp
);
590 * Now delete any old entries that aren't in the kernel's
593 for (aip
= atmarp_intf_head
; aip
; aip
= aip
->ai_next
) {
594 for (i
= 0; i
< ATMARP_HASHSIZ
; i
++) {
595 for (aap
= aip
->ai_arptbl
[i
]; aap
;
596 aap
= aap
->aa_next
) {
598 * Don't delete the entry for the server
600 if (aap
->aa_flags
& AAF_SERVER
)
603 * Delete any entry that isn't marked
606 rc
= atmarp_scsp_update(aap
,
609 ATMARP_DELETE(aip
, aap
);
616 * Free the ioctl response
618 UM_FREE(air
.air_buf_addr
);
623 * Process an ATMARP cache entry from the kernel. If we already
624 * have the entry in our local cache, update it, otherwise, add
625 * it. In either case, mark our local copy so we know it's still
626 * in the kernel's cache.
629 * cp pointer to kernel's cache entry
636 atmarp_process_cache_entry(struct air_arp_rsp
*cp
)
639 struct sockaddr_in
*ipp
= (struct sockaddr_in
*)&cp
->aap_arp_addr
;
644 * See whether the entry is for an interface that's
645 * both configured and up
647 aip
= atmarp_find_intf_name(cp
->aap_intf
);
648 if (!aip
|| aip
->ai_state
!= AI_STATE_UP
)
652 * Make sure the entry is valid
654 if (!(cp
->aap_flags
& ARPF_VALID
))
658 * See whether we have the entry in our cache already
660 ATMARP_LOOKUP(aip
, ipp
->sin_addr
.s_addr
, aap
);
663 * We already have this in our cache--update it
666 if ((cp
->aap_flags
& ARPF_REFRESH
) &&
667 cp
->aap_origin
!= UAO_SCSP
) {
669 rc
= atmarp_scsp_update(aap
, SCSP_ASTATE_UPD
);
673 * This is a new entry--add it to the cache
675 aap
= atmarp_copy_cache_entry(cp
);
678 ATMARP_ADD(aip
, aap
);
680 rc
= atmarp_scsp_update(aap
, SCSP_ASTATE_NEW
);
691 * df pointer to a FILE for the dump
692 * ip pointer to the SCSP ID to print
699 print_scsp_id(FILE *df
, Scsp_id
*ip
)
703 fprintf(df
, "\t next: %p\n", ip
->next
);
704 fprintf(df
, "\t id_len: %d\n", ip
->id_len
);
705 fprintf(df
, "\t id: 0x");
706 for (i
= 0; i
< ip
->id_len
; i
++) {
707 fprintf(df
, "%0x ", ip
->id
[i
]);
714 * Print an SCSP cacke key
717 * df pointer to a FILE for the dump
718 * cp pointer to the cacke key to print
725 print_scsp_cache_key(FILE *df
, Scsp_ckey
*cp
)
729 fprintf(df
, "\t key_len: %d\n", cp
->key_len
);
730 fprintf(df
, "\t key: 0x");
731 for (i
= 0; i
< cp
->key_len
; i
++) {
732 fprintf(df
, "%0x ", cp
->key
[i
]);
739 * Print an ATMARP interface entry
742 * df pointer to a FILE for the dump
743 * aip pointer to interface entry
750 print_atmarp_intf(FILE *df
, Atmarp_intf
*aip
)
753 fprintf(df
, "print_atmarp_intf: NULL interface entry address\n");
757 fprintf(df
, "ATMARP network interface entry at %p\n", aip
);
758 fprintf(df
, "\tai_next: %p\n", aip
->ai_next
);
759 fprintf(df
, "\tai_intf: %s\n", aip
->ai_intf
);
760 fprintf(df
, "\tai_ip_addr: %s\n",
761 format_ip_addr(&aip
->ai_ip_addr
));
762 fprintf(df
, "\tai_subnet_mask: %s\n",
763 inet_ntoa(aip
->ai_subnet_mask
));
764 fprintf(df
, "\tai_mtu: %d\n", aip
->ai_mtu
);
765 fprintf(df
, "\tai_atm_addr: %s\n",
766 format_atm_addr(&aip
->ai_atm_addr
));
767 fprintf(df
, "\tai_atm_subaddr: %s\n",
768 format_atm_addr(&aip
->ai_atm_subaddr
));
769 fprintf(df
, "\tai_scsp_sock: %d\n", aip
->ai_scsp_sock
);
770 fprintf(df
, "\tai_scsp_sockname: %s\n", aip
->ai_scsp_sockname
);
771 fprintf(df
, "\tai_state: %d\n", aip
->ai_state
);
772 fprintf(df
, "\tai_mark: %d\n", aip
->ai_mark
);
777 * Print an ATMARP cache entry
780 * df pointer to a FILE for the dump
781 * aap pointer to cache entry
788 print_atmarp_cache(FILE *df
, Atmarp
*aap
)
791 fprintf(df
, "print_atmarp_cache: NULL ATMARP entry address\n");
795 fprintf(df
, "ATMARP entry at %p\n", aap
);
796 fprintf(df
, "\taa_next: %p\n", aap
->aa_next
);
797 fprintf(df
, "\taa_dstip: %s\n", inet_ntoa(aap
->aa_dstip
));
798 fprintf(df
, "\taa_dstatm: %s\n",
799 format_atm_addr(&aap
->aa_dstatm
));
800 fprintf(df
, "\taa_dstatmsub: %s\n",
801 format_atm_addr(&aap
->aa_dstatmsub
));
802 fprintf(df
, "\taa_key:\n");
803 print_scsp_cache_key(df
, &aap
->aa_key
);
804 fprintf(df
, "\taa_oid:\n");
805 print_scsp_id(df
, &aap
->aa_oid
);
806 fprintf(df
, "\taa_seq: %ld (0x%lx)\n", aap
->aa_seq
,
808 fprintf(df
, "\taa_intf: %p\n", aap
->aa_intf
);
809 fprintf(df
, "\taa_flags: ");
810 if (aap
->aa_flags
& AAF_PERM
)
811 fprintf(df
, "Permanent ");
812 if (aap
->aa_flags
& AAF_SERVER
)
813 fprintf(df
, "Server ");
815 fprintf(df
, "\taa_origin: %d\n", aap
->aa_origin
);
816 fprintf(df
, "\taa_mark: %d\n", aap
->aa_mark
);
821 * Print the entire ATMARP cache
824 * df pointer to a FILE for the dump
825 * aip pointer to interface whose cache is to be printed
832 dump_atmarp_cache(FILE *df
, Atmarp_intf
*aip
)
838 fprintf(df
, "dump_atmarp_cache: NULL interface address\n");
842 fprintf(df
, "ATMARP cache for interface %s\n", aip
->ai_intf
);
843 for (i
=0; i
<ATMARP_HASHSIZ
; i
++) {
844 for (aap
=aip
->ai_arptbl
[i
]; aap
; aap
=aap
->aa_next
) {
845 print_atmarp_cache(df
, aap
);
853 * Print an ATMARP super-LIS entry
856 * df pointer to a FILE for the dump
857 * asp pointer to super-LIS entry to be printed
864 print_atmarp_slis(FILE *df
, Atmarp_slis
*asp
)
869 fprintf(df
, "print_atmarp_slis: NULL SLIS address\n");
873 fprintf(df
, "SLIS entry at 0x%0x\n", (u_long
)asp
);
874 fprintf(df
, "\tas_next: 0x%0x\n", (u_long
)asp
->as_next
);
875 fprintf(df
, "\tas_name: %s\n", asp
->as_name
);
876 fprintf(df
, "\tas_cnt: %d\n", asp
->as_cnt
);
877 for (aipp
= &asp
->as_intfs
; *aipp
; aipp
++) {
878 fprintf(df
, "\t%s (%s)\n", (*aipp
)->ai_name
,
886 * Dump ATMARPD information
888 * Called as the result of a SIGINT signal.
898 atmarp_sigint(int sig
)
903 static int dump_no
= 0;
908 UM_ZERO(fname
, sizeof(fname
));
909 sprintf(fname
, "/tmp/atmarpd.%d.%03d.out", getpid(), dump_no
++);
912 * Open the output file
914 df
= fopen(fname
, "w");
919 * Dump the interface control blocks and
920 * associated ATMARP caches
922 for (aip
= atmarp_intf_head
; aip
; aip
= aip
->ai_next
) {
923 print_atmarp_intf(df
, aip
);
925 dump_atmarp_cache(df
, aip
);
930 * Close the output file