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.3 2003/09/28 14:39:16 hmp 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] = "";
216 main(int argc, char **argv)
221 * Save program name, ignoring any path components
223 if ((prog = (char *)strrchr(argv[0], '/')) != NULL)
235 * Validate and process command
237 if ((error = do_cmd(cmds, argc, argv)) != 0)
245 * Validate and process user command
248 * descp pointer to command description array
249 * argc number of arguments left in command
250 * argv pointer to argument strings
257 do_cmd(struct cmd *descp, int argc, char **argv)
259 struct cmd *cmdp = 0;
262 * Make sure we have paramaters to process
270 * Figure out what command user wants
272 for (; descp->name; descp++) {
274 * Use an exact match if there is one
276 if (!strcasecmp(descp->name, argv[0])) {
281 * Look for a match on the first part of keyword
283 if (!strncasecmp(descp->name, argv[0], strlen(argv[0]))) {
285 fprintf(stderr, "%s: Ambiguous parameter \"%s\"\n",
297 * See if this command has subcommands
299 if (cmdp->func == NULL) {
300 strcat(prefix, cmdp->name);
302 return(do_cmd((struct cmd *)cmdp->help, argc, argv));
308 if ((argc < cmdp->minp) || (argc > cmdp->maxp)) {
309 fprintf(stderr, "%s: Invalid number of arguments\n",
311 fprintf(stderr, "\tformat is: %s%s %s\n",
312 prefix, cmdp->name, cmdp->help);
319 (*cmdp->func)(argc, argv, cmdp);
325 * Print command usage information
328 * cmdp pointer to command description
329 * pref pointer current command prefix
336 usage(struct cmd *cmdp, char *pref)
338 fprintf(stderr, "usage: %s command [arg] [arg]...\n", prog);
339 fprintf(stderr, USAGE_STR);
344 * Process interface attach command
347 * atm attach <interface_name> <protocol_name>
350 * argc number of arguments to command
351 * argv pointer to argument strings
352 * cmdp pointer to command description
359 attach(int argc, char **argv, struct cmd *cmdp)
361 struct atmcfgreq aar;
366 * Validate interface name
368 if (strlen(argv[0]) > sizeof(aar.acr_att_intf) - 1) {
369 fprintf(stderr, "%s: Illegal interface name\n", prog);
374 * Find/validate requested signalling protocol
376 for (prp = protos; prp->p_name; prp++) {
377 if (strcasecmp(prp->p_name, argv[1]) == 0)
380 if (prp->p_name == NULL) {
381 fprintf(stderr, "%s: Unknown signalling protocol\n", prog);
387 * Build ioctl request
389 aar.acr_opcode = AIOCS_CFG_ATT;
390 strncpy(aar.acr_att_intf, argv[0], sizeof(aar.acr_att_intf));
391 aar.acr_att_proto = prp->p_id;
394 * Tell the kernel to do the attach
396 s = socket(AF_ATM, SOCK_DGRAM, 0);
400 if (ioctl(s, AIOCCFG, (caddr_t)&aar) < 0) {
401 fprintf(stderr, "%s: ", prog);
405 case EPROTONOSUPPORT:
406 perror("Internal error");
409 fprintf(stderr, "Kernel memory exhausted\n");
412 fprintf(stderr, "Signalling manager already attached to %s\n",
416 fprintf(stderr, "ATM network is inoperable\n");
419 fprintf(stderr, "Must be super user to use attach subcommand\n");
422 fprintf(stderr, "%s is not an ATM device\n",
426 fprintf(stderr, "%s has too few or too many network interfaces\n",
430 perror("Ioctl (AIOCCFG) attach");
440 * Process interface detach command
443 * atm detach <interface_name>
446 * argc number of arguments to command
447 * argv pointer to argument strings
448 * cmdp pointer to command description
455 detach(int argc, char **argv, struct cmd *cmdp)
457 struct atmcfgreq adr;
461 * Validate interface name
463 if (strlen(argv[0]) > sizeof(adr.acr_det_intf) - 1) {
464 fprintf(stderr, "%s: Illegal interface name\n", prog);
469 * Build ioctl request
471 adr.acr_opcode = AIOCS_CFG_DET;
472 strncpy(adr.acr_det_intf, argv[0], sizeof(adr.acr_det_intf));
475 * Tell the kernel to do the detach
477 s = socket(AF_ATM, SOCK_DGRAM, 0);
481 if (ioctl(s, AIOCCFG, (caddr_t)&adr) < 0) {
482 fprintf(stderr, "%s: ", prog);
485 fprintf(stderr, "Signalling manager already detaching from %s\n",
489 perror("Internal error");
492 fprintf(stderr, "Must be super user to use detach subcommand\n");
495 perror("ioctl (AIOCCFG) detach");
505 * Process PVC add command
508 * atm add PVC <interface_name> <vpi> <vci> <aal> <encaps>
512 * argc number of arguments to command
513 * argv pointer to argument strings
514 * cmdp pointer to command description
521 pvc_add(int argc, char **argv, struct cmd *cmdp)
523 struct atmaddreq apr;
524 struct atminfreq air;
525 struct air_int_rsp *int_info;
534 * Initialize opcode and flags
536 apr.aar_opcode = AIOCS_ADD_PVC;
537 apr.aar_pvc_flags = 0;
540 * Validate interface name and issue an information
541 * request IOCTL for the interface
543 if (strlen(argv[0]) > sizeof(apr.aar_pvc_intf) - 1) {
544 fprintf(stderr, "%s: Illegal interface name\n", prog);
547 UM_ZERO(air.air_int_intf, sizeof(air.air_int_intf));
548 strcpy(air.air_int_intf, argv[0]);
549 buf_len = sizeof(struct air_int_rsp);
550 air.air_opcode = AIOCS_INF_INT;
551 buf_len = do_info_ioctl(&air, buf_len);
553 fprintf(stderr, "%s: ", prog);
557 perror("Internal error");
560 fprintf(stderr, "%s is not an ATM device\n",
564 perror("ioctl (AIOCINFO)");
569 int_info = (struct air_int_rsp *) air.air_buf_addr;
570 strcpy(apr.aar_pvc_intf, argv[0]);
574 * Validate vpi/vci values
576 v = strtol(argv[0], &cp, 0);
577 if ((*cp != '\0') || (v < 0) || (v >= 1 << 8)) {
578 fprintf(stderr, "%s: Invalid VPI value\n", prog);
581 apr.aar_pvc_vpi = (u_short) v;
584 v = strtol(argv[0], &cp, 0);
585 if ((*cp != '\0') || (v < MIN_VCI) || (v >= 1 << 16)) {
586 fprintf(stderr, "%s: Invalid VCI value\n", prog);
589 apr.aar_pvc_vci = (u_short) v;
593 * Validate requested PVC AAL
595 for (alp = aals; alp->a_name; alp++) {
596 if (strcasecmp(alp->a_name, argv[0]) == 0)
599 if (alp->a_name == NULL) {
600 fprintf(stderr, "%s: Invalid PVC AAL\n", prog);
603 apr.aar_pvc_aal = alp->a_id;
607 * Validate requested PVC encapsulation
609 for (enp = encaps; enp->e_name; enp++) {
610 if (strcasecmp(enp->e_name, argv[0]) == 0)
613 if (enp->e_name == NULL) {
614 fprintf(stderr, "%s: Invalid PVC encapsulation\n", prog);
617 apr.aar_pvc_encaps = enp->e_id;
621 * Validate requested PVC owner
623 for (owp = owners; owp->o_name; owp++) {
624 if (strcasecmp(owp->o_name, argv[0]) == 0)
627 if (owp->o_name == NULL) {
628 fprintf(stderr, "%s: Unknown PVC owner\n", prog);
631 apr.aar_pvc_sap = owp->o_sap;
635 * Perform service user processing
638 (*owp->o_pvcadd)(argc, argv, cmdp, &apr, int_info);
640 fprintf(stderr, "%s: Unsupported PVC owner\n", prog);
645 * Tell the kernel to add the PVC
647 s = socket(AF_ATM, SOCK_DGRAM, 0);
651 if (ioctl(s, AIOCADD, (caddr_t)&apr) < 0) {
652 fprintf(stderr, "%s: ", prog);
654 case EPROTONOSUPPORT:
656 perror("Internal error");
659 fprintf(stderr, "Invalid parameter\n");
662 fprintf(stderr, "PVC already exists\n");
665 fprintf(stderr, "ATM network is inoperable\n");
668 fprintf(stderr, "Kernel memory exhausted\n");
671 fprintf(stderr, "Must be super user to use add subcommand\n");
674 fprintf(stderr, "Invalid VPI or VCI value\n");
677 perror("ioctl (AIOCADD) add PVC");
687 * Process ARP add command
690 * atm add arp [<netif>] <IP addr> <ATM addr>
693 * argc number of arguments to command
694 * argv pointer to argument strings
695 * cmdp pointer to command description
702 arp_add(int argc, char **argv, struct cmd *cmdp)
705 struct atmaddreq apr;
707 struct sockaddr_in *sin;
709 struct sockaddr_in sin;
714 * Initialize add request structure
716 UM_ZERO(&apr, sizeof(apr));
719 * Get network interface name if one is present
722 check_netif_name(argv[0]);
723 strcpy(apr.aar_arp_intf, argv[0]);
728 * Get IP address of specified host name
730 UM_ZERO(&host_ip, sizeof(host_ip));
731 host_ip.sa.sa_family = AF_INET;
732 sin = get_ip_addr(argv[0]);
733 host_ip.sin.sin_addr.s_addr = sin->sin_addr.s_addr;
737 * Get specified ATM address
739 len = get_hex_atm_addr(argv[0], (u_char *)host_atm.address,
740 sizeof(Atm_addr_nsap));
742 case sizeof(Atm_addr_nsap):
743 host_atm.address_format = T_ATM_ENDSYS_ADDR;
744 host_atm.address_length = sizeof(Atm_addr_nsap);
746 case sizeof(Atm_addr_spans):
747 host_atm.address_format = T_ATM_SPANS_ADDR;
748 host_atm.address_length = sizeof(Atm_addr_spans);
751 fprintf(stderr, "%s: Invalid ATM address\n", prog);
756 * Build IOCTL request
758 apr.aar_opcode = AIOCS_ADD_ARP;
759 apr.aar_arp_dst = host_ip.sa;
760 ATM_ADDR_COPY(&host_atm, &apr.aar_arp_addr);
761 apr.aar_arp_origin = ARP_ORIG_PERM;
764 * Tell the kernel to add the ARP table entry
766 s = socket(AF_ATM, SOCK_DGRAM, 0);
770 if (ioctl(s, AIOCADD, (caddr_t)&apr) < 0) {
771 fprintf(stderr, "%s: ", prog);
774 fprintf(stderr, "Invalid parameter\n");
777 fprintf(stderr, "Must be super user to use add subcommand\n");
780 fprintf(stderr, "IP address not valid for interface\n");
783 perror("ioctl (AIOCADD) add");
793 * Process PVC delete command
796 * atm delete pvc <interface_name> <vpi> <vci>
799 * argc number of arguments to command
800 * argv pointer to argument strings
801 * cmdp pointer to command description
808 pvc_dlt(int argc, char **argv, struct cmd *cmdp)
810 struct atmdelreq apr;
815 apr.adr_opcode = AIOCS_DEL_PVC;
818 * Complete request by calling subroutine
820 vcc_dlt(argc, argv, cmdp, &apr);
825 * Process SVC delete command
828 * atm delete svc <interface_name> <vpi> <vci>
831 * argc number of arguments to command
832 * argv pointer to argument strings
833 * cmdp pointer to command description
840 svc_dlt(int argc, char **argv, struct cmd *cmdp)
842 struct atmdelreq apr;
847 apr.adr_opcode = AIOCS_DEL_SVC;
850 * Complete request by calling subroutine
852 vcc_dlt(argc, argv, cmdp, &apr);
857 * Complete an SVC or PVC delete command
860 * argc number of arguments to command
861 * argv pointer to argument strings
862 * cmdp pointer to command description
863 * apr pointer to ATM delete IOCTL structure
870 vcc_dlt(int argc, char **argv, struct cmd *cmdp, struct atmdelreq *apr)
877 * Validate interface name
879 if (strlen(argv[0]) > sizeof(apr->adr_pvc_intf) - 1) {
880 fprintf(stderr, "%s: Illegal interface name\n", prog);
883 strcpy(apr->adr_pvc_intf, argv[0]);
887 * Validate vpi/vci values
889 v = strtol(argv[0], &cp, 0);
890 if ((*cp != '\0') || (v < 0) || (v >= 1 << 8)) {
891 fprintf(stderr, "%s: Invalid VPI value\n", prog);
894 apr->adr_pvc_vpi = (u_short) v;
897 v = strtol(argv[0], &cp, 0);
898 if ((*cp != '\0') || (v < MIN_VCI) || (v >= 1 << 16)) {
899 fprintf(stderr, "%s: Invalid VCI value\n", prog);
902 apr->adr_pvc_vci = (u_short) v;
906 * Tell the kernel to delete the VCC
908 s = socket(AF_ATM, SOCK_DGRAM, 0);
912 if (ioctl(s, AIOCDEL, (caddr_t)apr) < 0) {
913 fprintf(stderr, "%s: ", prog);
916 fprintf(stderr, "Invalid parameter\n");
919 fprintf(stderr, "VCC not found\n");
922 fprintf(stderr, "VCC already being closed\n");
925 fprintf(stderr, "%s is not an ATM device\n",
929 fprintf(stderr, "Must be super user to use delete subcommand\n");
932 perror("ioctl (AIOCDEL) delete");
942 * Process ARP delete command
945 * atm delete arp <IP addr>
948 * argc number of arguments to command
949 * argv pointer to argument strings
950 * cmdp pointer to command description
957 arp_dlt(int argc, char **argv, struct cmd *cmdp)
960 struct atmdelreq apr;
961 struct sockaddr_in *sin;
963 struct sockaddr_in sin;
970 UM_ZERO(&apr, sizeof(apr));
971 apr.adr_opcode = AIOCS_DEL_ARP;
974 * Get network interface name if one is present
977 check_netif_name(argv[0]);
978 strcpy(apr.adr_arp_intf, argv[0]);
983 * Get IP address of specified host name
985 UM_ZERO(&host_addr, sizeof(host_addr));
986 host_addr.sa.sa_family = AF_INET;
987 sin = get_ip_addr(argv[0]);
988 host_addr.sin.sin_addr.s_addr = sin->sin_addr.s_addr;
989 apr.adr_arp_dst = host_addr.sa;
992 * Tell the kernel to delete the ARP table entry
994 s = socket(AF_ATM, SOCK_DGRAM, 0);
998 if (ioctl(s, AIOCDEL, (caddr_t)&apr) < 0) {
999 fprintf(stderr, "%s: ", prog);
1002 fprintf(stderr, "Invalid parameter\n");
1005 fprintf(stderr, "Must be super user to use delete subcommand\n");
1008 perror("ioctl (AIOCDEL) delete");
1018 * Process help command
1021 * argc number of arguments to command
1022 * argv pointer to argument strings
1023 * cmdp pointer to command description
1030 help(int argc, char **argv, struct cmd *cmdp)