/*
 *===========================================================================
 *                    ipnet_config_add_inet_addr
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 *
 */
IP_STATIC int
ipnet_config_add_inet_addr(Ip_fd fd, char *ifname, char *option)
{
    char *inet_addr;
    char *prefix_len;
    char *argv[] = {
        "ifconfig",
        "-silent",
        IP_NULL,
        "inet",
        "add",
        IP_NULL,
        IP_NULL,
        IP_NULL,
        IP_NULL
    };
    int argc = 5;
    char inet_addr_str[IP_INET_ADDRSTRLEN];
    char inet_prefix_len_str[8];

    argv[2] = ifname;

    inet_addr = ipcom_strtok_r(option, " \t/", &option);
    if (inet_addr == IP_NULL)
    {
        IPCOM_LOG0(ERR, "inet address is missing or format is invalid");
        return -IP_ERRNO_EINVAL;
    }

    if (ipcom_strcmp(inet_addr, "dhcp") == 0)
    {
        struct Ip_ifreq  ifreq;

    use_dhcp:
        ipcom_strcpy(ifreq.ifr_name, ifname);
        ifreq.ifr_ifru.ifru_opt = 1;

		if (ipcom_socketioctl(fd, IP_SIOCXSDHCPRUNNING, &ifreq) < 0)
        {
            IPCOM_LOG1(ERR, "Failed to enable DHCP on %s", ifname);
            return ipcom_errno;
        }
        return 0;
    }

#ifdef IPNET_USE_RARP
    if (ipcom_strcmp(inet_addr, "rarp") == 0)
    {
        struct Ip_ethreq  ethreq;

        ipcom_strcpy(ethreq.ethr_name, ifname);
        ethreq.ethru.rarp = -1;

		if (ipcom_socketioctl(fd, IP_SIOCXETHSRARP, &ethreq) < 0)
        {
            IPCOM_LOG1(ERR, "Failed to enable RARPP on %s", ifname);
            return ipcom_errno;
        }
        return 0;
    }
#endif /* IPNET_USE_RARP */

    if (ipcom_strcmp(inet_addr, "driver") == 0)
    {
        /* Get the IPv4 address to use from the driver */
        struct Ip_ethreq ethreq;

        ipcom_strcpy(ethreq.ethr_name, ifname);
        if (ipcom_socketioctl(fd, IP_SIOCXETHGINET, &ethreq) < 0)
        {
            IPCOM_LOG1(ERR, "Failed to read the IPv4 address from the driver for %s", ifname);
            return ipcom_errno;
        }
        if (ethreq.ethru.inet.addr.s_addr == 0xffffffff)
            goto use_dhcp;
        inet_addr = inet_addr_str;
        (void) ipcom_inet_ntop(IP_AF_INET, &ethreq.ethru.inet.addr,
            inet_addr_str, sizeof(inet_addr_str));

        prefix_len = inet_prefix_len_str;
        ipcom_snprintf(inet_prefix_len_str, sizeof(inet_prefix_len_str), "%d",
            ipcom_mask_to_prefixlen(&ethreq.ethru.inet.mask, 32));
    }
    else
    {
        prefix_len = ipcom_strtok_r(option, " \t/", &option);
        if (prefix_len == IP_NULL)
        {
            IPCOM_LOG0(ERR, "prefix len is missing or format is invalid");
            return -IP_ERRNO_EINVAL;
        }
    }

    argv[argc++] = inet_addr;
    argv[argc++] = "prefixlen";
    argv[argc++] = prefix_len;

    return ipnet_config_cmd_ifconfig(argc, argv);
}
/*
 *===========================================================================
 *                      ipnet_cmd_qc_show_queue
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 *
 */
IP_STATIC int
ipnet_cmd_qc_show_queue(Ipnet_cmd_qc *p)
{
    Ipnet_cmd_qc_type_handler *h;

    if (ipcom_socketioctl(p->fd, IPNET_SIOCGIFQUEUE, &p->p.ifq) < 0)
    {
        ipcom_printf("Failed to get the queue: %s"IP_LF, ipcom_strerror(ipcom_errno));
        return -1;
    }

    h = ipnet_cmd_qc_get_type_handler(p->p.ifq.ifq_type);
    if (h == IP_NULL)
    {
        ipcom_printf("No 'show' handler implemented for queue type '%s'"IP_LF,
                     p->p.ifq.ifq_type);
        return -1;
    }

    ipnet_cmd_qc_output_indent(p);
    ipcom_printf("%s/%d[%d] queue at %s"IP_LF,
                 p->p.ifq.ifq_type,
                 p->p.ifq.ifq_id,
                 p->p.ifq.ifq_parent_id,
                 p->p.ifq.ifq_name);
    ipnet_cmd_qc_output_indent(p);

    return h->show(p);
}
/*
 *===========================================================================
 *                      ipnet_cmd_qc_del_queue
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 *
 */
IP_STATIC int
ipnet_cmd_qc_del_queue(Ipnet_cmd_qc *p)
{
    ipcom_strcpy(p->p.ifq.ifq_type, "none");
    if (ipcom_socketioctl(p->fd, IPNET_SIOCSIFQUEUE, &p->p.ifq) < 0)
    {
        ipcom_printf("Failed to delete the queue: %s"IP_LF, ipcom_strerror(ipcom_errno));
        return -1;
    }
    return 0;
}
/*
 *===========================================================================
 *                    ipsecctrl_selectorTable_print
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 *
 */
static void
ipsecctrl_selectorTable_print(Argvars *vars)
{
    Ipipsec_ctrl_selector   sel;
#ifdef IPCOM_USE_INET6
    char str[IP_INET6_ADDRSTRLEN];
#else
    char str[16];
#endif

    ipcom_printf(IP_LF"***** selectorTable ::"IP_LF);

    sel.Index = 0;  /* get first selector. */

    /* Get and print the Selectors in MIB format. */
    for (;;)
    {
        /* Get first/next Selector */
        if (ipcom_socketioctl(vars->fd, IP_SIOCXIPSEC_SELECTOR, &sel) < 0)
        {
            ipcom_printf("ipsecctrl: ipcom_socketioctl(SELECTOR) failed (%s)"IP_LF,
                         ipcom_strerror(ipcom_errno));
            return;
        }

        if (sel.Index == 0)
            break;

        /* Print selector index */
        ipcom_printf(IP_LF"Selector Entry #%ld:"IP_LF
                     "selectorIndex = %ld"IP_LF,
                     sel.Index,
                     sel.Index);

        ipcom_printf("selectorLocalId = %s"IP_LF
                     "selectorLocalIdType = %s"IP_LF,
                     ipcom_inet_ntop(sel.domain, &sel.LocalId, str, sizeof(str)),
                     sel.domain == IP_AF_INET ? "idIpv4Addr" : "idIpv6Addr");


        ipcom_printf("selectorRemoteId = %s"IP_LF
                     "selectorRemoteIdType = %s"IP_LF,
                     ipcom_inet_ntop(sel.domain, &sel.RemoteId, str, sizeof(str)),
                     sel.domain == IP_AF_INET ? "idIpv4Addr" : "idIpv6Addr");

        ipcom_printf("selectorProtocol = %s"IP_LF,
                     ipcom_ipproto_name(sel.Protocol));

        ipcom_printf("selectorLocalPort = %d"IP_LF,
                     ip_ntohs(sel.LocalPort));
        ipcom_printf("selectorRemotePort = %d"IP_LF,
                     ip_ntohs(sel.RemotePort));
    }
}
/*
 *===========================================================================
 *                      ipnet_cmd_qc_del_filter
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 *
 */
IP_STATIC int
ipnet_cmd_qc_del_filter(Ipnet_cmd_qc *p)
{
    ipnet_cmd_qc_set_filter_id(p);
    if (ipcom_socketioctl(p->fd, IPNET_SIOCXDIFQFILTER, &p->p.filter) < 0)
    {
        ipcom_printf("Failed to delete the filter: %s"IP_LF, ipcom_strerror(ipcom_errno));
        return -1;
    }

    return 0;
}
/*
 *===========================================================================
 *                      ipnet_cmd_qc_add_queue
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 *
 */
IP_STATIC int
ipnet_cmd_qc_add_queue(Ipnet_cmd_qc *p)
{
    if (ipnet_cmd_qc_parse_queue_type(p) < 0)
        return -1;

    if (ipcom_socketioctl(p->fd, IPNET_SIOCSIFQUEUE, &p->p.ifq) < 0)
    {
        ipcom_printf("Failed to add the queue: %s"IP_LF, ipcom_strerror(ipcom_errno));
        return -1;
    }
    return 0;
}
IP_STATIC Ip_size_t
ipcom_create_ifaddrs_inet6(Ip_fd                    fd,
                           const char               *ifname,
                           Ip_u8                    *ifa_first,
                           Ip_size_t                buf_len,
                           struct Ipnet_if_msghdr   *ifm,
                           struct Ip_ifaddrs        ***tail)
{
    struct Ip_in6_aliasreq   ifareq;
    struct Ipnet_ifa_msghdr *ifa;
    struct Ip_sockaddr_in6  *addrs[IPNET_RTAX_MAX];
    Ip_size_t                offset = 0;

    offset = 0;
    while (offset < buf_len)
    {
        struct Ip_ifaddrs        *nifa;

        ifa = (struct Ipnet_ifa_msghdr *) &ifa_first[offset];
#if defined(IP_PORT_VXWORKS) && !defined(_WRS_KERNEL)
        ipnet_cmd_init_addrs_rtp(ifa + 1, ifa->ifam_addrs, (struct Ip_sockaddr **) addrs);
#else
        ipnet_cmd_init_addrs(ifa + 1, ifa->ifam_addrs, (struct Ip_sockaddr **) addrs);
#endif

        if (ifa->ifam_type != IPNET_RTM_NEWADDR || addrs[IPNET_RTAX_IFA]->sin6_family != IP_AF_INET6)
            break;

        offset += ifa->ifam_msglen;

        ipcom_memset(&ifareq, 0, sizeof(ifareq));
        ipcom_memcpy(ifareq.ifra_name, ifname, IP_IFNAMSIZ);
        ipcom_memcpy(&ifareq.ifra_addr, addrs[IPNET_RTAX_IFA], sizeof(ifareq.ifra_addr));
        (void)ipcom_socketioctl(fd, IP_SIOCXGIFADDR_IN6, &ifareq);

        if (IP_BIT_ISSET(ifareq.ifra_flags, IP_IN6_IFF_ANYCAST))
            continue;

        if (IP_IN6_IS_ADDR_MULTICAST(&addrs[IPNET_RTAX_IFA]->sin6_addr))
            continue;

        nifa = ipcom_create_ifaddrs_entry(ifname, ifm, ifa, (struct Ip_sockaddr **)addrs);
        if (nifa != IP_NULL)
        {
            **tail = nifa;
            *tail  = &nifa->ifa_next;
        }
    }

    return offset;
}
Beispiel #8
0
int get_ip( char * ifname)
{ 
	struct Ip_ifreq ifr;
	int fd;
	int addr;
	
	        fd = ipcom_socket(IP_AF_INET, IP_SOCK_DGRAM, 0);
	
	ipcom_memset(&ifr,0,sizeof(ifr));
	ipcom_strcpy(ifr.ifr_name, ifname); 
	if (ipcom_socketioctl(fd, IP_SIOCGIFADDR, &ifr) != IP_SOCKERR)
	{ 
		addr =((struct Ip_sockaddr_in *)&ifr.ip_ifr_addr)->sin_addr.s_addr;
		
	return addr;
	}
}
/*
 *===========================================================================
 *                    ipnet_config_add_gateway
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 *
 */
IP_STATIC int
ipnet_config_add_gateway(Ip_fd fd, char *ifname, char *option)
{
    char gw_str[IP_INET_ADDRSTRLEN];
    char *gw;

    gw = ipcom_strtok_r(option, " \t", &option);
    if (gw == IP_NULL)
    {
        IPCOM_LOG1(ERR,
                   "Wrong gateway format specified for interface %s, must be 'gateway <driver|gw_address>",
                   ifname);
        IP_PANIC();
        return -IP_ERRNO_EINVAL;
    }

    if (ipcom_strcmp(gw, "driver") == 0)
    {
        /* Get the IPv4 gateway address to use from the driver */
        struct Ip_ethreq ethreq;

        ipcom_strcpy(ethreq.ethr_name, ifname);
        if (ipcom_socketioctl(fd, IP_SIOCXETHGINET, &ethreq) < 0)
        {
            IPCOM_LOG1(ERR, "Failed to read the IPv4 gateway address "
                       "from the driver for %s", ifname);
            return ipcom_errno;
        }
        if (ethreq.ethru.inet.gateway.s_addr == 0xffffffff)
            return 0; /* using dhcp, ignore gateway */
        if (ethreq.ethru.inet.gateway.s_addr == 0)
        {
            IPCOM_LOG1(NOTICE, "No IPv4 gateway address set in driver for %s", ifname);
            return 0;
        }

        (void) ipcom_inet_ntop(IP_AF_INET, &ethreq.ethru.inet.gateway,
                               gw_str, sizeof(gw_str));
        gw = gw_str;
    }

    return ipnet_config_add_route(IP_AF_INET, "0.0.0.0", 0, gw);
}
Beispiel #10
0
int vlan_check(int ifindex, char * parent)
{
    struct Ip_ifreq   ifreq;
    struct Ip_vlanreq vlanreq;
    
    int fd;
        fd = ipcom_socket(IP_AF_INET, IP_SOCK_DGRAM, 0);
        
    ipcom_memset(&vlanreq, 0, sizeof(struct Ip_vlanreq));
    ifreq.ip_ifr_data = &vlanreq;
    if (ipcom_if_indextoname(ifindex, ifreq.ifr_name) == IP_NULL
        || ipcom_socketioctl(fd, IP_SIOCGETVLAN, &ifreq) < 0)
        return 0;

    if(ipcom_strcmp(parent,vlanreq.vlr_parent) == 0)
    { 
        	return 1;
        }
    else
    	return -1; 
    
}
/*
 *===========================================================================
 *                    ipcom_waitif_gifaddr
 *===========================================================================
 * Description: Get interface address.
 * Parameters:  fd - socket descriptor
 *              ifindex - Interface index.
 *              domain - The address domain.
 * Returns:     0 = No address available, 1 = No address available, -1 = error.
 *
 */
IP_STATIC int
ipcom_waitif_gifaddr(Ip_fd fd, int ifindex, int domain)
{
    int ret = -1;

    switch (domain)
    {
    case IP_AF_INET:
    {
        struct Ip_ifreq ifreq;

        /* Get if name */
        ipcom_memset(&ifreq, 0, sizeof(ifreq));
        (void)ipcom_if_indextoname(ifindex, ifreq.ifr_name);

        /* Get main address */
        if (ipcom_socketioctl(fd, IP_SIOCGIFADDR, &ifreq) < 0)
        {
            if (ipcom_errno != IP_ERRNO_EADDRNOTAVAIL && ipcom_errno != IP_ERRNO_ENXIO)
            {
                IPCOM_LOG1(ERR, "ipcom_waitif :: ipcom_socketioctl(SIOCGIFADDR) failed, errno = %d", ipcom_errno);
            }
        }
        else
        {
            struct Ip_in_addr network = ((struct Ip_sockaddr_in *)&ifreq.ip_ifr_addr)->sin_addr;

            if (network.s_addr != IP_INADDR_DEFAULT)
            {
                ret = 0;
            }
        }
        break;
    }

#ifdef IPCOM_USE_INET6
    case IP_AF_INET6:
    {
        int len = IPNET_WAITIF_MAXIF * sizeof(struct Ip_ifreq);
        char ifname[IP_IFNAMSIZ];
        struct Ip_ifconf ifc;
        char *buf = IP_NULL;
        char *ptr;

        /* Get if name */
        (void)ipcom_if_indextoname(ifindex, ifname);

        /* Get if data buffer */
        if ((buf = ipcom_malloc(IPNET_WAITIF_MAXIF * sizeof(struct Ip_ifreq))) == IP_NULL)
        {
            IPCOM_LOG0(ERR, "ipcom_waitif :: Out of memory");
            goto leave;
        }

        /* Enter buf in ifconf struct */
        ifc.ifc_len = len;
        ifc.ip_ifc_buf = buf;

        if (ipcom_socketioctl(fd, IP_SIOCGIFCONF, &ifc) < 0)
        {
            IPCOM_LOG1(ERR, "ipcom_socketioctl(SIOCGIFCONF) failed, errno = %d\n", ipcom_errno);
            goto leave;
        }

        /* Loop for all interfaces */
        for (ptr = buf; ptr < buf + ifc.ifc_len; )
        {
            struct Ip_ifreq *ifr = (struct Ip_ifreq *)ptr;
            char *cptr;

            /* Calculate pointer to next if */
            len = IP_MAX(sizeof(struct Ip_sockaddr_in), ifr->ip_ifr_addr.sa_len);
            ptr += sizeof(ifr->ifr_name) + len;

            if ((cptr = ipcom_strchr(ifr->ifr_name, ':')) != IP_NULL)
            {
                *cptr = '\0';
            }

            /* Only for v6 addresses */
            if (ipcom_strcmp(ifr->ifr_name, ifname) == 0 &&
                ifr->ip_ifr_addr.sa_family == IP_AF_INET6)
            {
                struct Ip_sockaddr_in6 *in6 = (struct Ip_sockaddr_in6 *)&ifr->ip_ifr_addr;

                if (!IP_IN6_IS_ADDR_UNSPECIFIED(&in6->sin6_addr))
                {
                    ret = 0;
                    break;
                }
            }
        }

leave:
        if (buf != IP_NULL)
        {
            ipcom_free(buf);
        }
        break;
    }
#endif /* IPCOM_USE_INET6 */
    }

    return ret;
}
Beispiel #12
0
/*
 *===========================================================================
 *                    ipcom_shell_run_extcmd
 *===========================================================================
 * Description: Starts a shell command process and delivers the command arguments
 *              and stdio socket to that process.
 * Parameters:  argc, argv - traditional command arguments
 *              stdio_fd - the standard input, output and error sock
 *              ppid - parent pid
 *              cmd_pid - shell command process id
 *
 * Returns:          1 : command process started
 *                   0 : not an external command
 *                  -1 : error
 *
 */
IP_PUBLIC Ip_err
ipcom_shell_run_extcmd(int argc, char **argv, Ip_fd *stdio_fd, Ip_pid_t ppid, Ip_u32 seqno, Ip_pid_t *cmd_pid, int *proc_index)
{
    Ipcom_proc_attr  attr;
    Ipcom_ipc        ipc;
    Ipcom_shellcmd_info  *sinfo;
    Ipcom_shell_cmd   *cmd = IP_NULL;
    Ipcom_shell_cmd   *tcmd;
    Ip_err retval;
    char procname[40];
    Ip_u32    stack = IPCOM_PROC_STACK_DEFAULT;
    Ip_pid_t  pid;

    pid = ipcom_getpid();
    ipcom_sprintf(procname, "ipcom_sc_0x%lx_%d", (Ip_u32)pid, *proc_index);

    /* Find command and max stack size (since we are reusing the process). */
    if (argc > 0)
    {
        for (tcmd = IPCOM_LIST_FIRST(&ipcom_shell_cmd_head); tcmd; tcmd = IPCOM_LIST_NEXT(&tcmd->cmd_list))
        {
            stack = (Ip_u32)IP_MAX(stack, tcmd->stack_size);
            if (cmd == IP_NULL && ipcom_strcmp(tcmd->name, argv[0]) == 0)
            {
                cmd = tcmd;
                if (*cmd_pid != 0)
                    break;
            }
        }
        if (cmd == IP_NULL)
            return 0;

        /* Start the shell_cmd process. */
        if (*cmd_pid == 0)
        {
            ipcom_proc_attr_init(&attr);
            attr.priority  = (Ip_u32)cmd->priority;
            attr.stacksize = stack;
            attr.flags |= IPCOM_PROC_FLAG_FP;
            if (ipcom_proc_acreate(procname, (Ipcom_proc_func)ipcom_shell_cmd, &attr, cmd_pid))
            {
                IPCOM_LOG0(ERR, "ipcom_shell_run_extcmd :: ipcom_proc_acreate() failed");
                goto fail;
            }
            ip_assert(*cmd_pid != 0);
        }
    }
    else
    {
        /* argc == 0 is used to kill the shell_cmd process. */
        ip_assert(*cmd_pid != 0);
    }

    /* Open IPC with ipcom_shell. */
    retval = ipcom_ipc_open(&ipc, procname, -1);
    if (retval != IPCOM_SUCCESS)
    {
        IPCOM_LOG2(ERR, "ipcom_shell_run_extcmd :: ipcom_ipc_open(%s) failed, ret = %d", procname, retval);
        goto fail;
    }

    /* Send a message to ipcom_shell. */
    sinfo = ipcom_ipc_malloc(sizeof(Ipcom_shellcmd_info));
    if (sinfo == IP_NULL)
    {
        IPCOM_LOG1(ERR, "ipcom_shell_run_extcmd :: ipcom_ipc_malloc() failed, ret = %d", retval);
        goto fail;
    }

    /* Fill in IPC info. */
    sinfo->argc = argc;
    if (argc > 0)
    {
        sinfo->hook  = cmd->hook;
        sinfo->argv  = argv;
        sinfo->fd    = *stdio_fd;
        sinfo->pid   = pid;
        sinfo->ppid  = ppid;
        sinfo->seqno = seqno;
#if IPCOM_USE_FILE != IPCOM_FILE_NONE
        if (ipcom_getcwd(sinfo->cwd, sizeof(sinfo->cwd)) == IP_NULL)
            ipcom_memset(sinfo->cwd, 0, sizeof(sinfo->cwd));
        else
            sinfo->cwd[sizeof(sinfo->cwd)-1] = '\0';
#endif
        sinfo->prio = cmd->priority;
    }

    /* Send the IPC info. */
    retval = ipcom_ipc_send(&ipc, sinfo);
    if (retval != IPCOM_SUCCESS)
    {
        IPCOM_LOG1(ERR, "ipcom_shell_run_extcmd :: ipcom_ipc_send() failed, ret = %d", retval);
        ipcom_ipc_free(sinfo);
        goto fail;
     }

    (void)ipcom_ipc_close(&ipc);

#ifdef IP_PORT_OSE5
    if (argc > 0)
    {
        /* OSE5 has process specific sockets -> donate child fd */
        ip_assert(*cmd_pid != 0);
        retval = (Ip_err)efs_donate_fd(*stdio_fd, *cmd_pid);
        if (retval != 0)
        {
            IPCOM_LOG1(ERR, "ipcom_shell_run_extcmd :: efs_donate_fd, ret = %d", retval);
            goto fail;
        }
    }
#endif /* IP_PORT_OSE5 */

    /* Wait for exit message from shell_cmd process. */
    retval = ipcom_ipc_receive(IP_NULL, &sinfo, -1);
    if (retval != IPCOM_SUCCESS)
    {
        IPCOM_LOG1(ERR, "ipcom_shell_run_extcmd :: ipcom_ipc_receive(shell_cmd) failed, ret = %d", retval);
        goto fail;
    }
    ip_assert(argc > 0 || *(Ip_u32 *)sinfo == 1);
    if (*(Ip_u32 *)sinfo == 1)
    {
        *cmd_pid = 0;  /* shell command called ipcom_exit(). */
        (*proc_index)++;
    }
    else
    {
#ifdef IP_PORT_OSE5
        *stdio_fd = efs_receive_fd(0);
        if (*stdio_fd == -1)
        {
            IP_PANIC();
            goto fail;
        }
#endif
#if defined(IP_PORT_OSE) || defined(IP_PORT_OSE5)
        /* Change child socket owner (A must for OSE to work due to poor ipcom_block impl). */
        pid = ipcom_getpid();
        if (ipcom_socketioctl(*stdio_fd, IP_SIOCSPGRP, &pid) < 0)
        {
            IP_PANIC2();
            IPCOM_LOG1(WARNING, "ipcom_shell_run_extcmd :: ipcom_socketioctl(IP_SIOCSPGRP) failed, errno = %d", ipcom_errno);
        }
#endif

    }
    ipcom_ipc_free(sinfo);

    return 1;

 fail:
    if (ipcom_ipc_isopen(&ipc))
        (void)ipcom_ipc_close(&ipc);
    return -1;
}
/*
 *===========================================================================
 *                      ipwlan_cmd_wlan_en
 *===========================================================================
 * Description: Parses and executes wlan shell commands.
 * Parameters:  'en' == 0 => Do not print to console,
 * Returns:     0 on success
 */
IP_STATIC int
ipwlan_cmd_wlan_en(int en, int argc, char **argv)
{
    int i;
    int j;
    int k;

    Ip_fd fd;
    char *endp;
    char ssid[32];
    Ipcom_iwreq iwreq;
    unsigned char oid_data[10];
    Ip_err ret = IPCOM_SUCCESS;

    if (argc < 3)
    {
        /* To few arguments */
        ipwlan_print_usage(en);

        return ret;
    }

#ifdef IPCOM_USE_INET
    fd = ipcom_socket(IP_AF_INET, IP_SOCK_DGRAM, 0);
#else
    fd = ipcom_socket(IP_AF_INET6, IP_SOCK_DGRAM, 0);
#endif
    if (fd == IP_SOCKERR)
    {
        ipwlan_printf(en, "Error: unable to create command socket"IP_LF);

        return IPCOM_ERR_FAILED;
    }

    /* Verify interface existance */
    ipcom_sprintf(iwreq.if_name, "%.*s", IP_IFNAMSIZ - 1, argv[1]);
    if(ipcom_if_nametoindex(iwreq.if_name) < 1)
    {
        ipwlan_printf(en, "Error: Interface '%s' does not exist"IP_LF, iwreq.if_name);

        goto error;
    }

    /* Reset WLAN device */
    if (!ipcom_strcmp(argv[2], "reset"))
    {
        ipcom_socketioctl(fd, IP_SIOCSIWRESET, &iwreq);

        goto done;
    }

    /* Set/Get mode */
    if (!ipcom_strcmp(argv[2], "mode"))
    {
        if(argc < 4)
        {
            if(ipcom_socketioctl(fd, IP_SIOCGIWMODE, &iwreq) < 0)
            {
                goto error;
            }
            if(iwreq.u.mode == IP_IW_MODE_INFRA)
            {
                i = wlan_mode_client_infra;
            }
            else if(iwreq.u.mode == IP_IW_MODE_AUTO)
            {
                i = wlan_mode_client_auto;
            }
            else if(iwreq.u.mode == IP_IW_MODE_ADHOC)
            {
                i = wlan_mode_client_adhoc;
            }
            else if(iwreq.u.mode == IP_IW_MODE_MASTER)
            {
                i = wlan_mode_ap;
            }
            else
            {
                i = wlan_mode_unknown;
            }
            ipwlan_printf(en, "Current mode is: %s"IP_LF, wlan_mode_text[i]);
        }
        else
        {
            /* Set mode */
            if (!strcmp(argv[3], "client"))
            {
                if(argc < 5 || (strcmp(argv[4], "adhoc") && strcmp(argv[4], "auto") && strcmp(argv[4], "infra")))
                {
                    ipwlan_printf(en, "prism <interface> mode client [auto|adhoc|infra]"IP_LF);

                    goto done;
                }
                iwreq.u.mode = !strcmp(argv[4], "auto") ? IP_IW_MODE_AUTO : (!strcmp(argv[4], "infra") ? IP_IW_MODE_INFRA : IP_IW_MODE_ADHOC);

            }
            else if (!strcmp(argv[3], "ap"))
            {
                iwreq.u.mode = IP_IW_MODE_MASTER;
            }
            else
            {
                ipwlan_printf(en, "prism <interface> mode ap"IP_LF);
                ipwlan_printf(en, "prism <interface> mode client auto|adhoc|infra"IP_LF);

                goto done;
            }
            if (ipcom_socketioctl(fd, IP_SIOCSIWMODE, &iwreq) < 0)
            {
                goto error;
            }
        }
        goto done;
    }

    /* Get/Set SSID */
    if (!ipcom_strcmp(argv[2], "ssid"))
    {
        iwreq.u.essid.pointer = ssid;
        if (argc < 4)
        {
            /* Get SSID */
            iwreq.u.essid.length = sizeof(ssid);
            if (ipcom_socketioctl(fd, IP_SIOCGIWESSID, &iwreq) == 0)
            {
                if(ssid[0])
                {
                    ipwlan_printf(en, "ssid: %s"IP_LF, ssid);
                }
                else
                {
                    ipwlan_printf(en, "-- Not associated --"IP_LF);
                }
                goto done;
            }
        }
        else
        {
            /* Set SSID */
            iwreq.u.essid.length = ipcom_sprintf(ssid, "%.*s", sizeof(ssid) - 1, argv[3]);
            if (ipcom_socketioctl(fd, IP_SIOCSIWESSID, &iwreq) == 0)
            {
                goto done;
            }
        }
        goto error;
    }

    /* Get/Set frequency */
    if (!ipcom_strcmp(argv[2], "freq"))
    {
        if(argc < 4)
        {
            /* Get frequency */
            if (ipcom_socketioctl(fd, IP_SIOCGIWFREQ, &iwreq) < 0)
            {
                goto error;
            }
            ipwlan_printf(en, "RF frequency: %d kHz"IP_LF, iwreq.u.freq.m);
        }
        else
        {
            /* Set frequency */
            if (!strcmp(argv[3], "auto"))
            {
                iwreq.u.freq.flags = IP_IW_FREQ_AUTO;
                iwreq.u.freq.m = WLAN_FREQUENCY_BAND;
                iwreq.u.freq.e = 0;
            }
            else
            {
                i = ipcom_strtol(argv[3], &endp, 10);
                if (*endp != '\0')
                {
                    ipwlan_printf(en, "Error: invalid frequency value, '%s'"IP_LF, argv[3]);

                    goto done;
                }
                iwreq.u.freq.flags = IP_IW_FREQ_FIXED;
                iwreq.u.freq.m = i;
                iwreq.u.freq.e = 0;
                if (ipcom_socketioctl(fd, IP_SIOCSIWFREQ, &iwreq) < 0)
                {
                    goto error;
                }
            }
        }
        goto done;
    }

    /* Get/Set authentication */
    if (!ipcom_strcmp(argv[2], "auth"))
    {
        if (argc < 4)
        {
            /* Get authentication policy */
            ipwlan_printf(en, "Cannot get authentication policy. Try device specific shell command"IP_LF);
        }
        else
        {
            /* Set authentication policy */
            if (strcmp(argv[3], "open") && strcmp(argv[3], "shared-key") && strcmp(argv[3], "wpa-psk") && strcmp(argv[3], "wpa") && strcmp(argv[3], "wpa2-psk") && strcmp(argv[3], "wpa2"))
            {
                ipwlan_printf(en, "Error: invalid authentication policy, valid policies are 'open', 'shared-key', 'wpa-psk or 'wpa'" IP_LF);

                goto done;
            }
            if(strcmp(argv[3], "open") == 0)
                iwreq.u.auth_type = IP_IW_AUTH_ALG_OPEN_SYSTEM;
            else if(strcmp(argv[3], "shared-key") == 0)
                iwreq.u.auth_type = IP_IW_AUTH_ALG_SHARED_KEY;
            else if(strcmp(argv[3], "wpa2-psk") == 0)
                iwreq.u.auth_type = IP_IW_AUTH_ALG_WPA2_PSK;
            else if(strcmp(argv[3], "wpa2") == 0)
                iwreq.u.auth_type = IP_IW_AUTH_ALG_WPA2;
            else if(strcmp(argv[3], "wpa-psk") == 0)
                iwreq.u.auth_type = IP_IW_AUTH_ALG_WPA_PSK;
            else
                iwreq.u.auth_type = IP_IW_AUTH_ALG_WPA;

            if (ipcom_socketioctl(fd, IP_SIOCSIWAUTHTYPE, &iwreq) < 0)
            {
                goto error;
            }
        }
        goto done;
    }

    /* Get/Set encryption */
    if (!ipcom_strcmp(argv[2], "encr"))
    {
        if (argc < 4)
        {
            if (ipcom_socketioctl(fd, IP_SIOCGIWENCRTYPE, &iwreq) < 0)
            {
                goto error;
            }
            for(i = 0; i < (int) (sizeof(ipwlan_encr_policy)/sizeof(ipwlan_encr_policy[0])); i++)
            {
                if ((unsigned) ipwlan_encr_policy[i] == iwreq.u.encr_type)
                {
                    break;
                }
            }
            ipwlan_printf(en, "privacy: %s"IP_LF, wlan_encr_text[i]);
        }
        else
        {
            /* Set encryption parameters */
            if (!strcmp(argv[3], "wep"))
            {
                if (argc < 5 || argc > 6)
                {
                    ipwlan_printf(en, "Usage: wlan <interface> encr wep 1|2|3|4 [<key>]"IP_LF);

                    goto done;
                }
                i = ipcom_strtol(argv[4], &endp, 10);
                if (*endp != '\0' || i < 1 || i > 4)
                {
                    ipwlan_printf(en, "Error: Invalid index value allowed are 1 to 4" IP_LF);

                    goto done;
                }
                if(argc == 6)
                {
                    if (argv[5][0] == '0' && argv[5][1] == 'x')
                    {
                        if (ipcom_strspn(argv[5] + 2, "012345678ABCDEFabcdef") != ipcom_strlen(argv[5] + 2) || ipcom_strlen(argv[5] + 2) > 32 || (ipcom_strlen(argv[5] + 2) % 2) != 0) /* 32 nibbles => 128 bits */
                        {
                            ipwlan_printf(en, "Usage: wlan <interface> encr wep <index> 0x<hex key>|<string key>"IP_LF);

                            goto done;
                        }
                        for (j = 0; ipcom_sscanf(argv[5] + 2 + 2 * j, "%2x", &k); j++)
                        {
                            iwreq.u.key.key[j] = (unsigned char)k;
                        }
                        iwreq.u.key.len = j;
                    }
                    else
                    {
                        /* key is a text string */
                        iwreq.u.key.len = ipcom_sprintf((char *)iwreq.u.key.key, "%.*s", MIN(sizeof(iwreq.u.key.key) - 1, ipcom_strlen(argv[5])), argv[5]);
                    }
                    iwreq.u.key.flags = 0;
                }
                else
                {
                    iwreq.u.key.flags = IP_IW_KEY_FLAG_NOKEY;
                }
                iwreq.u.key.type = IP_IW_ENCR_ALG_WEP;
                iwreq.u.key.index = i - 1; /* Index 1 - 4 */
                if (ipcom_socketioctl(fd, IP_SIOCSIWENCRKEY, &iwreq) < 0)
                {
                    goto error;
                }

                iwreq.u.encr_type = IP_IW_ENCR_ALG_WEP;
                if (ipcom_socketioctl(fd, IP_SIOCSIWENCRTYPE, &iwreq) < 0)
                {
                    goto error;
                }
            }
            else if (!strcmp(argv[3], "none"))
            {
                iwreq.u.encr_type = IP_IW_ENCR_ALG_NONE;

                if (ipcom_socketioctl(fd, IP_SIOCSIWENCRTYPE, &iwreq) < 0)
                {
                    goto error;
                }
            }
            else if (!strcmp(argv[3], "tkip"))
            {
                iwreq.u.encr_type = IP_IW_ENCR_ALG_TKIP;

                if (ipcom_socketioctl(fd, IP_SIOCSIWENCRTYPE, &iwreq) < 0)
                {
                    goto error;
                }
            }
            else if (!strcmp(argv[3], "ccmp"))
            {
                iwreq.u.encr_type = IP_IW_ENCR_ALG_CCMP;

                if (ipcom_socketioctl(fd, IP_SIOCSIWENCRTYPE, &iwreq) < 0)
                {
                    goto error;
                }
            }
            else
            {
                goto error;
            }
        }

        goto done;
    }

    /* Commit changes */
    if (!ipcom_strcmp(argv[2], "commit"))
    {
        if (ipcom_socketioctl(fd, IP_SIOCSIWCOMMIT, &iwreq) < 0)
        {
            goto error;
        }

        goto done;
    }

    /* Get link quality */
    if (!ipcom_strcmp(argv[2], "quality"))
    {
        ipcom_socketioctl(fd, IP_SIOCGIWAP, &iwreq);
        ipcom_memcpy(oid_data, iwreq.u.addr.sa_data, 6);
        ipcom_memcpy(iwreq.u.quality.bssid, oid_data, 6);
        if (ipcom_socketioctl(fd, IP_SIOCGIWQUALITY, &iwreq) < 0)
        {
            goto error;
        }

        ipwlan_printf(en, "\r\nLink quality\r\n============\r\n");
        ipwlan_printf(en, "RSSI:   % 3d dBm\r\n", (int)iwreq.u.quality.level);
        ipwlan_printf(en, "Rate:   % 3d Mbps\r\n", (unsigned int)iwreq.u.quality.qual);

        goto done;
    }

error:

    ipwlan_printf(en, "Error: command %s failed"IP_LF, argv[2]);
    ret = IPCOM_ERR_FAILED;

done:
    (void)ipcom_socketclose(fd);

    return ret;
}
/*
 *===========================================================================
 *                    ipnet_config_add_inet6_addr
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 *
 */
IP_STATIC int
ipnet_config_add_inet6_addr(Ip_fd fd, char *ifname, char *option)
{
    char *opt;
    char *inet6_addr;
    char *prefix_len;
    char *argv[] = {
        "ifconfig",
        "-silent",
        IP_NULL,
        "inet6",
        "add",
        IP_NULL,
        IP_NULL,
        IP_NULL,
        IP_NULL,
        IP_NULL,
        IP_NULL
    };
    int argc = 6;
    char inet6_addr_str[IP_INET6_ADDRSTRLEN];
    char prefixlen_str[4];

    argv[2] = ifname;

    for (;;)
    {
        /* Parse options */
        opt = ipcom_strtok_r(option, " \t/", &option);
        if (opt == IP_NULL)
        {
            IPCOM_LOG0(ERR, "too few arguments");
            return -IP_ERRNO_EINVAL;
        }
        if (ipcom_strcmp(opt, "tentative") == 0)
            argv[argc++] = opt;
        else
            break;
    }

    inet6_addr = opt;
    if (ipcom_strcmp(inet6_addr, "driver") == 0)
    {
        /* Get the IPv6 address to use from the driver */
        struct Ip_ethreq ethreq;

        ipcom_strcpy(ethreq.ethr_name, ifname);
        if (ipcom_socketioctl(fd, IP_SIOCXETHGINET6, &ethreq) < 0)
        {
            IPCOM_LOG1(ERR, "Failed to read the IPv6 address from the driver for %s", ifname);
            return ipcom_errno;
        }
        inet6_addr = inet6_addr_str;
        (void) ipcom_inet_ntop(IP_AF_INET6, &ethreq.ethru.inet6.addr,
                               inet6_addr_str, sizeof(inet6_addr_str));

        ipcom_sprintf(prefixlen_str, "%u", ethreq.ethru.inet6.prefixlen);
        prefix_len = prefixlen_str;
    }
    else
    {
        prefix_len = ipcom_strtok_r(option, " \t/", &option);
        if (prefix_len == IP_NULL)
        {
            IPCOM_LOG0(ERR, "prefix len is missing or format is invalid");
            return -IP_ERRNO_EINVAL;
        }
    }

    argv[5] = inet6_addr;
    argv[argc++] = "prefixlen";
    argv[argc++] = prefix_len;

    return ipnet_config_cmd_ifconfig(argc, argv);
}
IP_STATIC
IPCOM_PROCESS( ipcom_cmd_smptest_server_spawn )
{
    union
    {
        struct Ip_sockaddr          sa;
#ifdef IPCOM_USE_INET6
        struct Ip_sockaddr_in6      sin6;
#endif
        struct Ip_sockaddr_storage  ss;
        struct Ip_sockaddr_in       sin;
    } addr;

    Ip_fd  listen_socket;
    Ip_fd  connect_sock = 0;
    int    opt_val = 1;
    int    portadd = spawn_number_server++;
    int    bytes = 0;
    int    sec = SECONDS_CLIENT + SECONDS_SERVER;
    unsigned char *buf = 0;
    int    num_recives = 0;
    unsigned long num_bytes = 0;
    struct Ip_sockaddr from;
    struct Ip_linger   linger;
    Ip_socklen_t       from_length = 0;
    int     retry_count = 0;

    ipcom_proc_init();

    ipcom_memset( &addr.ss, 0, sizeof( addr.ss ) );
    ipcom_memcpy( &addr.sa, smp_opt_server.res->ai_addr, smp_opt_server.res->ai_addrlen );

    linger.l_onoff  = 1;
    linger.l_linger = 2;

    listen_socket = ipcom_socket( smp_opt_server.res->ai_family, smp_opt_server.res->ai_socktype, smp_opt_server.res->ai_protocol );
    if (listen_socket == IP_SOCKERR)
    {
        ipcom_printf("Failed to create socket: %s"IP_LF, ipcom_strerror(ipcom_errno));
        return_server = 1;
        ipcom_sem_post( sem_wait_server );
        return;
    }

    if ( 0 != ipcom_setsockopt(listen_socket, IP_SOL_SOCKET, IP_SO_REUSEPORT, &opt_val, sizeof (opt_val)) )
    {
        ipcom_printf("ipcom_setsockopt failed: %s"IP_LF, ipcom_strerror(ipcom_errno));
        return_server = 1;
        ipcom_sem_post( sem_wait_server );
        return;
    }

    addr.sin.sin_port = ip_htons( smp_opt_server.port + portadd );   /* port is in the same place for IPv4 and IPv6 */
    if ( 0 != ipcom_bind( listen_socket, &addr.sa, sizeof( addr.ss ) ) )
    {
        ipcom_printf("Failed to bind: %s"IP_LF, ipcom_strerror(ipcom_errno));
        return_server = 1;
        ipcom_sem_post( sem_wait_server );
        return;
    }

    buf = ipcom_malloc( smp_opt_server.num_bytes );

    if ( smp_opt_server.tcp )
    {
        if ( -1 == ipcom_listen( listen_socket, 0 ) )
        {
            ipcom_printf("Listen failed: %s"IP_LF, ipcom_strerror(ipcom_errno));
            return_server = 1;
            ipcom_sem_post( sem_wait_server );
            return;
        }
        if ( verbose )
            ipcom_printf("Thread %d listens to %s:%d"IP_LF, portadd, smp_opt_server.res->ai_canonname, ip_ntohs( addr.sin.sin_port ) );
    }

    if ( 0 == ipcom_atomic_sub_and_return( &listen_wait, 1 ) )
    {
        /* Send to the test-server or write to stdout? */
        if ( server_out >= 0 )
        {
            char ready[] = "Ready.";
            ipcom_socketwrite(server_out, ready, 8 );
        }
        else
            ipcom_printf("Ready."IP_LF );
    }

    if ( 0 != ipcom_socketioctl( listen_socket, IP_X_SIOCSINTR, &sec ) )
    {
        ipcom_printf("ipcom_socketioctl failed: %s"IP_LF, ipcom_strerror(ipcom_errno));
        return_server = 1;
        ipcom_sem_post( sem_wait_server );
        return;
    }

    if ( smp_opt_server.tcp )
    {
retry:
        connect_sock = ipcom_accept( listen_socket, IP_NULL, 0 );
        if ( -1 == connect_sock )
        {
            if ( ipcom_errno == IP_ERRNO_EINTR )
            {
                if ( verbose )
                {
                    if ( ++retry_count < 5 )
                    {
                        ipcom_printf("Accept failed for thread %d: %s.. Retrying."IP_LF, portadd, ipcom_strerror(ipcom_errno));
                        goto retry;
                    }
                }
            }
            ipcom_printf("Accept failed for thread %d: %s"IP_LF, portadd, ipcom_strerror(ipcom_errno));
            return_server = 1;
            ipcom_socketclose( listen_socket );
            ipcom_sem_post( sem_wait_server );
            return;
        }

        if ( 0 != ipcom_socketioctl( connect_sock, IP_X_SIOCSINTR, &sec ) )
        {
            ipcom_printf("ipcom_socketioctl failed: %s"IP_LF, ipcom_strerror(ipcom_errno));
            return_server = 1;
            ipcom_sem_post( sem_wait_server );
            return;
        }

        if ( 0 != ipcom_setsockopt( connect_sock, IP_SOL_SOCKET, IP_SO_LINGER, &linger, sizeof (linger)) )
        {
            ipcom_printf("ipcom_setsockopt failed: %s"IP_LF, ipcom_strerror(ipcom_errno));
            return_server = 1;
            ipcom_sem_post( sem_wait_server );
            return;
        }
    }

    while ( 1 )
    {
        num_recives++;
        if ( smp_opt_server.tcp )
            bytes = ipcom_recv( connect_sock, buf, smp_opt_server.num_bytes, 0);
        else
        {
            bytes = ipcom_recvfrom( listen_socket, buf, smp_opt_server.num_bytes, 0, &from, &from_length );
            if ( num_recives == 1 && 0 == smp_opt_server.tcp )
            {
                sec = SECONDS_CLIENT+2+portadd;
                if ( 0 != ipcom_socketioctl( listen_socket, IP_X_SIOCSINTR, &sec ) )
                {
                    ipcom_printf("ipcom_socketioctl failed: %s"IP_LF, ipcom_strerror(ipcom_errno));
                    return_server = 1;
                    ipcom_sem_post( sem_wait_server );
                    return;
                }
            }
        }

        if ( bytes > 0 )
            num_bytes += bytes;
        if (bytes == 0)
        {
            if ( verbose )
            {
                ipcom_printf("Thread %d done."IP_LF, portadd );
                ipcom_printf("  Recives: %d"IP_LF, num_recives );
                ipcom_printf("  MB/s:    %f"IP_LF, ((float)(num_bytes)/(1024.0f*1024.0f) )/5.0f );
            }
            break;
        }
        else if (bytes < 0)
        {
            if ( ipcom_errno == IP_ERRNO_EINTR )
            {
                if ( smp_opt_server.tcp )
                {
                    return_server = 1;
                    ipcom_printf("Error! Out of time!"IP_LF );
                    break;
                }
                else
                {
                    if ( verbose )
                    {
                        ipcom_printf("Thread %d done."IP_LF, portadd );
                        ipcom_printf("  Recives: %d"IP_LF, num_recives );
                        ipcom_printf("  MB/s:    %f"IP_LF, ((float)(num_bytes)/(1024.0f*1024.0f) )/5.0f );
                    }
                    break;
                }
            }
            else if ( bytes == IP_SOCKERR )    /* Connection reset by peer */
            {
            }

            return_server = 1;
            ipcom_printf("recv failed: %s"IP_LF, ipcom_strerror(ipcom_errno));
            return;
        }
    }

    if ( verbose )
    {
        if ( spawn_number_server != smp_opt_server.num_sock )
        {
            ipcom_printf("Error. Only %d server-sockets seemed to work."IP_LF, spawn_number_server );
        }
    }

    if ( smp_opt_server.tcp )
        ipcom_shutdown( connect_sock, IP_SHUT_RDWR );

    ipcom_free( buf );
    ipcom_socketclose( listen_socket );

    if ( 0 == ipcom_atomic_sub_and_return( &num_wait_server, 1 ) )
        ipcom_sem_post( sem_wait_server );

    if ( smp_opt_server.tcp )
        ipcom_socketclose( connect_sock );

    ipcom_proc_exit();
}
/*
 *===========================================================================
 *                         ipsecctrl_sa
 *===========================================================================
 */
static int
ipsecctrl_sa(Argvars *vars)
{
    Ipipsec_ioctl_sactrl   sa_next;
    Ipipsec_ioctl_sactrl   sa_group;
    int       num;
    Ip_err    retval;
    Ip_tag    tags[7];
#ifdef IPCOM_USE_INET6
    char str[IP_INET6_ADDRSTRLEN];
    char str2[IP_INET6_ADDRSTRLEN];
#else
    char str[16], str2[16];
#endif

    /* Print all SAs. */
    ipcom_printf("SA - Security Associations:"IP_LF);

    sa_next.arg.next.spi_n = 0;  /* get first SA. */

    for (num = 0;;)
    {
        ipcom_memcpy(&sa_next.sa, &sa_next.arg.next, sizeof(Ipipsec_sa_handle));
        sa_next.arg.next.direction = IPIPSEC_SADIR_ANY;
        sa_next.arg.next.protocol  = 0;
        sa_next.arg.next.domain    = 0;

        /* Get first/next Selector */
        if (ipcom_socketioctl(vars->fd, IP_SIOCXIPSEC_NEXT_SA, &sa_next) < 0)
        {
            ipcom_printf("ipsecctrl: ipcom_socketioctl(NEXT_SA) failed (%s)"IP_LF,
                         ipcom_strerror(ipcom_errno));
            return -1;
        }

        if (sa_next.arg.next.spi_n == 0)
            break;

        /* Get additional information. */
        tags[0] = IPIPSEC_SACTRLT_GET_AuthAlg;
        tags[2] = IPIPSEC_SACTRLT_GET_EncAlg;
        tags[4] = IP_TAG_END;
        retval = ipipsec_sactrl(&sa_next.arg.next, tags);
        if (retval != IPCOM_SUCCESS)
        {
            ipcom_printf("ipsecctrl: ipipsec_sactrl(info) failed, error = %d"IP_LF, retval);
            return -1;
        }
        ipcom_printf("[%2d] ::  %-6s %s spi=0x%-5lx src=%-17s dst=%-17s auth=%s",
                     ++num,
                     sa_next.arg.next.direction == IPIPSEC_SADIR_INPUT ? "input" :
                     sa_next.arg.next.direction == IPIPSEC_SADIR_OUTPUT ? "output" : "any",
                     ipcom_ipproto_name(sa_next.arg.next.protocol),
                     ip_ntohl(sa_next.arg.next.spi_n),
                     ipcom_inet_ntop(sa_next.arg.next.domain, &sa_next.arg.next.src, str, sizeof(str)),
                     ipcom_inet_ntop(sa_next.arg.next.domain, &sa_next.arg.next.dst, str2, sizeof(str2)),
                     mib_AuthAlg[tags[1]]);


        if (sa_next.arg.next.protocol == IP_IPPROTO_ESP)
            ipcom_printf(" enc=%s", mib_EncAlg[tags[3]]);
        if (sa_next.arg.next.priority != 0)
            ipcom_printf(" pri=%d", (int)sa_next.arg.next.priority);
        if (sa_next.arg.next.dscp != 0)
            ipcom_printf(" DSCP=%d", (int)sa_next.arg.next.dscp);
        ipcom_printf(IP_LF);

        /* Get grouped info */
        ipcom_memcpy(&sa_group.sa, &sa_next.arg.next, sizeof(Ipipsec_sa_handle));
        if (ipcom_socketioctl(vars->fd, IP_SIOCXIPSEC_Grouped, &sa_group) < 0)
        {
            ipcom_printf("ipsecctrl: ipcom_socketioctl(Grouped) failed (%s)"IP_LF,
                         ipcom_strerror(ipcom_errno));
            return -1;
        }
        if (sa_group.arg.group.spi_n) /*lint !e530 */
        {
            ipcom_printf("           ->   %s spi=0x%-5lx src=%-17s dst=%-17s",
                         ipcom_ipproto_name(sa_group.arg.group.protocol),
                         ip_ntohl(sa_group.arg.group.spi_n),
                         ipcom_inet_ntop(sa_next.arg.next.domain, &sa_next.arg.next.src, str, sizeof(str)),
                         ipcom_inet_ntop(sa_group.arg.group.domain, &sa_next.arg.next.dst, str2, sizeof(str2)));
            if (sa_group.arg.group.priority != 0)
                ipcom_printf(" pri=%d", (int)sa_group.arg.group.priority);
            if (sa_group.arg.group.dscp != 0)
                ipcom_printf(" DSCP=%d", (int)sa_group.arg.group.dscp);
            ipcom_printf(IP_LF);
        }
    }

    ipcom_printf("Total of %d SAs."IP_LF, num);
    return 0;
}
/*
 *===========================================================================
 *                         ipsecctrl_flows
 *===========================================================================
 */
static int
ipsecctrl_flows(Argvars *vars)
{
    Ipipsec_ctrl_selector   sel;
    char   srcport[32], dstport[32];
    int    num = 0;
    char   str[IP_INET6_ADDRSTRLEN];
    char   str2[IP_INET6_ADDRSTRLEN+1];

    ipcom_printf("Flows:"IP_LF);

    sel.Index = 0;  /* get first selector. */

    /* Get and print the Selectors in MIB format. */
    for (;;)
    {
        /* Get first/next Selector */
        if (ipcom_socketioctl(vars->fd, IP_SIOCXIPSEC_SELECTOR, &sel) < 0)
        {
            ipcom_printf("ipsecctrl: ipcom_socketioctl(SELECTOR) failed (%s)"IP_LF,
                         ipcom_strerror(ipcom_errno));
            return -1;
        }

        if (sel.Index == 0)
            break;

        /* Print selector aka flow: */
        num++;
        ipcom_printf("[%ld] :: %s ", sel.Index, FLOW_TYPE(sel.flowtype));

        if (sel.flowpri != 0)
            ipcom_printf("pri=%d ", (signed char)sel.flowpri);

        /* source */
        if (sel.LocalPort != sel.LocalMaxPort)
            ipcom_sprintf(srcport, "%d-%d",
                          (int)ip_ntohs(sel.LocalPort), (int)ip_ntohs(sel.LocalMaxPort));
        else if (sel.LocalPort == 0)
            ipcom_strcpy(srcport, "any");
        else
            ipcom_sprintf(srcport, "%d", (int)ip_ntohs(sel.LocalPort));
        if (ipcom_memcmp(&sel.LocalId, &sel.LocalMaxId, sizeof(union Ip_in_addr_union)))
            ipcom_sprintf(str2, "-%s",
                          ipcom_inet_ntop(sel.domain, &sel.LocalMaxId, str, sizeof(str)));
        else
            *str2 = '\0';
        ipcom_printf("src=%s%s/%d:%s ",
                     ipcom_inet_ntop(sel.domain, &sel.LocalId, str, sizeof(str)),
                     str2,
                     ipipsec_addrmasklen(sel.domain, (Ip_u8 *)&sel.local_mask),
                     srcport);

        /* destination */
        if (sel.RemotePort != sel.RemoteMaxPort)
            ipcom_sprintf(dstport, "%d-%d",
                          (int)ip_ntohs(sel.RemotePort), (int)ip_ntohs(sel.RemoteMaxPort));
        else if (sel.RemotePort == 0)
            ipcom_strcpy(dstport, "any");
        else
            ipcom_sprintf(dstport, "%d", (int)ip_ntohs(sel.RemotePort));
        if (ipcom_memcmp(&sel.RemoteId, &sel.RemoteMaxId, sizeof(union Ip_in_addr_union)))
            ipcom_sprintf(str2, "-%s",
                          ipcom_inet_ntop(sel.domain, &sel.RemoteMaxId, str, sizeof(str)));
        else
            *str2 = '\0';
        ipcom_printf("dst=%s%s/%d:%s ",
                     ipcom_inet_ntop(sel.domain, &sel.RemoteId, str, sizeof(str)),
                     str2,
                     ipipsec_addrmasklen(sel.domain, (Ip_u8 *)&sel.remote_mask),
                     dstport);

        ipcom_printf("%s", ipcom_ipproto_name(sel.Protocol));
        switch (sel.Protocol)
        {
        case IP_IPPROTO_ICMP:
        case IP_IPPROTO_ICMPV6:
            if (sel.ports[0] || sel.ports[1])
                ipcom_printf(" type=%d code=%d", sel.ports[0], sel.ports[1]);
            break;
        case IP_IPPROTO_MH:
            if (sel.ports[0])
                ipcom_printf(" type=%d", sel.ports[0]);
            break;
        default:
            break;
        }

        /* Print SA */
        if (sel.sa.domain)
        {
            if (sel.sa.domain == IPIPSEC_AF_BYPASS)
                ipcom_printf(" %s SA: %s",
                             sel.direction == IPIPSEC_SADIR_INPUT ? "<-" :
                             sel.direction == IPIPSEC_SADIR_OUTPUT ? "->" : "--",
                             IPSECSATYPENAME(sel.sa.satype));
            else
                ipcom_printf(" %s SA: %s spi=0x%lx src=%s dst=%s",
                             sel.direction == IPIPSEC_SADIR_INPUT ? "<-" :
                             sel.direction == IPIPSEC_SADIR_OUTPUT ? "->" : "--",
                             IPSECSATYPENAME(sel.sa.satype),
                             ip_ntohl(sel.sa.spi_n),
                             ipcom_inet_ntop(sel.sa.domain, &sel.sa.src, str, sizeof(str)),
                             ipcom_inet_ntop(sel.sa.domain, &sel.sa.dst, str2, sizeof(str2)));
        }
        else
            ipcom_printf(" %s SA: none",
                         sel.direction == IPIPSEC_SADIR_INPUT ? "<-" :
                         sel.direction == IPIPSEC_SADIR_OUTPUT ? "->" : "--");
        ipcom_printf(IP_LF);
    }
    ipcom_printf("Total of %d flows."IP_LF, num);

    return 0;
}
IP_PUBLIC int
ipcom_socketpair_tcp(int fd[2])
{
	int server;
	union Ip_sockaddr_union  sock;
	Ip_socklen_t socklen;
	Ip_bool connected = IP_FALSE;
    int opt;
    struct Ip_addrinfo   hints;
    struct Ip_addrinfo  *res = IP_NULL;

	fd[0] = fd[1] = server = -1;

    ipcom_memset(&hints, 0, sizeof(hints));
    hints.ai_socktype = IP_SOCK_STREAM;
    if (ipcom_getaddrinfo(IP_NULL, "0", &hints, &res) != 0)
        goto failed;

    /* Server socket */
    server = ipcom_socket(res->ai_family, res->ai_socktype, res->ai_protocol);
	if (server == -1)
        goto failed;
    opt = 1;
	(void)ipcom_setsockopt(server, IP_SOL_SOCKET, IP_SO_REUSEADDR, &opt, sizeof(opt));
    if (ipcom_bind(server, res->ai_addr, res->ai_addrlen) != 0)
        goto failed;
	if (ipcom_listen(server, 1) != 0)
        goto failed;
    socklen = res->ai_addrlen;
	if (ipcom_getsockname(server, &sock.sa, &socklen) != 0)
        goto failed;

    /* Client socket */
    fd[1] = ipcom_socket(res->ai_family, res->ai_socktype, res->ai_protocol);
	if (fd[1] == -1)
        goto failed;
    opt = 1;
	(void)ipcom_setsockopt(fd[1], IP_SOL_SOCKET, IP_SO_REUSEADDR, &opt, sizeof(opt));
    opt = 1;
    (void)ipcom_socketioctl(fd[1], IP_FIONBIO, &opt);

	if (ipcom_connect(fd[1], &sock.sa, socklen) == -1)
    {
		if (ipcom_errno != IP_ERRNO_EINPROGRESS)
            goto failed;
	}
    else
		connected = IP_TRUE;

    /* Spawn socket */
    fd[0] = ipcom_accept(server, IP_NULL, IP_NULL);
	if (fd[0] == -1)
        goto failed;
    opt = 1;
	(void)ipcom_setsockopt(fd[0], IP_SOL_SOCKET, IP_SO_REUSEADDR, &opt, sizeof(opt));
	ipcom_socketclose(server);

    /* Client socket revisited */
	if (connected == IP_FALSE)
    {
        Ip_fd_set  write_set;
        IP_FD_ZERO(&write_set);
        IP_FD_SET(fd[1], &write_set);
        if (ipcom_socketselect(fd[1] + 1, IP_NULL, &write_set, IP_NULL, IP_NULL) != 1)
            goto failed;
	}
    opt = 0;
    (void)ipcom_socketioctl(fd[1], IP_FIONBIO, &opt);

    if (res != IP_NULL)
        ipcom_freeaddrinfo(res);
	return 0;

 failed:
    if (res != IP_NULL)
        ipcom_freeaddrinfo(res);
	if (fd[0] != -1)
        ipcom_socketclose(fd[0]);
	if (fd[1] != -1)
        ipcom_socketclose(fd[1]);
	if (server != -1)
        ipcom_socketclose(server);
	return -1;
}
IP_STATIC
IPCOM_PROCESS( ipcom_cmd_smptest_client_spawn )
{
    union
    {
        struct Ip_sockaddr          sa;
#ifdef IPCOM_USE_INET6
        struct Ip_sockaddr_in6      sin6;
#endif
        struct Ip_sockaddr_storage  ss;
        struct Ip_sockaddr_in       sin;
    } addr;
    Ip_fd socket;
    unsigned char *buf = 0;
    int portadd = spawn_number_client++;
    int opt_val = 1;
    int sec = SECONDS_CLIENT;
    int send = 0;
    int num_sends = 0;
    unsigned long num_bytes = 0;

    ipcom_proc_init();

    ipcom_memset( &addr.ss, 0, sizeof( addr.ss ) );
    ipcom_memcpy( &addr.sa, smp_opt_client.res->ai_addr, smp_opt_client.res->ai_addrlen );

    socket = ipcom_socket( smp_opt_client.res->ai_family, smp_opt_client.res->ai_socktype, smp_opt_client.res->ai_protocol );
    if (socket == IP_SOCKERR)
    {
        ipcom_printf("Failed to create socket for thread %d: %s"IP_LF, portadd, ipcom_strerror(ipcom_errno));
        return_client = 1;
        ipcom_sem_post( sem_wait_client );
        return;
    }

    if ( 0 != ipcom_setsockopt(socket, IP_SOL_SOCKET, IP_SO_REUSEPORT, &opt_val, sizeof (opt_val)) )
    {
        ipcom_printf("ipcom_setsockopt failed: %s"IP_LF, ipcom_strerror(ipcom_errno));
        return_client = 1;
        ipcom_sem_post( sem_wait_client );
        return;
    }

    if ( 0 != ipcom_socketioctl( socket, IP_X_SIOCSINTR, &sec ) )
    {
        ipcom_printf("ipcom_socketioctl failed: %s"IP_LF, ipcom_strerror(ipcom_errno));
        return_client = 1;
        ipcom_sem_post( sem_wait_client );
        return;
    }

    addr.sin.sin_port = ip_htons( smp_opt_client.port + portadd );   /* port is in the same place for IPv4 and IPv6 */
    if ( smp_opt_client.tcp )
    {
        if ( 0 != ipcom_connect( socket, &addr.sa, smp_opt_client.res->ai_addrlen ) )
        {
            ipcom_printf("Thread %d failed to connect: %s"IP_LF, portadd, ipcom_strerror(ipcom_errno));
            return_client = 1;
            ipcom_sem_post( sem_wait_client );
            return;
        }
        if ( verbose )
            ipcom_printf("Thread %d connected to port %d"IP_LF, portadd, smp_opt_client.port + portadd );
    }

    buf = ipcom_malloc( smp_opt_client.num_bytes );
    while ( 1 )
    {
        if ( smp_opt_client.tcp )
            send = ipcom_send( socket, buf, smp_opt_client.num_bytes, 0);
        else
            send = ipcom_sendto( socket, buf, smp_opt_client.num_bytes, 0, &addr.sa, smp_opt_client.res->ai_addrlen );

        if ( send > 0 )
           num_bytes += send;
        num_sends++;
        if ( send == 0 )
        {
           ipcom_printf( "Error: Disconnected"IP_LF );
           return_client = 1;
           break;
        }
        else if ( send < 0 )
        {
            if ( ipcom_errno == IP_ERRNO_EINTR )
            {
                if ( verbose )
                {
                    ipcom_printf("Thread %d done."IP_LF, portadd );
                    ipcom_printf("  Sends: %d"IP_LF, num_sends );
                    ipcom_printf("  MB/s:  %f"IP_LF, ((float)(num_bytes)/(1024.0f*1024.0f) )/5.0f );
                }
                break;
            }
            return_client = 1;
            ipcom_printf("Error on thread %d: %s"IP_LF, portadd, ipcom_strerror(ipcom_errno));
            break;
        }
    }

    if ( verbose )
    {
        if ( spawn_number_client != smp_opt_client.num_sock )
        {
            ipcom_printf("Error. Only %d client-sockets seemed to work."IP_LF, spawn_number_client );
        }
    }

    ipcom_socketclose( socket );

    ipcom_free( buf );
    if ( 0 == ipcom_atomic_sub_and_return( &num_wait_client, 1 ) )
        ipcom_sem_post( sem_wait_client );

    ipcom_proc_exit();
}
static void
ipsecctrl_saTables_print(Argvars *vars, Ip_u8 direction, Ip_u8 protocol, int domain)
{
    Ipipsec_ioctl_sactrl   sa_next;
    Ipipsec_ioctl_sactrl   sa_u64;
    Ip_err   retval;
    int  i, num;
    Ip_tag tags[41];
    char table[32];
#ifdef IPCOM_USE_INET6
    char str[IP_INET6_ADDRSTRLEN];
#else
    char str[16];
#endif

    /* pre-init print stuff. */
    ipcom_sprintf(table, "ipsecSa%s%s",
                  protocol == IP_IPPROTO_AH ? "Ah" : "Esp",
                  direction == IPIPSEC_SADIR_INPUT ? "In" :
                  direction == IPIPSEC_SADIR_OUTPUT ? "Out" :
                  "Any");

    /* Fill in the info tags. */
    tags[0] = IPIPSEC_SACTRLT_GET_SaSelector;
    tags[2] = IPIPSEC_SACTRLT_GET_SaCreator;
    tags[4] = IPIPSEC_SACTRLT_GET_Encapsulation;
    tags[6] = IPIPSEC_SACTRLT_GET_EncAlg;
    tags[8] = IPIPSEC_SACTRLT_GET_EncKeyLength;
    tags[10] = IPIPSEC_SACTRLT_GET_AuthAlg;
    tags[12] = IPIPSEC_SACTRLT_GET_AuthKeyLength;
    tags[14] = IPIPSEC_SACTRLT_GET_RepWinSize;
    tags[16] = IPIPSEC_SACTRLT_GET_LimitSeconds;
    tags[18] = IPIPSEC_SACTRLT_GET_LimitKbytes;
    tags[20] = IPIPSEC_SACTRLT_GET_AccSeconds;
    tags[22] = IPIPSEC_SACTRLT_GET_InAccKbytes;
    tags[24] = IPIPSEC_SACTRLT_GET_DecryptErrors;
    tags[26] = IPIPSEC_SACTRLT_GET_AuthErrors;
    tags[28] = IPIPSEC_SACTRLT_GET_ReplayErrors;
    tags[30] = IPIPSEC_SACTRLT_GET_PolicyErrors;
    tags[32] = IPIPSEC_SACTRLT_GET_PadErrors;
    tags[34] = IPIPSEC_SACTRLT_GET_OtherReceiveErrors;
    tags[36] = IPIPSEC_SACTRLT_GET_OutAccKbytes;
    tags[38] = IPIPSEC_SACTRLT_GET_OutSendErrors;
    tags[40] = IP_TAG_END;

    ipcom_printf(IP_LF"***** %stable ::"IP_LF, table);

    /* Get and print the SAs in MIB format. */
    sa_next.arg.next.spi_n = 0;

    for (num = 0;;)
    {
        ipcom_memcpy(&sa_next.sa, &sa_next.arg.next, sizeof(Ipipsec_sa_handle));
        sa_next.arg.next.direction = direction;
        sa_next.arg.next.protocol  = protocol;
        sa_next.arg.next.domain    = (Ip_u8)domain;
        if (ipcom_socketioctl(vars->fd, IP_SIOCXIPSEC_NEXT_SA, &sa_next) < 0)
        {
            ipcom_printf("ipsecctrl: ipcom_socketioctl(NEXT_SA) failed (%s)"IP_LF,
                         ipcom_strerror(ipcom_errno));
            return;
        }

        if (sa_next.arg.next.spi_n == 0)
            break;

        retval = ipipsec_sactrl(&sa_next.arg.next, tags);
        if (retval != IPCOM_SUCCESS)
        {
            ipcom_printf("ipsecctrl: ipipsec_sactrl(info) failed, error = %d"IP_LF, retval);
            return;
        }

        /* SA id */
        ipcom_printf(IP_LF"%sEntry #%d:"IP_LF
                     "%sAddresstype = %d"IP_LF
                     "%sAddress = %s"IP_LF
                     "%sSpi = 0x%lx"IP_LF
                     , table, num
                     , table, domain == IP_AF_INET ? 1 : domain == IP_AF_INET6 ? 2 : 3
                     , table, ipcom_inet_ntop(sa_next.arg.next.domain, &sa_next.arg.next.dst, str, sizeof(str))
                     , table, ip_ntohl(sa_next.arg.next.spi_n));

        /* SA MIB entries */
        for (i = 0; tags[i] != IP_TAG_END; i += 2)
        {
            switch(tags[i])
            {
            case IPIPSEC_SACTRLT_GET_SaSelector :
                ipcom_printf("%sSelector = %ld"IP_LF, table, tags[i+1]);
                break;

            case IPIPSEC_SACTRLT_GET_SaCreator :
                ipcom_printf("%sCreator = %s"IP_LF, table, mib_Creator[tags[i+1]]);
                break;

            case IPIPSEC_SACTRLT_GET_Encapsulation :
                ipcom_printf("%sEncapsulation = %s"IP_LF, table, mib_Encapsulation[tags[i+1]]);
                break;

            case IPIPSEC_SACTRLT_GET_EncAlg :
                ipcom_printf("%sEncAlg = %s"IP_LF, table, mib_EncAlg[tags[i+1]]);
                break;

            case IPIPSEC_SACTRLT_GET_EncKeyLength :
                ipcom_printf("%sEncKeyLength = %ld"IP_LF, table, tags[i+1]);
                break;

            case IPIPSEC_SACTRLT_GET_AuthAlg :
                ipcom_printf("%sAuthAlg = %s"IP_LF, table, mib_AuthAlg[tags[i+1]]);
                break;

            case IPIPSEC_SACTRLT_GET_AuthKeyLength :
                ipcom_printf("%sAuthKeyLength = %ld"IP_LF, table, tags[i+1]);
                break;

            case IPIPSEC_SACTRLT_GET_RepWinSize :
                ipcom_printf("%sRepWinSize = %ld"IP_LF, table, tags[i+1]);
                break;

            case IPIPSEC_SACTRLT_GET_LimitSeconds :
                ipcom_printf("%sLimitSeconds = %ld"IP_LF, table, tags[i+1]);
                break;

            case IPIPSEC_SACTRLT_GET_LimitKbytes :
                ipcom_printf("%sLimitKbytes = %ld"IP_LF, table, tags[i+1]);
                break;

            case IPIPSEC_SACTRLT_GET_AccSeconds :
                ipcom_printf("%sAccSeconds = %ld"IP_LF, table, tags[i+1]);
                break;

            case IPIPSEC_SACTRLT_GET_InAccKbytes :
                ipcom_printf("%sInAccKbytes = %ld"IP_LF, table, tags[i+1]);
                break;

            case IPIPSEC_SACTRLT_GET_OutAccKbytes :
                ipcom_printf("%sOutAccKbytes = %ld"IP_LF, table, tags[i+1]);
                break;

            case IPIPSEC_SACTRLT_GET_DecryptErrors :
                ipcom_printf("%sDecryptErrors = %ld"IP_LF, table, tags[i+1]);
                break;

            case IPIPSEC_SACTRLT_GET_AuthErrors :
                ipcom_printf("%sAuthErrors = %ld"IP_LF, table, tags[i+1]);
                break;

            case IPIPSEC_SACTRLT_GET_ReplayErrors :
                ipcom_printf("%sReplayErrors = %ld"IP_LF, table, tags[i+1]);
                break;

            case IPIPSEC_SACTRLT_GET_PolicyErrors :
                ipcom_printf("%sPolicyErrors = %ld"IP_LF, table, tags[i+1]);
                break;

            case IPIPSEC_SACTRLT_GET_PadErrors :
                ipcom_printf("%sPadErrors = %ld"IP_LF, table, tags[i+1]);
                break;

            case IPIPSEC_SACTRLT_GET_OtherReceiveErrors :
                ipcom_printf("%sOtherReceiveErrors = %ld"IP_LF, table, tags[i+1]);
                break;

            case IPIPSEC_SACTRLT_GET_OutSendErrors :
                ipcom_printf("%sOutSendErrors = %ld"IP_LF, table, tags[i+1]);
                break;

            default:
                ipcom_printf("error: unknown tag type '%ld'"IP_LF, tags[i]);
                break;
            }
        } /* for */

        ipcom_memcpy(&sa_u64.sa, &sa_next.arg.next, sizeof(Ipipsec_sa_handle));
        if (ipcom_socketioctl(vars->fd, IP_SIOCXIPSEC_InUserOctets, &sa_u64) == 0)
            ipcom_printf("%sInUserOctets = %ld"IP_LF, table, IP_U64_GETLO(sa_u64.arg.u64)); /*lint !e530 */
        if (ipcom_socketioctl(vars->fd, IP_SIOCXIPSEC_InUserPackets, &sa_u64) == 0)
            ipcom_printf("%sInUserPackets = %ld"IP_LF, table, IP_U64_GETLO(sa_u64.arg.u64)); /*lint !e530 */
        if (ipcom_socketioctl(vars->fd, IP_SIOCXIPSEC_OutUserOctets, &sa_u64) == 0)
            ipcom_printf("%sOutUserOctets = %ld"IP_LF, table, IP_U64_GETLO(sa_u64.arg.u64)); /*lint !e530 */
        if (ipcom_socketioctl(vars->fd, IP_SIOCXIPSEC_OutUserPackets, &sa_u64) == 0)
            ipcom_printf("%sOutUserPackets = %ld"IP_LF, table, IP_U64_GETLO(sa_u64.arg.u64)); /*lint !e530 */
    }
}