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.
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$");
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)
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, sizeof(struct air_asrv_rsp));
195 if ((ssize_t)buf_len == -1)
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)
227 Atmarp *aap = (Atmarp *)0;
228 struct atminfreq air;
229 struct air_netif_rsp *netif_rsp = (struct air_netif_rsp *)0;
230 struct air_int_rsp *intf_rsp = (struct air_int_rsp *)0;
231 struct sockaddr_in *ip_addr;
232 struct sockaddr_in subnet_mask;
236 * Get the IP address and physical interface name
237 * associated with the network interface
239 bzero(&air, sizeof(struct atminfreq));
240 air.air_opcode = AIOCS_INF_NIF;
241 strcpy(air.air_netif_intf, aip->ai_intf);
242 len = do_info_ioctl(&air, sizeof(struct air_netif_rsp));
243 if ((ssize_t)len == -1)
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 bzero(&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));
279 if ((ssize_t)len == -1)
281 intf_rsp = (struct air_int_rsp *)air.air_buf_addr;
284 * Check the signalling manager
286 if (intf_rsp->anp_sig_proto != ATM_SIG_UNI30 &&
287 intf_rsp->anp_sig_proto != ATM_SIG_UNI31 &&
288 intf_rsp->anp_sig_proto != ATM_SIG_UNI40) {
294 * Check the interface state
296 if (intf_rsp->anp_sig_state != UNISIG_ACTIVE) {
302 * Check the address format
304 if (intf_rsp->anp_addr.address_format != T_ATM_ENDSYS_ADDR &&
305 !(intf_rsp->anp_addr.address_format ==
307 intf_rsp->anp_subaddr.address_format ==
308 T_ATM_ENDSYS_ADDR)) {
314 * Find the selector byte value for the interface
316 for (i=0; i<strlen(aip->ai_intf); i++) {
317 if (aip->ai_intf[i] >= '0' &&
318 aip->ai_intf[i] <= '9')
321 sel = atoi(&aip->ai_intf[i]);
324 * Make sure we're the server for this interface's LIS
326 if (!atmarp_is_server(aip)) {
332 * If we already have the interface active and the address
333 * hasn't changed, return
335 if (aip->ai_state != AI_STATE_NULL &&
336 bcmp((caddr_t) &((struct sockaddr_in *)
337 &netif_rsp->anp_proto_addr)->sin_addr,
338 (caddr_t)&aip->ai_ip_addr,
339 sizeof(aip->ai_ip_addr)) == 0 &&
340 ATM_ADDR_EQUAL(&intf_rsp->anp_addr,
341 &aip->ai_atm_addr) &&
342 ATM_ADDR_EQUAL(&intf_rsp->anp_subaddr,
343 &aip->ai_atm_subaddr)) {
348 * Delete any existing ATMARP cache entry for this interface
350 ATMARP_LOOKUP(aip, aip->ai_ip_addr.s_addr, aap);
352 ATMARP_DELETE(aip, aap);
357 * Update the interface entry
359 aip->ai_ip_addr = ((struct sockaddr_in *)
360 &netif_rsp->anp_proto_addr)->sin_addr;
361 aip->ai_subnet_mask = subnet_mask.sin_addr;
362 aip->ai_mtu = mtu + 8;
363 ATM_ADDR_COPY(&intf_rsp->anp_addr,
365 ATM_ADDR_COPY(&intf_rsp->anp_subaddr,
366 &aip->ai_atm_subaddr);
367 anp = (Atm_addr_nsap *)aip->ai_atm_addr.address;
368 if (aip->ai_atm_addr.address_format == T_ATM_ENDSYS_ADDR) {
370 } else if (aip->ai_atm_addr.address_format ==
372 aip->ai_atm_subaddr.address_format ==
378 * Get a new ATMARP cache for the interface
380 aap = calloc(1, sizeof(Atmarp));
382 atmarp_mem_err("atmarp_if_ready: sizeof(Atmarp)");
387 aap->aa_dstip = aip->ai_ip_addr;
388 ATM_ADDR_COPY(&intf_rsp->anp_addr, &aap->aa_dstatm);
389 ATM_ADDR_COPY(&intf_rsp->anp_subaddr,
391 aap->aa_key.key_len = SCSP_ATMARP_KEY_LEN;
392 scsp_cache_key(&aap->aa_dstatm, &aap->aa_dstip,
393 SCSP_ATMARP_KEY_LEN, aap->aa_key.key);
394 aap->aa_oid.id_len = SCSP_ATMARP_ID_LEN;
395 aap->aa_seq = SCSP_CSA_SEQ_MIN;
396 bcopy(&aap->aa_dstip.s_addr, aap->aa_oid.id, SCSP_ATMARP_ID_LEN);
398 aap->aa_flags = AAF_SERVER;
399 aap->aa_origin = UAO_LOCAL;
402 * Add the entry to the cache
404 ATMARP_ADD(aip, aap);
423 * Copy an ATMARP cache entry from kernel format into an entry
424 * suitable for our cache
427 * cp pointer to kernel entry
430 * pointer to a new cache entry
435 atmarp_copy_cache_entry(cp)
436 struct air_arp_rsp *cp;
439 struct sockaddr_in *ipp;
448 aip = atmarp_find_intf_name(cp->aap_intf);
453 * Get a new cache entry
455 aap = calloc(1, sizeof(Atmarp));
463 * Copy fields from the kernel entry to the new entry
465 ipp = (struct sockaddr_in *)&cp->aap_arp_addr;
466 bcopy(&ipp->sin_addr.s_addr, &aap->aa_dstip.s_addr,
467 sizeof(aap->aa_dstip.s_addr));
468 ATM_ADDR_COPY(&cp->aap_addr, &aap->aa_dstatm);
469 ATM_ADDR_COPY(&cp->aap_subaddr, &aap->aa_dstatmsub);
470 if (cp->aap_origin == UAO_PERM)
471 aap->aa_flags |= AAF_PERM;
472 aap->aa_origin = cp->aap_origin;
475 * Set up fields for SCSP
477 aap->aa_key.key_len = SCSP_ATMARP_KEY_LEN;
478 scsp_cache_key(&cp->aap_addr, &aap->aa_dstip,
479 SCSP_ATMARP_KEY_LEN, (char *)aap->aa_key.key);
480 aap->aa_oid.id_len = SCSP_ATMARP_ID_LEN;
481 bcopy(&aip->ai_ip_addr.s_addr, aap->aa_oid.id, SCSP_ATMARP_ID_LEN);
482 aap->aa_seq = SCSP_CSA_SEQ_MIN;
489 * Send an updated ATMARP cache entry to the kernel
492 * aap pointer to updated entry
496 * errno reason for failure
500 atmarp_update_kernel(aap)
504 struct atmaddreq aar;
505 struct sockaddr_in *ipp;
508 * Build ioctl request
510 bzero(&aar, sizeof(aar));
511 aar.aar_opcode = AIOCS_ADD_ARP;
512 strncpy(aar.aar_arp_intf, aap->aa_intf->ai_intf,
513 sizeof(aar.aar_arp_intf));
514 aar.aar_arp_origin = UAO_SCSP;
515 ATM_ADDR_COPY(&aap->aa_dstatm, &aar.aar_arp_addr);
516 ipp = (struct sockaddr_in *)&aar.aar_arp_dst;
517 ipp->sin_family = AF_INET;
518 #if (defined(BSD) && (BSD >= 199103))
519 ipp->sin_len = sizeof(struct sockaddr_in);
521 ipp->sin_addr = aap->aa_dstip;
524 * Pass the new mapping to the kernel
526 sd = socket(AF_ATM, SOCK_DGRAM, 0);
530 if (ioctl(sd, AIOCADD, (caddr_t)&aar) < 0) {
540 * Read the ATMARP cache from the kernel and scan it, processing
551 atmarp_get_updated_cache()
555 struct atminfreq air;
556 struct air_arp_rsp *cp;
557 struct sockaddr_in *ipp;
564 air.air_opcode = AIOCS_INF_ARP;
565 air.air_arp_flags = ARP_RESET_REF;
566 ipp = (struct sockaddr_in *)&air.air_arp_addr;
567 #if (defined(BSD) && (BSD >= 199103))
568 ipp->sin_len = sizeof(struct sockaddr_in);
570 ipp->sin_family = AF_INET;
571 ipp->sin_addr.s_addr = INADDR_ANY;
574 * Issue an ATMARP information request IOCTL
576 len = do_info_ioctl(&air, sizeof(struct air_arp_rsp) * 200);
577 if ((ssize_t)len == -1)
581 * Clear marks on all our cache entries
583 atmarp_clear_marks();
586 * Loop through the cache, processing each entry
588 for (cp = (struct air_arp_rsp *) air.air_buf_addr;
590 cp++, len -= sizeof(struct air_arp_rsp)) {
591 atmarp_process_cache_entry(cp);
595 * Now delete any old entries that aren't in the kernel's
598 for (aip = atmarp_intf_head; aip; aip = aip->ai_next) {
599 for (i = 0; i < ATMARP_HASHSIZ; i++) {
600 for (aap = aip->ai_arptbl[i]; aap;
601 aap = aap->aa_next) {
603 * Don't delete the entry for the server
605 if (aap->aa_flags & AAF_SERVER)
608 * Delete any entry that isn't marked
611 rc = atmarp_scsp_update(aap,
614 ATMARP_DELETE(aip, aap);
621 * Free the ioctl response
623 free(air.air_buf_addr);
628 * Process an ATMARP cache entry from the kernel. If we already
629 * have the entry in our local cache, update it, otherwise, add
630 * it. In either case, mark our local copy so we know it's still
631 * in the kernel's cache.
634 * cp pointer to kernel's cache entry
641 atmarp_process_cache_entry(cp)
642 struct air_arp_rsp *cp;
646 struct sockaddr_in *ipp = (struct sockaddr_in *)&cp->aap_arp_addr;
651 * See whether the entry is for an interface that's
652 * both configured and up
654 aip = atmarp_find_intf_name(cp->aap_intf);
655 if (!aip || aip->ai_state != AI_STATE_UP)
659 * Make sure the entry is valid
661 if (!(cp->aap_flags & ARPF_VALID))
665 * See whether we have the entry in our cache already
667 ATMARP_LOOKUP(aip, ipp->sin_addr.s_addr, aap);
670 * We already have this in our cache--update it
673 if ((cp->aap_flags & ARPF_REFRESH) &&
674 cp->aap_origin != UAO_SCSP) {
676 rc = atmarp_scsp_update(aap, SCSP_ASTATE_UPD);
680 * This is a new entry--add it to the cache
682 aap = atmarp_copy_cache_entry(cp);
685 ATMARP_ADD(aip, aap);
687 rc = atmarp_scsp_update(aap, SCSP_ASTATE_NEW);
698 * df pointer to a FILE for the dump
699 * ip pointer to the SCSP ID to print
706 print_scsp_id(df, ip)
712 fprintf(df, "\t next: %p\n", ip->next);
713 fprintf(df, "\t id_len: %d\n", ip->id_len);
714 fprintf(df, "\t id: 0x");
715 for (i = 0; i < ip->id_len; i++) {
716 fprintf(df, "%0x ", ip->id[i]);
723 * Print an SCSP cacke key
726 * df pointer to a FILE for the dump
727 * cp pointer to the cacke key to print
734 print_scsp_cache_key(df, cp)
740 fprintf(df, "\t key_len: %d\n", cp->key_len);
741 fprintf(df, "\t key: 0x");
742 for (i = 0; i < cp->key_len; i++) {
743 fprintf(df, "%0x ", cp->key[i]);
750 * Print an ATMARP interface entry
753 * df pointer to a FILE for the dump
754 * aip pointer to interface entry
761 print_atmarp_intf(df, aip)
766 fprintf(df, "print_atmarp_intf: NULL interface entry address\n");
770 fprintf(df, "ATMARP network interface entry at %p\n", aip);
771 fprintf(df, "\tai_next: %p\n", aip->ai_next);
772 fprintf(df, "\tai_intf: %s\n", aip->ai_intf);
773 fprintf(df, "\tai_ip_addr: %s\n",
774 format_ip_addr(&aip->ai_ip_addr));
775 fprintf(df, "\tai_subnet_mask: %s\n",
776 inet_ntoa(aip->ai_subnet_mask));
777 fprintf(df, "\tai_mtu: %d\n", aip->ai_mtu);
778 fprintf(df, "\tai_atm_addr: %s\n",
779 format_atm_addr(&aip->ai_atm_addr));
780 fprintf(df, "\tai_atm_subaddr: %s\n",
781 format_atm_addr(&aip->ai_atm_subaddr));
782 fprintf(df, "\tai_scsp_sock: %d\n", aip->ai_scsp_sock);
783 fprintf(df, "\tai_scsp_sockname: %s\n", aip->ai_scsp_sockname);
784 fprintf(df, "\tai_state: %d\n", aip->ai_state);
785 fprintf(df, "\tai_mark: %d\n", aip->ai_mark);
790 * Print an ATMARP cache entry
793 * df pointer to a FILE for the dump
794 * aap pointer to cache entry
801 print_atmarp_cache(df, aap)
806 fprintf(df, "print_atmarp_cache: NULL ATMARP entry address\n");
810 fprintf(df, "ATMARP entry at %p\n", aap);
811 fprintf(df, "\taa_next: %p\n", aap->aa_next);
812 fprintf(df, "\taa_dstip: %s\n", inet_ntoa(aap->aa_dstip));
813 fprintf(df, "\taa_dstatm: %s\n",
814 format_atm_addr(&aap->aa_dstatm));
815 fprintf(df, "\taa_dstatmsub: %s\n",
816 format_atm_addr(&aap->aa_dstatmsub));
817 fprintf(df, "\taa_key:\n");
818 print_scsp_cache_key(df, &aap->aa_key);
819 fprintf(df, "\taa_oid:\n");
820 print_scsp_id(df, &aap->aa_oid);
821 fprintf(df, "\taa_seq: %ld (0x%lx)\n", aap->aa_seq,
823 fprintf(df, "\taa_intf: %p\n", aap->aa_intf);
824 fprintf(df, "\taa_flags: ");
825 if (aap->aa_flags & AAF_PERM)
826 fprintf(df, "Permanent ");
827 if (aap->aa_flags & AAF_SERVER)
828 fprintf(df, "Server ");
830 fprintf(df, "\taa_origin: %d\n", aap->aa_origin);
831 fprintf(df, "\taa_mark: %d\n", aap->aa_mark);
836 * Print the entire ATMARP cache
839 * df pointer to a FILE for the dump
840 * aip pointer to interface whose cache is to be printed
847 dump_atmarp_cache(df, aip)
855 fprintf(df, "dump_atmarp_cache: NULL interface address\n");
859 fprintf(df, "ATMARP cache for interface %s\n", aip->ai_intf);
860 for (i=0; i<ATMARP_HASHSIZ; i++) {
861 for (aap=aip->ai_arptbl[i]; aap; aap=aap->aa_next) {
862 print_atmarp_cache(df, aap);
870 * Print an ATMARP super-LIS entry
873 * df pointer to a FILE for the dump
874 * asp pointer to super-LIS entry to be printed
881 print_atmarp_slis(df, asp)
888 fprintf(df, "print_atmarp_slis: NULL SLIS address\n");
892 fprintf(df, "SLIS entry at 0x%0x\n", (u_long)asp);
893 fprintf(df, "\tas_next: 0x%0x\n", (u_long)asp->as_next);
894 fprintf(df, "\tas_name: %s\n", asp->as_name);
895 fprintf(df, "\tas_cnt: %d\n", asp->as_cnt);
896 for (aipp = &asp->as_intfs; *aipp; aipp++) {
897 fprintf(df, "\t%s (%s)\n", (*aipp)->ai_name,
905 * Dump ATMARPD information
907 * Called as the result of a SIGINT signal.
923 static int dump_no = 0;
928 bzero(&fname, sizeof(fname));
929 sprintf(fname, "/tmp/atmarpd.%d.%03d.out", getpid(), dump_no++);
932 * Open the output file
934 df = fopen(fname, "w");
939 * Dump the interface control blocks and
940 * associated ATMARP caches
942 for (aip = atmarp_intf_head; aip; aip = aip->ai_next) {
943 print_atmarp_intf(df, aip);
945 dump_atmarp_cache(df, aip);
950 * Close the output file