Use GNU style like the rest of the file for my last commit.
[dragonfly/vkernel-mp.git] / usr.sbin / atm / atmarpd / atmarp_subr.c
blobb6bad845a529c23ac5df42563b1c1219536c8cd1
1 /*
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 23: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>
43 #include <net/if.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>
57 #include <errno.h>
58 #include <libatm.h>
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <string.h>
62 #include <syslog.h>
63 #include <unistd.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
73 * Arguments:
74 * sd socket descriptor
76 * Returns:
77 * 0 failure
78 * else pointer to interface associated with socket
81 Atmarp_intf *
82 atmarp_find_intf_sock(int sd)
84 Atmarp_intf *aip;
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)
91 break;
94 return(aip);
99 * Find an ATMARP interface, given its name
101 * Arguments:
102 * name pointer to network interface name
104 * Returns:
105 * 0 failure
106 * else pointer to interface associated with name
109 Atmarp_intf *
110 atmarp_find_intf_name(char *name)
112 Atmarp_intf *aip;
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)
119 break;
122 return(aip);
127 * Clear the mark field on all ATMARP cache entries
129 * Arguments:
130 * none
132 * Returns:
133 * none
136 void
137 atmarp_clear_marks(void)
139 int i;
140 Atmarp_intf *aip;
141 Atmarp *aap;
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) {
153 aap->aa_mark = 0;
161 * Check whether the host system is an ATMARP server for
162 * the LIS associated with a given interface
164 * Arguments:
165 * aip pointer to an ATMARP interface control block
167 * Returns:
168 * 1 host is a server
169 * 0 host is not a server
173 atmarp_is_server(Atmarp_intf *aip)
175 int rc;
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);
186 if (buf_len < 0)
187 return(0);
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 ==
195 T_ATM_ABSENT);
196 UM_FREE(asrv_info);
197 return(rc);
202 * Check whether an interface is up and ready for service
204 * Arguments:
205 * aip pointer to network interface block
207 * Returns:
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;
216 Atmarp *aap = (Atmarp *)0;
217 struct atminfreq air;
218 struct air_netif_rsp *netif_rsp = (struct air_netif_rsp *)0;
219 struct air_int_rsp *intf_rsp = (struct air_int_rsp *)0;
220 struct sockaddr_in *ip_addr;
221 struct sockaddr_in subnet_mask;
222 Atm_addr_nsap *anp;
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));
232 if (len <= 0) {
233 goto if_ready_fail;
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;
241 goto if_ready_fail;
245 * Get the MTU for the network interface
247 mtu = get_mtu(aip->ai_intf);
248 if (mtu < 0) {
249 goto if_ready_fail;
254 * Get the subnet mask associated with the
255 * network interface
257 rc = get_subnet_mask(aip->ai_intf, &subnet_mask);
258 if (rc || subnet_mask.sin_family != AF_INET) {
259 goto if_ready_fail;
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));
269 if (len <= 0) {
270 goto if_ready_fail;
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) {
280 errno = EINVAL;
281 goto if_ready_fail;
285 * Check the interface state
287 if (intf_rsp->anp_sig_state != UNISIG_ACTIVE) {
288 errno = EINVAL;
289 goto if_ready_fail;
293 * Check the address format
295 if (intf_rsp->anp_addr.address_format != T_ATM_ENDSYS_ADDR &&
296 !(intf_rsp->anp_addr.address_format ==
297 T_ATM_E164_ADDR &&
298 intf_rsp->anp_subaddr.address_format ==
299 T_ATM_ENDSYS_ADDR)) {
300 errno = EINVAL;
301 goto if_ready_fail;
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')
310 break;
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)) {
318 rc = EINVAL;
319 goto if_ready_fail;
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)) {
335 return(1);
339 * Delete any existing ATMARP cache entry for this interface
341 ATMARP_LOOKUP(aip, aip->ai_ip_addr.s_addr, aap);
342 if (aap) {
343 ATMARP_DELETE(aip, aap);
344 UM_FREE(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,
355 &aip->ai_atm_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) {
360 anp->aan_sel = sel;
361 } else if (aip->ai_atm_addr.address_format ==
362 T_ATM_E164_ADDR &&
363 aip->ai_atm_subaddr.address_format ==
364 T_ATM_ENDSYS_ADDR) {
365 anp->aan_sel = sel;
369 * Get a new ATMARP cache for the interface
371 aap = (Atmarp *)UM_ALLOC(sizeof(Atmarp));
372 if (!aap) {
373 atmarp_mem_err("atmarp_if_ready: sizeof(Atmarp)");
375 UM_ZERO(aap, sizeof(Atmarp));
378 * Fill out the entry
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,
383 &aap->aa_dstatmsub);
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,
390 SCSP_ATMARP_ID_LEN);
391 aap->aa_intf = aip;
392 aap->aa_flags = AAF_SERVER;
393 aap->aa_origin = UAO_LOCAL;
396 * Add the entry to the cache
398 ATMARP_ADD(aip, aap);
401 * Free dynamic data
403 UM_FREE(netif_rsp);
404 UM_FREE(intf_rsp);
406 return(1);
408 if_ready_fail:
409 if (netif_rsp)
410 UM_FREE(netif_rsp);
411 if (intf_rsp)
412 UM_FREE(intf_rsp);
414 return(0);
419 * Copy an ATMARP cache entry from kernel format into an entry
420 * suitable for our cache
422 * Arguments:
423 * cp pointer to kernel entry
425 * Returns:
426 * pointer to a new cache entry
427 * 0 error
430 Atmarp *
431 atmarp_copy_cache_entry(struct air_arp_rsp *cp)
433 struct sockaddr_in *ipp;
434 Atmarp_intf *aip;
435 Atmarp *aap;
438 * Sanity checks
440 if (!cp)
441 return((Atmarp *)0);
442 aip = atmarp_find_intf_name(cp->aap_intf);
443 if (!aip)
444 return((Atmarp *)0);
447 * Get a new cache entry
449 aap = (Atmarp *)UM_ALLOC(sizeof(Atmarp));
450 if (!aap) {
451 errno = ENOMEM;
452 return((Atmarp *)0);
454 UM_ZERO(aap, sizeof(Atmarp));
455 aap->aa_intf = aip;
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,
477 SCSP_ATMARP_ID_LEN);
478 aap->aa_seq = SCSP_CSA_SEQ_MIN;
480 return(aap);
485 * Send an updated ATMARP cache entry to the kernel
487 * Arguments:
488 * aap pointer to updated entry
490 * Returns:
491 * 0 success
492 * errno reason for failure
496 atmarp_update_kernel(Atmarp *aap)
498 int rc = 0, sd;
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);
515 #endif
516 ipp->sin_addr = aap->aa_dstip;
519 * Pass the new mapping to the kernel
521 sd = socket(AF_ATM, SOCK_DGRAM, 0);
522 if (sd < 0) {
523 return(errno);
525 if (ioctl(sd, AIOCADD, (caddr_t)&aar) < 0) {
526 rc = errno;
529 close(sd);
530 return(rc);
535 * Read the ATMARP cache from the kernel and scan it, processing
536 * all entries
538 * Arguments:
539 * none
541 * Returns:
542 * none
545 void
546 atmarp_get_updated_cache(void)
548 int i, len, rc;
549 struct atminfreq air;
550 struct air_arp_rsp *cp;
551 struct sockaddr_in *ipp;
552 Atmarp_intf *aip;
553 Atmarp *aap;
556 * Set up the request
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);
563 #endif
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);
571 if (len < 0) {
572 return;
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;
584 len > 0;
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
591 * cache any more
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)
601 continue;
603 * Delete any entry that isn't marked
605 if (!aap->aa_mark) {
606 rc = atmarp_scsp_update(aap,
607 SCSP_ASTATE_DEL);
608 if (rc == 0)
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.
628 * Arguments:
629 * cp pointer to kernel's cache entry
631 * Returns:
632 * none
635 void
636 atmarp_process_cache_entry(struct air_arp_rsp *cp)
638 int rc;
639 struct sockaddr_in *ipp = (struct sockaddr_in *)&cp->aap_arp_addr;
640 Atmarp_intf *aip;
641 Atmarp *aap;
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)
649 return;
652 * Make sure the entry is valid
654 if (!(cp->aap_flags & ARPF_VALID))
655 return;
658 * See whether we have the entry in our cache already
660 ATMARP_LOOKUP(aip, ipp->sin_addr.s_addr, aap);
661 if (aap) {
663 * We already have this in our cache--update it
665 aap->aa_mark = 1;
666 if ((cp->aap_flags & ARPF_REFRESH) &&
667 cp->aap_origin != UAO_SCSP) {
668 aap->aa_seq++;
669 rc = atmarp_scsp_update(aap, SCSP_ASTATE_UPD);
671 } else {
673 * This is a new entry--add it to the cache
675 aap = atmarp_copy_cache_entry(cp);
676 if (!aap)
677 return;
678 ATMARP_ADD(aip, aap);
679 aap->aa_mark = 1;
680 rc = atmarp_scsp_update(aap, SCSP_ASTATE_NEW);
683 return;
688 * Print an SCSP ID
690 * Arguments:
691 * df pointer to a FILE for the dump
692 * ip pointer to the SCSP ID to print
694 * Returns:
695 * None
698 static void
699 print_scsp_id(FILE *df, Scsp_id *ip)
701 int i;
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]);
709 fprintf(df, "\n");
714 * Print an SCSP cacke key
716 * Arguments:
717 * df pointer to a FILE for the dump
718 * cp pointer to the cacke key to print
720 * Returns:
721 * None
724 static void
725 print_scsp_cache_key(FILE *df, Scsp_ckey *cp)
727 int i;
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]);
734 fprintf(df, "\n");
739 * Print an ATMARP interface entry
741 * Arguments:
742 * df pointer to a FILE for the dump
743 * aip pointer to interface entry
745 * Returns:
746 * None
749 void
750 print_atmarp_intf(FILE *df, Atmarp_intf *aip)
752 if (!aip) {
753 fprintf(df, "print_atmarp_intf: NULL interface entry address\n");
754 return;
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
779 * Arguments:
780 * df pointer to a FILE for the dump
781 * aap pointer to cache entry
783 * Returns:
784 * None
787 void
788 print_atmarp_cache(FILE *df, Atmarp *aap)
790 if (!aap) {
791 fprintf(df, "print_atmarp_cache: NULL ATMARP entry address\n");
792 return;
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,
807 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 ");
814 fprintf(df, "\n");
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
823 * Arguments:
824 * df pointer to a FILE for the dump
825 * aip pointer to interface whose cache is to be printed
827 * Returns:
828 * None
831 void
832 dump_atmarp_cache(FILE *df, Atmarp_intf *aip)
834 int i;
835 Atmarp *aap;
837 if (!aip) {
838 fprintf(df, "dump_atmarp_cache: NULL interface address\n");
839 return;
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);
851 #ifdef NOTDEF
853 * Print an ATMARP super-LIS entry
855 * Arguments:
856 * df pointer to a FILE for the dump
857 * asp pointer to super-LIS entry to be printed
859 * Returns:
860 * None
863 void
864 print_atmarp_slis(FILE *df, Atmarp_slis *asp)
866 Atmarp_intf **aipp;
868 if (!asp) {
869 fprintf(df, "print_atmarp_slis: NULL SLIS address\n");
870 return;
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,
879 (*aipp)->ai_intf);
882 #endif
886 * Dump ATMARPD information
888 * Called as the result of a SIGINT signal.
890 * Arguments:
891 * sig signal number
893 * Returns:
894 * None
897 void
898 atmarp_sigint(int sig)
900 Atmarp_intf *aip;
901 FILE *df;
902 char fname[64];
903 static int dump_no = 0;
906 * Build a file name
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");
915 if (df == (FILE *)0)
916 return;
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);
924 fprintf(df, "\n");
925 dump_atmarp_cache(df, aip);
926 fprintf(df, "\n");
930 * Close the output file
932 fclose(df);