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