Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[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  *      @(#) $DragonFly: src/usr.sbin/atm/atmarpd/atmarp_subr.c,v 1.2 2003/06/17 04:29:52 dillon Exp $
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 /*
71  * Find an ATMARP interface, given its socket number
72  *
73  * Arguments:
74  *      sd      socket descriptor
75  *
76  * Returns:
77  *      0       failure
78  *      else    pointer to interface associated with socket
79  *
80  */
81 Atmarp_intf *
82 atmarp_find_intf_sock(sd)
83         int     sd;
84 {
85         Atmarp_intf     *aip;
86
87         /*
88          * Loop through the list of interfaces
89          */
90         for (aip = atmarp_intf_head; aip; aip = aip->ai_next) {
91                 if (aip->ai_scsp_sock == sd)
92                         break;
93         }
94
95         return(aip);
96 }
97
98
99 /*
100  * Find an ATMARP interface, given its name
101  *
102  * Arguments:
103  *      name    pointer to network interface name
104  *
105  * Returns:
106  *      0       failure
107  *      else    pointer to interface associated with name
108  *
109  */
110 Atmarp_intf *
111 atmarp_find_intf_name(name)
112         char    *name;
113 {
114         Atmarp_intf     *aip;
115
116         /*
117          * Loop through the list of interfaces
118          */
119         for (aip = atmarp_intf_head; aip; aip = aip->ai_next) {
120                 if (strcmp(name, aip->ai_intf) == 0)
121                         break;
122         }
123
124         return(aip);
125 }
126
127
128 /*
129  * Clear the mark field on all ATMARP cache entries
130  *
131  * Arguments:
132  *      none
133  *
134  * Returns:
135  *      none
136  *
137  */
138 void
139 atmarp_clear_marks()
140
141 {
142         int             i;
143         Atmarp_intf     *aip;
144         Atmarp          *aap;
145
146         /*
147          * Loop through list of interfaces
148          */
149         for (aip = atmarp_intf_head; aip; aip = aip->ai_next) {
150                 /*
151                  * Clear mark on every entry in the interface's cache
152                  */
153                 for (i = 0; i < ATMARP_HASHSIZ; i++ ) {
154                         for (aap = aip->ai_arptbl[i]; aap;
155                                         aap = aap->aa_next) {
156                                 aap->aa_mark = 0;
157                         }
158                 }
159         }
160 }
161
162
163 /*
164  * Check whether the host system is an ATMARP server for
165  * the LIS associated with a given interface
166  *
167  * Arguments:
168  *      aip     pointer to an ATMARP interface control block
169  *
170  * Returns:
171  *      1       host is a server
172  *      0       host is not a server
173  *
174  */
175 int
176 atmarp_is_server(aip)
177         Atmarp_intf     *aip;
178 {
179         int                     rc;
180         int                     buf_len = sizeof(struct air_asrv_rsp);
181         struct atminfreq        air;
182         struct air_asrv_rsp     *asrv_info;
183
184         /*
185          * Get interface information from the kernel
186          */
187         strcpy(air.air_int_intf, aip->ai_intf);
188         air.air_opcode = AIOCS_INF_ASV;
189         buf_len = do_info_ioctl(&air, buf_len);
190         if (buf_len < 0)
191                 return(0);
192
193         /*
194          * Check the interface's ATMARP server address
195          */
196         asrv_info = (struct air_asrv_rsp *) air.air_buf_addr;
197         rc = (asrv_info->asp_addr.address_format == T_ATM_ABSENT) &&
198                         (asrv_info->asp_subaddr.address_format ==
199                                 T_ATM_ABSENT);
200         UM_FREE(asrv_info);
201         return(rc);
202 }
203
204
205 /*
206  * Check whether an interface is up and ready for service
207  *
208  * Arguments:
209  *      aip     pointer to network interface block
210  *
211  * Returns:
212  *      0       interface not ready, errno has reason
213  *      1       interface is ready to go (interface block is updated)
214  *
215  */
216 int
217 atmarp_if_ready(aip)
218         Atmarp_intf     *aip;
219 {
220         int                     i, len, mtu, rc, sel;
221         Atmarp                  *aap = (Atmarp *)0;
222         struct atminfreq        air;
223         struct air_netif_rsp    *netif_rsp = (struct air_netif_rsp *)0;
224         struct air_int_rsp      *intf_rsp = (struct air_int_rsp *)0;
225         struct sockaddr_in      *ip_addr;
226         struct sockaddr_in      subnet_mask;
227         Atm_addr_nsap           *anp;
228
229         /*
230          * Get the IP address and physical interface name
231          * associated with the network interface
232          */
233         UM_ZERO(&air, sizeof(struct atminfreq));
234         air.air_opcode = AIOCS_INF_NIF;
235         strcpy(air.air_netif_intf, aip->ai_intf);
236         len = do_info_ioctl(&air, sizeof(struct air_netif_rsp));
237         if (len <= 0) {
238                 goto if_ready_fail;
239         }
240         netif_rsp = (struct air_netif_rsp *)air.air_buf_addr;
241
242         ip_addr = (struct sockaddr_in *)&netif_rsp->anp_proto_addr;
243         if (ip_addr->sin_family != AF_INET ||
244                         ip_addr->sin_addr.s_addr == 0) {
245                 errno = EAFNOSUPPORT;
246                 goto if_ready_fail;
247         }
248
249         /*
250          * Get the MTU for the network interface
251          */
252         mtu = get_mtu(aip->ai_intf);
253         if (mtu < 0) {
254                 goto if_ready_fail;
255         }
256
257
258         /*
259          * Get the subnet mask associated with the
260          * network interface
261          */
262         rc = get_subnet_mask(aip->ai_intf, &subnet_mask);
263         if (rc || subnet_mask.sin_family != AF_INET) {
264                 goto if_ready_fail;
265         }
266
267         /*
268          * Get physical interface information
269          */
270         UM_ZERO(&air, sizeof(struct atminfreq));
271         air.air_opcode = AIOCS_INF_INT;
272         strcpy(air.air_int_intf, netif_rsp->anp_phy_intf);
273         len = do_info_ioctl(&air, sizeof(struct air_int_rsp));
274         if (len <= 0) {
275                 goto if_ready_fail;
276         }
277         intf_rsp = (struct air_int_rsp *)air.air_buf_addr;
278
279         /*
280          * Check the signalling manager
281          */
282         if (intf_rsp->anp_sig_proto != ATM_SIG_UNI30 &&
283                         intf_rsp->anp_sig_proto != ATM_SIG_UNI31 &&
284                         intf_rsp->anp_sig_proto != ATM_SIG_UNI40) {
285                 errno = EINVAL;
286                 goto if_ready_fail;
287         }
288
289         /*
290          * Check the interface state
291          */
292         if (intf_rsp->anp_sig_state != UNISIG_ACTIVE) {
293                 errno = EINVAL;
294                 goto if_ready_fail;
295         }
296
297         /*
298          * Check the address format
299          */
300         if (intf_rsp->anp_addr.address_format != T_ATM_ENDSYS_ADDR &&
301                         !(intf_rsp->anp_addr.address_format ==
302                                 T_ATM_E164_ADDR &&
303                         intf_rsp->anp_subaddr.address_format ==
304                                 T_ATM_ENDSYS_ADDR)) {
305                 errno = EINVAL;
306                 goto if_ready_fail;
307         }
308
309         /*
310          * Find the selector byte value for the interface
311          */
312         for (i=0; i<strlen(aip->ai_intf); i++) {
313                 if (aip->ai_intf[i] >= '0' &&
314                                 aip->ai_intf[i] <= '9')
315                         break;
316         }
317         sel = atoi(&aip->ai_intf[i]);
318
319         /*
320          * Make sure we're the server for this interface's LIS
321          */
322         if (!atmarp_is_server(aip)) {
323                 rc = EINVAL;
324                 goto if_ready_fail;
325         }
326
327         /*
328          * If we already have the interface active and the address
329          * hasn't changed, return
330          */
331         if (aip->ai_state != AI_STATE_NULL &&
332                         bcmp((caddr_t) &((struct sockaddr_in *)
333                                 &netif_rsp->anp_proto_addr)->sin_addr,
334                                 (caddr_t)&aip->ai_ip_addr,
335                                 sizeof(aip->ai_ip_addr)) == 0 &&
336                         ATM_ADDR_EQUAL(&intf_rsp->anp_addr,
337                                 &aip->ai_atm_addr) &&
338                         ATM_ADDR_EQUAL(&intf_rsp->anp_subaddr,
339                                 &aip->ai_atm_subaddr)) {
340                 return(1);
341         }
342
343         /*
344          * Delete any existing ATMARP cache entry for this interface
345          */
346         ATMARP_LOOKUP(aip, aip->ai_ip_addr.s_addr, aap);
347         if (aap) {
348                 ATMARP_DELETE(aip, aap);
349                 UM_FREE(aap);
350         }
351
352         /*
353          * Update the interface entry
354          */
355         aip->ai_ip_addr = ((struct sockaddr_in *)
356                         &netif_rsp->anp_proto_addr)->sin_addr;
357         aip->ai_subnet_mask = subnet_mask.sin_addr;
358         aip->ai_mtu = mtu + 8;
359         ATM_ADDR_COPY(&intf_rsp->anp_addr,
360                         &aip->ai_atm_addr);
361         ATM_ADDR_COPY(&intf_rsp->anp_subaddr,
362                         &aip->ai_atm_subaddr);
363         anp = (Atm_addr_nsap *)aip->ai_atm_addr.address;
364         if (aip->ai_atm_addr.address_format == T_ATM_ENDSYS_ADDR) {
365                 anp->aan_sel = sel;
366         } else if (aip->ai_atm_addr.address_format ==
367                                 T_ATM_E164_ADDR &&
368                         aip->ai_atm_subaddr.address_format ==
369                                 T_ATM_ENDSYS_ADDR) {
370                 anp->aan_sel = sel;
371         }
372
373         /*
374          * Get a new ATMARP cache for the interface
375          */
376         aap = (Atmarp *)UM_ALLOC(sizeof(Atmarp));
377         if (!aap) {
378                 atmarp_mem_err("atmarp_if_ready: sizeof(Atmarp)");
379         }
380         UM_ZERO(aap, sizeof(Atmarp));
381         
382         /*
383          * Fill out the entry
384          */
385         aap->aa_dstip = aip->ai_ip_addr;
386         ATM_ADDR_COPY(&intf_rsp->anp_addr, &aap->aa_dstatm);
387         ATM_ADDR_COPY(&intf_rsp->anp_subaddr,
388                         &aap->aa_dstatmsub);
389         aap->aa_key.key_len = SCSP_ATMARP_KEY_LEN;
390         scsp_cache_key(&aap->aa_dstatm, &aap->aa_dstip,
391                         SCSP_ATMARP_KEY_LEN, aap->aa_key.key);
392         aap->aa_oid.id_len = SCSP_ATMARP_ID_LEN;
393         aap->aa_seq = SCSP_CSA_SEQ_MIN;
394         UM_COPY(&aap->aa_dstip.s_addr, aap->aa_oid.id,
395                         SCSP_ATMARP_ID_LEN);
396         aap->aa_intf = aip;
397         aap->aa_flags = AAF_SERVER;
398         aap->aa_origin = UAO_LOCAL;
399
400         /*
401          * Add the entry to the cache
402          */
403         ATMARP_ADD(aip, aap);
404         
405         /*
406          * Free dynamic data
407          */
408         UM_FREE(netif_rsp);
409         UM_FREE(intf_rsp);
410
411         return(1);
412
413 if_ready_fail:
414         if (netif_rsp)
415                 UM_FREE(netif_rsp);
416         if (intf_rsp)
417                 UM_FREE(intf_rsp);
418
419         return(0);
420 }
421
422
423 /*
424  * Copy an ATMARP cache entry from kernel format into an entry
425  * suitable for our cache
426  *
427  * Arguments:
428  *      cp      pointer to kernel entry
429  *
430  * Returns:
431  *      pointer to a new cache entry
432  *      0       error
433  *
434  */
435 Atmarp *
436 atmarp_copy_cache_entry(cp)
437         struct air_arp_rsp      *cp;
438
439 {
440         struct sockaddr_in      *ipp;
441         Atmarp_intf             *aip;
442         Atmarp                  *aap;
443
444         /*
445          * Sanity checks
446          */
447         if (!cp)
448                 return((Atmarp *)0);
449         aip = atmarp_find_intf_name(cp->aap_intf);
450         if (!aip)
451                 return((Atmarp *)0);
452
453         /*
454          * Get a new cache entry
455          */
456         aap = (Atmarp *)UM_ALLOC(sizeof(Atmarp));
457         if (!aap) {
458                 errno = ENOMEM;
459                 return((Atmarp *)0);
460         }
461         UM_ZERO(aap, sizeof(Atmarp));
462         aap->aa_intf = aip;
463
464         /*
465          * Copy fields from the kernel entry to the new entry
466          */
467         ipp = (struct sockaddr_in *)&cp->aap_arp_addr;
468         UM_COPY(&ipp->sin_addr.s_addr, &aap->aa_dstip.s_addr,
469                         sizeof(aap->aa_dstip.s_addr));
470         ATM_ADDR_COPY(&cp->aap_addr, &aap->aa_dstatm);
471         ATM_ADDR_COPY(&cp->aap_subaddr, &aap->aa_dstatmsub);
472         if (cp->aap_origin == UAO_PERM)
473                 aap->aa_flags |= AAF_PERM;
474         aap->aa_origin = cp->aap_origin;
475
476         /*
477          * Set up fields for SCSP
478          */
479         aap->aa_key.key_len = SCSP_ATMARP_KEY_LEN;
480         scsp_cache_key(&cp->aap_addr, &aap->aa_dstip,
481                         SCSP_ATMARP_KEY_LEN, (char *)aap->aa_key.key);
482         aap->aa_oid.id_len = SCSP_ATMARP_ID_LEN;
483         UM_COPY(&aip->ai_ip_addr.s_addr, aap->aa_oid.id,
484                         SCSP_ATMARP_ID_LEN);
485         aap->aa_seq = SCSP_CSA_SEQ_MIN;
486
487         return(aap);
488 }
489
490
491 /*
492  * Send an updated ATMARP cache entry to the kernel
493  *
494  * Arguments:
495  *      aap     pointer to updated entry
496  *
497  * Returns:
498  *      0       success
499  *      errno   reason for failure
500  *
501  */
502 int
503 atmarp_update_kernel(aap)
504         Atmarp  *aap;
505 {
506         int                     rc = 0, sd;
507         struct atmaddreq        aar;
508         struct sockaddr_in      *ipp;
509
510         /*
511          * Build ioctl request
512          */
513         UM_ZERO(&aar, sizeof(aar));
514         aar.aar_opcode = AIOCS_ADD_ARP;
515         strncpy(aar.aar_arp_intf, aap->aa_intf->ai_intf,
516                         sizeof(aar.aar_arp_intf));
517         aar.aar_arp_origin = UAO_SCSP;
518         ATM_ADDR_COPY(&aap->aa_dstatm, &aar.aar_arp_addr);
519         ipp = (struct sockaddr_in *)&aar.aar_arp_dst;
520         ipp->sin_family = AF_INET;
521 #if (defined(BSD) && (BSD >= 199103))
522         ipp->sin_len = sizeof(struct sockaddr_in);
523 #endif
524         ipp->sin_addr = aap->aa_dstip;
525         
526         /*
527          * Pass the new mapping to the kernel
528          */
529         sd = socket(AF_ATM, SOCK_DGRAM, 0);
530         if (sd < 0) {
531                 return(errno);
532         }
533         if (ioctl(sd, AIOCADD, (caddr_t)&aar) < 0) {
534                 rc = errno;
535         }
536
537         (void)close(sd);
538         return(rc);
539 }
540
541
542 /*
543  * Read the ATMARP cache from the kernel and scan it, processing
544  * all entries
545  *
546  * Arguments:
547  *      none
548  *
549  * Returns:
550  *      none
551  *
552  */
553 void
554 atmarp_get_updated_cache()
555 {
556         int                     i, len, rc;
557         struct atminfreq        air;
558         struct air_arp_rsp      *cp;
559         struct sockaddr_in      *ipp;
560         Atmarp_intf             *aip;
561         Atmarp                  *aap;
562
563         /*
564          * Set up the request
565          */
566         air.air_opcode = AIOCS_INF_ARP;
567         air.air_arp_flags = ARP_RESET_REF;
568         ipp = (struct sockaddr_in *)&air.air_arp_addr;
569 #if (defined(BSD) && (BSD >= 199103))
570         ipp->sin_len = sizeof(struct sockaddr_in);
571 #endif
572         ipp->sin_family = AF_INET;
573         ipp->sin_addr.s_addr = INADDR_ANY;
574
575         /*
576          * Issue an ATMARP information request IOCTL
577          */
578         len = do_info_ioctl(&air, sizeof(struct air_arp_rsp) * 200);
579         if (len < 0) {
580                 return;
581         }
582
583         /*
584          * Clear marks on all our cache entries
585          */
586         atmarp_clear_marks();
587
588         /*
589          * Loop through the cache, processing each entry
590          */
591         for (cp = (struct air_arp_rsp *) air.air_buf_addr;
592                         len > 0;
593                         cp++, len -= sizeof(struct air_arp_rsp)) {
594                 atmarp_process_cache_entry(cp);
595         }
596
597         /*
598          * Now delete any old entries that aren't in the kernel's
599          * cache any more
600          */
601         for (aip = atmarp_intf_head; aip; aip = aip->ai_next) {
602                 for (i = 0; i < ATMARP_HASHSIZ; i++) {
603                         for (aap = aip->ai_arptbl[i]; aap;
604                                         aap = aap->aa_next) {
605                                 /*
606                                  * Don't delete the entry for the server
607                                  */
608                                 if (aap->aa_flags & AAF_SERVER)
609                                         continue;
610                                 /*
611                                  * Delete any entry that isn't marked
612                                  */
613                                 if (!aap->aa_mark) {
614                                         rc = atmarp_scsp_update(aap,
615                                                 SCSP_ASTATE_DEL);
616                                         if (rc == 0)
617                                                 ATMARP_DELETE(aip, aap);
618                                 }
619                         }
620                 }
621         }
622
623         /*
624          * Free the ioctl response
625          */
626         UM_FREE(air.air_buf_addr);
627 }
628
629
630 /*
631  * Process an ATMARP cache entry from the kernel.  If we already
632  * have the entry in our local cache, update it, otherwise, add
633  * it.  In either case, mark our local copy so we know it's still
634  * in the kernel's cache.
635  *
636  * Arguments:
637  *      cp      pointer to kernel's cache entry
638  *
639  * Returns:
640  *      none
641  *
642  */
643 void
644 atmarp_process_cache_entry(cp)
645         struct air_arp_rsp      *cp;
646
647 {
648         int                     rc;
649         struct sockaddr_in      *ipp = (struct sockaddr_in *)&cp->aap_arp_addr;
650         Atmarp_intf             *aip;
651         Atmarp                  *aap;
652
653         /*
654          * See whether the entry is for an interface that's
655          * both configured and up
656          */
657         aip = atmarp_find_intf_name(cp->aap_intf);
658         if (!aip || aip->ai_state != AI_STATE_UP)
659                 return;
660
661         /*
662          * Make sure the entry is valid
663          */
664         if (!(cp->aap_flags & ARPF_VALID))
665                 return;
666
667         /*
668          * See whether we have the entry in our cache already
669          */
670         ATMARP_LOOKUP(aip, ipp->sin_addr.s_addr, aap);
671         if (aap) {
672                 /*
673                  * We already have this in our cache--update it
674                  */
675                 aap->aa_mark = 1;
676                 if ((cp->aap_flags & ARPF_REFRESH) &&
677                                 cp->aap_origin != UAO_SCSP) {
678                         aap->aa_seq++;
679                         rc = atmarp_scsp_update(aap, SCSP_ASTATE_UPD);
680                 }
681         } else {
682                 /*
683                  * This is a new entry--add it to the cache
684                  */
685                 aap = atmarp_copy_cache_entry(cp);
686                 if (!aap)
687                         return;
688                 ATMARP_ADD(aip, aap);
689                 aap->aa_mark = 1;
690                 rc = atmarp_scsp_update(aap, SCSP_ASTATE_NEW);
691         }
692
693         return;
694 }
695
696
697 /*
698  * Print an SCSP ID
699  *
700  * Arguments:
701  *      df      pointer to a FILE for the dump
702  *      ip      pointer to the SCSP ID to print
703  *
704  * Returns:
705  *      None
706  *
707  */
708 static void
709 print_scsp_id(df, ip)
710         FILE    *df;
711         Scsp_id *ip;
712 {
713         int     i;
714
715         fprintf(df, "\t  next:            %p\n", ip->next);
716         fprintf(df, "\t  id_len:          %d\n", ip->id_len);
717         fprintf(df, "\t  id:              0x");
718         for (i = 0; i < ip->id_len; i++) {
719                 fprintf(df, "%0x ", ip->id[i]);
720         }
721         fprintf(df, "\n");
722 }
723
724
725 /*
726  * Print an SCSP cacke key
727  *
728  * Arguments:
729  *      df      pointer to a FILE for the dump
730  *      cp      pointer to the cacke key to print
731  *
732  * Returns:
733  *      None
734  *
735  */
736 static void
737 print_scsp_cache_key(df, cp)
738         FILE            *df;
739         Scsp_ckey       *cp;
740 {
741         int     i;
742
743         fprintf(df, "\t  key_len:         %d\n", cp->key_len);
744         fprintf(df, "\t  key:             0x");
745         for (i = 0; i < cp->key_len; i++) {
746                 fprintf(df, "%0x ", cp->key[i]);
747         }
748         fprintf(df, "\n");
749 }
750
751
752 /*
753  * Print an ATMARP interface entry
754  *
755  * Arguments:
756  *      df      pointer to a FILE for the dump
757  *      aip     pointer to interface entry
758  *
759  * Returns:
760  *      None
761  *
762  */
763 void
764 print_atmarp_intf(df, aip)
765         FILE            *df;
766         Atmarp_intf     *aip;
767 {
768         if (!aip) {
769                 fprintf(df, "print_atmarp_intf: NULL interface entry address\n");
770                 return;
771         }
772
773         fprintf(df, "ATMARP network interface entry at %p\n", aip);
774         fprintf(df, "\tai_next:           %p\n", aip->ai_next);
775         fprintf(df, "\tai_intf:           %s\n", aip->ai_intf);
776         fprintf(df, "\tai_ip_addr:        %s\n",
777                         format_ip_addr(&aip->ai_ip_addr));
778         fprintf(df, "\tai_subnet_mask:    %s\n",
779                         inet_ntoa(aip->ai_subnet_mask));
780         fprintf(df, "\tai_mtu:            %d\n", aip->ai_mtu);
781         fprintf(df, "\tai_atm_addr:       %s\n",
782                         format_atm_addr(&aip->ai_atm_addr));
783         fprintf(df, "\tai_atm_subaddr:    %s\n",
784                         format_atm_addr(&aip->ai_atm_subaddr));
785         fprintf(df, "\tai_scsp_sock:      %d\n", aip->ai_scsp_sock);
786         fprintf(df, "\tai_scsp_sockname:  %s\n", aip->ai_scsp_sockname);
787         fprintf(df, "\tai_state:          %d\n", aip->ai_state);
788         fprintf(df, "\tai_mark:           %d\n", aip->ai_mark);
789 }
790
791
792 /*
793  * Print an ATMARP cache entry
794  *
795  * Arguments:
796  *      df      pointer to a FILE for the dump
797  *      aap     pointer to cache entry
798  *
799  * Returns:
800  *      None
801  *
802  */
803 void
804 print_atmarp_cache(df, aap)
805         FILE    *df;
806         Atmarp  *aap;
807 {
808         if (!aap) {
809                 fprintf(df, "print_atmarp_cache: NULL ATMARP entry address\n");
810                 return;
811         }
812
813         fprintf(df, "ATMARP entry at %p\n", aap);
814         fprintf(df, "\taa_next:      %p\n", aap->aa_next);
815         fprintf(df, "\taa_dstip:     %s\n", inet_ntoa(aap->aa_dstip));
816         fprintf(df, "\taa_dstatm:    %s\n",
817                         format_atm_addr(&aap->aa_dstatm));
818         fprintf(df, "\taa_dstatmsub: %s\n",
819                         format_atm_addr(&aap->aa_dstatmsub));
820         fprintf(df, "\taa_key:\n");
821         print_scsp_cache_key(df, &aap->aa_key);
822         fprintf(df, "\taa_oid:\n");
823         print_scsp_id(df, &aap->aa_oid);
824         fprintf(df, "\taa_seq:       %ld (0x%lx)\n", aap->aa_seq,
825                         aap->aa_seq);
826         fprintf(df, "\taa_intf:      %p\n", aap->aa_intf);
827         fprintf(df, "\taa_flags:     ");
828         if (aap->aa_flags & AAF_PERM)
829                 fprintf(df, "Permanent ");
830         if (aap->aa_flags & AAF_SERVER)
831                 fprintf(df, "Server ");
832         fprintf(df, "\n");
833         fprintf(df, "\taa_origin:    %d\n", aap->aa_origin);
834         fprintf(df, "\taa_mark:      %d\n", aap->aa_mark);
835 }
836
837
838 /*
839  * Print the entire ATMARP cache
840  *
841  * Arguments:
842  *      df      pointer to a FILE for the dump
843  *      aip     pointer to interface whose cache is to be printed
844  *
845  * Returns:
846  *      None
847  *
848  */
849 void
850 dump_atmarp_cache(df, aip)
851         FILE            *df;
852         Atmarp_intf     *aip;
853 {
854         int     i;
855         Atmarp  *aap;
856
857         if (!aip) {
858                 fprintf(df, "dump_atmarp_cache: NULL interface address\n");
859                 return;
860         }
861
862         fprintf(df, "ATMARP cache for interface %s\n", aip->ai_intf);
863         for (i=0; i<ATMARP_HASHSIZ; i++) {
864                 for (aap=aip->ai_arptbl[i]; aap; aap=aap->aa_next) {
865                         print_atmarp_cache(df, aap);
866                 }
867         }
868 }
869
870
871 #ifdef NOTDEF
872 /*
873  * Print an ATMARP super-LIS entry
874  *
875  * Arguments:
876  *      df      pointer to a FILE for the dump
877  *      asp     pointer to super-LIS entry to be printed
878  *
879  * Returns:
880  *      None
881  *
882  */
883 void
884 print_atmarp_slis(df, asp)
885         FILE            *df;
886         Atmarp_slis     *asp;
887 {
888         Atmarp_intf     **aipp;
889
890         if (!asp) {
891                 fprintf(df, "print_atmarp_slis: NULL SLIS address\n");
892                 return;
893         }
894
895         fprintf(df, "SLIS entry at 0x%0x\n", (u_long)asp);
896         fprintf(df, "\tas_next:      0x%0x\n", (u_long)asp->as_next);
897         fprintf(df, "\tas_name:      %s\n", asp->as_name);
898         fprintf(df, "\tas_cnt:       %d\n", asp->as_cnt);
899         for (aipp = &asp->as_intfs; *aipp; aipp++) {
900                 fprintf(df, "\t%s (%s)\n", (*aipp)->ai_name,
901                                 (*aipp)->ai_intf);
902         }
903 }
904 #endif
905
906
907 /*
908  * Dump ATMARPD information
909  *
910  * Called as the result of a SIGINT signal.
911  *
912  * Arguments:
913  *      sig     signal number
914  *
915  * Returns:
916  *      None
917  *
918  */
919 void
920 atmarp_sigint(sig)
921         int                     sig;
922 {
923         Atmarp_intf     *aip;
924         FILE            *df;
925         char            fname[64];
926         static int      dump_no = 0;
927
928         /*
929          * Build a file name
930          */
931         UM_ZERO(fname, sizeof(fname));
932         sprintf(fname, "/tmp/atmarpd.%d.%03d.out", getpid(), dump_no++);
933
934         /*
935          * Open the output file
936          */
937         df = fopen(fname, "w");
938         if (df == (FILE *)0)
939                 return;
940
941         /*
942          * Dump the interface control blocks and
943          * associated ATMARP caches
944          */
945         for (aip = atmarp_intf_head; aip; aip = aip->ai_next) {
946                 print_atmarp_intf(df, aip);
947                 fprintf(df, "\n");
948                 dump_atmarp_cache(df, aip);
949                 fprintf(df, "\n");
950         }
951
952         /*
953          * Close the output file
954          */
955         (void)fclose(df);
956 }