3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
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.
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.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
26 * @(#) $FreeBSD: src/sbin/atm/atm/atm.c,v 1.3.2.1 2000/07/01 06:02:14 ps Exp $
27 * @(#) $DragonFly: src/sbin/atm/atm/atm.c,v 1.5 2006/10/16 00:15:35 pavalos Exp $
31 * User configuration and display program
32 * --------------------------------------
38 #include <sys/param.h>
39 #include <sys/socket.h>
40 #include <sys/sockio.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_cm.h>
49 #include <netatm/atm_sigmgr.h>
50 #include <netatm/atm_ioctl.h>
64 #define USAGE_STR "Interface management subcommands:\n\
65 attach <intf> <protocol>\n\
67 set mac <intf> <MAC/ESI address>\n\
68 set netif <intf> <prefix> <n>\n\
69 set prefix <intf> <NSAP prefix>\n\
70 show config [<intf>]\n\
71 show interface [<intf>]\n\
72 show netif [<netif>]\n\
73 show stats interface [<intf> phy | dev | atm | aal0 | aal4 |\n\
76 VC management subcommands:\n\
77 add pvc <intf> <vpi> <vci> <aal> <encaps> <owner> ...\n\
78 delete pvc <intf> <vpi> <vci>\n\
79 delete svc <intf> <vpi> <vci>\n\
80 show stats vcc [<intf> [vpi [vci]]]\n\
81 show vcc [<intf> [<vpi> [<vci>] | SVC | PVC]]\n\
83 IP management subcommands:\n\
84 add arp [<netif>] <IP addr> <ATM addr>\n\
85 add pvc <intf> <vpi> <vci> <aal> <encaps> IP <netif> <IP addr> |\n\
87 delete arp [<netif>] <IP addr>\n\
88 set arpserver <netif> <server> <IP prefix> ...\n\
90 show arpserver [<netif>]\n\
91 show ipvcc [<IP addr> | <netif>]\n\
93 Miscellaneous subcommands:\n\
102 static int do_cmd(const struct cmd *, int, char **);
103 static void usage(const struct cmd *, const char *);
104 static void attach(int, char **, const struct cmd *);
105 static void detach(int, char **, const struct cmd *);
106 static void pvc_add(int, char **, const struct cmd *);
107 static void arp_add(int, char **, const struct cmd *);
108 static void pvc_dlt(int, char **, const struct cmd *);
109 static void svc_dlt(int, char **, const struct cmd *);
110 static void vcc_dlt(int, char **, const struct cmd *, struct atmdelreq *);
111 static void arp_dlt(int, char **, const struct cmd *);
112 static void help(int, char **, const struct cmd *);
114 static const struct cmd add_subcmd[] = {
115 { "arp", 2, 3, arp_add, "[<netif>] <IP addr> <ATM addr>" },
116 { "pvc", 6, 12, pvc_add, "<intf> <vpi> <vci> <aal> <encaps> <owner> ..." },
117 { 0, 0, 0, NULL, "" }
120 static const struct cmd dlt_subcmd[] = {
121 { "arp", 1, 2, arp_dlt, "[<netif>] <IP addr>" },
122 { "pvc", 3, 3, pvc_dlt, "<intf> <vpi> <vci>" },
123 { "svc", 3, 3, svc_dlt, "<intf> <vpi> <vci>" },
124 { 0, 0, 0, NULL, "" }
127 static const struct cmd set_subcmd[] = {
128 { "arpserver", 2, 18, set_arpserver, "<netif> <server>" },
129 { "mac", 2, 2, set_macaddr, "<intf> <MAC/ESI address>" },
130 { "netif", 3, 3, set_netif, "<intf> <prefix> <n>" },
131 { "prefix", 2, 2, set_prefix, "<intf> <NSAP prefix>" },
135 static const struct cmd stats_subcmd[] = {
136 { "interface", 0, 2, show_intf_stats, "[<intf> [cfg | phy | dev | atm | aal0 | aal4 | aal5 | driver]]" },
137 { "vcc", 0, 3, show_vcc_stats, "[<intf> [vpi [vci]]]" },
138 { 0, 0, 0, NULL, "" }
141 static const struct cmd show_subcmd[] = {
142 { "arp", 0, 1, show_arp, "[<host>]" },
143 { "arpserver", 0, 1, show_arpserv, "[<netif>]" },
144 { "config", 0, 1, show_config, "[<intf>]" },
145 { "interface", 0, 1, show_intf, "[<intf>]" },
146 { "ipvcc", 0, 3, show_ip_vcc, "[<IP addr> | <netif>]" },
147 { "netif", 0, 1, show_netif, "[<netif>]" },
148 { "stats", 0, 3, NULL, (const char *) stats_subcmd },
149 { "vcc", 0, 3, show_vcc, "[<intf>] [<vpi> [<vci>] | SVC | PVC]" },
150 { "version", 0, 0, show_version, "" },
151 { 0, 0, 0, NULL, "" }
154 static const struct cmd cmds[] = {
155 { "add", 0, 0, NULL, (const char *) add_subcmd },
156 { "attach", 2, 2, attach, "<intf> <protocol>" },
157 { "delete", 0, 0, NULL, (const char *) dlt_subcmd },
158 { "detach", 1, 1, detach, "<intf>" },
159 { "set", 0, 0, NULL, (const char *) set_subcmd },
160 { "show", 0, 0, NULL, (const char *) show_subcmd },
161 { "help", 0, 99, help, "" },
162 { 0, 0, 0, NULL, "" }
167 * Supported signalling protocols
169 static const struct proto protos[] = {
170 { "SIGPVC", ATM_SIG_PVC },
171 { "SPANS", ATM_SIG_SPANS },
172 { "UNI30", ATM_SIG_UNI30 },
173 { "UNI31", ATM_SIG_UNI31 },
174 { "UNI40", ATM_SIG_UNI40 },
179 * Supported VCC owners
181 static const struct owner owners[] = {
182 { "IP", ENDPT_IP, ip_pvcadd },
183 { "SPANS", ENDPT_SPANS_SIG,0 },
184 { "SPANS CLS", ENDPT_SPANS_CLS,0 },
185 { "UNI SIG", ENDPT_UNI_SIG, 0 },
190 * Supported AAL parameters
192 const struct aal aals[] = {
193 { "Null", ATM_AAL0 },
194 { "AAL0", ATM_AAL0 },
195 { "AAL1", ATM_AAL1 },
196 { "AAL2", ATM_AAL2 },
197 { "AAL4", ATM_AAL3_4 },
198 { "AAL3", ATM_AAL3_4 },
199 { "AAL3/4", ATM_AAL3_4 },
200 { "AAL5", ATM_AAL5 },
205 * Supported VCC encapsulations
207 const struct encaps encaps[] = {
208 { "Null", ATM_ENC_NULL },
209 { "None", ATM_ENC_NULL },
210 { "LLC/SNAP", ATM_ENC_LLC },
211 { "LLC", ATM_ENC_LLC },
212 { "SNAP", ATM_ENC_LLC },
218 char prefix[128] = "";
222 main(int argc, char **argv)
227 * Save program name, ignoring any path components
229 if ((prog = (char *)strrchr(argv[0], '/')) != NULL)
241 * Validate and process command
243 if ((error = do_cmd(cmds, argc, argv)) != 0)
251 * Validate and process user command
254 * descp pointer to command description array
255 * argc number of arguments left in command
256 * argv pointer to argument strings
263 do_cmd(const struct cmd *descp, int argc, char **argv)
265 const struct cmd *cmdp = NULL;
268 * Make sure we have paramaters to process
276 * Figure out what command user wants
278 for (; descp->name; descp++) {
280 * Use an exact match if there is one
282 if (!strcasecmp(descp->name, argv[0])) {
287 * Look for a match on the first part of keyword
289 if (!strncasecmp(descp->name, argv[0], strlen(argv[0]))) {
291 fprintf(stderr, "%s: Ambiguous parameter \"%s\"\n",
303 * See if this command has subcommands
305 if (cmdp->func == NULL) {
306 strcat(prefix, cmdp->name);
308 return(do_cmd((const struct cmd *)cmdp->help, argc, argv));
314 if ((argc < cmdp->minp) || (argc > cmdp->maxp)) {
315 fprintf(stderr, "%s: Invalid number of arguments\n",
317 fprintf(stderr, "\tformat is: %s%s %s\n",
318 prefix, cmdp->name, cmdp->help);
325 (*cmdp->func)(argc, argv, cmdp);
331 * Print command usage information
334 * cmdp pointer to command description
335 * pref pointer current command prefix
342 usage(__unused const struct cmd *cmdp, __unused const char *pref)
344 fprintf(stderr, "usage: %s command [arg] [arg]...\n", prog);
345 fprintf(stderr, USAGE_STR);
350 * Process interface attach command
353 * atm attach <interface_name> <protocol_name>
356 * argc number of arguments to command
357 * argv pointer to argument strings
358 * cmdp pointer to command description
365 attach(__unused int argc, char **argv, __unused const struct cmd *cmdp)
367 struct atmcfgreq aar;
368 const struct proto *prp;
372 * Validate interface name
374 if (strlen(argv[0]) > sizeof(aar.acr_att_intf) - 1) {
375 fprintf(stderr, "%s: Illegal interface name\n", prog);
380 * Find/validate requested signalling protocol
382 for (prp = protos; prp->p_name; prp++) {
383 if (strcasecmp(prp->p_name, argv[1]) == 0)
386 if (prp->p_name == NULL) {
387 fprintf(stderr, "%s: Unknown signalling protocol\n", prog);
393 * Build ioctl request
395 aar.acr_opcode = AIOCS_CFG_ATT;
396 strncpy(aar.acr_att_intf, argv[0], sizeof(aar.acr_att_intf));
397 aar.acr_att_proto = prp->p_id;
400 * Tell the kernel to do the attach
402 s = socket(AF_ATM, SOCK_DGRAM, 0);
406 if (ioctl(s, AIOCCFG, (caddr_t)&aar) < 0) {
407 fprintf(stderr, "%s: ", prog);
411 case EPROTONOSUPPORT:
412 perror("Internal error");
415 fprintf(stderr, "Kernel memory exhausted\n");
418 fprintf(stderr, "Signalling manager already attached to %s\n",
422 fprintf(stderr, "ATM network is inoperable\n");
425 fprintf(stderr, "Must be super user to use attach subcommand\n");
428 fprintf(stderr, "%s is not an ATM device\n",
432 fprintf(stderr, "%s has too few or too many network interfaces\n",
436 perror("Ioctl (AIOCCFG) attach");
446 * Process interface detach command
449 * atm detach <interface_name>
452 * argc number of arguments to command
453 * argv pointer to argument strings
454 * cmdp pointer to command description
461 detach(__unused int argc, char **argv, __unused const struct cmd *cmdp)
463 struct atmcfgreq adr;
467 * Validate interface name
469 if (strlen(argv[0]) > sizeof(adr.acr_det_intf) - 1) {
470 fprintf(stderr, "%s: Illegal interface name\n", prog);
475 * Build ioctl request
477 adr.acr_opcode = AIOCS_CFG_DET;
478 strncpy(adr.acr_det_intf, argv[0], sizeof(adr.acr_det_intf));
481 * Tell the kernel to do the detach
483 s = socket(AF_ATM, SOCK_DGRAM, 0);
487 if (ioctl(s, AIOCCFG, (caddr_t)&adr) < 0) {
488 fprintf(stderr, "%s: ", prog);
491 fprintf(stderr, "Signalling manager already detaching from %s\n",
495 perror("Internal error");
498 fprintf(stderr, "Must be super user to use detach subcommand\n");
501 perror("ioctl (AIOCCFG) detach");
511 * Process PVC add command
514 * atm add PVC <interface_name> <vpi> <vci> <aal> <encaps>
518 * argc number of arguments to command
519 * argv pointer to argument strings
520 * cmdp pointer to command description
527 pvc_add(int argc, char **argv, const struct cmd *cmdp)
529 struct atmaddreq apr;
530 struct atminfreq air;
531 struct air_int_rsp *int_info;
532 const struct owner *owp;
533 const struct aal *alp;
534 const struct encaps *enp;
540 * Initialize opcode and flags
542 apr.aar_opcode = AIOCS_ADD_PVC;
543 apr.aar_pvc_flags = 0;
546 * Validate interface name and issue an information
547 * request IOCTL for the interface
549 if (strlen(argv[0]) > sizeof(apr.aar_pvc_intf) - 1) {
550 fprintf(stderr, "%s: Illegal interface name\n", prog);
553 UM_ZERO(air.air_int_intf, sizeof(air.air_int_intf));
554 strcpy(air.air_int_intf, argv[0]);
555 buf_len = sizeof(struct air_int_rsp);
556 air.air_opcode = AIOCS_INF_INT;
557 buf_len = do_info_ioctl(&air, buf_len);
559 fprintf(stderr, "%s: ", prog);
563 perror("Internal error");
566 fprintf(stderr, "%s is not an ATM device\n",
570 perror("ioctl (AIOCINFO)");
575 int_info = (struct air_int_rsp *) air.air_buf_addr;
576 strcpy(apr.aar_pvc_intf, argv[0]);
580 * Validate vpi/vci values
582 v = strtol(argv[0], &cp, 0);
583 if ((*cp != '\0') || (v < 0) || (v >= 1 << 8)) {
584 fprintf(stderr, "%s: Invalid VPI value\n", prog);
587 apr.aar_pvc_vpi = (u_short) v;
590 v = strtol(argv[0], &cp, 0);
591 if ((*cp != '\0') || (v < MIN_VCI) || (v >= 1 << 16)) {
592 fprintf(stderr, "%s: Invalid VCI value\n", prog);
595 apr.aar_pvc_vci = (u_short) v;
599 * Validate requested PVC AAL
601 for (alp = aals; alp->a_name; alp++) {
602 if (strcasecmp(alp->a_name, argv[0]) == 0)
605 if (alp->a_name == NULL) {
606 fprintf(stderr, "%s: Invalid PVC AAL\n", prog);
609 apr.aar_pvc_aal = alp->a_id;
613 * Validate requested PVC encapsulation
615 for (enp = encaps; enp->e_name; enp++) {
616 if (strcasecmp(enp->e_name, argv[0]) == 0)
619 if (enp->e_name == NULL) {
620 fprintf(stderr, "%s: Invalid PVC encapsulation\n", prog);
623 apr.aar_pvc_encaps = enp->e_id;
627 * Validate requested PVC owner
629 for (owp = owners; owp->o_name; owp++) {
630 if (strcasecmp(owp->o_name, argv[0]) == 0)
633 if (owp->o_name == NULL) {
634 fprintf(stderr, "%s: Unknown PVC owner\n", prog);
637 apr.aar_pvc_sap = owp->o_sap;
641 * Perform service user processing
644 (*owp->o_pvcadd)(argc, argv, cmdp, &apr, int_info);
646 fprintf(stderr, "%s: Unsupported PVC owner\n", prog);
651 * Tell the kernel to add the PVC
653 s = socket(AF_ATM, SOCK_DGRAM, 0);
657 if (ioctl(s, AIOCADD, (caddr_t)&apr) < 0) {
658 fprintf(stderr, "%s: ", prog);
660 case EPROTONOSUPPORT:
662 perror("Internal error");
665 fprintf(stderr, "Invalid parameter\n");
668 fprintf(stderr, "PVC already exists\n");
671 fprintf(stderr, "ATM network is inoperable\n");
674 fprintf(stderr, "Kernel memory exhausted\n");
677 fprintf(stderr, "Must be super user to use add subcommand\n");
680 fprintf(stderr, "Invalid VPI or VCI value\n");
683 perror("ioctl (AIOCADD) add PVC");
693 * Process ARP add command
696 * atm add arp [<netif>] <IP addr> <ATM addr>
699 * argc number of arguments to command
700 * argv pointer to argument strings
701 * cmdp pointer to command description
708 arp_add(int argc, char **argv, __unused const struct cmd *cmdp)
711 struct atmaddreq apr;
713 struct sockaddr_in *sin;
715 struct sockaddr_in sin;
720 * Initialize add request structure
722 UM_ZERO(&apr, sizeof(apr));
725 * Get network interface name if one is present
728 check_netif_name(argv[0]);
729 strcpy(apr.aar_arp_intf, argv[0]);
734 * Get IP address of specified host name
736 UM_ZERO(&host_ip, sizeof(host_ip));
737 host_ip.sa.sa_family = AF_INET;
738 sin = get_ip_addr(argv[0]);
739 host_ip.sin.sin_addr.s_addr = sin->sin_addr.s_addr;
743 * Get specified ATM address
745 len = get_hex_atm_addr(argv[0], (u_char *)host_atm.address,
746 sizeof(Atm_addr_nsap));
748 case sizeof(Atm_addr_nsap):
749 host_atm.address_format = T_ATM_ENDSYS_ADDR;
750 host_atm.address_length = sizeof(Atm_addr_nsap);
752 case sizeof(Atm_addr_spans):
753 host_atm.address_format = T_ATM_SPANS_ADDR;
754 host_atm.address_length = sizeof(Atm_addr_spans);
757 fprintf(stderr, "%s: Invalid ATM address\n", prog);
762 * Build IOCTL request
764 apr.aar_opcode = AIOCS_ADD_ARP;
765 apr.aar_arp_dst = host_ip.sa;
766 ATM_ADDR_COPY(&host_atm, &apr.aar_arp_addr);
767 apr.aar_arp_origin = ARP_ORIG_PERM;
770 * Tell the kernel to add the ARP table entry
772 s = socket(AF_ATM, SOCK_DGRAM, 0);
776 if (ioctl(s, AIOCADD, (caddr_t)&apr) < 0) {
777 fprintf(stderr, "%s: ", prog);
780 fprintf(stderr, "Invalid parameter\n");
783 fprintf(stderr, "Must be super user to use add subcommand\n");
786 fprintf(stderr, "IP address not valid for interface\n");
789 perror("ioctl (AIOCADD) add");
799 * Process PVC delete command
802 * atm delete pvc <interface_name> <vpi> <vci>
805 * argc number of arguments to command
806 * argv pointer to argument strings
807 * cmdp pointer to command description
814 pvc_dlt(int argc, char **argv, const struct cmd *cmdp)
816 struct atmdelreq apr;
821 apr.adr_opcode = AIOCS_DEL_PVC;
824 * Complete request by calling subroutine
826 vcc_dlt(argc, argv, cmdp, &apr);
831 * Process SVC delete command
834 * atm delete svc <interface_name> <vpi> <vci>
837 * argc number of arguments to command
838 * argv pointer to argument strings
839 * cmdp pointer to command description
846 svc_dlt(int argc, char **argv, const struct cmd *cmdp)
848 struct atmdelreq apr;
853 apr.adr_opcode = AIOCS_DEL_SVC;
856 * Complete request by calling subroutine
858 vcc_dlt(argc, argv, cmdp, &apr);
863 * Complete an SVC or PVC delete command
866 * argc number of arguments to command
867 * argv pointer to argument strings
868 * cmdp pointer to command description
869 * apr pointer to ATM delete IOCTL structure
876 vcc_dlt(int argc, char **argv, __unused const struct cmd *cmdp, struct atmdelreq *apr)
883 * Validate interface name
885 if (strlen(argv[0]) > sizeof(apr->adr_pvc_intf) - 1) {
886 fprintf(stderr, "%s: Illegal interface name\n", prog);
889 strcpy(apr->adr_pvc_intf, argv[0]);
893 * Validate vpi/vci values
895 v = strtol(argv[0], &cp, 0);
896 if ((*cp != '\0') || (v < 0) || (v >= 1 << 8)) {
897 fprintf(stderr, "%s: Invalid VPI value\n", prog);
900 apr->adr_pvc_vpi = (u_short) v;
903 v = strtol(argv[0], &cp, 0);
904 if ((*cp != '\0') || (v < MIN_VCI) || (v >= 1 << 16)) {
905 fprintf(stderr, "%s: Invalid VCI value\n", prog);
908 apr->adr_pvc_vci = (u_short) v;
912 * Tell the kernel to delete the VCC
914 s = socket(AF_ATM, SOCK_DGRAM, 0);
918 if (ioctl(s, AIOCDEL, (caddr_t)apr) < 0) {
919 fprintf(stderr, "%s: ", prog);
922 fprintf(stderr, "Invalid parameter\n");
925 fprintf(stderr, "VCC not found\n");
928 fprintf(stderr, "VCC already being closed\n");
931 fprintf(stderr, "%s is not an ATM device\n",
935 fprintf(stderr, "Must be super user to use delete subcommand\n");
938 perror("ioctl (AIOCDEL) delete");
948 * Process ARP delete command
951 * atm delete arp <IP addr>
954 * argc number of arguments to command
955 * argv pointer to argument strings
956 * cmdp pointer to command description
963 arp_dlt(int argc, char **argv, __unused const struct cmd *cmdp)
966 struct atmdelreq apr;
967 struct sockaddr_in *sin;
969 struct sockaddr_in sin;
976 UM_ZERO(&apr, sizeof(apr));
977 apr.adr_opcode = AIOCS_DEL_ARP;
980 * Get network interface name if one is present
983 check_netif_name(argv[0]);
984 strcpy(apr.adr_arp_intf, argv[0]);
989 * Get IP address of specified host name
991 UM_ZERO(&host_addr, sizeof(host_addr));
992 host_addr.sa.sa_family = AF_INET;
993 sin = get_ip_addr(argv[0]);
994 host_addr.sin.sin_addr.s_addr = sin->sin_addr.s_addr;
995 apr.adr_arp_dst = host_addr.sa;
998 * Tell the kernel to delete the ARP table entry
1000 s = socket(AF_ATM, SOCK_DGRAM, 0);
1004 if (ioctl(s, AIOCDEL, (caddr_t)&apr) < 0) {
1005 fprintf(stderr, "%s: ", prog);
1008 fprintf(stderr, "Invalid parameter\n");
1011 fprintf(stderr, "Must be super user to use delete subcommand\n");
1014 perror("ioctl (AIOCDEL) delete");
1024 * Process help command
1027 * argc number of arguments to command
1028 * argv pointer to argument strings
1029 * cmdp pointer to command description
1036 help(__unused int argc, __unused char **argv, __unused const struct cmd *cmdp)