/* ****************************************************************************** * SOURCE FILE * * Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipl2tp_cmd.c,v $ $Revision: 1.21.14.2 $ * $Source: /home/interpeak/CVSRoot/ipl2tp/src/ipl2tp_cmd.c,v $ * $Author: jren $ * $State: Exp $ $Locker: $ * * INTERPEAK_COPYRIGHT_STRING * ****************************************************************************** */ /* **************************************************************************** * DESCRIPTION **************************************************************************** * * Command-line service routines. */ /* **************************************************************************** * INCLUDE FILES **************************************************************************** */ #define IPCOM_USE_CLIB_PROTO #include "ipcom.h" #include "ipcom_os.h" #include "ipcom_shell.h" #include "ipcom_sock2.h" #include "ipcom_sock6.h" #include "ipcom_cmd.h" #include "ipl2tp.h" #include "ipl2tp_api.h" #include "ipl2tp_api_session.h" #include "ipl2tp_api_tunnel.h" #include "ipl2tp_attr.h" #include "ipl2tp_cmd.h" /* **************************************************************************** * DEFINES **************************************************************************** */ /* L2TP control port */ #define IPL2TP_PORT_NUMBER 1701 /* Extra header space allocated before L2TP header */ #define HEADER_SPACE 0 #define IPL2TP_CMD_ATTR_DELIM " \t=," /* "poke" command used for debugging */ #ifdef IPL2TP_ALLOW_CMD_POKE #undef IPL2TP_ALLOW_CMD_POKE #endif /*lint -e534*/ /* **************************************************************************** * TYPES **************************************************************************** */ typedef struct Ipl2tp_cmd_session_key { Ip_u32 ifindex; Ipl2tp_key key; } Ipl2tp_cmd_session_key; /* **************************************************************************** * LOCAL DATA **************************************************************************** */ /* Output formatting */ #define IPL2TP_CMD_GET 1 #define IPL2TP_CMD_SET 2 IP_STATIC Ipcom_cmd_int_str_map ipl2tp_cmd_getset[] = { { IPL2TP_CMD_GET, "get" }, { IPL2TP_CMD_SET, "set" }, { 0, 0 } }; #define IPL2TP_CMD_POKE 1 #define IPL2TP_CMD_ATTR 2 #define IPL2TP_CMD_SATTR 3 #define IPL2TP_CMD_TATTR 4 #define IPL2TP_CMD_STATS 5 #define IPL2TP_CMD_SSTATS 6 #define IPL2TP_CMD_TSTATS 7 #define IPL2TP_CMD_TOPEN 8 #define IPL2TP_CMD_TCLOSE 9 #define IPL2TP_CMD_SOPEN 10 #define IPL2TP_CMD_SCLOSE 11 IP_STATIC Ipcom_cmd_int_str_map ipl2tp_cmd_cmds[] = { #ifdef IPL2TP_ALLOW_CMD_POKE { IPL2TP_CMD_POKE, "poke" }, #endif { IPL2TP_CMD_ATTR, "attr" }, { IPL2TP_CMD_SATTR, "sattr" }, { IPL2TP_CMD_TATTR, "tattr" }, { IPL2TP_CMD_STATS, "stats" }, { IPL2TP_CMD_SSTATS, "sstats" }, { IPL2TP_CMD_TSTATS, "tstats" }, { IPL2TP_CMD_TOPEN, "topen" }, { IPL2TP_CMD_TCLOSE, "tclose" }, { IPL2TP_CMD_SOPEN, "sopen" }, { IPL2TP_CMD_SCLOSE, "sclose" }, { 0, 0 } }; /* List of sessions per interface */ IP_STATIC Ipcom_hash *ipl2tp_cmd_session_hash_table = IP_NULL; IP_STATIC Ipcom_once_t ipl2tp_cmd_session_once = IPCOM_ONCE_INIT; /* **************************************************************************** * PUBLIC DATA **************************************************************************** */ /* Poke vars */ IP_PUBLIC int poke_count = 0; IP_PUBLIC int poke_mtype = 0; IP_PUBLIC int poke_avp = 0; IP_PUBLIC int poke_offset = 0; IP_PUBLIC int poke_value = 0; IP_PUBLIC int poke_skip = 0; IP_PUBLIC char ipl2tp_poke_abort[4] = ""; /* **************************************************************************** * PROTOTYPES **************************************************************************** */ /* **************************************************************************** * LOCAL FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipl2tp_cmd_attr_print_hdr *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC void ipl2tp_cmd_attr_print_hdr(Ipl2tp_attr_info *attr) { int len = (int)ipcom_strlen(attr->name); ipcom_printf(" %s", attr->name); if (len < 32) { char buf[64]; ipcom_snprintf(buf, sizeof(buf), "%%%ds", 32 - len); ipcom_printf(buf, ": "); } else { ipcom_printf(":"); } } /* *=========================================================================== * ipl2tp_cmd_attr_print_attr *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC void ipl2tp_cmd_attr_print_attr(Ipl2tp_attr a, Ipl2tp_attr_info *attr) { if (attr->type == IPL2TP_ATTR_TYPE_VECTOR || attr->type == IPL2TP_ATTR_TYPE_NONE) return; ipl2tp_cmd_attr_print_hdr(attr); switch (attr->type) { case IPL2TP_ATTR_TYPE_STRING: ipcom_printf("%s"IP_LF, ipl2tp_attr_strdata(a)); break; case IPL2TP_ATTR_TYPE_SEC: ipcom_printf("%u s"IP_LF, ipl2tp_attr_idata(a)); break; case IPL2TP_ATTR_TYPE_INT: if (attr->hr != IP_NULL) { ipcom_printf("%s"IP_LF, attr->hr[ipl2tp_attr_idata(a)]); } else { ipcom_printf("%u"IP_LF, ipl2tp_attr_idata(a)); } break; case IPL2TP_ATTR_TYPE_INT64: { Ip_u64 v; ipl2tp_attr_idata64(a, &v); ipcom_printf("hi=%lu lo=%lu"IP_LF, IP_U64_GETHI(v), IP_U64_GETLO(v)); } break; case IPL2TP_ATTR_TYPE_ADDRESS: { union Ip_sockaddr_union *addr = ipl2tp_attr_addrdata(a); char buf[64]; if(addr == IP_NULL) { return; } switch (addr->sa.sa_family) { case IP_AF_INET: ipcom_inet_ntop(IP_AF_INET, &addr->sin.sin_addr, buf, sizeof(buf)); break; #ifdef IPCOM_USE_INET6 case IP_AF_INET6: ipcom_inet_ntop(IP_AF_INET6, &addr->sin6.sin6_addr, buf, sizeof(buf)); break; #endif default: ipcom_strcpy(buf, ""); break; } ipcom_printf("%s"IP_LF, buf); } break; case IPL2TP_ATTR_TYPE_KEY: { Ipl2tp_key *key = ipl2tp_attr_keydata(a); if(key == IP_NULL) { return; } ipcom_printf("v%u %u"IP_LF, key->version, key->ident); } break; case IPL2TP_ATTR_TYPE_FUNCTION: case IPL2TP_ATTR_TYPE_POINTER: ipcom_printf("%p"IP_LF, ipl2tp_attr_pdata(a)); break; case IPL2TP_ATTR_TYPE_VEC8: { Ip_size_t len = ipl2tp_attr_length(a); Ip_u8 *vdata = ipl2tp_attr_vdata(a); Ip_size_t i; for (i = 0; i < len; i++) { if (attr->hr) { ipcom_printf("%s%s", i? "," : "", attr->hr[vdata[i]]); } else { ipcom_printf("%s%u", i? "," : "", (int)vdata[i]); } } ipcom_printf(IP_LF); } break; case IPL2TP_ATTR_TYPE_VEC16: { Ip_size_t len = ipl2tp_attr_length(a); Ip_u16 *vdata = (Ip_u16 *)ipl2tp_attr_vdata(a); Ip_size_t i; len /= 2; for (i = 0; i < len; i++) { Ip_u16 val; ipcom_memcpy(&val, vdata + i, sizeof(val)); if (attr->hr) { ipcom_printf("%s%s", i? "," : "", attr->hr[val]); } else { ipcom_printf("%s%u", i? "," : "", (int) val); } } ipcom_printf(IP_LF); } break; } } /* *=========================================================================== * ipl2tp_cmd_attr_list *=========================================================================== * Description: List all available attributes * Parameters: info - The attribute list. * rw - IP_TRUE if we're only interested in RW attr. * Returns: * */ IP_STATIC void ipl2tp_cmd_attr_list(Ipl2tp_attr_info *info, Ip_bool rw) { int i; ipcom_printf("Available %s attributes:"IP_LF, rw? "Read/Write" : "Read"); for (i = 0; info[i].value != 0; i++) { /* If we're looking at read/write */ if (rw && info->rw != rw) continue; ipcom_printf(" %s"IP_LF, info[i].name); } } /* *=========================================================================== * ipl2tp_cmd_attr_print_syntax *=========================================================================== * Description: Print the syntax of an attribute * Parameters: info - The attribute * Returns: * */ IP_STATIC void ipl2tp_cmd_attr_print_syntax(Ipl2tp_attr_info *info) { int i; ipcom_printf("%s: ", info->name); switch (info->type) { case IPL2TP_ATTR_TYPE_STRING: ipcom_printf(""IP_LF); break; case IPL2TP_ATTR_TYPE_SEC: ipcom_printf(""IP_LF); break; case IPL2TP_ATTR_TYPE_INT: if (info->hr) { int first = 0; for (i = 0; info->hr[i] != IP_NULL; i++) { if (ipcom_strlen(info->hr[i]) == 0) continue; ipcom_printf("%s%s", first == 0? "<" : "|", info->hr[i]); first++; } ipcom_printf(">"IP_LF); } else { ipcom_printf("<32 bit integer>"IP_LF); } break; case IPL2TP_ATTR_TYPE_INT64: ipcom_printf("<64 bit integer>"IP_LF); break; case IPL2TP_ATTR_TYPE_ADDRESS: ipcom_printf(""IP_LF); break; case IPL2TP_ATTR_TYPE_KEY: ipcom_printf(" "IP_LF); break; case IPL2TP_ATTR_TYPE_FUNCTION: case IPL2TP_ATTR_TYPE_POINTER: ipcom_printf(""IP_LF); break; case IPL2TP_ATTR_TYPE_VECTOR: ipcom_printf(""IP_LF); break; case IPL2TP_ATTR_TYPE_VEC8: if (info->hr) { int first = 0; ipcom_printf("hr[i] != IP_NULL; i++) { if (ipcom_strlen(info->hr[i]) == 0) continue; ipcom_printf("%s%s", first == 0? "" : "|", info->hr[i]); first++; } ipcom_printf(" or hexadecimal array (0xabcd)>"IP_LF); } else { ipcom_printf(""IP_LF); } break; case IPL2TP_ATTR_TYPE_VEC16: if (info->hr) { int first = 0; ipcom_printf("hr[i] != IP_NULL; i++) { if (ipcom_strlen(info->hr[i]) == 0) continue; ipcom_printf("%s%s", first == 0? "" : "|", info->hr[i]); first++; } ipcom_printf(" or hexadecimal array (0xabcd)>"IP_LF); } else { ipcom_printf(""IP_LF); } break; default: case IPL2TP_ATTR_TYPE_NONE: ipcom_printf("no available input method"IP_LF); break; } } /* *=========================================================================== * ipl2tp_cmd_session_obj_hash_ifindex *=========================================================================== * Description: * Parameters: * Returns: */ IP_STATIC unsigned ipl2tp_cmd_session_obj_hash_ifindex(Ipl2tp_cmd_session_key *key) { /* Hash the tunnel ifindex ID */ return ipcom_hash_update(&key->ifindex, sizeof(key->ifindex), 0); } /* *=========================================================================== * ipl2tp_cmd_session_key_hash_ifindex *=========================================================================== * Description: * Parameters: * Returns: */ IP_STATIC unsigned ipl2tp_cmd_session_key_hash_ifindex(Ip_u32 *ifindex) { /* Hash the tunnel ifindex ID */ return ipcom_hash_update(ifindex, sizeof(*ifindex), 0); } /* *=========================================================================== * ipl2tp_cmd_session_cmp_ifindex *=========================================================================== * Description: * Parameters: * Returns: */ IP_STATIC Ip_bool ipl2tp_cmd_session_cmp_ifindex(Ipl2tp_cmd_session_key *key, Ip_u32 *ifindex) { return key->ifindex == *ifindex; } /* *=========================================================================== * ipcom_shellalias_init *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC Ip_err ipl2tp_cmd_session_init(void *unused) { (void)unused; /* The address tunnel hash */ ipl2tp_cmd_session_hash_table = ipcom_hash_new((Ipcom_hash_obj_func)ipl2tp_cmd_session_obj_hash_ifindex, (Ipcom_hash_key_func)ipl2tp_cmd_session_key_hash_ifindex, (Ipcom_hash_cmp_func)ipl2tp_cmd_session_cmp_ifindex); return IPCOM_SUCCESS; } /* *=========================================================================== * ipl2tp_cmd_session_wait_establish *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC Ipl2tp_status ipl2tp_cmd_session_wait_establish(Ipl2tp_key *key, int timeout) { Ipl2tp_attrobj attr = IP_NULL; Ipl2tp_attrobj replies = IP_NULL; Ipl2tp_status status = IPL2TP_STATUS_TIMEOUT; /* While we've gotten timeout left */ while (timeout--) { int oper; Ipl2tp_attr a; /* Retrieve the administrative status of the tunnel, wait * until we're established or we've failed, or the timeout's * elapsed */ ipl2tp_attr_clear(attr); ipl2tp_attr_clear(replies); ipl2tp_attr_add_query(&attr, IPL2TP_SATTR_GET_l2tpSessionStatsState); if ((status = ipl2tp_api_session_attribute_get(key,attr,&replies)) != IPL2TP_STATUS_OK) break; if((a = ipl2tp_attr_first(replies)) == IP_NULL) break; oper = ipl2tp_attr_idata(a); if (oper == IPL2TP_MIB_CONNECTING) { status = IPL2TP_STATUS_TIMEOUT; if (timeout) ipcom_sleep(1); } else if (oper == IPL2TP_MIB_ESTABLISHED) { /* We're done */ break; } else { /* We're in disconnecting or idle state */ status = IPL2TP_STATUS_TEARDOWN; break; } } ipl2tp_attr_delete(&attr); ipl2tp_attr_delete(&replies); /* OK */ return status; } /* *=========================================================================== * ipl2tp_cmd_tunnel_wait_establish *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC Ipl2tp_status ipl2tp_cmd_tunnel_wait_establish(Ipl2tp_key *key, int timeout) { Ipl2tp_attrobj attr = IP_NULL; Ipl2tp_attrobj replies = IP_NULL; Ipl2tp_status status = IPL2TP_STATUS_TIMEOUT; /* While we've gotten timeout left */ while (timeout--) { int oper; Ipl2tp_attr a; /* Retrieve the administrative status of the tunnel, wait * until we're established or we've failed, or the timeout's * elapsed */ ipl2tp_attr_clear(attr); ipl2tp_attr_clear(replies); ipl2tp_attr_add_query(&attr, IPL2TP_TATTR_GET_l2tpTunnelStatsState); if ((status = ipl2tp_api_tunnel_attribute_get(key,attr,&replies)) != IPL2TP_STATUS_OK) break; if((a = ipl2tp_attr_first(replies)) == IP_NULL) break; oper = ipl2tp_attr_idata(a); if (oper == IPL2TP_MIB_CONNECTING) { status = IPL2TP_STATUS_TIMEOUT; if (timeout) ipcom_sleep(1); } else if (oper == IPL2TP_MIB_ESTABLISHED) { /* We're done */ break; } else { /* We're in disconnecting or idle state */ status = IPL2TP_STATUS_TEARDOWN; break; } } ipl2tp_attr_delete(&attr); ipl2tp_attr_delete(&replies); /* OK */ return status; } /* **************************************************************************** * PUBLIC FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipl2tp_cmd_session_key *=========================================================================== * Description: Find a session key based on ifindex * Parameters: ifindex - The interface index. * Returns: * */ IP_PUBLIC Ipl2tp_key * ipl2tp_cmd_session_key(Ip_u32 ifindex) { Ipl2tp_cmd_session_key *key; Ip_err err; err = ipcom_once(&ipl2tp_cmd_session_once, ipl2tp_cmd_session_init, IP_NULL); if (err != IPCOM_SUCCESS) return IP_NULL; key = ipcom_hash_get(ipl2tp_cmd_session_hash_table, &ifindex); if (key) return &key->key; return IP_NULL; } /* *=========================================================================== * ipl2tp_cmd_session_hash_add *=========================================================================== * Description: Add an interface index - session ID pair to the hash table. * Parameters: ifindex - The interface index. * skey - pointer to key having session ID. * Returns: None. * */ IP_PUBLIC Ip_err ipl2tp_cmd_session_hash_add(Ip_u32 ifindex, Ipl2tp_key *skey) { Ip_err err; Ipl2tp_cmd_session_key *ikey = ipcom_malloc(sizeof(*ikey)); if(ikey == IP_NULL) { return IPCOM_ERR_FAILED; } err = ipcom_once(&ipl2tp_cmd_session_once, ipl2tp_cmd_session_init, IP_NULL); if (err != IPCOM_SUCCESS) { ipcom_free(ikey); return err; } ikey->ifindex = ifindex; ipcom_memcpy(&ikey->key, skey, sizeof(Ipl2tp_key)); return (ipcom_hash_add(ipl2tp_cmd_session_hash_table, ikey)); } /* *=========================================================================== * ipl2tp_cmd_session_hash_remove *=========================================================================== * Description: Find a session key based on ifindex * Parameters: ifindex - The interface index. * Returns: * */ IP_PUBLIC Ip_err ipl2tp_cmd_session_hash_remove(Ip_u32 ifindex) { Ipl2tp_cmd_session_key *key; Ip_err err; err = ipcom_once(&ipl2tp_cmd_session_once, ipl2tp_cmd_session_init, IP_NULL); if (err != IPCOM_SUCCESS) return err; key = ipcom_hash_get(ipl2tp_cmd_session_hash_table, &ifindex); if (key == IP_NULL) return IPCOM_ERR_NOT_FOUND; return(ipcom_hash_remove(ipl2tp_cmd_session_hash_table, key)); } /* *=========================================================================== * ipl2tp_cmd_topen *=========================================================================== * Description: Tunnel open command. * Parameters: argc - No of arguments. * argv - Argument vector. * Returns: 0 if success. * */ IP_PUBLIC int ipl2tp_cmd_topen(int argc, char **argv) { Ipl2tp_attrobj tattr = IP_NULL; union Ip_sockaddr_union uaddr; Ipl2tp_key tkey[2]; Ipl2tp_status status; int establish = 1; int opt; int timeout = 10; Ip_bool hs = IP_FALSE; if (argc < 2) goto usage; ipcom_getopt_clear(); ipcom_memset(tkey, 0, sizeof(tkey)); /* Get options */ tkey[0].version = IPL2TP_VERSION_L2TPV2; while ((opt = ipcom_getopt(argc, argv, "d23w:")) != -1) { switch (opt) { case '3': tkey[0].version = IPL2TP_VERSION_L2TPV3; break; case '2': hs = IP_TRUE; break; case 'd': establish = 0; break; case 'w': timeout = (int)ipcom_strtoul(ip_optarg, IP_NULL, 10); break; default: goto usage; } } /* Host address must be supplied */ if (ip_optind == argc) goto usage; /* Get host */ if ((ipcom_strchr(argv[ip_optind], '.') == IP_NULL) || (ipl2tp_api_attribute_address_parse(argv[ip_optind], &uaddr) == IP_FALSE)) { ipcom_printf("l2tp topen: unknown host %s"IP_LF, argv[ip_optind]); return -1; } /* Move past the host */ ip_optind++; /* Set some default tunnel attributes */ if (hs || tkey[0].version == IPL2TP_VERSION_L2TPV2) { if ((status = ipl2tp_attr_iappend(&tattr, IPL2TP_TATTR_SET_FRAMING_CAPABILITIES, IPL2TP_MIB_FRAMING_ASYNC)) != IPL2TP_STATUS_OK || (status = ipl2tp_attr_iappend(&tattr, IPL2TP_TATTR_SET_BEARER_CAPABILITIES, IPL2TP_MIB_BEARER_ANALOG)) != IPL2TP_STATUS_OK) { ipcom_printf("l2tp topen: failed to set default attributes: error %d, %s"IP_LF, (int)status, ipl2tp_api_errname(status)); return -1; } } /* Do go through the remaining attributes */ for (; ip_optind < argc; ip_optind++) { Ipl2tp_attr_info *info; char *value = IP_NULL; if ((info = ipl2tp_api_attribute_find(ipl2tp_tunnel_tags, argv[ip_optind], &value)) == IP_NULL) { ipcom_printf("l2tp topen: unknown attribute name %s"IP_LF, argv[ip_optind]); return -1; } /* Parse the value */ if (ipl2tp_api_attribute_parse(&tattr, info, &value) == IP_FALSE) { ipcom_printf("l2tp topen: error parsing value"IP_LF); ipl2tp_cmd_attr_print_syntax(info); return -1; } } /* Open session */ if ((status = ipl2tp_api_tunnel_open(tkey, &uaddr, tattr, establish, hs)) == IPL2TP_STATUS_OK) { /* If the second key's version field is zero, we don't have a versioning */ if (tkey[1].version == 0) hs = IP_FALSE; if (establish) { Ipl2tp_key *key = &tkey[0]; if (hs) { while (timeout) { int ret = ipl2tp_api_tunnel_negotiation(tkey, &key); if (ret == IPL2TP_STATUS_OK) break; if (ret == IPL2TP_STATUS_NEGOTIATION) { timeout--; ipcom_sleep(1); continue; } break; } if (key == IP_NULL) { ipcom_printf("l2tp topen: failed to negotiate tunnel: %s"IP_LF, ipl2tp_api_errname(status)); goto done; } } if ((status = ipl2tp_cmd_tunnel_wait_establish(key, timeout)) != IPL2TP_STATUS_OK) { if (status != IPL2TP_STATUS_TIMEOUT) { ipcom_printf("l2tp topen: failed to create tunnel: %s"IP_LF, ipl2tp_api_errname(status)); } else { ipcom_printf("l2tp topen: tunnel still connecting"IP_LF); } } else { ipcom_printf("l2tp topen: tunnel v%u ident=%u successfully opened"IP_LF, key->version, key->ident); } } else { ipcom_printf("l2tp topen: tunnel v%u ident=%u opened in passive mode"IP_LF, tkey[0].version, tkey[0].ident); } } else { ipcom_printf("l2tp topen: error %d, %s"IP_LF, (int)status, ipl2tp_api_errname(status)); } done: /* Release attribute object */ ipl2tp_attr_delete(&tattr); return status == IPL2TP_STATUS_OK ? 0 : -1; usage: ipcom_printf("usage: l2tp topen [-3] [-2] [-d] [-w timeout] [ATTRIBUTES]"IP_LF "Parameters:"IP_LF "-3 L2TP v3"IP_LF "-d Open tunnel in DOWN state."IP_LF "-w timeout Number of seconds to wait and see if the tunnel was established"IP_LF " Host name or IP address."IP_LF); return -1; } /* *=========================================================================== * ipl2tp_cmd_topen *=========================================================================== * Description: Tunnel open command. * Parameters: argc - No of arguments. * argv - Argument vector. * Returns: 0 if success. * */ IP_PUBLIC int ipl2tp_cmd_tclose(int argc, char **argv) { int opt; Ipl2tp_key tkey; Ipl2tp_status status; ipcom_getopt_clear(); /**/ tkey.version = IPL2TP_VERSION_L2TPV2; tkey.ident = 0; /* Get options */ while ((opt = ipcom_getopt(argc, argv, "23")) != -1) { switch (opt) { case '3': tkey.version = IPL2TP_VERSION_L2TPV3; break; case '2': tkey.version = IPL2TP_VERSION_L2TPV2; break; default: goto usage; } } if (ip_optind == argc) goto usage; tkey.ident = 0; if (ipcom_strcmp(argv[ip_optind], "all") == 0) { Ipl2tp_key nkey; /* Nothing at all */ if (ipl2tp_api_tunnel_next(&tkey, &nkey) != IPL2TP_STATUS_OK) return 0; do { /* Copy data */ ipcom_memcpy(&tkey, &nkey, sizeof(tkey)); /* TKEY contains current, get next */ status = ipl2tp_api_tunnel_next(&tkey, &nkey); ipcom_printf("ipl2tp tclose: disconnecting tunnel v%u %u"IP_LF, tkey.version, tkey.ident); /* Close the tunnel */ ipl2tp_api_tunnel_close(&tkey); /* Next version? */ if (tkey.version != nkey.version) break; } while (status == IPL2TP_STATUS_OK); } else { /* Grab the tunnel key */ tkey.ident = (Ip_u32)ipcom_strtoul(argv[ip_optind], IP_NULL, 10); /* Get id */ if (tkey.ident == 0) { ipcom_printf("l2tp tclose: invalid tunnel ID: %s"IP_LF, argv[ip_optind]); return -1; } /* Close tunnel */ if ((status = ipl2tp_api_tunnel_close(&tkey)) != IPL2TP_STATUS_OK) { ipcom_printf("l2tp tclose: error %d, %s"IP_LF, (int)status, ipl2tp_api_errname(status)); } } return status == IPL2TP_STATUS_OK ? 0 : -1; usage: ipcom_printf("usage: l2tp tclose [-3] "IP_LF "Parameters:"IP_LF "[-3] L2TP v3"IP_LF " Tunnel ID."IP_LF); return -1; } /* *=========================================================================== * ipl2tp_cmd_sopen *=========================================================================== * Description: Session open command. * Parameters: argc - No of arguments. * argv - Argument vector. * Returns: 0 if success. * */ IP_PUBLIC int ipl2tp_cmd_sopen(int argc, char **argv) { Ipl2tp_attrobj sattr = IP_NULL; Ipl2tp_attrobj tattr = IP_NULL; Ipl2tp_attrobj *attr; Ipl2tp_attr_info *tags; Ipl2tp_key tkey; Ipl2tp_key skey; Ipl2tp_status status; int use_confreq = 0; int proxy = 0; int opt; char *ifname = IP_NULL; Ip_u32 ifindex = 0; union Ip_sockaddr_union uaddr; int timeout = 10; Ip_bool incoming = IP_TRUE; if (argc < 2) goto usage; ipcom_getopt_clear(); tkey.version = IPL2TP_VERSION_L2TPV2; skey.version = IPL2TP_VERSION_L2TPV2; /* Get options */ while ((opt = ipcom_getopt(argc, argv, "o23dxi:w:")) != -1) { switch (opt) { case '3': tkey.version = IPL2TP_VERSION_L2TPV3; skey.version = IPL2TP_VERSION_L2TPV3; break; case '2': tkey.version = IPL2TP_VERSION_L2TPV2; skey.version = IPL2TP_VERSION_L2TPV2; break; case 'o': incoming = IP_FALSE; break; case 'd': use_confreq = 1; break; case 'x': proxy = 1; break; case 'i': ifname = ip_optarg; break; case 'w': timeout = (int)ipcom_strtoul(ip_optarg, IP_NULL, 10); break; default: goto usage; } } /* Tunnel identifier must be supplied */ if (ip_optind == argc) goto usage; /* Get host */ tkey.ident = 0; if ((ipcom_strchr(argv[ip_optind], '.') == IP_NULL) || (ipl2tp_api_attribute_address_parse(argv[ip_optind], &uaddr) == IP_FALSE)) { /* Get tunnel key, we failed to do uaddr */ tkey.ident = (Ip_u32)ipcom_strtoul(argv[ip_optind], IP_NULL, 10); if (tkey.ident == 0) { ipcom_printf("l2tp sopen: unknown tunnel identifier %s"IP_LF, argv[ip_optind]); return -1; } } ip_optind++; /* Get interface index */ if (ifname != IP_NULL) { if ((ifindex = ipcom_if_nametoindex(ifname)) == 0) { /* Not running yet */ ipcom_printf("l2tp sopen: cannot find interface %s"IP_LF, ifname); return -1; } if (ipl2tp_cmd_session_key(ifindex)) { ipcom_printf("l2tp sopen: already tunneling interface %s"IP_LF, ifname); return -1; } } /* Set session attributes */ /* Do append some default values; Last found value will always win, * so even if the user overrides a few, it's OK */ if (skey.version == IPL2TP_VERSION_L2TPV2) { if ((status = ipl2tp_attr_iappend(&sattr, IPL2TP_SATTR_SET_TX_CONNECT_SPEED, 38400)) != IPL2TP_STATUS_OK || (status = ipl2tp_attr_iappend(&sattr, IPL2TP_SATTR_SET_FRAMING_TYPE, IPL2TP_MIB_FRAMING_ASYNC)) != IPL2TP_STATUS_OK || (status = ipl2tp_attr_iappend(&sattr, IPL2TP_SATTR_SET_BEARER_TYPE, IPL2TP_MIB_BEARER_ANALOG)) != IPL2TP_STATUS_OK) { ipcom_printf("l2tp sopen: failed to set default attributes: error %d, %s"IP_LF, (int)status, ipl2tp_api_errname(status)); return -1; } /* Append user data ifindex */ if (ifindex) { unsigned long ifindexul = (unsigned long)ifindex; if ((status = ipl2tp_attr_pappend(&sattr, IPL2TP_SATTR_SET_USER_DATA, (void *)ifindexul)) != IPL2TP_STATUS_OK) { ipcom_printf("l2tp sopen: failed to set interface: error %d, %s"IP_LF, (int)status, ipl2tp_api_errname(status)); } } } else { Ip_u64 v; IP_U64_SET(v,0,38400); ipl2tp_attr_iappend64(&sattr, IPL2TP_SATTR_SET_TX_CONNECT_SPEED64, &v); } /* Do go through the remaining attributes */ tags = ipl2tp_session_tags; attr = &sattr; for (; ip_optind < argc; ip_optind++) { Ipl2tp_attr_info *info; char *value = IP_NULL; /* Tunnel attribute delimiter */ if (ipcom_strcmp("--", argv[ip_optind]) == 0) { if (tkey.ident != 0) { ipcom_printf("l2tp sopen: when creating tunnels, the address of the peer must be specified."IP_LF); ipl2tp_attr_delete(&sattr); ipl2tp_attr_delete(&tattr); return -1; } tags = ipl2tp_tunnel_tags; attr = &tattr; continue; } if ((info = ipl2tp_api_attribute_find(tags, argv[ip_optind], &value)) == IP_NULL) { ipcom_printf("l2tp sopen: unknown attribute name %s"IP_LF, argv[ip_optind]); ipl2tp_attr_delete(&sattr); ipl2tp_attr_delete(&tattr); return -1; } /* Parse the value */ if (ipl2tp_api_attribute_parse(attr, info, &value) == IP_FALSE) { ipcom_printf("l2tp sopen: error parsing value"IP_LF); ipl2tp_cmd_attr_print_syntax(info); ipl2tp_attr_delete(&sattr); ipl2tp_attr_delete(&tattr); return -1; } } if (use_confreq) { static char fr_confreq[] = "FR"; static char lr_confreq[] = "LR"; static char ls_confreq[] = "LS"; ipl2tp_attr_vappend(&sattr, IPL2TP_SATTR_SET_FIRST_RECEIVED_CONFREQ, fr_confreq, sizeof(fr_confreq)); ipl2tp_attr_vappend(&sattr, IPL2TP_SATTR_SET_LAST_RECEIVED_CONFREQ, lr_confreq, sizeof(lr_confreq)); ipl2tp_attr_vappend(&sattr, IPL2TP_SATTR_SET_LAST_SENT_CONFREQ, ls_confreq, sizeof(ls_confreq)); } if (proxy) { static char proxy_challenge[] = "CH"; static char proxy_response[] = "RS"; if ((status = ipl2tp_attr_vappend(&sattr, IPL2TP_SATTR_SET_PROXY_AUTHEN_CHALLENGE, proxy_challenge, sizeof(proxy_challenge))) != IPL2TP_STATUS_OK || (status = ipl2tp_attr_iappend(&sattr, IPL2TP_SATTR_SET_PROXY_AUTHEN_ID, 1)) != IPL2TP_STATUS_OK || (status = ipl2tp_attr_pappend(&sattr, IPL2TP_SATTR_SET_PROXY_AUTHEN_NAME, "NM")) != IPL2TP_STATUS_OK || (status = ipl2tp_attr_vappend(&sattr, IPL2TP_SATTR_SET_PROXY_AUTHEN_RESPONSE, proxy_response, sizeof(proxy_response))) != IPL2TP_STATUS_OK) { ipcom_printf("l2tp sopen: failed to set proxy attributes: error %d, %s"IP_LF, (int)status, ipl2tp_api_errname(status)); } } /* Open session */ if ((status = ipl2tp_api_session_open(&skey, &tkey, tkey.ident? IP_NULL : &uaddr, tattr, sattr, incoming)) == IPL2TP_STATUS_OK) { /* Save session ID */ if (ifindex != 0) { Ipl2tp_cmd_session_key *ikey = ipcom_malloc(sizeof(*ikey)); ikey->ifindex = ifindex; ipcom_memcpy(&ikey->key, &skey, sizeof(skey)); ipcom_hash_add(ipl2tp_cmd_session_hash_table, ikey); } if ((status = ipl2tp_cmd_session_wait_establish(&skey, timeout)) != IPL2TP_STATUS_OK) { if (status != IPL2TP_STATUS_TIMEOUT) { ipcom_printf("l2tp sopen: failed to create session: %s"IP_LF, ipl2tp_api_errname(status)); } else { ipcom_printf("l2tp sopen: session still connecting"IP_LF); } } else { ipcom_printf("l2tp sopen: session v%u ident=%u successfully opened"IP_LF, skey.version, skey.ident); } } else { ipcom_printf("l2tp sopen: error %d, %s"IP_LF, (int)status, ipl2tp_api_errname(status)); } /* Release attribute objects */ ipl2tp_attr_delete(&sattr); return status == IPL2TP_STATUS_OK ? 0 : -1; usage: ipcom_printf("usage: l2tp sopen [-2] [-3] [-w ] [-x] [-d] [-o] [-i name] [ATTRIBUTE_LIST]"IP_LF "Parameters:"IP_LF "-d Send dummy PPP CONFREQ packets to LNS."IP_LF "-x Send dummy proxy packets to LNS."IP_LF "-o Open an outbound tunnel (OCRQ) instead of inbound"IP_LF "-2 Version 2"IP_LF "-3 Version 3"IP_LF "-w Number of seconds to wait for establishment"IP_LF " Tunnel ID or peer address to create session in"IP_LF "[ATTRIBUTES] List of attributes and their values"IP_LF); return -1; } /* *=========================================================================== * ipl2tp_cmd_sclose *=========================================================================== * Description: Session close command. * Parameters: argc - No of arguments. * argv - Argument vector. * Returns: 0 if success. * */ IP_PUBLIC int ipl2tp_cmd_sclose(int argc, char **argv) { int opt; Ipl2tp_key skey; Ipl2tp_status status; ipcom_getopt_clear(); /**/ skey.version = IPL2TP_VERSION_L2TPV2; skey.ident = 0; /* Get options */ while ((opt = ipcom_getopt(argc, argv, "23")) != -1) { switch (opt) { case '3': skey.version = IPL2TP_VERSION_L2TPV3; break; case '2': skey.version = IPL2TP_VERSION_L2TPV2; break; default: goto usage; } } if (ip_optind == argc) goto usage; /* Grab the tunnel key */ skey.ident = (Ip_u32)ipcom_strtoul(argv[ip_optind], IP_NULL, 10); /* Get id */ if (skey.ident == 0) { ipcom_printf("l2tp sclose: invalid session ID: %s"IP_LF, argv[ip_optind]); return -1; } /* Close session */ if ((status = ipl2tp_api_session_close(&skey)) != IPL2TP_STATUS_OK) { ipcom_printf("l2tp sclose: error %d, %s"IP_LF, (int)status, ipl2tp_api_errname(status)); } return status == IPL2TP_STATUS_OK ? 0 : -1; usage: ipcom_printf("usage: l2tp sclose [-3] "IP_LF "Parameters:"IP_LF "[-3] L2TP v3."IP_LF " Session ID."IP_LF); return -1; } /* *=========================================================================== * ipl2tp_cmd_attr *=========================================================================== * Description: Attribute command. * Parameters: argc - No of arguments. * argv - Argument vector. * Returns: 0 if success * */ IP_PUBLIC int ipl2tp_cmd_attr(int argc, char **argv) { Ipl2tp_status status = IPL2TP_STATUS_OK; int op_val; Ipl2tp_attr_info *info; char *value = IP_NULL; int i; if (argc < 2) goto usage; /* Set or get */ if ((op_val = ipcom_cmd_str_to_key(ipl2tp_cmd_getset, argv[1])) == -1) goto usage; if (argc == 2) { ipl2tp_cmd_attr_list(ipl2tp_tags, op_val == IPL2TP_CMD_SET); return 0; } for (i = 2; i < argc; i++) { Ipl2tp_attrobj attr = IP_NULL; Ipl2tp_attrobj replies = IP_NULL; /* Try find the attribute */ if ((info = ipl2tp_api_attribute_find(ipl2tp_tags, argv[i], &value)) == IP_NULL) { ipcom_printf("Error: Unknown attribute %s"IP_LF, argv[i]); return -1; } /* Is it a set request but the attribute is RO? */ if (info->rw == IP_FALSE && op_val == IPL2TP_CMD_SET) { ipcom_printf("Error: Attempting to 'set' RO attribute %s"IP_LF, argv[2]); return -1; } if (op_val == IPL2TP_CMD_GET) { Ipl2tp_attr a; get_value: ipl2tp_attr_add_query(&attr, info->value); if ((status = ipl2tp_api_attribute_get(attr, &replies)) != IPL2TP_STATUS_OK) { ipcom_printf("Error %d, %s"IP_LF, (int)status, ipl2tp_api_errname(status)); ipl2tp_attr_delete(&attr); return -1; } /* Delete the query object */ ipl2tp_attr_delete(&attr); a = ipl2tp_attr_first(replies); if(a == IP_NULL) { ipl2tp_attr_delete(&replies); return -1; } if (ipl2tp_attr_status(a) != IPL2TP_STATUS_OK) { ipcom_printf("Error %d, %s"IP_LF, (int)status, ipl2tp_api_errname(status)); ipl2tp_attr_delete(&replies); return -1; } /* Print the attribute */ ipl2tp_cmd_attr_print_attr(a, info); ipl2tp_attr_delete(&replies); continue; } /* Parse the value */ if (ipl2tp_api_attribute_parse(&attr, info, &value) == IP_FALSE) { ipcom_printf("Error parsing value"IP_LF); ipl2tp_cmd_attr_print_syntax(info); return -1; } if ((status = ipl2tp_api_attribute_set(attr)) != IPL2TP_STATUS_OK) { ipcom_printf("Error %d, %s"IP_LF, (int)status, ipl2tp_api_errname(status)); } else { ipl2tp_attr_clear(attr); goto get_value; } ipl2tp_attr_delete(&attr); } return status == IPL2TP_STATUS_OK ? 0 : -1; usage: ipcom_printf("usage: l2tp attr get|set []"IP_LF "Parameters:"IP_LF " Attribute name."IP_LF " Attribute value."IP_LF IP_LF); ipl2tp_cmd_attr_list(ipl2tp_tags, IP_FALSE); return -1; } /* *=========================================================================== * ipl2tp_cmd_tattr *=========================================================================== * Description: Tunnel attribute command. * Parameters: argc - No of arguments. * argv - Argument vector. * Returns: 0 if success * */ IP_PUBLIC int ipl2tp_cmd_tattr(int argc, char **argv) { int opt; Ipl2tp_attrobj attr = IP_NULL; Ipl2tp_attrobj replies = IP_NULL; Ipl2tp_status status = IPL2TP_STATUS_OK; int op_val; Ipl2tp_attr_info *info; Ipl2tp_key tkey; char *value = IP_NULL; int i; ipcom_getopt_clear(); /**/ tkey.version = IPL2TP_VERSION_L2TPV2; tkey.ident = 0; /* Get options */ while ((opt = ipcom_getopt(argc, argv, "23")) != -1) { switch (opt) { case '3': tkey.version = IPL2TP_VERSION_L2TPV3; break; case '2': tkey.version = IPL2TP_VERSION_L2TPV2; break; default: goto usage; } } if (ip_optind == argc) goto usage; /* Set or get */ if ((op_val = ipcom_cmd_str_to_key(ipl2tp_cmd_getset, argv[ip_optind++])) == -1) goto usage; if (argc == ip_optind) { ipl2tp_cmd_attr_list(ipl2tp_tunnel_tags, op_val == IPL2TP_CMD_SET); return 0; } if ((argc - ip_optind) < 2) goto usage; /* Grab the tunnel key */ /* Grab the session key */ if (ipcom_strcasecmp(argv[ip_optind], "default") == 0) { tkey.ident = 0; } else { tkey.ident = (Ip_u32)ipcom_strtoul(argv[ip_optind], IP_NULL, 10); } for (i = ip_optind + 1; i < argc; i++) { /* Try find the attribute */ if ((info = ipl2tp_api_attribute_find(ipl2tp_tunnel_tags, argv[i], &value)) == IP_NULL) { ipcom_printf("Error: Unknown attribute %s"IP_LF, argv[i]); return -1; } /* Is it a set request but the attribute is RO? */ if (info->rw == IP_FALSE && op_val == IPL2TP_CMD_SET) { ipcom_printf("Error: Attempting to 'set' RO attribute %s"IP_LF, info->name); return -1; } if (op_val == IPL2TP_CMD_GET) { Ipl2tp_attr a; get_value: ipl2tp_attr_add_query(&attr, info->value); if ((status = ipl2tp_api_tunnel_attribute_get(&tkey, attr, &replies)) != IPL2TP_STATUS_OK) { ipcom_printf("Error %d, %s"IP_LF, (int)status, ipl2tp_api_errname(status)); ipl2tp_attr_delete(&attr); return -1; } /* Delete the query object */ ipl2tp_attr_delete(&attr); a = ipl2tp_attr_first(replies); if (a == IP_NULL || ipl2tp_attr_status(a) != IPL2TP_STATUS_OK) { ipcom_printf("Error %d, %s"IP_LF, (int)status, ipl2tp_api_errname(status)); ipl2tp_attr_delete(&replies); return -1; } /* Print the attribute */ ipl2tp_cmd_attr_print_attr(a, info); ipl2tp_attr_delete(&replies); continue; } /* Set request */ if (ipl2tp_api_attribute_parse(&attr, info, &value) == IP_FALSE) { ipcom_printf("Error parsing value"IP_LF); ipl2tp_cmd_attr_print_syntax(info); return -1; } if ((status = ipl2tp_api_tunnel_attribute_set(&tkey, attr)) != IPL2TP_STATUS_OK) { ipcom_printf("Error %d, %s"IP_LF, (int)status, ipl2tp_api_errname(status)); } else { ipl2tp_attr_clear(attr); goto get_value; } ipl2tp_attr_delete(&attr); } return status == IPL2TP_STATUS_OK ? 0 : -1; usage: ipcom_printf("usage: l2tp tattr [-2] [-3] get|set [ATTRIBUTES]"IP_LF "Parameters:"IP_LF "[-3] L2TP v3."IP_LF "[-2] L2TP v2."IP_LF " Tunnel ID or 'default'."IP_LF "ATTRIBUTES Attribute list."IP_LF); ipl2tp_cmd_attr_list(ipl2tp_tunnel_tags, IP_FALSE); return -1; } /* *=========================================================================== * ipl2tp_cmd_sattr *=========================================================================== * Description: Session attribute command. * Parameters: argc - No of arguments. * argv - Argument vector. * Returns: 0 if success * */ IP_PUBLIC int ipl2tp_cmd_sattr(int argc, char **argv) { int opt; Ipl2tp_attrobj attr = IP_NULL; Ipl2tp_attrobj replies = IP_NULL; Ipl2tp_status status = IPL2TP_STATUS_OK; Ipl2tp_attr_info *info; Ipl2tp_key skey; int op_val; char *value = IP_NULL; int i; ipcom_getopt_clear(); /**/ skey.version = IPL2TP_VERSION_L2TPV2; skey.ident = 0; /* Get options */ while ((opt = ipcom_getopt(argc, argv, "23")) != -1) { switch (opt) { case '3': skey.version = IPL2TP_VERSION_L2TPV3; break; case '2': skey.version = IPL2TP_VERSION_L2TPV2; break; default: goto usage; } } if (ip_optind == argc) goto usage; /* Set or get */ if ((op_val = ipcom_cmd_str_to_key(ipl2tp_cmd_getset, argv[ip_optind++])) == -1) goto usage; if (ip_optind == argc) { ipl2tp_cmd_attr_list(ipl2tp_session_tags, op_val == IPL2TP_CMD_SET); return 0; } if ((argc - ip_optind) < 2) goto usage; /* Grab the session key */ if (ipcom_strcasecmp(argv[ip_optind], "default") == 0) { skey.ident = 0; } else { skey.ident = (Ip_u32)ipcom_strtoul(argv[ip_optind], IP_NULL, 10); } for (i = ip_optind + 1; i < argc; i++) { /* Try find the attribute */ if ((info = ipl2tp_api_attribute_find(ipl2tp_session_tags, argv[i], &value)) == IP_NULL) { ipcom_printf("Error: Unknown attribute %s"IP_LF, argv[i]); return -1; } /* Is it a set request but the attribute is RO? */ if (info->rw == IP_FALSE && op_val == IPL2TP_CMD_SET) { ipcom_printf("Error: Attempting to 'set' RO attribute %s"IP_LF, argv[3]); return -1; } if (op_val == IPL2TP_CMD_GET) { Ipl2tp_attr a; get_value: ipl2tp_attr_add_query(&attr, info->value); if ((status = ipl2tp_api_session_attribute_get(&skey, attr, &replies)) != IPL2TP_STATUS_OK) { ipcom_printf("Error %d, %s"IP_LF, (int)status, ipl2tp_api_errname(status)); ipl2tp_attr_delete(&attr); return -1; } /* Delete the query object */ ipl2tp_attr_delete(&attr); a = ipl2tp_attr_first(replies); if(a == IP_NULL) { ipl2tp_attr_delete(&replies); return -1; } if (ipl2tp_attr_status(a) != IPL2TP_STATUS_OK) { ipcom_printf("Error %d, %s"IP_LF, (int)status, ipl2tp_api_errname(status)); ipl2tp_attr_delete(&replies); return -1; } /* Print the attribute */ ipl2tp_cmd_attr_print_attr(a, info); ipl2tp_attr_delete(&replies); continue; } /* Parse the value */ if (ipl2tp_api_attribute_parse(&attr, info, &value) == IP_FALSE) { ipcom_printf("Error parsing value"IP_LF); ipl2tp_cmd_attr_print_syntax(info); return -1; } if ((status = ipl2tp_api_session_attribute_set(&skey, attr)) != IPL2TP_STATUS_OK) { ipcom_printf("Error %d, %s"IP_LF, (int)status, ipl2tp_api_errname(status)); } else { ipl2tp_attr_clear(attr); goto get_value; } ipl2tp_attr_delete(&attr); } return status == IPL2TP_STATUS_OK ? 0 : -1; usage: ipcom_printf("usage: l2tp sattr [-2] [-3] set|get [ATTRIBUTES]"IP_LF "Parameters:"IP_LF "[-3] L2TP v3."IP_LF "[-2] L2TP v2."IP_LF " Session ID or 'default'."IP_LF "ATTRIBUTES Attributes"IP_LF); ipl2tp_cmd_attr_list(ipl2tp_session_tags, IP_FALSE); return -1; } /* *=========================================================================== * ipl2tp_cmd_stats *=========================================================================== * Description: Statistics command. * Parameters: argc - No of arguments. * argv - Argument vector. * Returns: 0 if success. * */ IP_PUBLIC int ipl2tp_cmd_stats(int argc, char **argv) { Ipl2tp_status status; Ipl2tp_attrobj attr = IP_NULL; Ipl2tp_attrobj replies = IP_NULL; Ipl2tp_attr a; int i; (void)argv; if (argc != 1) goto usage; /* Query all global attributes */ for (i = 0; ipl2tp_tags[i].value != 0; i++) ipl2tp_attr_add_query(&attr, ipl2tp_tags[i].value); /* Get attributes */ if ((status = ipl2tp_api_attribute_get(attr, &replies)) != IPL2TP_STATUS_OK) { ipcom_printf("Error %d, %s"IP_LF, (int)status, ipl2tp_api_errname(status)); } else { for (a = ipl2tp_attr_first(replies); a != IP_NULL; a = ipl2tp_attr_next(a)) { Ipl2tp_attr_info * info; /* */ if (ipl2tp_attr_status(a) != IPL2TP_STATUS_OK) continue; /* Print the attribute */ if((info = ipl2tp_api_attribute_info(ipl2tp_attr_tag(a)))!= IP_NULL) ipl2tp_cmd_attr_print_attr(a, info); } ipl2tp_attr_delete(&replies); } ipl2tp_attr_delete(&attr); return status == IPL2TP_STATUS_OK ? 0 : -1; usage: ipcom_printf("usage: l2tp stats"IP_LF); return -1; } /* *=========================================================================== * ipl2tp_cmd_tstats *=========================================================================== * Description: Tunnel statistics command. * Parameters: argc - No of arguments. * argv - Argument vector. * Returns: 0 if success. * */ IP_PUBLIC int ipl2tp_cmd_tstats(int argc, char **argv) { int opt; Ipl2tp_status status; Ipl2tp_attrobj attr = IP_NULL; Ipl2tp_attrobj replies = IP_NULL; Ipl2tp_attr a; Ipl2tp_key tkey; Ip_bool have_ident = IP_FALSE; ipcom_getopt_clear(); /**/ tkey.version = IPL2TP_VERSION_L2TPV2; tkey.ident = 0; /* Get options */ while ((opt = ipcom_getopt(argc, argv, "23")) != -1) { switch (opt) { case '3': tkey.version = IPL2TP_VERSION_L2TPV3; break; case '2': tkey.version = IPL2TP_VERSION_L2TPV2; break; default: goto usage; } } if (ip_optind < argc) { if (ipcom_strcasecmp(argv[ip_optind], "default") == 0) { tkey.ident = 0; } else { tkey.ident = (Ip_u32)ipcom_strtoul(argv[ip_optind], IP_NULL, 10); } have_ident = IP_TRUE; } if (have_ident) { int i; /* Add all non-vector queries */ for (i = 0; ipl2tp_tunnel_tags[i].value != 0; i++) { if (ipl2tp_tunnel_tags[i].type != IPL2TP_ATTR_TYPE_VECTOR) ipl2tp_attr_add_query(&attr, ipl2tp_tunnel_tags[i].value); } if ((status = ipl2tp_api_tunnel_attribute_get(&tkey, attr, &replies)) != IPL2TP_STATUS_OK) { ipcom_printf("Error %d, %s"IP_LF, (int)status, ipl2tp_api_errname(status)); } else { for (a = ipl2tp_attr_first(replies); a != IP_NULL; a = ipl2tp_attr_next(a)) { Ipl2tp_attr_info* info = IP_NULL; /* */ if (ipl2tp_attr_status(a) != IPL2TP_STATUS_OK) continue; /* Print the attribute */ if ((info = ipl2tp_api_attribute_info(ipl2tp_attr_tag(a))) != IP_NULL) ipl2tp_cmd_attr_print_attr(a, info); } ipl2tp_attr_delete(&replies); } ipl2tp_attr_delete(&attr); } else do { Ipl2tp_key nkey; if ((status = ipl2tp_api_tunnel_next(&tkey, &nkey)) != IPL2TP_STATUS_OK) break; for (;;) { /* Don't go past the version */ if (tkey.version != nkey.version) break; ipcom_memcpy(&tkey, &nkey, sizeof(tkey)); attr = IP_NULL; replies = IP_NULL; ipl2tp_attr_add_query(&attr, IPL2TP_TATTR_GET_l2tpTunnelStatsState); ipl2tp_attr_add_query(&attr, IPL2TP_TATTR_GET_l2tpTunnelStatsDrainingTunnel); ipl2tp_attr_add_query(&attr, IPL2TP_TATTR_GET_l2tpTunnelStatsControlRecvPackets); ipl2tp_attr_add_query(&attr, IPL2TP_TATTR_GET_l2tpTunnelStatsControlSendPackets); ipl2tp_attr_add_query(&attr, IPL2TP_TATTR_GET_l2tpTunnelStatsControlAckTimeouts); ipl2tp_attr_add_query(&attr, IPL2TP_TATTR_GET_l2tpTunnelStatsControlOutOfSequence); ipl2tp_attr_add_query(&attr, IPL2TP_TATTR_GET_l2tpTunnelStatsControlOutOfWindow); ipl2tp_attr_add_query(&attr, IPL2TP_TATTR_GET_l2tpTunnelStatsInitiated); ipl2tp_attr_add_query(&attr, IPL2TP_TATTR_GET_l2tpTunnelConfigAuthentication); ipl2tp_attr_add_query(&attr, IPL2TP_TATTR_GET_HIDE_AVP); ipl2tp_attr_add_query(&attr, IPL2TP_TATTR_GET_l2tpTunnelStatsActiveSessions); ipl2tp_attr_add_query(&attr, IPL2TP_TATTR_GET_l2tpTunnelStatsRemoteHostName); ipl2tp_attr_add_query(&attr, IPL2TP_TATTR_GET_tunnelRemoteAddress); if ((status = ipl2tp_api_tunnel_attribute_get(&tkey, attr, &replies)) != IPL2TP_STATUS_OK) { ipcom_printf("Error %d, %s"IP_LF, (int)status, ipl2tp_api_errname(status)); ipl2tp_attr_delete(&attr); return -1; } ipcom_printf("v%u %u:"IP_LF, tkey.version, tkey.ident); for (a = ipl2tp_attr_first(replies); a != IP_NULL; a = ipl2tp_attr_next(a)) { Ipl2tp_attr_info * info; /* */ if (ipl2tp_attr_status(a) != IPL2TP_STATUS_OK) continue; /* Print the attribute */ if((info = ipl2tp_api_attribute_info(ipl2tp_attr_tag(a)))!= IP_NULL) ipl2tp_cmd_attr_print_attr(a, info); } ipl2tp_attr_delete(&replies); ipl2tp_attr_delete(&attr); if (ipl2tp_api_tunnel_next(&tkey, &nkey) != IPL2TP_STATUS_OK) break; } } while (0); return status == IPL2TP_STATUS_OK ? 0 : -1; usage: ipcom_printf("usage: l2tp tstats [-2] [-3] []"IP_LF "Parameters:"IP_LF "-2 Version 2"IP_LF "-3 Version 3"IP_LF "id Tunnel ID or 'default'"IP_LF); return -1; } /* *=========================================================================== * ipl2tp_cmd_sstats *=========================================================================== * Description: Session statistics command. * Parameters: argc - No of arguments. * argv - Argument vector. * Returns: 0 if success. * */ IP_PUBLIC int ipl2tp_cmd_sstats(int argc, char **argv) { int opt; Ipl2tp_status status; Ipl2tp_attrobj attr = IP_NULL; Ipl2tp_attrobj replies = IP_NULL; Ipl2tp_attr a; Ipl2tp_key skey; Ipl2tp_key tkey; Ip_bool have_ident = IP_FALSE; ipcom_getopt_clear(); /**/ skey.version = IPL2TP_VERSION_L2TPV2; tkey.version = IPL2TP_VERSION_L2TPV2; skey.ident = 0; tkey.ident = 0; /* Get options */ while ((opt = ipcom_getopt(argc, argv, "23t:")) != -1) { switch (opt) { case '3': tkey.version = IPL2TP_VERSION_L2TPV3; skey.version = IPL2TP_VERSION_L2TPV3; break; case '2': tkey.version = IPL2TP_VERSION_L2TPV2; skey.version = IPL2TP_VERSION_L2TPV2; break; case 't': tkey.ident = (Ip_u32)ipcom_strtoul(ip_optarg, IP_NULL, 10); break; default: goto usage; } } if (ip_optind < argc) { have_ident = IP_TRUE; if (ipcom_strcasecmp(argv[ip_optind], "default") != 0) skey.ident = (Ip_u32)ipcom_strtoul(argv[ip_optind], IP_NULL, 10);; } if (have_ident) { int i; /* Add all non-vector queries */ for (i = 0; ipl2tp_session_tags[i].value != 0; i++) { if (ipl2tp_session_tags[i].type != IPL2TP_ATTR_TYPE_VECTOR) { /**/ ipl2tp_attr_add_query(&attr, ipl2tp_session_tags[i].value); } } if ((status = ipl2tp_api_session_attribute_get(&skey, attr, &replies)) != IPL2TP_STATUS_OK) { ipcom_printf("Error %d, %s"IP_LF, (int)status, ipl2tp_api_errname(status)); } else { for (a = ipl2tp_attr_first(replies); a != IP_NULL; a = ipl2tp_attr_next(a)) { Ipl2tp_attr_info* info = IP_NULL; /* */ if (ipl2tp_attr_status(a) != IPL2TP_STATUS_OK) continue; /* Print the attribute */ if ((info = ipl2tp_api_attribute_info(ipl2tp_attr_tag(a))) != IP_NULL) ipl2tp_cmd_attr_print_attr(a, info); } ipl2tp_attr_delete(&replies); } ipl2tp_attr_delete(&attr); } else do { Ipl2tp_key nkey; if ((status = ipl2tp_api_session_next(&tkey, IP_NULL, &nkey)) != IPL2TP_STATUS_OK) break; for (;;) { ipcom_memcpy(&skey, &nkey, sizeof(skey)); attr = IP_NULL; replies = IP_NULL; ipl2tp_attr_add_query(&attr, IPL2TP_SATTR_GET_l2tpSessionStatsState); ipl2tp_attr_add_query(&attr, IPL2TP_SATTR_GET_l2tpSessionStatsCallType); ipl2tp_attr_add_query(&attr, IPL2TP_SATTR_GET_l2tpSessionStatsCallBearerType); ipl2tp_attr_add_query(&attr, IPL2TP_SATTR_GET_l2tpSessionStatsFramingType); ipl2tp_attr_add_query(&attr, IPL2TP_SATTR_GET_l2tpSessionStatsSendSeq); ipl2tp_attr_add_query(&attr, IPL2TP_SATTR_GET_l2tpSessionStatsRecvSeq); ipl2tp_attr_add_query(&attr, IPL2TP_SATTR_GET_l2tpSessionStatsTxConnectSpeed); ipl2tp_attr_add_query(&attr, IPL2TP_SATTR_GET_l2tpSessionStatsRxConnectSpeed); ipl2tp_attr_add_query(&attr, IPL2TP_SATTR_GET_l2tpSessionStatsCLID); ipl2tp_attr_add_query(&attr, IPL2TP_SATTR_GET_l2tpSessionStatsDNIS); if ((status = ipl2tp_api_session_attribute_get(&skey, attr, &replies)) != IPL2TP_STATUS_OK) { ipcom_printf("Error %d, %s"IP_LF, (int)status, ipl2tp_api_errname(status)); ipl2tp_attr_delete(&attr); return -1; } ipcom_printf("v%u %u:"IP_LF, skey.version, skey.ident); for (a = ipl2tp_attr_first(replies); a != IP_NULL; a = ipl2tp_attr_next(a)) { Ipl2tp_attr_info * info; /* */ if (ipl2tp_attr_status(a) != IPL2TP_STATUS_OK) continue; /* Print the attribute */ if((info = ipl2tp_api_attribute_info(ipl2tp_attr_tag(a)))!= IP_NULL) ipl2tp_cmd_attr_print_attr(a, info); } ipl2tp_attr_delete(&replies); ipl2tp_attr_delete(&attr); if (ipl2tp_api_session_next(&tkey, &skey, &nkey) != IPL2TP_STATUS_OK) break; } } while (0); return status == IPL2TP_STATUS_OK ? 0 : -1; usage: ipcom_printf("usage: l2tp sstats [-2] [-3] [-t tid] []"IP_LF "Parameters:"IP_LF "-2 Version 2"IP_LF "-3 Version 3"IP_LF "-t Tunnel ID."IP_LF "id Session ID or 'default'"IP_LF); return -1; } /* *=========================================================================== * ipl2tp_cmd_poke *=========================================================================== * Description: Setup poke information for incoming messages. * Parameters: argc - No of arguments. * argv - Argument vector. * Returns: 0 if success * */ IP_PUBLIC int ipl2tp_cmd_poke(int argc, char **argv) { int opt; if (argc < 2) { goto usage; } ipcom_getopt_clear(); poke_count = 1; poke_mtype = 0; poke_avp = 0; poke_offset = 0; poke_value = 0; poke_skip = 0; ipl2tp_poke_abort[0] = '\0'; /* Get options */ while ((opt = ipcom_getopt(argc, argv, "a:cim:n:o:r:")) != -1) { switch (opt) { case 'a': poke_avp = ipcom_atoi(ip_optarg); break; case 'c': poke_count = 0; break; case 'i': poke_skip = 1; break; case 'm': poke_mtype = ipcom_atoi(ip_optarg); break; case 'n': poke_count = ipcom_atoi(ip_optarg); break; case 'o': poke_offset = ipcom_atoi(ip_optarg); break; case 'r': strncpy(ipl2tp_poke_abort, ip_optarg, 3); ipl2tp_poke_abort[3] = '\0'; break; default: goto usage; } } if (ip_optind == argc ) { if (poke_count != 0 && poke_skip != 1 && ipl2tp_poke_abort[0] == '\0') { goto usage; } } else { poke_value = ipcom_atoi(argv[ip_optind]); } return IP_NULL; usage: ipcom_printf("usage: l2tp poke [options] "IP_LF "Parameters:"IP_LF "-a Poke AVP with number ."IP_LF "-c Clear a pending poke."IP_LF "-i Ignore message altogether."IP_LF "-m Poke messages of type . Default all messages."IP_LF "-n Set number of messages to poke. Default 1."IP_LF "-o Offset in octets from start of message. Default 0."IP_LF "-r Return 1 from status callback ."IP_LF " Value to insert."IP_LF); return -1; } /* *=========================================================================== * ipl2tp_cmd_main *=========================================================================== * Description: Main L2TP command. * Parameters: argc - No of arguments. * argv - Argument vector. * Returns: 0 if success * */ IP_PUBLIC int ipl2tp_cmd_main(int argc, char **argv) { int op_val; /* Check if call for help */ if (argc <= 1) goto usage; /* Set or get */ if ((op_val = ipcom_cmd_str_to_key(ipl2tp_cmd_cmds, argv[1])) == -1) goto usage; switch (op_val) { #ifdef IPL2TP_ALLOW_CMD_POKE case IPL2TP_CMD_POKE: return ipl2tp_cmd_poke(argc - 1, argv + 1); #endif case IPL2TP_CMD_ATTR: return ipl2tp_cmd_attr(argc - 1, argv + 1); case IPL2TP_CMD_SATTR: return ipl2tp_cmd_sattr(argc - 1, argv + 1); case IPL2TP_CMD_TATTR: return ipl2tp_cmd_tattr(argc - 1, argv + 1); case IPL2TP_CMD_STATS: return ipl2tp_cmd_stats(argc - 1, argv + 1); case IPL2TP_CMD_SSTATS: return ipl2tp_cmd_sstats(argc - 1, argv + 1); case IPL2TP_CMD_TSTATS: return ipl2tp_cmd_tstats(argc - 1, argv + 1); case IPL2TP_CMD_TOPEN: return ipl2tp_cmd_topen(argc - 1, argv + 1); case IPL2TP_CMD_TCLOSE: return ipl2tp_cmd_tclose(argc - 1, argv + 1); case IPL2TP_CMD_SOPEN: return ipl2tp_cmd_sopen(argc - 1, argv + 1); case IPL2TP_CMD_SCLOSE: return ipl2tp_cmd_sclose(argc - 1, argv + 1); default: break; } usage: /* Command summary */ ipcom_printf("Available l2tp commands:"IP_LF #ifdef IPL2TP_ALLOW_CMD_POKE " poke - Set poke values"IP_LF #endif " attr - Set global attributes"IP_LF " tattr - Set tunnel attributes"IP_LF " sattr - Set session attributes"IP_LF " topen - Open a tunnel"IP_LF " tclose - Close a tunnel"IP_LF " sopen - Open a session"IP_LF " sclose - Close a session"IP_LF " stats - Show global stats"IP_LF " tstats - Show tunnel stats"IP_LF " sstats - Show session stats"IP_LF); return 0; } /* **************************************************************************** * END OF FILE **************************************************************************** */