]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - 6/usr.sbin/atm/atmarpd/atmarp_subr.c
merge fix for boot-time hang on centos' xen
[FreeBSD/FreeBSD.git] / 6 / usr.sbin / atm / atmarpd / atmarp_subr.c
1 /*
2  *
3  * ===================================
4  * HARP  |  Host ATM Research Platform
5  * ===================================
6  *
7  *
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.
12  *
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.
20  *
21  * Copyright 1994-1998 Network Computing Services, Inc.
22  *
23  * Copies of this Software may be made, however, the above copyright
24  * notice must be reproduced on all copies.
25  *
26  *      @(#) $FreeBSD$
27  *
28  */
29
30
31 /*
32  * Server Cache Synchronization Protocol (SCSP) Support
33  * ----------------------------------------------------
34  *
35  * SCSP-ATMARP server interface: misc. subroutines
36  *
37  */
38
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>
56  
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>
64
65 #include "../scspd/scsp_msg.h"
66 #include "../scspd/scsp_if.h"
67 #include "../scspd/scsp_var.h"
68 #include "atmarp_var.h"
69
70 #ifndef lint
71 __RCSID("@(#) $FreeBSD$");
72 #endif
73
74
75 /*
76  * Find an ATMARP interface, given its socket number
77  *
78  * Arguments:
79  *      sd      socket descriptor
80  *
81  * Returns:
82  *      0       failure
83  *      else    pointer to interface associated with socket
84  *
85  */
86 Atmarp_intf *
87 atmarp_find_intf_sock(sd)
88         int     sd;
89 {
90         Atmarp_intf     *aip;
91
92         /*
93          * Loop through the list of interfaces
94          */
95         for (aip = atmarp_intf_head; aip; aip = aip->ai_next) {
96                 if (aip->ai_scsp_sock == sd)
97                         break;
98         }
99
100         return(aip);
101 }
102
103
104 /*
105  * Find an ATMARP interface, given its name
106  *
107  * Arguments:
108  *      name    pointer to network interface name
109  *
110  * Returns:
111  *      0       failure
112  *      else    pointer to interface associated with name
113  *
114  */
115 Atmarp_intf *
116 atmarp_find_intf_name(name)
117         char    *name;
118 {
119         Atmarp_intf     *aip;
120
121         /*
122          * Loop through the list of interfaces
123          */
124         for (aip = atmarp_intf_head; aip; aip = aip->ai_next) {
125                 if (strcmp(name, aip->ai_intf) == 0)
126                         break;
127         }
128
129         return(aip);
130 }
131
132
133 /*
134  * Clear the mark field on all ATMARP cache entries
135  *
136  * Arguments:
137  *      none
138  *
139  * Returns:
140  *      none
141  *
142  */
143 void
144 atmarp_clear_marks()
145
146 {
147         int             i;
148         Atmarp_intf     *aip;
149         Atmarp          *aap;
150
151         /*
152          * Loop through list of interfaces
153          */
154         for (aip = atmarp_intf_head; aip; aip = aip->ai_next) {
155                 /*
156                  * Clear mark on every entry in the interface's cache
157                  */
158                 for (i = 0; i < ATMARP_HASHSIZ; i++ ) {
159                         for (aap = aip->ai_arptbl[i]; aap;
160                                         aap = aap->aa_next) {
161                                 aap->aa_mark = 0;
162                         }
163                 }
164         }
165 }
166
167
168 /*
169  * Check whether the host system is an ATMARP server for
170  * the LIS associated with a given interface
171  *
172  * Arguments:
173  *      aip     pointer to an ATMARP interface control block
174  *
175  * Returns:
176  *      1       host is a server
177  *      0       host is not a server
178  *
179  */
180 int
181 atmarp_is_server(aip)
182         Atmarp_intf     *aip;
183 {
184         int                     rc;
185         size_t buf_len;
186         struct atminfreq        air;
187         struct air_asrv_rsp     *asrv_info;
188
189         /*
190          * Get interface information from the kernel
191          */
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)
196                 return(0);
197
198         /*
199          * Check the interface's ATMARP server address
200          */
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 ==
204                                 T_ATM_ABSENT);
205         free(asrv_info);
206         return(rc);
207 }
208
209
210 /*
211  * Check whether an interface is up and ready for service
212  *
213  * Arguments:
214  *      aip     pointer to network interface block
215  *
216  * Returns:
217  *      0       interface not ready, errno has reason
218  *      1       interface is ready to go (interface block is updated)
219  *
220  */
221 int
222 atmarp_if_ready(aip)
223         Atmarp_intf     *aip;
224 {
225         int                     i, mtu, rc, sel;
226         size_t len;
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;
233         Atm_addr_nsap           *anp;
234
235         /*
236          * Get the IP address and physical interface name
237          * associated with the network interface
238          */
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)
244                 goto if_ready_fail;
245         netif_rsp = (struct air_netif_rsp *)air.air_buf_addr;
246
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;
251                 goto if_ready_fail;
252         }
253
254         /*
255          * Get the MTU for the network interface
256          */
257         mtu = get_mtu(aip->ai_intf);
258         if (mtu < 0) {
259                 goto if_ready_fail;
260         }
261
262
263         /*
264          * Get the subnet mask associated with the
265          * network interface
266          */
267         rc = get_subnet_mask(aip->ai_intf, &subnet_mask);
268         if (rc || subnet_mask.sin_family != AF_INET) {
269                 goto if_ready_fail;
270         }
271
272         /*
273          * Get physical interface information
274          */
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)
280                 goto if_ready_fail;
281         intf_rsp = (struct air_int_rsp *)air.air_buf_addr;
282
283         /*
284          * Check the signalling manager
285          */
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) {
289                 errno = EINVAL;
290                 goto if_ready_fail;
291         }
292
293         /*
294          * Check the interface state
295          */
296         if (intf_rsp->anp_sig_state != UNISIG_ACTIVE) {
297                 errno = EINVAL;
298                 goto if_ready_fail;
299         }
300
301         /*
302          * Check the address format
303          */
304         if (intf_rsp->anp_addr.address_format != T_ATM_ENDSYS_ADDR &&
305                         !(intf_rsp->anp_addr.address_format ==
306                                 T_ATM_E164_ADDR &&
307                         intf_rsp->anp_subaddr.address_format ==
308                                 T_ATM_ENDSYS_ADDR)) {
309                 errno = EINVAL;
310                 goto if_ready_fail;
311         }
312
313         /*
314          * Find the selector byte value for the interface
315          */
316         for (i=0; i<strlen(aip->ai_intf); i++) {
317                 if (aip->ai_intf[i] >= '0' &&
318                                 aip->ai_intf[i] <= '9')
319                         break;
320         }
321         sel = atoi(&aip->ai_intf[i]);
322
323         /*
324          * Make sure we're the server for this interface's LIS
325          */
326         if (!atmarp_is_server(aip)) {
327                 rc = EINVAL;
328                 goto if_ready_fail;
329         }
330
331         /*
332          * If we already have the interface active and the address
333          * hasn't changed, return
334          */
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)) {
344                 return(1);
345         }
346
347         /*
348          * Delete any existing ATMARP cache entry for this interface
349          */
350         ATMARP_LOOKUP(aip, aip->ai_ip_addr.s_addr, aap);
351         if (aap) {
352                 ATMARP_DELETE(aip, aap);
353                 free(aap);
354         }
355
356         /*
357          * Update the interface entry
358          */
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,
364                         &aip->ai_atm_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) {
369                 anp->aan_sel = sel;
370         } else if (aip->ai_atm_addr.address_format ==
371                                 T_ATM_E164_ADDR &&
372                         aip->ai_atm_subaddr.address_format ==
373                                 T_ATM_ENDSYS_ADDR) {
374                 anp->aan_sel = sel;
375         }
376
377         /*
378          * Get a new ATMARP cache for the interface
379          */
380         aap = calloc(1, sizeof(Atmarp));
381         if (aap == NULL)
382                 atmarp_mem_err("atmarp_if_ready: sizeof(Atmarp)");
383         
384         /*
385          * Fill out the entry
386          */
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,
390                         &aap->aa_dstatmsub);
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);
397         aap->aa_intf = aip;
398         aap->aa_flags = AAF_SERVER;
399         aap->aa_origin = UAO_LOCAL;
400
401         /*
402          * Add the entry to the cache
403          */
404         ATMARP_ADD(aip, aap);
405         
406         /*
407          * Free dynamic data
408          */
409         free(netif_rsp);
410         free(intf_rsp);
411         return(1);
412
413 if_ready_fail:
414         if (netif_rsp)
415                 free(netif_rsp);
416         if (intf_rsp)
417                 free(intf_rsp);
418         return(0);
419 }
420
421
422 /*
423  * Copy an ATMARP cache entry from kernel format into an entry
424  * suitable for our cache
425  *
426  * Arguments:
427  *      cp      pointer to kernel entry
428  *
429  * Returns:
430  *      pointer to a new cache entry
431  *      0       error
432  *
433  */
434 Atmarp *
435 atmarp_copy_cache_entry(cp)
436         struct air_arp_rsp      *cp;
437
438 {
439         struct sockaddr_in      *ipp;
440         Atmarp_intf             *aip;
441         Atmarp                  *aap;
442
443         /*
444          * Sanity checks
445          */
446         if (!cp)
447                 return((Atmarp *)0);
448         aip = atmarp_find_intf_name(cp->aap_intf);
449         if (!aip)
450                 return((Atmarp *)0);
451
452         /*
453          * Get a new cache entry
454          */
455         aap = calloc(1, sizeof(Atmarp));
456         if (aap == NULL) {
457                 errno = ENOMEM;
458                 return(NULL);
459         }
460         aap->aa_intf = aip;
461
462         /*
463          * Copy fields from the kernel entry to the new entry
464          */
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;
473
474         /*
475          * Set up fields for SCSP
476          */
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;
483
484         return(aap);
485 }
486
487
488 /*
489  * Send an updated ATMARP cache entry to the kernel
490  *
491  * Arguments:
492  *      aap     pointer to updated entry
493  *
494  * Returns:
495  *      0       success
496  *      errno   reason for failure
497  *
498  */
499 int
500 atmarp_update_kernel(aap)
501         Atmarp  *aap;
502 {
503         int                     rc = 0, sd;
504         struct atmaddreq        aar;
505         struct sockaddr_in      *ipp;
506
507         /*
508          * Build ioctl request
509          */
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);
520 #endif
521         ipp->sin_addr = aap->aa_dstip;
522         
523         /*
524          * Pass the new mapping to the kernel
525          */
526         sd = socket(AF_ATM, SOCK_DGRAM, 0);
527         if (sd < 0) {
528                 return(errno);
529         }
530         if (ioctl(sd, AIOCADD, (caddr_t)&aar) < 0) {
531                 rc = errno;
532         }
533
534         (void)close(sd);
535         return(rc);
536 }
537
538
539 /*
540  * Read the ATMARP cache from the kernel and scan it, processing
541  * all entries
542  *
543  * Arguments:
544  *      none
545  *
546  * Returns:
547  *      none
548  *
549  */
550 void
551 atmarp_get_updated_cache()
552 {
553         int                     i, rc;
554         size_t len;
555         struct atminfreq        air;
556         struct air_arp_rsp      *cp;
557         struct sockaddr_in      *ipp;
558         Atmarp_intf             *aip;
559         Atmarp                  *aap;
560
561         /*
562          * Set up the request
563          */
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);
569 #endif
570         ipp->sin_family = AF_INET;
571         ipp->sin_addr.s_addr = INADDR_ANY;
572
573         /*
574          * Issue an ATMARP information request IOCTL
575          */
576         len = do_info_ioctl(&air, sizeof(struct air_arp_rsp) * 200);
577         if ((ssize_t)len == -1)
578                 return;
579
580         /*
581          * Clear marks on all our cache entries
582          */
583         atmarp_clear_marks();
584
585         /*
586          * Loop through the cache, processing each entry
587          */
588         for (cp = (struct air_arp_rsp *) air.air_buf_addr;
589                         len > 0;
590                         cp++, len -= sizeof(struct air_arp_rsp)) {
591                 atmarp_process_cache_entry(cp);
592         }
593
594         /*
595          * Now delete any old entries that aren't in the kernel's
596          * cache any more
597          */
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) {
602                                 /*
603                                  * Don't delete the entry for the server
604                                  */
605                                 if (aap->aa_flags & AAF_SERVER)
606                                         continue;
607                                 /*
608                                  * Delete any entry that isn't marked
609                                  */
610                                 if (!aap->aa_mark) {
611                                         rc = atmarp_scsp_update(aap,
612                                                 SCSP_ASTATE_DEL);
613                                         if (rc == 0)
614                                                 ATMARP_DELETE(aip, aap);
615                                 }
616                         }
617                 }
618         }
619
620         /*
621          * Free the ioctl response
622          */
623         free(air.air_buf_addr);
624 }
625
626
627 /*
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.
632  *
633  * Arguments:
634  *      cp      pointer to kernel's cache entry
635  *
636  * Returns:
637  *      none
638  *
639  */
640 void
641 atmarp_process_cache_entry(cp)
642         struct air_arp_rsp      *cp;
643
644 {
645         int                     rc;
646         struct sockaddr_in      *ipp = (struct sockaddr_in *)&cp->aap_arp_addr;
647         Atmarp_intf             *aip;
648         Atmarp                  *aap;
649
650         /*
651          * See whether the entry is for an interface that's
652          * both configured and up
653          */
654         aip = atmarp_find_intf_name(cp->aap_intf);
655         if (!aip || aip->ai_state != AI_STATE_UP)
656                 return;
657
658         /*
659          * Make sure the entry is valid
660          */
661         if (!(cp->aap_flags & ARPF_VALID))
662                 return;
663
664         /*
665          * See whether we have the entry in our cache already
666          */
667         ATMARP_LOOKUP(aip, ipp->sin_addr.s_addr, aap);
668         if (aap) {
669                 /*
670                  * We already have this in our cache--update it
671                  */
672                 aap->aa_mark = 1;
673                 if ((cp->aap_flags & ARPF_REFRESH) &&
674                                 cp->aap_origin != UAO_SCSP) {
675                         aap->aa_seq++;
676                         rc = atmarp_scsp_update(aap, SCSP_ASTATE_UPD);
677                 }
678         } else {
679                 /*
680                  * This is a new entry--add it to the cache
681                  */
682                 aap = atmarp_copy_cache_entry(cp);
683                 if (!aap)
684                         return;
685                 ATMARP_ADD(aip, aap);
686                 aap->aa_mark = 1;
687                 rc = atmarp_scsp_update(aap, SCSP_ASTATE_NEW);
688         }
689
690         return;
691 }
692
693
694 /*
695  * Print an SCSP ID
696  *
697  * Arguments:
698  *      df      pointer to a FILE for the dump
699  *      ip      pointer to the SCSP ID to print
700  *
701  * Returns:
702  *      None
703  *
704  */
705 static void
706 print_scsp_id(df, ip)
707         FILE    *df;
708         Scsp_id *ip;
709 {
710         int     i;
711
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]);
717         }
718         fprintf(df, "\n");
719 }
720
721
722 /*
723  * Print an SCSP cacke key
724  *
725  * Arguments:
726  *      df      pointer to a FILE for the dump
727  *      cp      pointer to the cacke key to print
728  *
729  * Returns:
730  *      None
731  *
732  */
733 static void
734 print_scsp_cache_key(df, cp)
735         FILE            *df;
736         Scsp_ckey       *cp;
737 {
738         int     i;
739
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]);
744         }
745         fprintf(df, "\n");
746 }
747
748
749 /*
750  * Print an ATMARP interface entry
751  *
752  * Arguments:
753  *      df      pointer to a FILE for the dump
754  *      aip     pointer to interface entry
755  *
756  * Returns:
757  *      None
758  *
759  */
760 void
761 print_atmarp_intf(df, aip)
762         FILE            *df;
763         Atmarp_intf     *aip;
764 {
765         if (!aip) {
766                 fprintf(df, "print_atmarp_intf: NULL interface entry address\n");
767                 return;
768         }
769
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);
786 }
787
788
789 /*
790  * Print an ATMARP cache entry
791  *
792  * Arguments:
793  *      df      pointer to a FILE for the dump
794  *      aap     pointer to cache entry
795  *
796  * Returns:
797  *      None
798  *
799  */
800 void
801 print_atmarp_cache(df, aap)
802         FILE    *df;
803         Atmarp  *aap;
804 {
805         if (!aap) {
806                 fprintf(df, "print_atmarp_cache: NULL ATMARP entry address\n");
807                 return;
808         }
809
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,
822                         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 ");
829         fprintf(df, "\n");
830         fprintf(df, "\taa_origin:    %d\n", aap->aa_origin);
831         fprintf(df, "\taa_mark:      %d\n", aap->aa_mark);
832 }
833
834
835 /*
836  * Print the entire ATMARP cache
837  *
838  * Arguments:
839  *      df      pointer to a FILE for the dump
840  *      aip     pointer to interface whose cache is to be printed
841  *
842  * Returns:
843  *      None
844  *
845  */
846 void
847 dump_atmarp_cache(df, aip)
848         FILE            *df;
849         Atmarp_intf     *aip;
850 {
851         int     i;
852         Atmarp  *aap;
853
854         if (!aip) {
855                 fprintf(df, "dump_atmarp_cache: NULL interface address\n");
856                 return;
857         }
858
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);
863                 }
864         }
865 }
866
867
868 #ifdef NOTDEF
869 /*
870  * Print an ATMARP super-LIS entry
871  *
872  * Arguments:
873  *      df      pointer to a FILE for the dump
874  *      asp     pointer to super-LIS entry to be printed
875  *
876  * Returns:
877  *      None
878  *
879  */
880 void
881 print_atmarp_slis(df, asp)
882         FILE            *df;
883         Atmarp_slis     *asp;
884 {
885         Atmarp_intf     **aipp;
886
887         if (!asp) {
888                 fprintf(df, "print_atmarp_slis: NULL SLIS address\n");
889                 return;
890         }
891
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,
898                                 (*aipp)->ai_intf);
899         }
900 }
901 #endif
902
903
904 /*
905  * Dump ATMARPD information
906  *
907  * Called as the result of a SIGINT signal.
908  *
909  * Arguments:
910  *      sig     signal number
911  *
912  * Returns:
913  *      None
914  *
915  */
916 void
917 atmarp_sigint(sig)
918         int                     sig;
919 {
920         Atmarp_intf     *aip;
921         FILE            *df;
922         char            fname[64];
923         static int      dump_no = 0;
924
925         /*
926          * Build a file name
927          */
928         bzero(&fname, sizeof(fname));
929         sprintf(fname, "/tmp/atmarpd.%d.%03d.out", getpid(), dump_no++);
930
931         /*
932          * Open the output file
933          */
934         df = fopen(fname, "w");
935         if (df == (FILE *)0)
936                 return;
937
938         /*
939          * Dump the interface control blocks and
940          * associated ATMARP caches
941          */
942         for (aip = atmarp_intf_head; aip; aip = aip->ai_next) {
943                 print_atmarp_intf(df, aip);
944                 fprintf(df, "\n");
945                 dump_atmarp_cache(df, aip);
946                 fprintf(df, "\n");
947         }
948
949         /*
950          * Close the output file
951          */
952         (void)fclose(df);
953 }