]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sbin/atm/atm/atm_show.c
This commit was generated by cvs2svn to compensate for changes in r53660,
[FreeBSD/FreeBSD.git] / sbin / atm / atm / atm_show.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  * User configuration and display program
32  * --------------------------------------
33  *
34  * Routines for "show" subcommand
35  *
36  */
37
38 #include <sys/types.h>  
39 #include <sys/param.h>  
40 #include <sys/socket.h> 
41 #include <net/if.h>
42 #include <netinet/in.h>
43 #include <netatm/port.h>
44 #include <netatm/atm.h>
45 #include <netatm/atm_if.h> 
46 #include <netatm/atm_sap.h>
47 #include <netatm/atm_sys.h>
48 #include <netatm/atm_vc.h>
49 #include <netatm/atm_ioctl.h>
50
51 #include <errno.h>
52 #include <libatm.h>
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <string.h>
56
57 #include "atm.h"
58
59 #ifndef lint
60 __RCSID("@(#) $FreeBSD$");
61 #endif
62
63
64 /*
65  * Local functions
66  */
67 static int      vcc_compare __P((const void *, const void *));
68 static int      ip_vcc_compare __P((const void *, const void *));
69 static int      arp_compare __P((const void *, const void *));
70
71
72 /*
73  * Process show ARP command
74  * 
75  * Command format: 
76  *      atm show ARP [<ip-addr>]
77  *
78  * Arguments:
79  *      argc    number of remaining arguments to command
80  *      argv    pointer to remaining argument strings
81  *      cmdp    pointer to command description 
82  *
83  * Returns:
84  *      none
85  *
86  */
87 void
88 show_arp(argc, argv, cmdp)
89         int             argc;
90         char            **argv;
91         struct cmd      *cmdp;
92 {
93         int                     buf_len, arp_info_len;
94         struct atminfreq        air;
95         struct air_arp_rsp      *arp_info, *arp_info_base;
96         struct sockaddr_in      *sin;
97         union {
98                 struct sockaddr_in      sin;
99                 struct sockaddr         sa;
100         } host_addr;
101
102         /*
103          * Get IP address of specified host name
104          */
105         UM_ZERO(&host_addr, sizeof(host_addr));
106         host_addr.sa.sa_family = AF_INET;
107         if (argc) {
108                 sin = get_ip_addr(argv[0]);
109                 if (!sin) {
110                         fprintf(stderr, "%s: host \'%s\' not found\n",
111                                         prog, argv[0]);
112                         exit(1);
113                 }
114                 host_addr.sin.sin_addr.s_addr = sin->sin_addr.s_addr;
115         } else {
116                 host_addr.sin.sin_addr.s_addr = INADDR_ANY;
117         }
118
119         /*
120          * Get ARP information from the kernel
121          */
122         UM_ZERO(&air, sizeof(air));
123         buf_len = sizeof(struct air_arp_rsp) * 10;
124         air.air_opcode = AIOCS_INF_ARP;
125         air.air_arp_addr = host_addr.sa;
126         arp_info_len = do_info_ioctl(&air, buf_len);
127         if (arp_info_len < 0) {
128                 fprintf(stderr, "%s: ", prog);
129                 switch (errno) {
130                 case ENOPROTOOPT:
131                 case EOPNOTSUPP:
132                         perror("Internal error");
133                         break;
134                 case ENXIO:
135                         fprintf(stderr, "not an ATM device\n");
136                         break;
137                 default:
138                         perror("ioctl (AIOCINFO)");
139                         break;
140                 }
141                 exit(1);
142         }
143         arp_info_base = arp_info =
144                         (struct air_arp_rsp *) air.air_buf_addr;
145
146         /*
147          * Sort the ARP table
148          */
149         qsort((void *) arp_info,
150                         arp_info_len / sizeof(struct air_arp_rsp),
151                         sizeof(struct air_arp_rsp),
152                         arp_compare);
153
154         /*
155          * Print the relevant information
156          */
157         while (arp_info_len > 0) {
158                 print_arp_info(arp_info);
159                 arp_info++;
160                 arp_info_len -= sizeof(struct air_arp_rsp);
161         }
162
163         /*
164          * Release the information from the kernel
165          */
166         UM_FREE(arp_info_base);
167 }
168
169
170 /*
171  * Process show ATM ARP server command
172  * 
173  * Command format: 
174  *      atm show arpserver [<interface-name>]
175  *
176  * Arguments:
177  *      argc    number of remaining arguments to command
178  *      argv    pointer to remaining argument strings
179  *      cmdp    pointer to command description 
180  *
181  * Returns:
182  *      none
183  *
184  */
185 void
186 show_arpserv(argc, argv, cmdp)
187         int             argc;
188         char            **argv;
189         struct cmd      *cmdp;
190 {
191         int     asrv_info_len, buf_len = sizeof(struct air_asrv_rsp) * 3;
192         struct atminfreq        air;
193         struct air_asrv_rsp     *asrv_info, *asrv_info_base;
194
195         /*
196          * Validate interface name
197          */
198         UM_ZERO(air.air_int_intf, sizeof(air.air_int_intf));
199         if (argc) {
200                 if (strlen(argv[0]) > IFNAMSIZ - 1) {
201                         fprintf(stderr, "%s: Illegal interface name\n",
202                                         prog);
203                         exit(1);
204                 }
205                 strcpy(air.air_int_intf, argv[0]);
206                 argc--; argv++;
207         }
208
209         /*
210          * Get interface information from the kernel
211          */
212         air.air_opcode = AIOCS_INF_ASV;
213         buf_len = do_info_ioctl(&air, buf_len);
214         if (buf_len < 0) {
215                 fprintf(stderr, "%s: ", prog);
216                 switch (errno) {
217                 case ENOPROTOOPT:
218                 case EOPNOTSUPP:
219                         perror("Internal error");
220                         break;
221                 case ENXIO:
222                         fprintf(stderr, "%s is not an ATM device\n",
223                                         argv[0]);
224                         break;
225                 default:
226                         perror("ioctl (AIOCINFO)");
227                         break;
228                 }
229                 exit(1);
230         }
231
232         /*
233          * Print the interface information
234          */
235         asrv_info_base = asrv_info =
236                         (struct air_asrv_rsp *) air.air_buf_addr;
237         for (; buf_len >= sizeof(struct air_asrv_rsp);
238                         asrv_info = (struct air_asrv_rsp *)
239                                 ((u_long)asrv_info + asrv_info_len),
240                         buf_len -= asrv_info_len) {
241                 print_asrv_info(asrv_info);
242                 asrv_info_len = sizeof(struct air_asrv_rsp) +
243                                 asrv_info->asp_nprefix *
244                                 sizeof(struct in_addr) * 2;
245         }
246         UM_FREE(asrv_info_base);
247 }
248
249
250 /*
251  * Process show ATM adapter configuration command
252  * 
253  * Command format: 
254  *      atm show config [<interface-name>]
255  *
256  * Arguments:
257  *      argc    number of remaining arguments to command
258  *      argv    pointer to remaining argument strings
259  *      cmdp    pointer to command description 
260  *
261  * Returns:
262  *      none
263  *
264  */
265 void
266 show_config(argc, argv, cmdp)
267         int             argc;
268         char            **argv;
269         struct cmd      *cmdp;
270 {
271         int     buf_len = sizeof(struct air_asrv_rsp) * 3;
272         struct atminfreq        air;
273         struct air_cfg_rsp      *cfg_info, *cfg_info_base;
274
275         /*
276          * Validate interface name
277          */
278         UM_ZERO(air.air_cfg_intf, sizeof(air.air_cfg_intf));
279         if (argc) {
280                 if (strlen(argv[0]) > IFNAMSIZ - 1) {
281                         fprintf(stderr, "%s: Illegal interface name\n",
282                                         prog);
283                         exit(1);
284                 }
285                 strcpy(air.air_cfg_intf, argv[0]);
286                 argc--; argv++;
287         }
288
289         /*
290          * Get configuration information from the kernel
291          */
292         air.air_opcode = AIOCS_INF_CFG;
293         buf_len = do_info_ioctl(&air, buf_len);
294         if (buf_len < 0) {
295                 fprintf(stderr, "%s: ", prog);
296                 switch (errno) {
297                 case ENOPROTOOPT:
298                 case EOPNOTSUPP:
299                         perror("Internal error");
300                         break;
301                 case ENXIO:
302                         fprintf(stderr, "%s is not an ATM device\n",
303                                         argv[0]);
304                         break;
305                 default:
306                         perror("ioctl (AIOCINFO)");
307                         break;
308                 }
309                 exit(1);
310         }
311
312         /*
313          * Print the interface information
314          */
315         cfg_info_base = cfg_info =
316                         (struct air_cfg_rsp *) air.air_buf_addr;
317         for (; buf_len >= sizeof(struct air_cfg_rsp); cfg_info++,
318                         buf_len -= sizeof(struct air_cfg_rsp)) {
319                 print_cfg_info(cfg_info);
320         }
321         UM_FREE(cfg_info_base);
322 }
323
324
325 /*
326  * Process show interface command
327  * 
328  * Command format: 
329  *      atm show interface [<interface-name>]
330  *
331  * Arguments:
332  *      argc    number of remaining arguments to command
333  *      argv    pointer to remaining argument strings
334  *      cmdp    pointer to command description 
335  *
336  * Returns:
337  *      none
338  *
339  */
340 void
341 show_intf(argc, argv, cmdp)
342         int             argc;
343         char            **argv;
344         struct cmd      *cmdp;
345 {
346         int     buf_len = sizeof(struct air_int_rsp) * 3;
347         struct atminfreq        air;
348         struct air_int_rsp      *int_info, *int_info_base;
349
350         /*
351          * Validate interface name
352          */
353         UM_ZERO(&air, sizeof(air));
354         if (argc) {
355                 if (strlen(argv[0]) > IFNAMSIZ - 1) {
356                         fprintf(stderr, "%s: Illegal interface name\n",
357                                         prog);
358                         exit(1);
359                 }
360                 strcpy(air.air_int_intf, argv[0]);
361                 argc--; argv++;
362         }
363
364         /*
365          * Get interface information from the kernel
366          */
367         air.air_opcode = AIOCS_INF_INT;
368         buf_len = do_info_ioctl(&air, buf_len);
369         if (buf_len < 0) {
370                 fprintf(stderr, "%s: ", prog);
371                 switch (errno) {
372                 case ENOPROTOOPT:
373                 case EOPNOTSUPP:
374                         perror("Internal error");
375                         break;
376                 case ENXIO:
377                         fprintf(stderr, "%s is not an ATM device\n",
378                                         argv[0]);
379                         break;
380                 default:
381                         perror("ioctl (AIOCINFO)");
382                         break;
383                 }
384                 exit(1);
385         }
386
387         /*
388          * Print the interface information
389          */
390         int_info_base = int_info =
391                         (struct air_int_rsp *) air.air_buf_addr;
392         for (; buf_len >= sizeof(struct air_int_rsp); int_info++,
393                         buf_len -= sizeof(struct air_int_rsp)) {
394                 print_intf_info(int_info);
395         }
396         UM_FREE(int_info_base);
397 }
398
399
400 /*
401  * Process show IP VCCs command
402  * 
403  * Command format: 
404  *      atm show ipvcc [<ip-addr>]
405  *
406  * Arguments:
407  *      argc    number of remaining arguments to command
408  *      argv    pointer to remaining argument strings
409  *      cmdp    pointer to command description 
410  *
411  * Returns:
412  *      none
413  *
414  */
415 void
416 show_ip_vcc(argc, argv, cmdp)
417         int             argc;
418         char            **argv;
419         struct cmd      *cmdp;
420 {
421         int                     buf_len, ip_info_len, rc;
422         char                    *if_name = (char *)0;
423         struct atminfreq        air;
424         struct air_ip_vcc_rsp   *ip_info, *ip_info_base;
425         struct sockaddr_in      *sin;
426         union {
427                 struct sockaddr_in      sin;
428                 struct sockaddr         sa;
429         } host_addr;
430
431         /*
432          * First parameter can be a netif name, an IP host name, or
433          * an IP address.  Figure out which it is.
434          */
435         UM_ZERO(&host_addr, sizeof(host_addr));
436         host_addr.sa.sa_family = AF_INET;
437         if (argc) {
438                 rc = verify_nif_name(argv[0]);
439                 if (rc < 0) {
440                         /*
441                          * Error occured
442                          */
443                         fprintf(stderr, "%s: ", prog);
444                         switch (errno) {
445                         case ENOPROTOOPT:
446                         case EOPNOTSUPP:
447                                 perror("Internal error");
448                                 break;
449                         case ENXIO:
450                                 fprintf(stderr, "%s is not an ATM device\n",
451                                                 argv[0]);
452                                 break;
453                         default:
454                                 perror("ioctl (AIOCINFO)");
455                                 break;
456                         }
457                         exit(1);
458                 } else if (rc > 0) {
459                         /*
460                          * Parameter is a valid netif name
461                          */
462                         if_name = argv[0];
463                 } else {
464                         /*
465                          * Get IP address of specified host name
466                          */
467                         sin = get_ip_addr(argv[0]);
468                         host_addr.sin.sin_addr.s_addr =
469                                         sin->sin_addr.s_addr;
470                 }
471         } else {
472                 host_addr.sin.sin_addr.s_addr = INADDR_ANY;
473         }
474
475         /*
476          * Get IP map information from the kernel
477          */
478         buf_len = sizeof(struct air_ip_vcc_rsp) * 10;
479         air.air_opcode = AIOCS_INF_IPM;
480         air.air_ip_addr = host_addr.sa;
481         ip_info_len = do_info_ioctl(&air, buf_len);
482         if (ip_info_len < 0) {
483                 fprintf(stderr, "%s: ", prog);
484                 switch (errno) {
485                 case ENOPROTOOPT:
486                 case EOPNOTSUPP:
487                         perror("Internal error");
488                         break;
489                 case ENXIO:
490                         fprintf(stderr, "not an ATM device\n");
491                         break;
492                 default:
493                         perror("ioctl (AIOCINFO)");
494                         break;
495                 }
496                 exit(1);
497         }
498         ip_info_base = ip_info =
499                         (struct air_ip_vcc_rsp *) air.air_buf_addr;
500
501         /*
502          * Sort the information
503          */
504         qsort((void *) ip_info,
505                         ip_info_len / sizeof(struct air_ip_vcc_rsp),
506                         sizeof(struct air_ip_vcc_rsp),
507                         ip_vcc_compare);
508
509         /*
510          * Print the relevant information
511          */
512         while (ip_info_len>0) {
513                 if (!if_name || !strcmp(if_name, ip_info->aip_intf)) {
514                         print_ip_vcc_info(ip_info);
515                 }
516                 ip_info++;
517                 ip_info_len -= sizeof(struct air_ip_vcc_rsp);
518         }
519
520         /*
521          * Release the information from the kernel
522          */
523         UM_FREE(ip_info_base);
524
525 }
526
527
528 /*
529  * Process show network interface command
530  * 
531  * Command format: 
532  *      atm show netif [<netif>]
533  *
534  * Arguments:
535  *      argc    number of remaining arguments to command
536  *      argv    pointer to remaining argument strings
537  *      cmdp    pointer to command description 
538  *
539  * Returns:
540  *      none
541  *
542  */
543 void
544 show_netif(argc, argv, cmdp)
545         int             argc;
546         char            **argv;
547         struct cmd      *cmdp;
548 {
549         int     buf_len = sizeof(struct air_netif_rsp) * 3;
550         struct atminfreq        air;
551         struct air_netif_rsp    *int_info, *int_info_base;
552
553         /*
554          * Validate network interface name
555          */
556         UM_ZERO(air.air_int_intf, sizeof(air.air_int_intf));
557         if (argc) {
558                 if (strlen(argv[0]) > IFNAMSIZ - 1) {
559                         fprintf(stderr, "%s: Illegal interface name\n", prog);
560                         exit(1);
561                 }
562                 strcpy(air.air_int_intf, argv[0]);
563                 argc--; argv++;
564         }
565
566         /*
567          * Get network interface information from the kernel
568          */
569         air.air_opcode = AIOCS_INF_NIF;
570         buf_len = do_info_ioctl(&air, buf_len);
571         if (buf_len < 0) {
572                 fprintf(stderr, "%s: ", prog);
573                 switch (errno) {
574                 case ENOPROTOOPT:
575                 case EOPNOTSUPP:
576                         perror("Internal error");
577                         break;
578                 case ENXIO:
579                         fprintf(stderr, "%s is not an ATM device\n",
580                                         argv[0]);
581                         break;
582                 default:
583                         perror("ioctl (AIOCINFO)");
584                         break;
585                 }
586                 exit(1);
587         }
588
589         /*
590          * Print the network interface information
591          */
592         int_info_base = int_info =
593                         (struct air_netif_rsp *) air.air_buf_addr;
594         for (; buf_len >= sizeof(struct air_netif_rsp); int_info++,
595                         buf_len -= sizeof(struct air_netif_rsp)) {
596                 print_netif_info(int_info);
597         }
598         UM_FREE(int_info_base);
599 }
600
601
602 /*
603  * Process interface statistics command
604  * 
605  * Command format: 
606  *      atm show stats interface [<interface-name>]
607  *
608  * Arguments:
609  *      argc    number of remaining arguments to command
610  *      argv    pointer to remaining argument strings
611  *      cmdp    pointer to command description 
612  *
613  * Returns:
614  *      none
615  *
616  */
617 void
618 show_intf_stats(argc, argv, cmdp)
619         int             argc;
620         char            **argv;
621         struct cmd      *cmdp;
622 {
623         int                     buf_len;
624         char                    intf[IFNAMSIZ];
625         struct atminfreq        air;
626         struct air_phy_stat_rsp *pstat_info, *pstat_info_base;
627         struct air_cfg_rsp      *cfg_info;
628
629         /*
630          * Validate interface name
631          */
632         UM_ZERO(intf, sizeof(intf));
633         if (argc) {
634                 if (strlen(argv[0]) > IFNAMSIZ - 1) {
635                         fprintf(stderr, "%s: Illegal interface name\n",
636                                         prog);
637                         exit(1);
638                 }
639                 strcpy(intf, argv[0]);
640                 argc--; argv++;
641         }
642
643         /*
644          * If there are parameters remaining, the request is for
645          * vendor-specific adaptor statistics
646          */
647         if (argc) {
648                 /*
649                  * Get adapter configuration information
650                  */
651                 buf_len = sizeof(struct air_cfg_rsp);
652                 air.air_opcode = AIOCS_INF_CFG;
653                 strcpy(air.air_cfg_intf, intf);
654                 buf_len = do_info_ioctl(&air, buf_len);
655                 if (buf_len < 0) {
656                         fprintf(stderr, "%s: ", prog);
657                         switch (errno) {
658                         case ENOPROTOOPT:
659                         case EOPNOTSUPP:
660                                 perror("Internal error");
661                                 break;
662                         case ENXIO:
663                                 fprintf(stderr, "%s is not an ATM device\n",
664                                                 intf);
665                                 break;
666                         default:
667                                 perror("ioctl (AIOCINFO)");
668                                 break;
669                         }
670                         exit(1);
671                 }
672                 cfg_info = (struct air_cfg_rsp *)air.air_buf_addr;
673
674                 /*
675                  * Call the appropriate vendor-specific routine
676                  */
677                 switch(cfg_info->acp_vendor) {
678                 case VENDOR_FORE:
679                         show_fore200_stats(intf, argc, argv);
680                         break;
681                 case VENDOR_ENI:
682                         show_eni_stats(intf, argc, argv);
683                         break;
684                 default:
685                         fprintf(stderr, "%s: Unknown adapter vendor\n",
686                                         prog);
687                         break;
688                 }
689
690                 UM_FREE(cfg_info);
691         } else {
692                 /*
693                  * Get generic interface statistics
694                  */
695                 buf_len = sizeof(struct air_phy_stat_rsp) * 3;
696                 air.air_opcode = AIOCS_INF_PIS;
697                 strcpy(air.air_physt_intf, intf);
698                 buf_len = do_info_ioctl(&air, buf_len);
699                 if (buf_len < 0) {
700                         fprintf(stderr, "%s: ", prog);
701                         switch (errno) {
702                         case ENOPROTOOPT:
703                         case EOPNOTSUPP:
704                                 perror("Internal error");
705                                 break;
706                         case ENXIO:
707                                 fprintf(stderr, "%s is not an ATM device\n",
708                                                 intf);
709                                 break;
710                         default:
711                                 perror("ioctl (AIOCINFO)");
712                                 break;
713                         }
714                         exit(1);
715                 }
716
717                 /*
718                  * Display the interface statistics
719                  */
720                 pstat_info_base = pstat_info =
721                                 (struct air_phy_stat_rsp *)air.air_buf_addr;
722                 for (; buf_len >= sizeof(struct air_phy_stat_rsp);
723                                 pstat_info++,
724                                 buf_len-=sizeof(struct air_phy_stat_rsp)) {
725                         print_intf_stats(pstat_info);
726                 }
727                 UM_FREE((caddr_t)pstat_info_base);
728         }
729 }
730
731
732 /*
733  * Process VCC statistics command
734  * 
735  * Command format: 
736  *      atm show stats VCC [<interface-name> [<vpi> [<vci>]]] 
737  *
738  * Arguments:
739  *      argc    number of remaining arguments to command
740  *      argv    pointer to remaining argument strings
741  *      cmdp    pointer to command description 
742  *
743  * Returns:
744  *      none
745  *
746  */
747 void
748 show_vcc_stats(argc, argv, cmdp)
749         int             argc;
750         char            **argv;
751         struct cmd      *cmdp;
752 {
753         int     vcc_info_len;
754         int     vpi = -1, vci = -1;
755         char    *cp, *intf = NULL;
756         struct air_vcc_rsp      *vcc_info, *vcc_info_base;
757
758         /*
759          * Validate interface name
760          */
761         if (argc) {
762                 if (strlen(argv[0]) > IFNAMSIZ - 1) {
763                         fprintf(stderr, "%s: Illegal interface name\n",
764                                         prog);
765                         exit(1);
766                 }
767                 intf = argv[0];
768                 argc--; argv++;
769         }
770
771         /*
772          * Validate VPI value
773          */
774         if (argc) {
775                 vpi = strtol(argv[0], &cp, 0);
776                 if ((*cp != '\0') || (vpi < 0) || (vpi >= 1 << 8)) {
777                         fprintf(stderr, "%s: Invalid VPI value\n", prog);
778                         exit(1);
779                 }
780                 argc--; argv++;
781         }
782
783         /*
784          * Validate VCI value
785          */
786         if (argc) {
787                 vci = strtol(argv[0], &cp, 0);
788                 if ((*cp != '\0') || (vci <= 0) || (vci >= 1 << 16)) {
789                         fprintf(stderr, "%s: Invalid VCI value\n",
790                                         prog);
791                         exit(1);
792                 }
793                 argc--; argv++;
794         }
795
796         /*
797          * Get VCC information
798          */
799         vcc_info_len = get_vcc_info(intf, &vcc_info);
800         if (vcc_info_len == 0)
801                 exit(1);
802         else if (vcc_info_len < 0) {
803                 fprintf(stderr, "%s: ", prog);
804                 switch (errno) {
805                 case ENOPROTOOPT:
806                 case EOPNOTSUPP:
807                         perror("Internal error");
808                         break;
809                 case ENXIO:
810                         fprintf(stderr, "Not an ATM device\n");
811                         break;
812                 default:
813                         perror("ioctl (AIOCINFO)");
814                         break;
815                 }
816                 exit(1);
817         }
818
819         /*
820          * Sort the VCC information
821          */
822         qsort((void *) vcc_info,
823                         vcc_info_len / sizeof(struct air_vcc_rsp),
824                         sizeof(struct air_vcc_rsp),
825                         vcc_compare);
826
827         /*
828          * Display the VCC statistics
829          */
830         vcc_info_base = vcc_info;
831         for (; vcc_info_len >= sizeof(struct air_vcc_rsp);
832                         vcc_info_len-=sizeof(struct air_vcc_rsp),
833                         vcc_info++) {
834                 if (vpi != -1 && vcc_info->avp_vpi != vpi)
835                         continue;
836                 if (vci != -1 && vcc_info->avp_vci != vci)
837                         continue;
838                 print_vcc_stats(vcc_info);
839         }
840         UM_FREE(vcc_info_base);
841 }
842
843
844 /*
845  * Process VCC information command
846  * 
847  * Command format: 
848  *      atm show VCC [<interface-name> [<vpi> [<vci>] | PVC | SVC]] 
849  *
850  * Arguments:
851  *      argc    number of remaining arguments to command
852  *      argv    pointer to remaining argument strings
853  *      cmdp    pointer to command description 
854  *
855  * Returns:
856  *      none
857  *
858  */
859 void
860 show_vcc(argc, argv, cmdp)
861         int             argc;
862         char            **argv;
863         struct cmd      *cmdp;
864 {
865         int     vcc_info_len;
866         int     vpi = -1, vci = -1, show_pvc = 0, show_svc = 0;
867         char    *cp, *intf = NULL;
868         struct air_vcc_rsp      *vcc_info, *vcc_info_base;
869
870         /*
871          * Validate interface name
872          */
873         if (argc) {
874                 if (strlen(argv[0]) > IFNAMSIZ - 1) {
875                         fprintf(stderr, "%s: Illegal interface name\n",
876                                         prog);
877                         exit(1);
878                 }
879                 intf = argv[0];
880                 argc--; argv++;
881         }
882
883         /*
884          * Validate VPI value
885          */
886         if (argc) {
887                 if (strcasecmp(argv[0], "pvc"))
888                         show_pvc = 1;
889                 else if (strcasecmp(argv[0], "svc"))
890                         show_svc = 1;
891                 else {
892                         vpi = strtol(argv[0], &cp, 0);
893                         if ((*cp != '\0') || (vpi < 0) ||
894                                         (vpi >= 1 << 8)) {
895                                 fprintf(stderr, "%s: Invalid VPI value\n", prog);
896                                 exit(1);
897                         }
898                 }
899                 argc--; argv++;
900         }
901
902         /*
903          * Validate VCI value
904          */
905         if (argc) {
906                 vci = strtol(argv[0], &cp, 0);
907                 if ((*cp != '\0') || (vci <= 0) || (vci >= 1 << 16)) {
908                         fprintf(stderr, "%s: Invalid VCI value\n",
909                                         prog);
910                         exit(1);
911                 }
912                 argc--; argv++;
913         }
914
915         /*
916          * Get VCC information
917          */
918         vcc_info_len = get_vcc_info(intf, &vcc_info);
919         if (vcc_info_len == 0)
920                 exit(1);
921         else if (vcc_info_len < 0) {
922                 fprintf(stderr, "%s: ", prog);
923                 switch (errno) {
924                 case ENOPROTOOPT:
925                 case EOPNOTSUPP:
926                         perror("Internal error");
927                         break;
928                 case ENXIO:
929                         fprintf(stderr, "Not an ATM device\n");
930                         break;
931                 default:
932                         perror("ioctl (AIOCINFO)");
933                         break;
934                 }
935                 exit(1);
936         }
937
938         /*
939          * Sort the VCC information
940          */
941         qsort((void *) vcc_info,
942                         vcc_info_len/sizeof(struct air_vcc_rsp),
943                         sizeof(struct air_vcc_rsp),
944                         vcc_compare);
945
946         /*
947          * Display the VCC information
948          */
949         vcc_info_base = vcc_info;
950         for (; vcc_info_len >= sizeof(struct air_vcc_rsp);
951                         vcc_info_len-=sizeof(struct air_vcc_rsp),
952                         vcc_info++) {
953                 if (vpi != -1 && vcc_info->avp_vpi != vpi)
954                         continue;
955                 if (vci != -1 && vcc_info->avp_vci != vci)
956                         continue;
957                 if (show_pvc && vcc_info->avp_type & VCC_PVC)
958                         continue;
959                 if (show_svc && vcc_info->avp_type & VCC_SVC)
960                         continue;
961                 print_vcc_info(vcc_info);
962         }
963         UM_FREE(vcc_info_base);
964 }
965
966
967 /*
968  * Process version command
969  * 
970  * Command format: 
971  *      atm show version
972  *
973  * Arguments:
974  *      argc    number of remaining arguments to command
975  *      argv    pointer to remaining argument strings
976  *      cmdp    pointer to command description 
977  *
978  * Returns:
979  *      none
980  *
981  */
982 void
983 show_version(argc, argv, cmdp)
984         int             argc;
985         char            **argv;
986         struct cmd      *cmdp;
987 {
988         int     buf_len = sizeof(struct air_version_rsp);
989         struct atminfreq        air;
990         struct air_version_rsp  *ver_info, *ver_info_base;
991
992         /*
993          * Get network interface information from the kernel
994          */
995         air.air_opcode = AIOCS_INF_VER;
996         buf_len = do_info_ioctl(&air, buf_len);
997         if (buf_len < 0) {
998                 fprintf(stderr, "%s: ", prog);
999                 switch (errno) {
1000                 case ENOPROTOOPT:
1001                 case EOPNOTSUPP:
1002                         perror("Internal error");
1003                         break;
1004                 case ENXIO:
1005                         fprintf(stderr, "Not an ATM device\n");
1006                         break;
1007                 default:
1008                         perror("ioctl (AIOCINFO)");
1009                         break;
1010                 }
1011                 exit(1);
1012         }
1013
1014         /*
1015          * Print the network interface information
1016          */
1017         ver_info_base = ver_info =
1018                         (struct air_version_rsp *) air.air_buf_addr;
1019         for (; buf_len >= sizeof(struct air_version_rsp); ver_info++,
1020                         buf_len -= sizeof(struct air_version_rsp)) {
1021                 print_version_info(ver_info);
1022         }
1023         UM_FREE(ver_info_base);
1024 }
1025
1026
1027 /*
1028  * Comparison function for qsort
1029  * 
1030  * Arguments:
1031  *      p1      pointer to the first VCC response
1032  *      p2      pointer to the second VCC response
1033  *
1034  * Returns:
1035  *      int     a number less than, greater than, or equal to zero,
1036  *              depending on whether *p1 is less than, greater than, or
1037  *              equal to *p2
1038  *
1039  */
1040 static int
1041 vcc_compare(p1, p2)
1042         const void *p1, *p2;
1043 {
1044         int rc;
1045         struct air_vcc_rsp      *c1, *c2;
1046
1047         c1 = (struct air_vcc_rsp *) p1;
1048         c2 = (struct air_vcc_rsp *) p2;
1049
1050         /*
1051          * Compare the interface names
1052          */
1053         rc = strcmp(c1->avp_intf, c2->avp_intf);
1054         if (rc)
1055                 return(rc);
1056
1057         /*
1058          * Compare the VPI values
1059          */
1060         rc = c1->avp_vpi - c2->avp_vpi;
1061         if (rc)
1062                 return(rc);
1063
1064         /*
1065          * Compare the VCI values
1066          */
1067         rc = c1->avp_vci - c2->avp_vci;
1068         if (rc)
1069                 return(rc);
1070
1071         /*
1072          * Compare the types
1073          */
1074         rc = c1->avp_type - c2->avp_type;
1075         return(rc);
1076 }
1077
1078
1079 /*
1080  * Comparison function for qsort
1081  * 
1082  * Arguments:
1083  *      p1      pointer to the first VCC response
1084  *      p2      pointer to the second VCC response
1085  *
1086  * Returns:
1087  *      int     a number less than, greater than, or equal to zero,
1088  *              depending on whether *p1 is less than, greater than, or
1089  *              equal to *p2
1090  *
1091  */
1092 static int
1093 ip_vcc_compare(p1, p2)
1094         const void *p1, *p2;
1095 {
1096         int rc;
1097         struct air_ip_vcc_rsp   *c1, *c2;
1098
1099         c1 = (struct air_ip_vcc_rsp *) p1;
1100         c2 = (struct air_ip_vcc_rsp *) p2;
1101
1102         /*
1103          * Compare the interface names
1104          */
1105         rc = strcmp(c1->aip_intf, c2->aip_intf);
1106         if (rc)
1107                 return(rc);
1108
1109         /*
1110          * Compare the VPI values
1111          */
1112         rc = c1->aip_vpi - c2->aip_vpi;
1113         if (rc)
1114                 return(rc);
1115
1116         /*
1117          * Compare the VCI values
1118          */
1119         rc = c1->aip_vci - c2->aip_vci;
1120         return(rc);
1121 }
1122
1123
1124 /*
1125  * Comparison function for qsort
1126  * 
1127  * Arguments:
1128  *      p1      pointer to the first ARP or IP map entry
1129  *      p2      pointer to the second ARP or IP map entry
1130  *
1131  * Returns:
1132  *      int     a number less than, greater than, or equal to zero,
1133  *              depending on whether *p1 is less than, greater than, or
1134  *              equal to *p2
1135  *
1136  */
1137 static int
1138 arp_compare(p1, p2)
1139         const void *p1, *p2;
1140 {
1141         int rc;
1142         struct air_arp_rsp      *c1, *c2;
1143         struct sockaddr_in      *sin1, *sin2;
1144
1145         c1 = (struct air_arp_rsp *) p1;
1146         c2 = (struct air_arp_rsp *) p2;
1147         sin1 = (struct sockaddr_in *) &c1->aap_arp_addr;
1148         sin2 = (struct sockaddr_in *) &c2->aap_arp_addr;
1149
1150         /*
1151          * Compare the IP addresses
1152          */
1153         if ((rc = sin1->sin_family - sin2->sin_family) != 0)
1154                 return(rc);
1155         if ((rc = sin1->sin_addr.s_addr - sin2->sin_addr.s_addr) != 0)
1156                 return(rc);
1157
1158         /*
1159          * Compare the ATM addresses
1160          */
1161         if ((rc = c1->aap_addr.address_format - c2->aap_addr.address_format) != 0)
1162                 return(rc);
1163         if ((rc = c1->aap_addr.address_length - c2->aap_addr.address_length) != 0)
1164                 return(rc);
1165         switch(c1->aap_addr.address_format) {
1166         case T_ATM_ABSENT:
1167                 rc = 0;
1168                 break;
1169         case T_ATM_ENDSYS_ADDR:
1170                 rc = bcmp((caddr_t)c1->aap_addr.address,
1171                                 (caddr_t)c2->aap_addr.address,
1172                                 sizeof(Atm_addr_nsap));
1173                 break;
1174         case T_ATM_E164_ADDR:
1175                 rc = bcmp((caddr_t)c1->aap_addr.address,
1176                                 (caddr_t)c2->aap_addr.address,
1177                                 sizeof(Atm_addr_e164));
1178                 break;
1179         case T_ATM_SPANS_ADDR:
1180                 rc = bcmp((caddr_t)c1->aap_addr.address,
1181                                 (caddr_t)c2->aap_addr.address,
1182                                 sizeof(Atm_addr_spans));
1183                 break;
1184         }
1185
1186         return(rc);
1187 }