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 $
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>
62 __RCSID("@(#) $FreeBSD: src/sbin/atm/atm/atm.c,v 1.3.2.1 2000/07/01 06:02:14 ps Exp $");
69 #define USAGE_STR "Interface management subcommands:\n\
70 attach <intf> <protocol>\n\
72 set mac <intf> <MAC/ESI address>\n\
73 set netif <intf> <prefix> <n>\n\
74 set prefix <intf> <NSAP prefix>\n\
75 show config [<intf>]\n\
76 show interface [<intf>]\n\
77 show netif [<netif>]\n\
78 show stats interface [<intf> phy | dev | atm | aal0 | aal4 |\n\
81 VC management subcommands:\n\
82 add pvc <intf> <vpi> <vci> <aal> <encaps> <owner> ...\n\
83 delete pvc <intf> <vpi> <vci>\n\
84 delete svc <intf> <vpi> <vci>\n\
85 show stats vcc [<intf> [vpi [vci]]]\n\
86 show vcc [<intf> [<vpi> [<vci>] | SVC | PVC]]\n\
88 IP management subcommands:\n\
89 add arp [<netif>] <IP addr> <ATM addr>\n\
90 add pvc <intf> <vpi> <vci> <aal> <encaps> IP <netif> <IP addr> |\n\
92 delete arp [<netif>] <IP addr>\n\
93 set arpserver <netif> <server> <IP prefix> ...\n\
95 show arpserver [<netif>]\n\
96 show ipvcc [<IP addr> | <netif>]\n\
98 Miscellaneous subcommands:\n\
107 struct cmd add_subcmd[];
108 struct cmd dlt_subcmd[];
109 struct cmd set_subcmd[];
110 struct cmd show_subcmd[];
111 struct cmd stats_subcmd[];
113 struct cmd cmds[] = {
114 { "add", 0, 0, NULL, (char *) add_subcmd },
115 { "attach", 2, 2, attach, "<intf> <protocol>" },
116 { "delete", 0, 0, NULL, (char *) dlt_subcmd },
117 { "detach", 1, 1, detach, "<intf>" },
118 { "set", 0, 0, NULL, (char *) set_subcmd },
119 { "show", 0, 0, NULL, (char *) show_subcmd },
120 { "help", 0, 99, help, "" },
121 { 0, 0, 0, NULL, "" }
124 struct cmd add_subcmd[] = {
125 { "arp", 2, 3, arp_add, "[<netif>] <IP addr> <ATM addr>" },
126 { "pvc", 6, 12, pvc_add, "<intf> <vpi> <vci> <aal> <encaps> <owner> ..." },
127 { 0, 0, 0, NULL, "" }
130 struct cmd dlt_subcmd[] = {
131 { "arp", 1, 2, arp_dlt, "[<netif>] <IP addr>" },
132 { "pvc", 3, 3, pvc_dlt, "<intf> <vpi> <vci>" },
133 { "svc", 3, 3, svc_dlt, "<intf> <vpi> <vci>" },
134 { 0, 0, 0, NULL, "" }
137 struct cmd set_subcmd[] = {
138 { "arpserver", 2, 18, set_arpserver, "<netif> <server>" },
139 { "mac", 2, 2, set_macaddr, "<intf> <MAC/ESI address>" },
140 { "netif", 3, 3, set_netif, "<intf> <prefix> <n>" },
141 { "prefix", 2, 2, set_prefix, "<intf> <NSAP prefix>" },
145 struct cmd show_subcmd[] = {
146 { "arp", 0, 1, show_arp, "[<host>]" },
147 { "arpserver", 0, 1, show_arpserv, "[<netif>]" },
148 { "config", 0, 1, show_config, "[<intf>]" },
149 { "interface", 0, 1, show_intf, "[<intf>]" },
150 { "ipvcc", 0, 3, show_ip_vcc, "[<IP addr> | <netif>]" },
151 { "netif", 0, 1, show_netif, "[<netif>]" },
152 { "stats", 0, 3, NULL, (char *) stats_subcmd },
153 { "vcc", 0, 3, show_vcc, "[<intf>] [<vpi> [<vci>] | SVC | PVC]" },
154 { "version", 0, 0, show_version, "" },
155 { 0, 0, 0, NULL, "" }
158 struct cmd stats_subcmd[] = {
159 { "interface", 0, 2, show_intf_stats, "[<intf> [cfg | phy | dev | atm | aal0 | aal4 | aal5 | driver]]" },
160 { "vcc", 0, 3, show_vcc_stats, "[<intf> [vpi [vci]]]" },
161 { 0, 0, 0, NULL, "" }
166 * Supported signalling protocols
168 struct proto protos[] = {
169 { "SIGPVC", ATM_SIG_PVC },
170 { "SPANS", ATM_SIG_SPANS },
171 { "UNI30", ATM_SIG_UNI30 },
172 { "UNI31", ATM_SIG_UNI31 },
173 { "UNI40", ATM_SIG_UNI40 },
178 * Supported VCC owners
180 struct owner owners[] = {
181 { "IP", ENDPT_IP, ip_pvcadd },
182 { "SPANS", ENDPT_SPANS_SIG,0 },
183 { "SPANS CLS", ENDPT_SPANS_CLS,0 },
184 { "UNI SIG", ENDPT_UNI_SIG, 0 },
189 * Supported AAL parameters
191 struct aal aals[] = {
192 { "Null", ATM_AAL0 },
193 { "AAL0", ATM_AAL0 },
194 { "AAL1", ATM_AAL1 },
195 { "AAL2", ATM_AAL2 },
196 { "AAL4", ATM_AAL3_4 },
197 { "AAL3", ATM_AAL3_4 },
198 { "AAL3/4", ATM_AAL3_4 },
199 { "AAL5", ATM_AAL5 },
204 * Supported VCC encapsulations
206 struct encaps encaps[] = {
207 { "Null", ATM_ENC_NULL },
208 { "None", ATM_ENC_NULL },
209 { "LLC/SNAP", ATM_ENC_LLC },
210 { "LLC", ATM_ENC_LLC },
211 { "SNAP", ATM_ENC_LLC },
217 char prefix[128] = "";
228 * Save program name, ignoring any path components
230 if ((prog = (char *)strrchr(argv[0], '/')) != NULL)
242 * Validate and process command
244 if ((error = do_cmd(cmds, argc, argv)) != 0)
252 * Validate and process user command
255 * descp pointer to command description array
256 * argc number of arguments left in command
257 * argv pointer to argument strings
264 do_cmd(descp, argc, argv)
269 struct cmd *cmdp = 0;
272 * Make sure we have paramaters to process
280 * Figure out what command user wants
282 for (; descp->name; descp++) {
284 * Use an exact match if there is one
286 if (!strcasecmp(descp->name, argv[0])) {
291 * Look for a match on the first part of keyword
293 if (!strncasecmp(descp->name, argv[0], strlen(argv[0]))) {
295 fprintf(stderr, "%s: Ambiguous parameter \"%s\"\n",
307 * See if this command has subcommands
309 if (cmdp->func == NULL) {
310 strcat(prefix, cmdp->name);
312 return(do_cmd((struct cmd *)cmdp->help, argc, argv));
318 if ((argc < cmdp->minp) || (argc > cmdp->maxp)) {
319 fprintf(stderr, "%s: Invalid number of arguments\n",
321 fprintf(stderr, "\tformat is: %s%s %s\n",
322 prefix, cmdp->name, cmdp->help);
329 (*cmdp->func)(argc, argv, cmdp);
335 * Print command usage information
338 * cmdp pointer to command description
339 * pref pointer current command prefix
350 fprintf(stderr, "usage: %s command [arg] [arg]...\n", prog);
351 fprintf(stderr, USAGE_STR);
356 * Process interface attach command
359 * atm attach <interface_name> <protocol_name>
362 * argc number of arguments to command
363 * argv pointer to argument strings
364 * cmdp pointer to command description
371 attach(argc, argv, cmdp)
376 struct atmcfgreq aar;
381 * Validate interface name
383 if (strlen(argv[0]) > sizeof(aar.acr_att_intf) - 1) {
384 fprintf(stderr, "%s: Illegal interface name\n", prog);
389 * Find/validate requested signalling protocol
391 for (prp = protos; prp->p_name; prp++) {
392 if (strcasecmp(prp->p_name, argv[1]) == 0)
395 if (prp->p_name == NULL) {
396 fprintf(stderr, "%s: Unknown signalling protocol\n", prog);
402 * Build ioctl request
404 aar.acr_opcode = AIOCS_CFG_ATT;
405 strncpy(aar.acr_att_intf, argv[0], sizeof(aar.acr_att_intf));
406 aar.acr_att_proto = prp->p_id;
409 * Tell the kernel to do the attach
411 s = socket(AF_ATM, SOCK_DGRAM, 0);
415 if (ioctl(s, AIOCCFG, (caddr_t)&aar) < 0) {
416 fprintf(stderr, "%s: ", prog);
420 case EPROTONOSUPPORT:
421 perror("Internal error");
424 fprintf(stderr, "Kernel memory exhausted\n");
427 fprintf(stderr, "Signalling manager already attached to %s\n",
431 fprintf(stderr, "ATM network is inoperable\n");
434 fprintf(stderr, "Must be super user to use attach subcommand\n");
437 fprintf(stderr, "%s is not an ATM device\n",
441 fprintf(stderr, "%s has too few or too many network interfaces\n",
445 perror("Ioctl (AIOCCFG) attach");
455 * Process interface detach command
458 * atm detach <interface_name>
461 * argc number of arguments to command
462 * argv pointer to argument strings
463 * cmdp pointer to command description
470 detach(argc, argv, cmdp)
475 struct atmcfgreq adr;
479 * Validate interface name
481 if (strlen(argv[0]) > sizeof(adr.acr_det_intf) - 1) {
482 fprintf(stderr, "%s: Illegal interface name\n", prog);
487 * Build ioctl request
489 adr.acr_opcode = AIOCS_CFG_DET;
490 strncpy(adr.acr_det_intf, argv[0], sizeof(adr.acr_det_intf));
493 * Tell the kernel to do the detach
495 s = socket(AF_ATM, SOCK_DGRAM, 0);
499 if (ioctl(s, AIOCCFG, (caddr_t)&adr) < 0) {
500 fprintf(stderr, "%s: ", prog);
503 fprintf(stderr, "Signalling manager already detaching from %s\n",
507 perror("Internal error");
510 fprintf(stderr, "Must be super user to use detach subcommand\n");
513 perror("ioctl (AIOCCFG) detach");
523 * Process PVC add command
526 * atm add PVC <interface_name> <vpi> <vci> <aal> <encaps>
530 * argc number of arguments to command
531 * argv pointer to argument strings
532 * cmdp pointer to command description
539 pvc_add(argc, argv, cmdp)
544 struct atmaddreq apr;
545 struct atminfreq air;
546 struct air_int_rsp *int_info;
555 * Initialize opcode and flags
557 apr.aar_opcode = AIOCS_ADD_PVC;
558 apr.aar_pvc_flags = 0;
561 * Validate interface name and issue an information
562 * request IOCTL for the interface
564 if (strlen(argv[0]) > sizeof(apr.aar_pvc_intf) - 1) {
565 fprintf(stderr, "%s: Illegal interface name\n", prog);
568 UM_ZERO(air.air_int_intf, sizeof(air.air_int_intf));
569 strcpy(air.air_int_intf, argv[0]);
570 buf_len = sizeof(struct air_int_rsp);
571 air.air_opcode = AIOCS_INF_INT;
572 buf_len = do_info_ioctl(&air, buf_len);
574 fprintf(stderr, "%s: ", prog);
578 perror("Internal error");
581 fprintf(stderr, "%s is not an ATM device\n",
585 perror("ioctl (AIOCINFO)");
590 int_info = (struct air_int_rsp *) air.air_buf_addr;
591 strcpy(apr.aar_pvc_intf, argv[0]);
595 * Validate vpi/vci values
597 v = strtol(argv[0], &cp, 0);
598 if ((*cp != '\0') || (v < 0) || (v >= 1 << 8)) {
599 fprintf(stderr, "%s: Invalid VPI value\n", prog);
602 apr.aar_pvc_vpi = (u_short) v;
605 v = strtol(argv[0], &cp, 0);
606 if ((*cp != '\0') || (v < MIN_VCI) || (v >= 1 << 16)) {
607 fprintf(stderr, "%s: Invalid VCI value\n", prog);
610 apr.aar_pvc_vci = (u_short) v;
614 * Validate requested PVC AAL
616 for (alp = aals; alp->a_name; alp++) {
617 if (strcasecmp(alp->a_name, argv[0]) == 0)
620 if (alp->a_name == NULL) {
621 fprintf(stderr, "%s: Invalid PVC AAL\n", prog);
624 apr.aar_pvc_aal = alp->a_id;
628 * Validate requested PVC encapsulation
630 for (enp = encaps; enp->e_name; enp++) {
631 if (strcasecmp(enp->e_name, argv[0]) == 0)
634 if (enp->e_name == NULL) {
635 fprintf(stderr, "%s: Invalid PVC encapsulation\n", prog);
638 apr.aar_pvc_encaps = enp->e_id;
642 * Validate requested PVC owner
644 for (owp = owners; owp->o_name; owp++) {
645 if (strcasecmp(owp->o_name, argv[0]) == 0)
648 if (owp->o_name == NULL) {
649 fprintf(stderr, "%s: Unknown PVC owner\n", prog);
652 apr.aar_pvc_sap = owp->o_sap;
656 * Perform service user processing
659 (*owp->o_pvcadd)(argc, argv, cmdp, &apr, int_info);
661 fprintf(stderr, "%s: Unsupported PVC owner\n", prog);
666 * Tell the kernel to add the PVC
668 s = socket(AF_ATM, SOCK_DGRAM, 0);
672 if (ioctl(s, AIOCADD, (caddr_t)&apr) < 0) {
673 fprintf(stderr, "%s: ", prog);
675 case EPROTONOSUPPORT:
677 perror("Internal error");
680 fprintf(stderr, "Invalid parameter\n");
683 fprintf(stderr, "PVC already exists\n");
686 fprintf(stderr, "ATM network is inoperable\n");
689 fprintf(stderr, "Kernel memory exhausted\n");
692 fprintf(stderr, "Must be super user to use add subcommand\n");
695 fprintf(stderr, "Invalid VPI or VCI value\n");
698 perror("ioctl (AIOCADD) add PVC");
708 * Process ARP add command
711 * atm add arp [<netif>] <IP addr> <ATM addr>
714 * argc number of arguments to command
715 * argv pointer to argument strings
716 * cmdp pointer to command description
723 arp_add(argc, argv, cmdp)
729 struct atmaddreq apr;
731 struct sockaddr_in *sin;
733 struct sockaddr_in sin;
738 * Initialize add request structure
740 UM_ZERO(&apr, sizeof(apr));
743 * Get network interface name if one is present
746 check_netif_name(argv[0]);
747 strcpy(apr.aar_arp_intf, argv[0]);
752 * Get IP address of specified host name
754 UM_ZERO(&host_ip, sizeof(host_ip));
755 host_ip.sa.sa_family = AF_INET;
756 sin = get_ip_addr(argv[0]);
757 host_ip.sin.sin_addr.s_addr = sin->sin_addr.s_addr;
761 * Get specified ATM address
763 len = get_hex_atm_addr(argv[0], (u_char *)host_atm.address,
764 sizeof(Atm_addr_nsap));
766 case sizeof(Atm_addr_nsap):
767 host_atm.address_format = T_ATM_ENDSYS_ADDR;
768 host_atm.address_length = sizeof(Atm_addr_nsap);
770 case sizeof(Atm_addr_spans):
771 host_atm.address_format = T_ATM_SPANS_ADDR;
772 host_atm.address_length = sizeof(Atm_addr_spans);
775 fprintf(stderr, "%s: Invalid ATM address\n", prog);
780 * Build IOCTL request
782 apr.aar_opcode = AIOCS_ADD_ARP;
783 apr.aar_arp_dst = host_ip.sa;
784 ATM_ADDR_COPY(&host_atm, &apr.aar_arp_addr);
785 apr.aar_arp_origin = ARP_ORIG_PERM;
788 * Tell the kernel to add the ARP table entry
790 s = socket(AF_ATM, SOCK_DGRAM, 0);
794 if (ioctl(s, AIOCADD, (caddr_t)&apr) < 0) {
795 fprintf(stderr, "%s: ", prog);
798 fprintf(stderr, "Invalid parameter\n");
801 fprintf(stderr, "Must be super user to use add subcommand\n");
804 fprintf(stderr, "IP address not valid for interface\n");
807 perror("ioctl (AIOCADD) add");
817 * Process PVC delete command
820 * atm delete pvc <interface_name> <vpi> <vci>
823 * argc number of arguments to command
824 * argv pointer to argument strings
825 * cmdp pointer to command description
832 pvc_dlt(argc, argv, cmdp)
837 struct atmdelreq apr;
842 apr.adr_opcode = AIOCS_DEL_PVC;
845 * Complete request by calling subroutine
847 vcc_dlt(argc, argv, cmdp, &apr);
852 * Process SVC delete command
855 * atm delete svc <interface_name> <vpi> <vci>
858 * argc number of arguments to command
859 * argv pointer to argument strings
860 * cmdp pointer to command description
867 svc_dlt(argc, argv, cmdp)
872 struct atmdelreq apr;
877 apr.adr_opcode = AIOCS_DEL_SVC;
880 * Complete request by calling subroutine
882 vcc_dlt(argc, argv, cmdp, &apr);
887 * Complete an SVC or PVC delete command
890 * argc number of arguments to command
891 * argv pointer to argument strings
892 * cmdp pointer to command description
893 * apr pointer to ATM delete IOCTL structure
900 vcc_dlt(argc, argv, cmdp, apr)
904 struct atmdelreq *apr;
911 * Validate interface name
913 if (strlen(argv[0]) > sizeof(apr->adr_pvc_intf) - 1) {
914 fprintf(stderr, "%s: Illegal interface name\n", prog);
917 strcpy(apr->adr_pvc_intf, argv[0]);
921 * Validate vpi/vci values
923 v = strtol(argv[0], &cp, 0);
924 if ((*cp != '\0') || (v < 0) || (v >= 1 << 8)) {
925 fprintf(stderr, "%s: Invalid VPI value\n", prog);
928 apr->adr_pvc_vpi = (u_short) v;
931 v = strtol(argv[0], &cp, 0);
932 if ((*cp != '\0') || (v < MIN_VCI) || (v >= 1 << 16)) {
933 fprintf(stderr, "%s: Invalid VCI value\n", prog);
936 apr->adr_pvc_vci = (u_short) v;
940 * Tell the kernel to delete the VCC
942 s = socket(AF_ATM, SOCK_DGRAM, 0);
946 if (ioctl(s, AIOCDEL, (caddr_t)apr) < 0) {
947 fprintf(stderr, "%s: ", prog);
950 fprintf(stderr, "Invalid parameter\n");
953 fprintf(stderr, "VCC not found\n");
956 fprintf(stderr, "VCC already being closed\n");
959 fprintf(stderr, "%s is not an ATM device\n",
963 fprintf(stderr, "Must be super user to use delete subcommand\n");
966 perror("ioctl (AIOCDEL) delete");
976 * Process ARP delete command
979 * atm delete arp <IP addr>
982 * argc number of arguments to command
983 * argv pointer to argument strings
984 * cmdp pointer to command description
991 arp_dlt(argc, argv, cmdp)
997 struct atmdelreq apr;
998 struct sockaddr_in *sin;
1000 struct sockaddr_in sin;
1007 UM_ZERO(&apr, sizeof(apr));
1008 apr.adr_opcode = AIOCS_DEL_ARP;
1011 * Get network interface name if one is present
1014 check_netif_name(argv[0]);
1015 strcpy(apr.adr_arp_intf, argv[0]);
1020 * Get IP address of specified host name
1022 UM_ZERO(&host_addr, sizeof(host_addr));
1023 host_addr.sa.sa_family = AF_INET;
1024 sin = get_ip_addr(argv[0]);
1025 host_addr.sin.sin_addr.s_addr = sin->sin_addr.s_addr;
1026 apr.adr_arp_dst = host_addr.sa;
1029 * Tell the kernel to delete the ARP table entry
1031 s = socket(AF_ATM, SOCK_DGRAM, 0);
1035 if (ioctl(s, AIOCDEL, (caddr_t)&apr) < 0) {
1036 fprintf(stderr, "%s: ", prog);
1039 fprintf(stderr, "Invalid parameter\n");
1042 fprintf(stderr, "Must be super user to use delete subcommand\n");
1045 perror("ioctl (AIOCDEL) delete");
1055 * Process help command
1058 * argc number of arguments to command
1059 * argv pointer to argument strings
1060 * cmdp pointer to command description
1067 help(argc, argv, cmdp)