Initial import from FreeBSD RELENG_4:
[dragonfly.git] / 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: src/usr.sbin/atm/atmarpd/atmarp_subr.c,v 1.3 1999/08/28 01:15:30 peter Exp $
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: src/usr.sbin/atm/atmarpd/atmarp_subr.c,v 1.3 1999/08/28 01:15:30 peter Exp $");
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         int                     buf_len = sizeof(struct air_asrv_rsp);
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, buf_len);
195         if (buf_len < 0)
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         UM_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, 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;
232         Atm_addr_nsap           *anp;
233
234         /*
235          * Get the IP address and physical interface name
236          * associated with the network interface
237          */
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));
242         if (len <= 0) {
243                 goto if_ready_fail;
244         }
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         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));
279         if (len <= 0) {
280                 goto if_ready_fail;
281         }
282         intf_rsp = (struct air_int_rsp *)air.air_buf_addr;
283
284         /*
285          * Check the signalling manager
286          */
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) {
290                 errno = EINVAL;
291                 goto if_ready_fail;
292         }
293
294         /*
295          * Check the interface state
296          */
297         if (intf_rsp->anp_sig_state != UNISIG_ACTIVE) {
298                 errno = EINVAL;
299                 goto if_ready_fail;
300         }
301
302         /*
303          * Check the address format
304          */
305         if (intf_rsp->anp_addr.address_format != T_ATM_ENDSYS_ADDR &&
306                         !(intf_rsp->anp_addr.address_format ==
307                                 T_ATM_E164_ADDR &&
308                         intf_rsp->anp_subaddr.address_format ==
309                                 T_ATM_ENDSYS_ADDR)) {
310                 errno = EINVAL;
311                 goto if_ready_fail;
312         }
313
314         /*
315          * Find the selector byte value for the interface
316          */
317         for (i=0; i<strlen(aip->ai_intf); i++) {
318                 if (aip->ai_intf[i] >= '0' &&
319                                 aip->ai_intf[i] <= '9')
320                         break;
321         }
322         sel = atoi(&aip->ai_intf[i]);
323
324         /*
325          * Make sure we're the server for this interface's LIS
326          */
327         if (!atmarp_is_server(aip)) {
328                 rc = EINVAL;
329                 goto if_ready_fail;
330         }
331
332         /*
333          * If we already have the interface active and the address
334          * hasn't changed, return
335          */
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)) {
345                 return(1);
346         }
347
348         /*
349          * Delete any existing ATMARP cache entry for this interface
350          */
351         ATMARP_LOOKUP(aip, aip->ai_ip_addr.s_addr, aap);
352         if (aap) {
353                 ATMARP_DELETE(aip, aap);
354                 UM_FREE(aap);
355         }
356
357         /*
358          * Update the interface entry
359          */
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,
365                         &aip->ai_atm_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) {
370                 anp->aan_sel = sel;
371         } else if (aip->ai_atm_addr.address_format ==
372                                 T_ATM_E164_ADDR &&
373                         aip->ai_atm_subaddr.address_format ==
374                                 T_ATM_ENDSYS_ADDR) {
375                 anp->aan_sel = sel;
376         }
377
378         /*
379          * Get a new ATMARP cache for the interface
380          */
381         aap = (Atmarp *)UM_ALLOC(sizeof(Atmarp));
382         if (!aap) {
383                 atmarp_mem_err("atmarp_if_ready: sizeof(Atmarp)");
384         }
385         UM_ZERO(aap, sizeof(Atmarp));
386         
387         /*
388          * Fill out the entry
389          */
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,
393                         &aap->aa_dstatmsub);
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,
400                         SCSP_ATMARP_ID_LEN);
401         aap->aa_intf = aip;
402         aap->aa_flags = AAF_SERVER;
403         aap->aa_origin = UAO_LOCAL;
404
405         /*
406          * Add the entry to the cache
407          */
408         ATMARP_ADD(aip, aap);
409         
410         /*
411          * Free dynamic data
412          */
413         UM_FREE(netif_rsp);
414         UM_FREE(intf_rsp);
415
416         return(1);
417
418 if_ready_fail:
419         if (netif_rsp)
420                 UM_FREE(netif_rsp);
421         if (intf_rsp)
422                 UM_FREE(intf_rsp);
423
424         return(0);
425 }
426
427
428 /*
429  * Copy an ATMARP cache entry from kernel format into an entry
430  * suitable for our cache
431  *
432  * Arguments:
433  *      cp      pointer to kernel entry
434  *
435  * Returns:
436  *      pointer to a new cache entry
437  *      0       error
438  *
439  */
440 Atmarp *
441 atmarp_copy_cache_entry(cp)
442         struct air_arp_rsp      *cp;
443
444 {
445         struct sockaddr_in      *ipp;
446         Atmarp_intf             *aip;
447         Atmarp                  *aap;
448
449         /*
450          * Sanity checks
451          */
452         if (!cp)
453                 return((Atmarp *)0);
454         aip = atmarp_find_intf_name(cp->aap_intf);
455         if (!aip)
456                 return((Atmarp *)0);
457
458         /*
459          * Get a new cache entry
460          */
461         aap = (Atmarp *)UM_ALLOC(sizeof(Atmarp));
462         if (!aap) {
463                 errno = ENOMEM;
464                 return((Atmarp *)0);
465         }
466         UM_ZERO(aap, sizeof(Atmarp));
467         aap->aa_intf = aip;
468
469         /*
470          * Copy fields from the kernel entry to the new entry
471          */
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;
480
481         /*
482          * Set up fields for SCSP
483          */
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,
489                         SCSP_ATMARP_ID_LEN);
490         aap->aa_seq = SCSP_CSA_SEQ_MIN;
491
492         return(aap);
493 }
494
495
496 /*
497  * Send an updated ATMARP cache entry to the kernel
498  *
499  * Arguments:
500  *      aap     pointer to updated entry
501  *
502  * Returns:
503  *      0       success
504  *      errno   reason for failure
505  *
506  */
507 int
508 atmarp_update_kernel(aap)
509         Atmarp  *aap;
510 {
511         int                     rc = 0, sd;
512         struct atmaddreq        aar;
513         struct sockaddr_in      *ipp;
514
515         /*
516          * Build ioctl request
517          */
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);
528 #endif
529         ipp->sin_addr = aap->aa_dstip;
530         
531         /*
532          * Pass the new mapping to the kernel
533          */
534         sd = socket(AF_ATM, SOCK_DGRAM, 0);
535         if (sd < 0) {
536                 return(errno);
537         }
538         if (ioctl(sd, AIOCADD, (caddr_t)&aar) < 0) {
539                 rc = errno;
540         }
541
542         (void)close(sd);
543         return(rc);
544 }
545
546
547 /*
548  * Read the ATMARP cache from the kernel and scan it, processing
549  * all entries
550  *
551  * Arguments:
552  *      none
553  *
554  * Returns:
555  *      none
556  *
557  */
558 void
559 atmarp_get_updated_cache()
560 {
561         int                     i, len, rc;
562         struct atminfreq        air;
563         struct air_arp_rsp      *cp;
564         struct sockaddr_in      *ipp;
565         Atmarp_intf             *aip;
566         Atmarp                  *aap;
567
568         /*
569          * Set up the request
570          */
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);
576 #endif
577         ipp->sin_family = AF_INET;
578         ipp->sin_addr.s_addr = INADDR_ANY;
579
580         /*
581          * Issue an ATMARP information request IOCTL
582          */
583         len = do_info_ioctl(&air, sizeof(struct air_arp_rsp) * 200);
584         if (len < 0) {
585                 return;
586         }
587
588         /*
589          * Clear marks on all our cache entries
590          */
591         atmarp_clear_marks();
592
593         /*
594          * Loop through the cache, processing each entry
595          */
596         for (cp = (struct air_arp_rsp *) air.air_buf_addr;
597                         len > 0;
598                         cp++, len -= sizeof(struct air_arp_rsp)) {
599                 atmarp_process_cache_entry(cp);
600         }
601
602         /*
603          * Now delete any old entries that aren't in the kernel's
604          * cache any more
605          */
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) {
610                                 /*
611                                  * Don't delete the entry for the server
612                                  */
613                                 if (aap->aa_flags & AAF_SERVER)
614                                         continue;
615                                 /*
616                                  * Delete any entry that isn't marked
617                                  */
618                                 if (!aap->aa_mark) {
619                                         rc = atmarp_scsp_update(aap,
620                                                 SCSP_ASTATE_DEL);
621                                         if (rc == 0)
622                                                 ATMARP_DELETE(aip, aap);
623                                 }
624                         }
625                 }
626         }
627
628         /*
629          * Free the ioctl response
630          */
631         UM_FREE(air.air_buf_addr);
632 }
633
634
635 /*
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.
640  *
641  * Arguments:
642  *      cp      pointer to kernel's cache entry
643  *
644  * Returns:
645  *      none
646  *
647  */
648 void
649 atmarp_process_cache_entry(cp)
650         struct air_arp_rsp      *cp;
651
652 {
653         int                     rc;
654         struct sockaddr_in      *ipp = (struct sockaddr_in *)&cp->aap_arp_addr;
655         Atmarp_intf             *aip;
656         Atmarp                  *aap;
657
658         /*
659          * See whether the entry is for an interface that's
660          * both configured and up
661          */
662         aip = atmarp_find_intf_name(cp->aap_intf);
663         if (!aip || aip->ai_state != AI_STATE_UP)
664                 return;
665
666         /*
667          * Make sure the entry is valid
668          */
669         if (!(cp->aap_flags & ARPF_VALID))
670                 return;
671
672         /*
673          * See whether we have the entry in our cache already
674          */
675         ATMARP_LOOKUP(aip, ipp->sin_addr.s_addr, aap);
676         if (aap) {
677                 /*
678                  * We already have this in our cache--update it
679                  */
680                 aap->aa_mark = 1;
681                 if ((cp->aap_flags & ARPF_REFRESH) &&
682                                 cp->aap_origin != UAO_SCSP) {
683                         aap->aa_seq++;
684                         rc = atmarp_scsp_update(aap, SCSP_ASTATE_UPD);
685                 }
686         } else {
687                 /*
688                  * This is a new entry--add it to the cache
689                  */
690                 aap = atmarp_copy_cache_entry(cp);
691                 if (!aap)
692                         return;
693                 ATMARP_ADD(aip, aap);
694                 aap->aa_mark = 1;
695                 rc = atmarp_scsp_update(aap, SCSP_ASTATE_NEW);
696         }
697
698         return;
699 }
700
701
702 /*
703  * Print an SCSP ID
704  *
705  * Arguments:
706  *      df      pointer to a FILE for the dump
707  *      ip      pointer to the SCSP ID to print
708  *
709  * Returns:
710  *      None
711  *
712  */
713 static void
714 print_scsp_id(df, ip)
715         FILE    *df;
716         Scsp_id *ip;
717 {
718         int     i;
719
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]);
725         }
726         fprintf(df, "\n");
727 }
728
729
730 /*
731  * Print an SCSP cacke key
732  *
733  * Arguments:
734  *      df      pointer to a FILE for the dump
735  *      cp      pointer to the cacke key to print
736  *
737  * Returns:
738  *      None
739  *
740  */
741 static void
742 print_scsp_cache_key(df, cp)
743         FILE            *df;
744         Scsp_ckey       *cp;
745 {
746         int     i;
747
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]);
752         }
753         fprintf(df, "\n");
754 }
755
756
757 /*
758  * Print an ATMARP interface entry
759  *
760  * Arguments:
761  *      df      pointer to a FILE for the dump
762  *      aip     pointer to interface entry
763  *
764  * Returns:
765  *      None
766  *
767  */
768 void
769 print_atmarp_intf(df, aip)
770         FILE            *df;
771         Atmarp_intf     *aip;
772 {
773         if (!aip) {
774                 fprintf(df, "print_atmarp_intf: NULL interface entry address\n");
775                 return;
776         }
777
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);
794 }
795
796
797 /*
798  * Print an ATMARP cache entry
799  *
800  * Arguments:
801  *      df      pointer to a FILE for the dump
802  *      aap     pointer to cache entry
803  *
804  * Returns:
805  *      None
806  *
807  */
808 void
809 print_atmarp_cache(df, aap)
810         FILE    *df;
811         Atmarp  *aap;
812 {
813         if (!aap) {
814                 fprintf(df, "print_atmarp_cache: NULL ATMARP entry address\n");
815                 return;
816         }
817
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,
830                         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 ");
837         fprintf(df, "\n");
838         fprintf(df, "\taa_origin:    %d\n", aap->aa_origin);
839         fprintf(df, "\taa_mark:      %d\n", aap->aa_mark);
840 }
841
842
843 /*
844  * Print the entire ATMARP cache
845  *
846  * Arguments:
847  *      df      pointer to a FILE for the dump
848  *      aip     pointer to interface whose cache is to be printed
849  *
850  * Returns:
851  *      None
852  *
853  */
854 void
855 dump_atmarp_cache(df, aip)
856         FILE            *df;
857         Atmarp_intf     *aip;
858 {
859         int     i;
860         Atmarp  *aap;
861
862         if (!aip) {
863                 fprintf(df, "dump_atmarp_cache: NULL interface address\n");
864                 return;
865         }
866
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);
871                 }
872         }
873 }
874
875
876 #ifdef NOTDEF
877 /*
878  * Print an ATMARP super-LIS entry
879  *
880  * Arguments:
881  *      df      pointer to a FILE for the dump
882  *      asp     pointer to super-LIS entry to be printed
883  *
884  * Returns:
885  *      None
886  *
887  */
888 void
889 print_atmarp_slis(df, asp)
890         FILE            *df;
891         Atmarp_slis     *asp;
892 {
893         Atmarp_intf     **aipp;
894
895         if (!asp) {
896                 fprintf(df, "print_atmarp_slis: NULL SLIS address\n");
897                 return;
898         }
899
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,
906                                 (*aipp)->ai_intf);
907         }
908 }
909 #endif
910
911
912 /*
913  * Dump ATMARPD information
914  *
915  * Called as the result of a SIGINT signal.
916  *
917  * Arguments:
918  *      sig     signal number
919  *
920  * Returns:
921  *      None
922  *
923  */
924 void
925 atmarp_sigint(sig)
926         int                     sig;
927 {
928         Atmarp_intf     *aip;
929         FILE            *df;
930         char            fname[64];
931         static int      dump_no = 0;
932
933         /*
934          * Build a file name
935          */
936         UM_ZERO(fname, sizeof(fname));
937         sprintf(fname, "/tmp/atmarpd.%d.%03d.out", getpid(), dump_no++);
938
939         /*
940          * Open the output file
941          */
942         df = fopen(fname, "w");
943         if (df == (FILE *)0)
944                 return;
945
946         /*
947          * Dump the interface control blocks and
948          * associated ATMARP caches
949          */
950         for (aip = atmarp_intf_head; aip; aip = aip->ai_next) {
951                 print_atmarp_intf(df, aip);
952                 fprintf(df, "\n");
953                 dump_atmarp_cache(df, aip);
954                 fprintf(df, "\n");
955         }
956
957         /*
958          * Close the output file
959          */
960         (void)fclose(df);
961 }