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 $
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 __RCSID("@(#) $FreeBSD: src/usr.sbin/atm/atmarpd/atmarp_subr.c,v 1.3 1999/08/28 01:15:30 peter Exp $");
76 * Find an ATMARP interface, given its socket number
79 * sd socket descriptor
83 * else pointer to interface associated with socket
87 atmarp_find_intf_sock(sd)
93 * Loop through the list of interfaces
95 for (aip = atmarp_intf_head; aip; aip = aip->ai_next) {
96 if (aip->ai_scsp_sock == sd)
105 * Find an ATMARP interface, given its name
108 * name pointer to network interface name
112 * else pointer to interface associated with name
116 atmarp_find_intf_name(name)
122 * Loop through the list of interfaces
124 for (aip = atmarp_intf_head; aip; aip = aip->ai_next) {
125 if (strcmp(name, aip->ai_intf) == 0)
134 * Clear the mark field on all ATMARP cache entries
152 * Loop through list of interfaces
154 for (aip = atmarp_intf_head; aip; aip = aip->ai_next) {
156 * Clear mark on every entry in the interface's cache
158 for (i = 0; i < ATMARP_HASHSIZ; i++ ) {
159 for (aap = aip->ai_arptbl[i]; aap;
160 aap = aap->aa_next) {
169 * Check whether the host system is an ATMARP server for
170 * the LIS associated with a given interface
173 * aip pointer to an ATMARP interface control block
177 * 0 host is not a server
181 atmarp_is_server(aip)
185 int buf_len = sizeof(struct air_asrv_rsp);
186 struct atminfreq air;
187 struct air_asrv_rsp *asrv_info;
190 * Get interface information from the kernel
192 strcpy(air.air_int_intf, aip->ai_intf);
193 air.air_opcode = AIOCS_INF_ASV;
194 buf_len = do_info_ioctl(&air, buf_len);
199 * Check the interface's ATMARP server address
201 asrv_info = (struct air_asrv_rsp *) air.air_buf_addr;
202 rc = (asrv_info->asp_addr.address_format == T_ATM_ABSENT) &&
203 (asrv_info->asp_subaddr.address_format ==
211 * Check whether an interface is up and ready for service
214 * aip pointer to network interface block
217 * 0 interface not ready, errno has reason
218 * 1 interface is ready to go (interface block is updated)
225 int i, len, mtu, rc, sel;
226 Atmarp *aap = (Atmarp *)0;
227 struct atminfreq air;
228 struct air_netif_rsp *netif_rsp = (struct air_netif_rsp *)0;
229 struct air_int_rsp *intf_rsp = (struct air_int_rsp *)0;
230 struct sockaddr_in *ip_addr;
231 struct sockaddr_in subnet_mask;
235 * Get the IP address and physical interface name
236 * associated with the network interface
238 UM_ZERO(&air, sizeof(struct atminfreq));
239 air.air_opcode = AIOCS_INF_NIF;
240 strcpy(air.air_netif_intf, aip->ai_intf);
241 len = do_info_ioctl(&air, sizeof(struct air_netif_rsp));
245 netif_rsp = (struct air_netif_rsp *)air.air_buf_addr;
247 ip_addr = (struct sockaddr_in *)&netif_rsp->anp_proto_addr;
248 if (ip_addr->sin_family != AF_INET ||
249 ip_addr->sin_addr.s_addr == 0) {
250 errno = EAFNOSUPPORT;
255 * Get the MTU for the network interface
257 mtu = get_mtu(aip->ai_intf);
264 * Get the subnet mask associated with the
267 rc = get_subnet_mask(aip->ai_intf, &subnet_mask);
268 if (rc || subnet_mask.sin_family != AF_INET) {
273 * Get physical interface information
275 UM_ZERO(&air, sizeof(struct atminfreq));
276 air.air_opcode = AIOCS_INF_INT;
277 strcpy(air.air_int_intf, netif_rsp->anp_phy_intf);
278 len = do_info_ioctl(&air, sizeof(struct air_int_rsp));
282 intf_rsp = (struct air_int_rsp *)air.air_buf_addr;
285 * Check the signalling manager
287 if (intf_rsp->anp_sig_proto != ATM_SIG_UNI30 &&
288 intf_rsp->anp_sig_proto != ATM_SIG_UNI31 &&
289 intf_rsp->anp_sig_proto != ATM_SIG_UNI40) {
295 * Check the interface state
297 if (intf_rsp->anp_sig_state != UNISIG_ACTIVE) {
303 * Check the address format
305 if (intf_rsp->anp_addr.address_format != T_ATM_ENDSYS_ADDR &&
306 !(intf_rsp->anp_addr.address_format ==
308 intf_rsp->anp_subaddr.address_format ==
309 T_ATM_ENDSYS_ADDR)) {
315 * Find the selector byte value for the interface
317 for (i=0; i<strlen(aip->ai_intf); i++) {
318 if (aip->ai_intf[i] >= '0' &&
319 aip->ai_intf[i] <= '9')
322 sel = atoi(&aip->ai_intf[i]);
325 * Make sure we're the server for this interface's LIS
327 if (!atmarp_is_server(aip)) {
333 * If we already have the interface active and the address
334 * hasn't changed, return
336 if (aip->ai_state != AI_STATE_NULL &&
337 bcmp((caddr_t) &((struct sockaddr_in *)
338 &netif_rsp->anp_proto_addr)->sin_addr,
339 (caddr_t)&aip->ai_ip_addr,
340 sizeof(aip->ai_ip_addr)) == 0 &&
341 ATM_ADDR_EQUAL(&intf_rsp->anp_addr,
342 &aip->ai_atm_addr) &&
343 ATM_ADDR_EQUAL(&intf_rsp->anp_subaddr,
344 &aip->ai_atm_subaddr)) {
349 * Delete any existing ATMARP cache entry for this interface
351 ATMARP_LOOKUP(aip, aip->ai_ip_addr.s_addr, aap);
353 ATMARP_DELETE(aip, aap);
358 * Update the interface entry
360 aip->ai_ip_addr = ((struct sockaddr_in *)
361 &netif_rsp->anp_proto_addr)->sin_addr;
362 aip->ai_subnet_mask = subnet_mask.sin_addr;
363 aip->ai_mtu = mtu + 8;
364 ATM_ADDR_COPY(&intf_rsp->anp_addr,
366 ATM_ADDR_COPY(&intf_rsp->anp_subaddr,
367 &aip->ai_atm_subaddr);
368 anp = (Atm_addr_nsap *)aip->ai_atm_addr.address;
369 if (aip->ai_atm_addr.address_format == T_ATM_ENDSYS_ADDR) {
371 } else if (aip->ai_atm_addr.address_format ==
373 aip->ai_atm_subaddr.address_format ==
379 * Get a new ATMARP cache for the interface
381 aap = (Atmarp *)UM_ALLOC(sizeof(Atmarp));
383 atmarp_mem_err("atmarp_if_ready: sizeof(Atmarp)");
385 UM_ZERO(aap, sizeof(Atmarp));
390 aap->aa_dstip = aip->ai_ip_addr;
391 ATM_ADDR_COPY(&intf_rsp->anp_addr, &aap->aa_dstatm);
392 ATM_ADDR_COPY(&intf_rsp->anp_subaddr,
394 aap->aa_key.key_len = SCSP_ATMARP_KEY_LEN;
395 scsp_cache_key(&aap->aa_dstatm, &aap->aa_dstip,
396 SCSP_ATMARP_KEY_LEN, aap->aa_key.key);
397 aap->aa_oid.id_len = SCSP_ATMARP_ID_LEN;
398 aap->aa_seq = SCSP_CSA_SEQ_MIN;
399 UM_COPY(&aap->aa_dstip.s_addr, aap->aa_oid.id,
402 aap->aa_flags = AAF_SERVER;
403 aap->aa_origin = UAO_LOCAL;
406 * Add the entry to the cache
408 ATMARP_ADD(aip, aap);
429 * Copy an ATMARP cache entry from kernel format into an entry
430 * suitable for our cache
433 * cp pointer to kernel entry
436 * pointer to a new cache entry
441 atmarp_copy_cache_entry(cp)
442 struct air_arp_rsp *cp;
445 struct sockaddr_in *ipp;
454 aip = atmarp_find_intf_name(cp->aap_intf);
459 * Get a new cache entry
461 aap = (Atmarp *)UM_ALLOC(sizeof(Atmarp));
466 UM_ZERO(aap, sizeof(Atmarp));
470 * Copy fields from the kernel entry to the new entry
472 ipp = (struct sockaddr_in *)&cp->aap_arp_addr;
473 UM_COPY(&ipp->sin_addr.s_addr, &aap->aa_dstip.s_addr,
474 sizeof(aap->aa_dstip.s_addr));
475 ATM_ADDR_COPY(&cp->aap_addr, &aap->aa_dstatm);
476 ATM_ADDR_COPY(&cp->aap_subaddr, &aap->aa_dstatmsub);
477 if (cp->aap_origin == UAO_PERM)
478 aap->aa_flags |= AAF_PERM;
479 aap->aa_origin = cp->aap_origin;
482 * Set up fields for SCSP
484 aap->aa_key.key_len = SCSP_ATMARP_KEY_LEN;
485 scsp_cache_key(&cp->aap_addr, &aap->aa_dstip,
486 SCSP_ATMARP_KEY_LEN, (char *)aap->aa_key.key);
487 aap->aa_oid.id_len = SCSP_ATMARP_ID_LEN;
488 UM_COPY(&aip->ai_ip_addr.s_addr, aap->aa_oid.id,
490 aap->aa_seq = SCSP_CSA_SEQ_MIN;
497 * Send an updated ATMARP cache entry to the kernel
500 * aap pointer to updated entry
504 * errno reason for failure
508 atmarp_update_kernel(aap)
512 struct atmaddreq aar;
513 struct sockaddr_in *ipp;
516 * Build ioctl request
518 UM_ZERO(&aar, sizeof(aar));
519 aar.aar_opcode = AIOCS_ADD_ARP;
520 strncpy(aar.aar_arp_intf, aap->aa_intf->ai_intf,
521 sizeof(aar.aar_arp_intf));
522 aar.aar_arp_origin = UAO_SCSP;
523 ATM_ADDR_COPY(&aap->aa_dstatm, &aar.aar_arp_addr);
524 ipp = (struct sockaddr_in *)&aar.aar_arp_dst;
525 ipp->sin_family = AF_INET;
526 #if (defined(BSD) && (BSD >= 199103))
527 ipp->sin_len = sizeof(struct sockaddr_in);
529 ipp->sin_addr = aap->aa_dstip;
532 * Pass the new mapping to the kernel
534 sd = socket(AF_ATM, SOCK_DGRAM, 0);
538 if (ioctl(sd, AIOCADD, (caddr_t)&aar) < 0) {
548 * Read the ATMARP cache from the kernel and scan it, processing
559 atmarp_get_updated_cache()
562 struct atminfreq air;
563 struct air_arp_rsp *cp;
564 struct sockaddr_in *ipp;
571 air.air_opcode = AIOCS_INF_ARP;
572 air.air_arp_flags = ARP_RESET_REF;
573 ipp = (struct sockaddr_in *)&air.air_arp_addr;
574 #if (defined(BSD) && (BSD >= 199103))
575 ipp->sin_len = sizeof(struct sockaddr_in);
577 ipp->sin_family = AF_INET;
578 ipp->sin_addr.s_addr = INADDR_ANY;
581 * Issue an ATMARP information request IOCTL
583 len = do_info_ioctl(&air, sizeof(struct air_arp_rsp) * 200);
589 * Clear marks on all our cache entries
591 atmarp_clear_marks();
594 * Loop through the cache, processing each entry
596 for (cp = (struct air_arp_rsp *) air.air_buf_addr;
598 cp++, len -= sizeof(struct air_arp_rsp)) {
599 atmarp_process_cache_entry(cp);
603 * Now delete any old entries that aren't in the kernel's
606 for (aip = atmarp_intf_head; aip; aip = aip->ai_next) {
607 for (i = 0; i < ATMARP_HASHSIZ; i++) {
608 for (aap = aip->ai_arptbl[i]; aap;
609 aap = aap->aa_next) {
611 * Don't delete the entry for the server
613 if (aap->aa_flags & AAF_SERVER)
616 * Delete any entry that isn't marked
619 rc = atmarp_scsp_update(aap,
622 ATMARP_DELETE(aip, aap);
629 * Free the ioctl response
631 UM_FREE(air.air_buf_addr);
636 * Process an ATMARP cache entry from the kernel. If we already
637 * have the entry in our local cache, update it, otherwise, add
638 * it. In either case, mark our local copy so we know it's still
639 * in the kernel's cache.
642 * cp pointer to kernel's cache entry
649 atmarp_process_cache_entry(cp)
650 struct air_arp_rsp *cp;
654 struct sockaddr_in *ipp = (struct sockaddr_in *)&cp->aap_arp_addr;
659 * See whether the entry is for an interface that's
660 * both configured and up
662 aip = atmarp_find_intf_name(cp->aap_intf);
663 if (!aip || aip->ai_state != AI_STATE_UP)
667 * Make sure the entry is valid
669 if (!(cp->aap_flags & ARPF_VALID))
673 * See whether we have the entry in our cache already
675 ATMARP_LOOKUP(aip, ipp->sin_addr.s_addr, aap);
678 * We already have this in our cache--update it
681 if ((cp->aap_flags & ARPF_REFRESH) &&
682 cp->aap_origin != UAO_SCSP) {
684 rc = atmarp_scsp_update(aap, SCSP_ASTATE_UPD);
688 * This is a new entry--add it to the cache
690 aap = atmarp_copy_cache_entry(cp);
693 ATMARP_ADD(aip, aap);
695 rc = atmarp_scsp_update(aap, SCSP_ASTATE_NEW);
706 * df pointer to a FILE for the dump
707 * ip pointer to the SCSP ID to print
714 print_scsp_id(df, ip)
720 fprintf(df, "\t next: %p\n", ip->next);
721 fprintf(df, "\t id_len: %d\n", ip->id_len);
722 fprintf(df, "\t id: 0x");
723 for (i = 0; i < ip->id_len; i++) {
724 fprintf(df, "%0x ", ip->id[i]);
731 * Print an SCSP cacke key
734 * df pointer to a FILE for the dump
735 * cp pointer to the cacke key to print
742 print_scsp_cache_key(df, cp)
748 fprintf(df, "\t key_len: %d\n", cp->key_len);
749 fprintf(df, "\t key: 0x");
750 for (i = 0; i < cp->key_len; i++) {
751 fprintf(df, "%0x ", cp->key[i]);
758 * Print an ATMARP interface entry
761 * df pointer to a FILE for the dump
762 * aip pointer to interface entry
769 print_atmarp_intf(df, aip)
774 fprintf(df, "print_atmarp_intf: NULL interface entry address\n");
778 fprintf(df, "ATMARP network interface entry at %p\n", aip);
779 fprintf(df, "\tai_next: %p\n", aip->ai_next);
780 fprintf(df, "\tai_intf: %s\n", aip->ai_intf);
781 fprintf(df, "\tai_ip_addr: %s\n",
782 format_ip_addr(&aip->ai_ip_addr));
783 fprintf(df, "\tai_subnet_mask: %s\n",
784 inet_ntoa(aip->ai_subnet_mask));
785 fprintf(df, "\tai_mtu: %d\n", aip->ai_mtu);
786 fprintf(df, "\tai_atm_addr: %s\n",
787 format_atm_addr(&aip->ai_atm_addr));
788 fprintf(df, "\tai_atm_subaddr: %s\n",
789 format_atm_addr(&aip->ai_atm_subaddr));
790 fprintf(df, "\tai_scsp_sock: %d\n", aip->ai_scsp_sock);
791 fprintf(df, "\tai_scsp_sockname: %s\n", aip->ai_scsp_sockname);
792 fprintf(df, "\tai_state: %d\n", aip->ai_state);
793 fprintf(df, "\tai_mark: %d\n", aip->ai_mark);
798 * Print an ATMARP cache entry
801 * df pointer to a FILE for the dump
802 * aap pointer to cache entry
809 print_atmarp_cache(df, aap)
814 fprintf(df, "print_atmarp_cache: NULL ATMARP entry address\n");
818 fprintf(df, "ATMARP entry at %p\n", aap);
819 fprintf(df, "\taa_next: %p\n", aap->aa_next);
820 fprintf(df, "\taa_dstip: %s\n", inet_ntoa(aap->aa_dstip));
821 fprintf(df, "\taa_dstatm: %s\n",
822 format_atm_addr(&aap->aa_dstatm));
823 fprintf(df, "\taa_dstatmsub: %s\n",
824 format_atm_addr(&aap->aa_dstatmsub));
825 fprintf(df, "\taa_key:\n");
826 print_scsp_cache_key(df, &aap->aa_key);
827 fprintf(df, "\taa_oid:\n");
828 print_scsp_id(df, &aap->aa_oid);
829 fprintf(df, "\taa_seq: %ld (0x%lx)\n", aap->aa_seq,
831 fprintf(df, "\taa_intf: %p\n", aap->aa_intf);
832 fprintf(df, "\taa_flags: ");
833 if (aap->aa_flags & AAF_PERM)
834 fprintf(df, "Permanent ");
835 if (aap->aa_flags & AAF_SERVER)
836 fprintf(df, "Server ");
838 fprintf(df, "\taa_origin: %d\n", aap->aa_origin);
839 fprintf(df, "\taa_mark: %d\n", aap->aa_mark);
844 * Print the entire ATMARP cache
847 * df pointer to a FILE for the dump
848 * aip pointer to interface whose cache is to be printed
855 dump_atmarp_cache(df, aip)
863 fprintf(df, "dump_atmarp_cache: NULL interface address\n");
867 fprintf(df, "ATMARP cache for interface %s\n", aip->ai_intf);
868 for (i=0; i<ATMARP_HASHSIZ; i++) {
869 for (aap=aip->ai_arptbl[i]; aap; aap=aap->aa_next) {
870 print_atmarp_cache(df, aap);
878 * Print an ATMARP super-LIS entry
881 * df pointer to a FILE for the dump
882 * asp pointer to super-LIS entry to be printed
889 print_atmarp_slis(df, asp)
896 fprintf(df, "print_atmarp_slis: NULL SLIS address\n");
900 fprintf(df, "SLIS entry at 0x%0x\n", (u_long)asp);
901 fprintf(df, "\tas_next: 0x%0x\n", (u_long)asp->as_next);
902 fprintf(df, "\tas_name: %s\n", asp->as_name);
903 fprintf(df, "\tas_cnt: %d\n", asp->as_cnt);
904 for (aipp = &asp->as_intfs; *aipp; aipp++) {
905 fprintf(df, "\t%s (%s)\n", (*aipp)->ai_name,
913 * Dump ATMARPD information
915 * Called as the result of a SIGINT signal.
931 static int dump_no = 0;
936 UM_ZERO(fname, sizeof(fname));
937 sprintf(fname, "/tmp/atmarpd.%d.%03d.out", getpid(), dump_no++);
940 * Open the output file
942 df = fopen(fname, "w");
947 * Dump the interface control blocks and
948 * associated ATMARP caches
950 for (aip = atmarp_intf_head; aip; aip = aip->ai_next) {
951 print_atmarp_intf(df, aip);
953 dump_atmarp_cache(df, aip);
958 * Close the output file