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.2 2003/06/17 04:27:32 dillon 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 struct cmd add_subcmd[];
103 struct cmd dlt_subcmd[];
104 struct cmd set_subcmd[];
105 struct cmd show_subcmd[];
106 struct cmd stats_subcmd[];
108 struct cmd cmds[] = {
109 { "add", 0, 0, NULL, (char *) add_subcmd },
110 { "attach", 2, 2, attach, "<intf> <protocol>" },
111 { "delete", 0, 0, NULL, (char *) dlt_subcmd },
112 { "detach", 1, 1, detach, "<intf>" },
113 { "set", 0, 0, NULL, (char *) set_subcmd },
114 { "show", 0, 0, NULL, (char *) show_subcmd },
115 { "help", 0, 99, help, "" },
116 { 0, 0, 0, NULL, "" }
119 struct cmd add_subcmd[] = {
120 { "arp", 2, 3, arp_add, "[<netif>] <IP addr> <ATM addr>" },
121 { "pvc", 6, 12, pvc_add, "<intf> <vpi> <vci> <aal> <encaps> <owner> ..." },
122 { 0, 0, 0, NULL, "" }
125 struct cmd dlt_subcmd[] = {
126 { "arp", 1, 2, arp_dlt, "[<netif>] <IP addr>" },
127 { "pvc", 3, 3, pvc_dlt, "<intf> <vpi> <vci>" },
128 { "svc", 3, 3, svc_dlt, "<intf> <vpi> <vci>" },
129 { 0, 0, 0, NULL, "" }
132 struct cmd set_subcmd[] = {
133 { "arpserver", 2, 18, set_arpserver, "<netif> <server>" },
134 { "mac", 2, 2, set_macaddr, "<intf> <MAC/ESI address>" },
135 { "netif", 3, 3, set_netif, "<intf> <prefix> <n>" },
136 { "prefix", 2, 2, set_prefix, "<intf> <NSAP prefix>" },
140 struct cmd show_subcmd[] = {
141 { "arp", 0, 1, show_arp, "[<host>]" },
142 { "arpserver", 0, 1, show_arpserv, "[<netif>]" },
143 { "config", 0, 1, show_config, "[<intf>]" },
144 { "interface", 0, 1, show_intf, "[<intf>]" },
145 { "ipvcc", 0, 3, show_ip_vcc, "[<IP addr> | <netif>]" },
146 { "netif", 0, 1, show_netif, "[<netif>]" },
147 { "stats", 0, 3, NULL, (char *) stats_subcmd },
148 { "vcc", 0, 3, show_vcc, "[<intf>] [<vpi> [<vci>] | SVC | PVC]" },
149 { "version", 0, 0, show_version, "" },
150 { 0, 0, 0, NULL, "" }
153 struct cmd stats_subcmd[] = {
154 { "interface", 0, 2, show_intf_stats, "[<intf> [cfg | phy | dev | atm | aal0 | aal4 | aal5 | driver]]" },
155 { "vcc", 0, 3, show_vcc_stats, "[<intf> [vpi [vci]]]" },
156 { 0, 0, 0, NULL, "" }
161 * Supported signalling protocols
163 struct proto protos[] = {
164 { "SIGPVC", ATM_SIG_PVC },
165 { "SPANS", ATM_SIG_SPANS },
166 { "UNI30", ATM_SIG_UNI30 },
167 { "UNI31", ATM_SIG_UNI31 },
168 { "UNI40", ATM_SIG_UNI40 },
173 * Supported VCC owners
175 struct owner owners[] = {
176 { "IP", ENDPT_IP, ip_pvcadd },
177 { "SPANS", ENDPT_SPANS_SIG,0 },
178 { "SPANS CLS", ENDPT_SPANS_CLS,0 },
179 { "UNI SIG", ENDPT_UNI_SIG, 0 },
184 * Supported AAL parameters
186 struct aal aals[] = {
187 { "Null", ATM_AAL0 },
188 { "AAL0", ATM_AAL0 },
189 { "AAL1", ATM_AAL1 },
190 { "AAL2", ATM_AAL2 },
191 { "AAL4", ATM_AAL3_4 },
192 { "AAL3", ATM_AAL3_4 },
193 { "AAL3/4", ATM_AAL3_4 },
194 { "AAL5", ATM_AAL5 },
199 * Supported VCC encapsulations
201 struct encaps encaps[] = {
202 { "Null", ATM_ENC_NULL },
203 { "None", ATM_ENC_NULL },
204 { "LLC/SNAP", ATM_ENC_LLC },
205 { "LLC", ATM_ENC_LLC },
206 { "SNAP", ATM_ENC_LLC },
212 char prefix[128] = "";
223 * Save program name, ignoring any path components
225 if ((prog = (char *)strrchr(argv[0], '/')) != NULL)
237 * Validate and process command
239 if ((error = do_cmd(cmds, argc, argv)) != 0)
247 * Validate and process user command
250 * descp pointer to command description array
251 * argc number of arguments left in command
252 * argv pointer to argument strings
259 do_cmd(descp, argc, argv)
264 struct cmd *cmdp = 0;
267 * Make sure we have paramaters to process
275 * Figure out what command user wants
277 for (; descp->name; descp++) {
279 * Use an exact match if there is one
281 if (!strcasecmp(descp->name, argv[0])) {
286 * Look for a match on the first part of keyword
288 if (!strncasecmp(descp->name, argv[0], strlen(argv[0]))) {
290 fprintf(stderr, "%s: Ambiguous parameter \"%s\"\n",
302 * See if this command has subcommands
304 if (cmdp->func == NULL) {
305 strcat(prefix, cmdp->name);
307 return(do_cmd((struct cmd *)cmdp->help, argc, argv));
313 if ((argc < cmdp->minp) || (argc > cmdp->maxp)) {
314 fprintf(stderr, "%s: Invalid number of arguments\n",
316 fprintf(stderr, "\tformat is: %s%s %s\n",
317 prefix, cmdp->name, cmdp->help);
324 (*cmdp->func)(argc, argv, cmdp);
330 * Print command usage information
333 * cmdp pointer to command description
334 * pref pointer current command prefix
345 fprintf(stderr, "usage: %s command [arg] [arg]...\n", prog);
346 fprintf(stderr, USAGE_STR);
351 * Process interface attach command
354 * atm attach <interface_name> <protocol_name>
357 * argc number of arguments to command
358 * argv pointer to argument strings
359 * cmdp pointer to command description
366 attach(argc, argv, cmdp)
371 struct atmcfgreq aar;
376 * Validate interface name
378 if (strlen(argv[0]) > sizeof(aar.acr_att_intf) - 1) {
379 fprintf(stderr, "%s: Illegal interface name\n", prog);
384 * Find/validate requested signalling protocol
386 for (prp = protos; prp->p_name; prp++) {
387 if (strcasecmp(prp->p_name, argv[1]) == 0)
390 if (prp->p_name == NULL) {
391 fprintf(stderr, "%s: Unknown signalling protocol\n", prog);
397 * Build ioctl request
399 aar.acr_opcode = AIOCS_CFG_ATT;
400 strncpy(aar.acr_att_intf, argv[0], sizeof(aar.acr_att_intf));
401 aar.acr_att_proto = prp->p_id;
404 * Tell the kernel to do the attach
406 s = socket(AF_ATM, SOCK_DGRAM, 0);
410 if (ioctl(s, AIOCCFG, (caddr_t)&aar) < 0) {
411 fprintf(stderr, "%s: ", prog);
415 case EPROTONOSUPPORT:
416 perror("Internal error");
419 fprintf(stderr, "Kernel memory exhausted\n");
422 fprintf(stderr, "Signalling manager already attached to %s\n",
426 fprintf(stderr, "ATM network is inoperable\n");
429 fprintf(stderr, "Must be super user to use attach subcommand\n");
432 fprintf(stderr, "%s is not an ATM device\n",
436 fprintf(stderr, "%s has too few or too many network interfaces\n",
440 perror("Ioctl (AIOCCFG) attach");
450 * Process interface detach command
453 * atm detach <interface_name>
456 * argc number of arguments to command
457 * argv pointer to argument strings
458 * cmdp pointer to command description
465 detach(argc, argv, cmdp)
470 struct atmcfgreq adr;
474 * Validate interface name
476 if (strlen(argv[0]) > sizeof(adr.acr_det_intf) - 1) {
477 fprintf(stderr, "%s: Illegal interface name\n", prog);
482 * Build ioctl request
484 adr.acr_opcode = AIOCS_CFG_DET;
485 strncpy(adr.acr_det_intf, argv[0], sizeof(adr.acr_det_intf));
488 * Tell the kernel to do the detach
490 s = socket(AF_ATM, SOCK_DGRAM, 0);
494 if (ioctl(s, AIOCCFG, (caddr_t)&adr) < 0) {
495 fprintf(stderr, "%s: ", prog);
498 fprintf(stderr, "Signalling manager already detaching from %s\n",
502 perror("Internal error");
505 fprintf(stderr, "Must be super user to use detach subcommand\n");
508 perror("ioctl (AIOCCFG) detach");
518 * Process PVC add command
521 * atm add PVC <interface_name> <vpi> <vci> <aal> <encaps>
525 * argc number of arguments to command
526 * argv pointer to argument strings
527 * cmdp pointer to command description
534 pvc_add(argc, argv, cmdp)
539 struct atmaddreq apr;
540 struct atminfreq air;
541 struct air_int_rsp *int_info;
550 * Initialize opcode and flags
552 apr.aar_opcode = AIOCS_ADD_PVC;
553 apr.aar_pvc_flags = 0;
556 * Validate interface name and issue an information
557 * request IOCTL for the interface
559 if (strlen(argv[0]) > sizeof(apr.aar_pvc_intf) - 1) {
560 fprintf(stderr, "%s: Illegal interface name\n", prog);
563 UM_ZERO(air.air_int_intf, sizeof(air.air_int_intf));
564 strcpy(air.air_int_intf, argv[0]);
565 buf_len = sizeof(struct air_int_rsp);
566 air.air_opcode = AIOCS_INF_INT;
567 buf_len = do_info_ioctl(&air, buf_len);
569 fprintf(stderr, "%s: ", prog);
573 perror("Internal error");
576 fprintf(stderr, "%s is not an ATM device\n",
580 perror("ioctl (AIOCINFO)");
585 int_info = (struct air_int_rsp *) air.air_buf_addr;
586 strcpy(apr.aar_pvc_intf, argv[0]);
590 * Validate vpi/vci values
592 v = strtol(argv[0], &cp, 0);
593 if ((*cp != '\0') || (v < 0) || (v >= 1 << 8)) {
594 fprintf(stderr, "%s: Invalid VPI value\n", prog);
597 apr.aar_pvc_vpi = (u_short) v;
600 v = strtol(argv[0], &cp, 0);
601 if ((*cp != '\0') || (v < MIN_VCI) || (v >= 1 << 16)) {
602 fprintf(stderr, "%s: Invalid VCI value\n", prog);
605 apr.aar_pvc_vci = (u_short) v;
609 * Validate requested PVC AAL
611 for (alp = aals; alp->a_name; alp++) {
612 if (strcasecmp(alp->a_name, argv[0]) == 0)
615 if (alp->a_name == NULL) {
616 fprintf(stderr, "%s: Invalid PVC AAL\n", prog);
619 apr.aar_pvc_aal = alp->a_id;
623 * Validate requested PVC encapsulation
625 for (enp = encaps; enp->e_name; enp++) {
626 if (strcasecmp(enp->e_name, argv[0]) == 0)
629 if (enp->e_name == NULL) {
630 fprintf(stderr, "%s: Invalid PVC encapsulation\n", prog);
633 apr.aar_pvc_encaps = enp->e_id;
637 * Validate requested PVC owner
639 for (owp = owners; owp->o_name; owp++) {
640 if (strcasecmp(owp->o_name, argv[0]) == 0)
643 if (owp->o_name == NULL) {
644 fprintf(stderr, "%s: Unknown PVC owner\n", prog);
647 apr.aar_pvc_sap = owp->o_sap;
651 * Perform service user processing
654 (*owp->o_pvcadd)(argc, argv, cmdp, &apr, int_info);
656 fprintf(stderr, "%s: Unsupported PVC owner\n", prog);
661 * Tell the kernel to add the PVC
663 s = socket(AF_ATM, SOCK_DGRAM, 0);
667 if (ioctl(s, AIOCADD, (caddr_t)&apr) < 0) {
668 fprintf(stderr, "%s: ", prog);
670 case EPROTONOSUPPORT:
672 perror("Internal error");
675 fprintf(stderr, "Invalid parameter\n");
678 fprintf(stderr, "PVC already exists\n");
681 fprintf(stderr, "ATM network is inoperable\n");
684 fprintf(stderr, "Kernel memory exhausted\n");
687 fprintf(stderr, "Must be super user to use add subcommand\n");
690 fprintf(stderr, "Invalid VPI or VCI value\n");
693 perror("ioctl (AIOCADD) add PVC");
703 * Process ARP add command
706 * atm add arp [<netif>] <IP addr> <ATM addr>
709 * argc number of arguments to command
710 * argv pointer to argument strings
711 * cmdp pointer to command description
718 arp_add(argc, argv, cmdp)
724 struct atmaddreq apr;
726 struct sockaddr_in *sin;
728 struct sockaddr_in sin;
733 * Initialize add request structure
735 UM_ZERO(&apr, sizeof(apr));
738 * Get network interface name if one is present
741 check_netif_name(argv[0]);
742 strcpy(apr.aar_arp_intf, argv[0]);
747 * Get IP address of specified host name
749 UM_ZERO(&host_ip, sizeof(host_ip));
750 host_ip.sa.sa_family = AF_INET;
751 sin = get_ip_addr(argv[0]);
752 host_ip.sin.sin_addr.s_addr = sin->sin_addr.s_addr;
756 * Get specified ATM address
758 len = get_hex_atm_addr(argv[0], (u_char *)host_atm.address,
759 sizeof(Atm_addr_nsap));
761 case sizeof(Atm_addr_nsap):
762 host_atm.address_format = T_ATM_ENDSYS_ADDR;
763 host_atm.address_length = sizeof(Atm_addr_nsap);
765 case sizeof(Atm_addr_spans):
766 host_atm.address_format = T_ATM_SPANS_ADDR;
767 host_atm.address_length = sizeof(Atm_addr_spans);
770 fprintf(stderr, "%s: Invalid ATM address\n", prog);
775 * Build IOCTL request
777 apr.aar_opcode = AIOCS_ADD_ARP;
778 apr.aar_arp_dst = host_ip.sa;
779 ATM_ADDR_COPY(&host_atm, &apr.aar_arp_addr);
780 apr.aar_arp_origin = ARP_ORIG_PERM;
783 * Tell the kernel to add the ARP table entry
785 s = socket(AF_ATM, SOCK_DGRAM, 0);
789 if (ioctl(s, AIOCADD, (caddr_t)&apr) < 0) {
790 fprintf(stderr, "%s: ", prog);
793 fprintf(stderr, "Invalid parameter\n");
796 fprintf(stderr, "Must be super user to use add subcommand\n");
799 fprintf(stderr, "IP address not valid for interface\n");
802 perror("ioctl (AIOCADD) add");
812 * Process PVC delete command
815 * atm delete pvc <interface_name> <vpi> <vci>
818 * argc number of arguments to command
819 * argv pointer to argument strings
820 * cmdp pointer to command description
827 pvc_dlt(argc, argv, cmdp)
832 struct atmdelreq apr;
837 apr.adr_opcode = AIOCS_DEL_PVC;
840 * Complete request by calling subroutine
842 vcc_dlt(argc, argv, cmdp, &apr);
847 * Process SVC delete command
850 * atm delete svc <interface_name> <vpi> <vci>
853 * argc number of arguments to command
854 * argv pointer to argument strings
855 * cmdp pointer to command description
862 svc_dlt(argc, argv, cmdp)
867 struct atmdelreq apr;
872 apr.adr_opcode = AIOCS_DEL_SVC;
875 * Complete request by calling subroutine
877 vcc_dlt(argc, argv, cmdp, &apr);
882 * Complete an SVC or PVC delete command
885 * argc number of arguments to command
886 * argv pointer to argument strings
887 * cmdp pointer to command description
888 * apr pointer to ATM delete IOCTL structure
895 vcc_dlt(argc, argv, cmdp, apr)
899 struct atmdelreq *apr;
906 * Validate interface name
908 if (strlen(argv[0]) > sizeof(apr->adr_pvc_intf) - 1) {
909 fprintf(stderr, "%s: Illegal interface name\n", prog);
912 strcpy(apr->adr_pvc_intf, argv[0]);
916 * Validate vpi/vci values
918 v = strtol(argv[0], &cp, 0);
919 if ((*cp != '\0') || (v < 0) || (v >= 1 << 8)) {
920 fprintf(stderr, "%s: Invalid VPI value\n", prog);
923 apr->adr_pvc_vpi = (u_short) v;
926 v = strtol(argv[0], &cp, 0);
927 if ((*cp != '\0') || (v < MIN_VCI) || (v >= 1 << 16)) {
928 fprintf(stderr, "%s: Invalid VCI value\n", prog);
931 apr->adr_pvc_vci = (u_short) v;
935 * Tell the kernel to delete the VCC
937 s = socket(AF_ATM, SOCK_DGRAM, 0);
941 if (ioctl(s, AIOCDEL, (caddr_t)apr) < 0) {
942 fprintf(stderr, "%s: ", prog);
945 fprintf(stderr, "Invalid parameter\n");
948 fprintf(stderr, "VCC not found\n");
951 fprintf(stderr, "VCC already being closed\n");
954 fprintf(stderr, "%s is not an ATM device\n",
958 fprintf(stderr, "Must be super user to use delete subcommand\n");
961 perror("ioctl (AIOCDEL) delete");
971 * Process ARP delete command
974 * atm delete arp <IP addr>
977 * argc number of arguments to command
978 * argv pointer to argument strings
979 * cmdp pointer to command description
986 arp_dlt(argc, argv, cmdp)
992 struct atmdelreq apr;
993 struct sockaddr_in *sin;
995 struct sockaddr_in sin;
1002 UM_ZERO(&apr, sizeof(apr));
1003 apr.adr_opcode = AIOCS_DEL_ARP;
1006 * Get network interface name if one is present
1009 check_netif_name(argv[0]);
1010 strcpy(apr.adr_arp_intf, argv[0]);
1015 * Get IP address of specified host name
1017 UM_ZERO(&host_addr, sizeof(host_addr));
1018 host_addr.sa.sa_family = AF_INET;
1019 sin = get_ip_addr(argv[0]);
1020 host_addr.sin.sin_addr.s_addr = sin->sin_addr.s_addr;
1021 apr.adr_arp_dst = host_addr.sa;
1024 * Tell the kernel to delete the ARP table entry
1026 s = socket(AF_ATM, SOCK_DGRAM, 0);
1030 if (ioctl(s, AIOCDEL, (caddr_t)&apr) < 0) {
1031 fprintf(stderr, "%s: ", prog);
1034 fprintf(stderr, "Invalid parameter\n");
1037 fprintf(stderr, "Must be super user to use delete subcommand\n");
1040 perror("ioctl (AIOCDEL) delete");
1050 * Process help command
1053 * argc number of arguments to command
1054 * argv pointer to argument strings
1055 * cmdp pointer to command description
1062 help(argc, argv, cmdp)