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.2 2003/06/17 04:29:52 dillon 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(sd)
88 * Loop through the list of interfaces
90 for (aip = atmarp_intf_head; aip; aip = aip->ai_next) {
91 if (aip->ai_scsp_sock == sd)
100 * Find an ATMARP interface, given its name
103 * name pointer to network interface name
107 * else pointer to interface associated with name
111 atmarp_find_intf_name(name)
117 * Loop through the list of interfaces
119 for (aip = atmarp_intf_head; aip; aip = aip->ai_next) {
120 if (strcmp(name, aip->ai_intf) == 0)
129 * Clear the mark field on all ATMARP cache entries
147 * Loop through list of interfaces
149 for (aip = atmarp_intf_head; aip; aip = aip->ai_next) {
151 * Clear mark on every entry in the interface's cache
153 for (i = 0; i < ATMARP_HASHSIZ; i++ ) {
154 for (aap = aip->ai_arptbl[i]; aap;
155 aap = aap->aa_next) {
164 * Check whether the host system is an ATMARP server for
165 * the LIS associated with a given interface
168 * aip pointer to an ATMARP interface control block
172 * 0 host is not a server
176 atmarp_is_server(aip)
180 int buf_len = sizeof(struct air_asrv_rsp);
181 struct atminfreq air;
182 struct air_asrv_rsp *asrv_info;
185 * Get interface information from the kernel
187 strcpy(air.air_int_intf, aip->ai_intf);
188 air.air_opcode = AIOCS_INF_ASV;
189 buf_len = do_info_ioctl(&air, buf_len);
194 * Check the interface's ATMARP server address
196 asrv_info = (struct air_asrv_rsp *) air.air_buf_addr;
197 rc = (asrv_info->asp_addr.address_format == T_ATM_ABSENT) &&
198 (asrv_info->asp_subaddr.address_format ==
206 * Check whether an interface is up and ready for service
209 * aip pointer to network interface block
212 * 0 interface not ready, errno has reason
213 * 1 interface is ready to go (interface block is updated)
220 int i, len, mtu, rc, sel;
221 Atmarp *aap = (Atmarp *)0;
222 struct atminfreq air;
223 struct air_netif_rsp *netif_rsp = (struct air_netif_rsp *)0;
224 struct air_int_rsp *intf_rsp = (struct air_int_rsp *)0;
225 struct sockaddr_in *ip_addr;
226 struct sockaddr_in subnet_mask;
230 * Get the IP address and physical interface name
231 * associated with the network interface
233 UM_ZERO(&air, sizeof(struct atminfreq));
234 air.air_opcode = AIOCS_INF_NIF;
235 strcpy(air.air_netif_intf, aip->ai_intf);
236 len = do_info_ioctl(&air, sizeof(struct air_netif_rsp));
240 netif_rsp = (struct air_netif_rsp *)air.air_buf_addr;
242 ip_addr = (struct sockaddr_in *)&netif_rsp->anp_proto_addr;
243 if (ip_addr->sin_family != AF_INET ||
244 ip_addr->sin_addr.s_addr == 0) {
245 errno = EAFNOSUPPORT;
250 * Get the MTU for the network interface
252 mtu = get_mtu(aip->ai_intf);
259 * Get the subnet mask associated with the
262 rc = get_subnet_mask(aip->ai_intf, &subnet_mask);
263 if (rc || subnet_mask.sin_family != AF_INET) {
268 * Get physical interface information
270 UM_ZERO(&air, sizeof(struct atminfreq));
271 air.air_opcode = AIOCS_INF_INT;
272 strcpy(air.air_int_intf, netif_rsp->anp_phy_intf);
273 len = do_info_ioctl(&air, sizeof(struct air_int_rsp));
277 intf_rsp = (struct air_int_rsp *)air.air_buf_addr;
280 * Check the signalling manager
282 if (intf_rsp->anp_sig_proto != ATM_SIG_UNI30 &&
283 intf_rsp->anp_sig_proto != ATM_SIG_UNI31 &&
284 intf_rsp->anp_sig_proto != ATM_SIG_UNI40) {
290 * Check the interface state
292 if (intf_rsp->anp_sig_state != UNISIG_ACTIVE) {
298 * Check the address format
300 if (intf_rsp->anp_addr.address_format != T_ATM_ENDSYS_ADDR &&
301 !(intf_rsp->anp_addr.address_format ==
303 intf_rsp->anp_subaddr.address_format ==
304 T_ATM_ENDSYS_ADDR)) {
310 * Find the selector byte value for the interface
312 for (i=0; i<strlen(aip->ai_intf); i++) {
313 if (aip->ai_intf[i] >= '0' &&
314 aip->ai_intf[i] <= '9')
317 sel = atoi(&aip->ai_intf[i]);
320 * Make sure we're the server for this interface's LIS
322 if (!atmarp_is_server(aip)) {
328 * If we already have the interface active and the address
329 * hasn't changed, return
331 if (aip->ai_state != AI_STATE_NULL &&
332 bcmp((caddr_t) &((struct sockaddr_in *)
333 &netif_rsp->anp_proto_addr)->sin_addr,
334 (caddr_t)&aip->ai_ip_addr,
335 sizeof(aip->ai_ip_addr)) == 0 &&
336 ATM_ADDR_EQUAL(&intf_rsp->anp_addr,
337 &aip->ai_atm_addr) &&
338 ATM_ADDR_EQUAL(&intf_rsp->anp_subaddr,
339 &aip->ai_atm_subaddr)) {
344 * Delete any existing ATMARP cache entry for this interface
346 ATMARP_LOOKUP(aip, aip->ai_ip_addr.s_addr, aap);
348 ATMARP_DELETE(aip, aap);
353 * Update the interface entry
355 aip->ai_ip_addr = ((struct sockaddr_in *)
356 &netif_rsp->anp_proto_addr)->sin_addr;
357 aip->ai_subnet_mask = subnet_mask.sin_addr;
358 aip->ai_mtu = mtu + 8;
359 ATM_ADDR_COPY(&intf_rsp->anp_addr,
361 ATM_ADDR_COPY(&intf_rsp->anp_subaddr,
362 &aip->ai_atm_subaddr);
363 anp = (Atm_addr_nsap *)aip->ai_atm_addr.address;
364 if (aip->ai_atm_addr.address_format == T_ATM_ENDSYS_ADDR) {
366 } else if (aip->ai_atm_addr.address_format ==
368 aip->ai_atm_subaddr.address_format ==
374 * Get a new ATMARP cache for the interface
376 aap = (Atmarp *)UM_ALLOC(sizeof(Atmarp));
378 atmarp_mem_err("atmarp_if_ready: sizeof(Atmarp)");
380 UM_ZERO(aap, sizeof(Atmarp));
385 aap->aa_dstip = aip->ai_ip_addr;
386 ATM_ADDR_COPY(&intf_rsp->anp_addr, &aap->aa_dstatm);
387 ATM_ADDR_COPY(&intf_rsp->anp_subaddr,
389 aap->aa_key.key_len = SCSP_ATMARP_KEY_LEN;
390 scsp_cache_key(&aap->aa_dstatm, &aap->aa_dstip,
391 SCSP_ATMARP_KEY_LEN, aap->aa_key.key);
392 aap->aa_oid.id_len = SCSP_ATMARP_ID_LEN;
393 aap->aa_seq = SCSP_CSA_SEQ_MIN;
394 UM_COPY(&aap->aa_dstip.s_addr, aap->aa_oid.id,
397 aap->aa_flags = AAF_SERVER;
398 aap->aa_origin = UAO_LOCAL;
401 * Add the entry to the cache
403 ATMARP_ADD(aip, aap);
424 * Copy an ATMARP cache entry from kernel format into an entry
425 * suitable for our cache
428 * cp pointer to kernel entry
431 * pointer to a new cache entry
436 atmarp_copy_cache_entry(cp)
437 struct air_arp_rsp *cp;
440 struct sockaddr_in *ipp;
449 aip = atmarp_find_intf_name(cp->aap_intf);
454 * Get a new cache entry
456 aap = (Atmarp *)UM_ALLOC(sizeof(Atmarp));
461 UM_ZERO(aap, sizeof(Atmarp));
465 * Copy fields from the kernel entry to the new entry
467 ipp = (struct sockaddr_in *)&cp->aap_arp_addr;
468 UM_COPY(&ipp->sin_addr.s_addr, &aap->aa_dstip.s_addr,
469 sizeof(aap->aa_dstip.s_addr));
470 ATM_ADDR_COPY(&cp->aap_addr, &aap->aa_dstatm);
471 ATM_ADDR_COPY(&cp->aap_subaddr, &aap->aa_dstatmsub);
472 if (cp->aap_origin == UAO_PERM)
473 aap->aa_flags |= AAF_PERM;
474 aap->aa_origin = cp->aap_origin;
477 * Set up fields for SCSP
479 aap->aa_key.key_len = SCSP_ATMARP_KEY_LEN;
480 scsp_cache_key(&cp->aap_addr, &aap->aa_dstip,
481 SCSP_ATMARP_KEY_LEN, (char *)aap->aa_key.key);
482 aap->aa_oid.id_len = SCSP_ATMARP_ID_LEN;
483 UM_COPY(&aip->ai_ip_addr.s_addr, aap->aa_oid.id,
485 aap->aa_seq = SCSP_CSA_SEQ_MIN;
492 * Send an updated ATMARP cache entry to the kernel
495 * aap pointer to updated entry
499 * errno reason for failure
503 atmarp_update_kernel(aap)
507 struct atmaddreq aar;
508 struct sockaddr_in *ipp;
511 * Build ioctl request
513 UM_ZERO(&aar, sizeof(aar));
514 aar.aar_opcode = AIOCS_ADD_ARP;
515 strncpy(aar.aar_arp_intf, aap->aa_intf->ai_intf,
516 sizeof(aar.aar_arp_intf));
517 aar.aar_arp_origin = UAO_SCSP;
518 ATM_ADDR_COPY(&aap->aa_dstatm, &aar.aar_arp_addr);
519 ipp = (struct sockaddr_in *)&aar.aar_arp_dst;
520 ipp->sin_family = AF_INET;
521 #if (defined(BSD) && (BSD >= 199103))
522 ipp->sin_len = sizeof(struct sockaddr_in);
524 ipp->sin_addr = aap->aa_dstip;
527 * Pass the new mapping to the kernel
529 sd = socket(AF_ATM, SOCK_DGRAM, 0);
533 if (ioctl(sd, AIOCADD, (caddr_t)&aar) < 0) {
543 * Read the ATMARP cache from the kernel and scan it, processing
554 atmarp_get_updated_cache()
557 struct atminfreq air;
558 struct air_arp_rsp *cp;
559 struct sockaddr_in *ipp;
566 air.air_opcode = AIOCS_INF_ARP;
567 air.air_arp_flags = ARP_RESET_REF;
568 ipp = (struct sockaddr_in *)&air.air_arp_addr;
569 #if (defined(BSD) && (BSD >= 199103))
570 ipp->sin_len = sizeof(struct sockaddr_in);
572 ipp->sin_family = AF_INET;
573 ipp->sin_addr.s_addr = INADDR_ANY;
576 * Issue an ATMARP information request IOCTL
578 len = do_info_ioctl(&air, sizeof(struct air_arp_rsp) * 200);
584 * Clear marks on all our cache entries
586 atmarp_clear_marks();
589 * Loop through the cache, processing each entry
591 for (cp = (struct air_arp_rsp *) air.air_buf_addr;
593 cp++, len -= sizeof(struct air_arp_rsp)) {
594 atmarp_process_cache_entry(cp);
598 * Now delete any old entries that aren't in the kernel's
601 for (aip = atmarp_intf_head; aip; aip = aip->ai_next) {
602 for (i = 0; i < ATMARP_HASHSIZ; i++) {
603 for (aap = aip->ai_arptbl[i]; aap;
604 aap = aap->aa_next) {
606 * Don't delete the entry for the server
608 if (aap->aa_flags & AAF_SERVER)
611 * Delete any entry that isn't marked
614 rc = atmarp_scsp_update(aap,
617 ATMARP_DELETE(aip, aap);
624 * Free the ioctl response
626 UM_FREE(air.air_buf_addr);
631 * Process an ATMARP cache entry from the kernel. If we already
632 * have the entry in our local cache, update it, otherwise, add
633 * it. In either case, mark our local copy so we know it's still
634 * in the kernel's cache.
637 * cp pointer to kernel's cache entry
644 atmarp_process_cache_entry(cp)
645 struct air_arp_rsp *cp;
649 struct sockaddr_in *ipp = (struct sockaddr_in *)&cp->aap_arp_addr;
654 * See whether the entry is for an interface that's
655 * both configured and up
657 aip = atmarp_find_intf_name(cp->aap_intf);
658 if (!aip || aip->ai_state != AI_STATE_UP)
662 * Make sure the entry is valid
664 if (!(cp->aap_flags & ARPF_VALID))
668 * See whether we have the entry in our cache already
670 ATMARP_LOOKUP(aip, ipp->sin_addr.s_addr, aap);
673 * We already have this in our cache--update it
676 if ((cp->aap_flags & ARPF_REFRESH) &&
677 cp->aap_origin != UAO_SCSP) {
679 rc = atmarp_scsp_update(aap, SCSP_ASTATE_UPD);
683 * This is a new entry--add it to the cache
685 aap = atmarp_copy_cache_entry(cp);
688 ATMARP_ADD(aip, aap);
690 rc = atmarp_scsp_update(aap, SCSP_ASTATE_NEW);
701 * df pointer to a FILE for the dump
702 * ip pointer to the SCSP ID to print
709 print_scsp_id(df, ip)
715 fprintf(df, "\t next: %p\n", ip->next);
716 fprintf(df, "\t id_len: %d\n", ip->id_len);
717 fprintf(df, "\t id: 0x");
718 for (i = 0; i < ip->id_len; i++) {
719 fprintf(df, "%0x ", ip->id[i]);
726 * Print an SCSP cacke key
729 * df pointer to a FILE for the dump
730 * cp pointer to the cacke key to print
737 print_scsp_cache_key(df, cp)
743 fprintf(df, "\t key_len: %d\n", cp->key_len);
744 fprintf(df, "\t key: 0x");
745 for (i = 0; i < cp->key_len; i++) {
746 fprintf(df, "%0x ", cp->key[i]);
753 * Print an ATMARP interface entry
756 * df pointer to a FILE for the dump
757 * aip pointer to interface entry
764 print_atmarp_intf(df, aip)
769 fprintf(df, "print_atmarp_intf: NULL interface entry address\n");
773 fprintf(df, "ATMARP network interface entry at %p\n", aip);
774 fprintf(df, "\tai_next: %p\n", aip->ai_next);
775 fprintf(df, "\tai_intf: %s\n", aip->ai_intf);
776 fprintf(df, "\tai_ip_addr: %s\n",
777 format_ip_addr(&aip->ai_ip_addr));
778 fprintf(df, "\tai_subnet_mask: %s\n",
779 inet_ntoa(aip->ai_subnet_mask));
780 fprintf(df, "\tai_mtu: %d\n", aip->ai_mtu);
781 fprintf(df, "\tai_atm_addr: %s\n",
782 format_atm_addr(&aip->ai_atm_addr));
783 fprintf(df, "\tai_atm_subaddr: %s\n",
784 format_atm_addr(&aip->ai_atm_subaddr));
785 fprintf(df, "\tai_scsp_sock: %d\n", aip->ai_scsp_sock);
786 fprintf(df, "\tai_scsp_sockname: %s\n", aip->ai_scsp_sockname);
787 fprintf(df, "\tai_state: %d\n", aip->ai_state);
788 fprintf(df, "\tai_mark: %d\n", aip->ai_mark);
793 * Print an ATMARP cache entry
796 * df pointer to a FILE for the dump
797 * aap pointer to cache entry
804 print_atmarp_cache(df, aap)
809 fprintf(df, "print_atmarp_cache: NULL ATMARP entry address\n");
813 fprintf(df, "ATMARP entry at %p\n", aap);
814 fprintf(df, "\taa_next: %p\n", aap->aa_next);
815 fprintf(df, "\taa_dstip: %s\n", inet_ntoa(aap->aa_dstip));
816 fprintf(df, "\taa_dstatm: %s\n",
817 format_atm_addr(&aap->aa_dstatm));
818 fprintf(df, "\taa_dstatmsub: %s\n",
819 format_atm_addr(&aap->aa_dstatmsub));
820 fprintf(df, "\taa_key:\n");
821 print_scsp_cache_key(df, &aap->aa_key);
822 fprintf(df, "\taa_oid:\n");
823 print_scsp_id(df, &aap->aa_oid);
824 fprintf(df, "\taa_seq: %ld (0x%lx)\n", aap->aa_seq,
826 fprintf(df, "\taa_intf: %p\n", aap->aa_intf);
827 fprintf(df, "\taa_flags: ");
828 if (aap->aa_flags & AAF_PERM)
829 fprintf(df, "Permanent ");
830 if (aap->aa_flags & AAF_SERVER)
831 fprintf(df, "Server ");
833 fprintf(df, "\taa_origin: %d\n", aap->aa_origin);
834 fprintf(df, "\taa_mark: %d\n", aap->aa_mark);
839 * Print the entire ATMARP cache
842 * df pointer to a FILE for the dump
843 * aip pointer to interface whose cache is to be printed
850 dump_atmarp_cache(df, aip)
858 fprintf(df, "dump_atmarp_cache: NULL interface address\n");
862 fprintf(df, "ATMARP cache for interface %s\n", aip->ai_intf);
863 for (i=0; i<ATMARP_HASHSIZ; i++) {
864 for (aap=aip->ai_arptbl[i]; aap; aap=aap->aa_next) {
865 print_atmarp_cache(df, aap);
873 * Print an ATMARP super-LIS entry
876 * df pointer to a FILE for the dump
877 * asp pointer to super-LIS entry to be printed
884 print_atmarp_slis(df, asp)
891 fprintf(df, "print_atmarp_slis: NULL SLIS address\n");
895 fprintf(df, "SLIS entry at 0x%0x\n", (u_long)asp);
896 fprintf(df, "\tas_next: 0x%0x\n", (u_long)asp->as_next);
897 fprintf(df, "\tas_name: %s\n", asp->as_name);
898 fprintf(df, "\tas_cnt: %d\n", asp->as_cnt);
899 for (aipp = &asp->as_intfs; *aipp; aipp++) {
900 fprintf(df, "\t%s (%s)\n", (*aipp)->ai_name,
908 * Dump ATMARPD information
910 * Called as the result of a SIGINT signal.
926 static int dump_no = 0;
931 UM_ZERO(fname, sizeof(fname));
932 sprintf(fname, "/tmp/atmarpd.%d.%03d.out", getpid(), dump_no++);
935 * Open the output file
937 df = fopen(fname, "w");
942 * Dump the interface control blocks and
943 * associated ATMARP caches
945 for (aip = atmarp_intf_head; aip; aip = aip->ai_next) {
946 print_atmarp_intf(df, aip);
948 dump_atmarp_cache(df, aip);
953 * Close the output file