Exemple #1
0
/*
 *===========================================================================
 *                    ipcom_buffer_new
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 *
 */
Ipcom_buffer*
ipcom_buffer_new(Ip_s32 size)
{
    Ipcom_buffer *buffer;

    buffer = ipcom_malloc(sizeof(Ipcom_buffer));
    if(!buffer)
    {
        IPCOM_LOG0(ERR, "ipcom_buffer_new() :: out of memory");
        return IP_NULL;
    }

    buffer->buf = ipcom_malloc(size);
    if(buffer->buf == IP_NULL)
    {
        IPCOM_LOG0(ERR, "ipcom_buffer_new() :: out of memory");
        ipcom_free(buffer);
        return IP_NULL;
    }

    buffer->alloc = size;
    buffer->offset = 0;
    buffer->end = 0;

#ifdef IP_DEBUG
    ipcom_memset(buffer->buf, 0xcc, size);
#endif

    return buffer;
}
/*
 *===========================================================================
 *                    ipdnsc_hostent_create
 *===========================================================================
 * Description: Creates a hostent structure with empty alias and address
 *              lists
 * Parameters:  type  - the type of hostent structure
 * Returns:     pointer to the newly created hostent structure
 */
IP_GLOBAL struct Ip_hostent*
ipdnsc_hostent_create(Ip_s32 type)
{
    struct Ip_hostent *he;

    /* Allocate the host entry structure */
    he = ipcom_malloc(sizeof(*he));
    if (he == IP_NULL)
    {
        return IP_NULL;
    }
    ipcom_memset(he, 0, sizeof(*he));

    /* Set the type and length fields */
    he->h_addrtype = type;
    if (type == IP_AF_INET)
    {
        he->h_length = IPDNSC_INADDRSZ;
    }
    else if (type == IP_AF_INET6)
    {
        he->h_length = IPDNSC_IN6ADDRSZ;
    }
    else
    {
        ipcom_free(he);
        return IP_NULL;
    }

    /* Allocate memory for the alias list */
    he->h_aliases = ipcom_malloc(sizeof(char *));
    if (he->h_aliases == IP_NULL)
    {
        ipcom_free(he);
        return IP_NULL;
    }
    he->h_aliases[0] = IP_NULL;

    /* Allocate memory for the address list */
    he->h_addr_list = ipcom_malloc(sizeof(char *));
    if (he->h_addr_list == IP_NULL)
    {
        ipcom_free(he->h_aliases);
        ipcom_free(he);
        return IP_NULL;
    }
    he->h_addr_list[0] = IP_NULL;

    return he;
}
/*
 *===========================================================================
 *                    ipcom_create_ifaddrs_entry
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 *
 */
IP_STATIC struct Ip_ifaddrs *
ipcom_create_ifaddrs_entry(const char                *ifname,
                           struct Ipnet_if_msghdr    *ifm,
                           struct Ipnet_ifa_msghdr   *ifa,
                           struct Ip_sockaddr        **addrs)
{
    /**/
    struct Ip_ifaddrs        *nifa = ipcom_calloc(1, sizeof(*nifa));

    if (nifa == IP_NULL)
        return IP_NULL;

    /* Interface name */
    nifa->ifa_name = ipcom_strdup(ifname);
    if(nifa->ifa_name == IP_NULL)
        goto fail;

    /* Interface flags */
    nifa->ifa_flags = ifm->ifm_flags;

    /* Interface address */
    nifa->ifa_addr = ipcom_malloc(sizeof(union Ip_sockaddr_union));
    if(nifa->ifa_addr == IP_NULL)
        goto fail;

    ipcom_memcpy(nifa->ifa_addr, addrs[IPNET_RTAX_IFA], IPCOM_SA_LEN_GET(addrs[IPNET_RTAX_IFA]));

    nifa->ifa_netmask = ipcom_malloc(sizeof(union Ip_sockaddr_union));
    if(nifa->ifa_netmask == IP_NULL)
        goto fail;

    ipcom_memcpy(nifa->ifa_netmask, addrs[IPNET_RTAX_NETMASK], IPCOM_SA_LEN_GET(addrs[IPNET_RTAX_IFA]));


    if (IP_BIT_ISSET(ifa->ifam_addrs, IPNET_RTA_BRD))
    {
        nifa->ifa_broadaddr = ipcom_malloc(sizeof(union Ip_sockaddr_union));
        if(nifa->ifa_broadaddr == IP_NULL)
            goto fail;

        ipcom_memcpy(nifa->ifa_broadaddr, addrs[IPNET_RTAX_BRD], IPCOM_SA_LEN_GET(addrs[IPNET_RTAX_BRD]));
    }

    return nifa;

fail:
    ipcom_ifaddrs_free(nifa);
    return IP_NULL;
}
Exemple #4
0
/*
 *===========================================================================
 *                    ipnet_wlan_if_init
 *===========================================================================
 * Description: WLAN uses the Ethernet interface with a few modifications
 * Parameters:
 * Returns:
 *
 */
IP_PUBLIC int
ipnet_wlan_if_init(Ipnet_netif *netif)
{
    int i;

    ipnet_eth_if_init(netif);

    netif->wlan = ipcom_malloc(sizeof(Ipnet_netif_wlan));
    if (netif->wlan == IP_NULL)
        return -IP_ERRNO_ENOMEM;
    ipcom_memset(netif->wlan, 0, sizeof(Ipnet_netif_wlan));

    i = 0;
    do
    {
        ipcom_sprintf(netif->ipcom.name, "wlan%d", i++);
    } while (ipnet_if_nametonetif(netif->vr_index, netif->ipcom.name) != IP_NULL);


    /* Setup link functions for WLAN use. */
    netif->wlan->eth_link_ioctl = (int (*)(Ipnet_netif *, Ip_u32, void *))netif->link_ioctl;
    netif->link_ioctl = (Ipnet_link_ioctl)ipnet_wlan_ioctl;

    return 0;
}
/*****************************************************************************
 * 
 * example_concatenate_tokens - Concatenate all options on this line
 *
 * .IP <tok>
 * The tokenizer buffer
 *
 * RETURNS:
 * A dynamically allocated memory buffer containing all the tokenized options
 * on success, IP_NULL otherwise.
 *
 * NOMANUAL
 */
IP_STATIC char *
example_concatenate_tokens(example_token_buffer_t *tok)
{
    char *value;
    char *conc = ipcom_malloc(256);

    if (conc != IP_NULL)
    {
        int no_values = 0;

        conc[0] = '\0';
        while ((value = example_get_token(tok, IP_FALSE)) != IP_NULL)
        {
            if (ipcom_strcasecmp(value, ";") == 0)
                break;

            no_values++;
            ipcom_strncat(conc, value, 256);
            ipcom_strncat(conc, " ", 256);
        }

        /* No semicolon or no values */
        if (no_values == 0 || value == IP_NULL)
        {
            ipcom_free(conc);
            return IP_NULL;
        }

        return conc;
    }
    return IP_NULL;
}
/*
 *===========================================================================
 *                    ipnet_nat_proxy_dns_add_transaction
 *===========================================================================
 * Description: Add a DNS transaction to the list of active transactions.
 * Parameters:  type    - DNS query type
 *              dns_hdr - pointer to the DNS protocol header.
 *              param   - pointer to NAT proxy parameters.
 * Returns:     pointer to the transaction or IP_NULL if failed to add.
 */
IP_STATIC Ipnet_nat_dns_transaction *
ipnet_nat_proxy_dns_add_transaction(int type,
                                    Ipnet_nat_dns_hdr *dns_hdr,
                                    Ipnet_nat_proxy_param *param,
                                    Ip_u8 *ptrname)
{
    Ipnet_nat_dns_transaction *trans;

    /* Check that there is room for another transaction */
    if(ipnet_nat_proxy_dns_list.size >= IPNET_NAT_DNS_TRANS_MAX_ENTRIES)
        return IP_NULL;
    trans = ipcom_malloc(sizeof(*trans));
    if (trans == IP_NULL)
        return IP_NULL;

    ipcom_memset(trans, 0, sizeof(*trans));
    trans->id      = (Ip_u16)IP_GET_NTOHS(&dns_hdr->id);
    trans->srcport = param->tuple.private_port;
    trans->dstaddr = param->tuple.public_addr;
    trans->type    = type;
    if (ptrname != IP_NULL)
        ipcom_strncpy((char *)trans->ptrname, (char *)ptrname, sizeof(trans->ptrname)-1);
    ipcom_list_insert_last(&ipnet_nat_proxy_dns_list, &trans->list);
    /* Add the timeout */
    if (ipnet_nat_proxy_timeout_schedule(IPNET_NAT_DNS_TRANS_TIMEOUT,
                                         ipnet_nat_proxy_dns_transaction_timeout,
                                         trans,
                                         &trans->tmo) < 0)
    {
        ipcom_list_remove(&trans->list);
        ipcom_free(trans);
        return IP_NULL;
    }
    return trans;
}
/*
 *===========================================================================
 *                    ipl2tp_cache_malloc
 *===========================================================================
 * Description: Allocate buffer from local cache
 * Parameters:  
 * Returns:     
 *
 */
IP_STATIC void *
ipl2tp_cache_malloc(Ip_u32 size)
{
    Ipl2tp_cache_head *head;
    Ip_u32 msr;

    msr = ipcom_interrupt_disable();

    if (free_list != IP_NULL)
    {
        head = free_list;
        free_list = head->next;
        ipcom_interrupt_enable(msr);
    }
    else
    {
        ipcom_interrupt_enable(msr);

        if ((head = ipcom_malloc(sizeof(*head) + size)) == IP_NULL)
        {
            return IP_NULL;
        }
    }

    return head + 1;
}
/*
 *===========================================================================
 *                    ipdnsc_hostent_insert_name
 *===========================================================================
 * Description: Inserts a host name in a hostent structure
 * Parameters:  he - pointer to the hostent structure
 *              name - the name to insert
 * Returns:     0 for OK, -1 for fail.
 */
IP_GLOBAL Ip_s32
ipdnsc_hostent_insert_name(struct Ip_hostent *he, char *name)
{
    if (he == IP_NULL)
        return -1;

    if (ipcom_strlen(name) > (IPDNSC_MAXNAME-1))
        return -1;

    /* Free the memory for the current name if any */
    if (he != IP_NULL && he->h_name != IP_NULL)
    {
        ipcom_free(he->h_name);
    }
    /* Allocate storage for the host name */
    he->h_name = ipcom_malloc(ipcom_strlen(name)+1);
    if (he->h_name == IP_NULL)
    {
        return -1;
    }
    /* Copy the host name */
    ipcom_strcpy(he->h_name, name);

    return 0;

}
/****************************************************************************
 *
 * example_restore_lease_db - restore DHCP Server lease database
 * 
 * This is an example on how the contents of the IPDHCPS lease database can
 * be restored by initializing it with data stored in a file system.
 *
 * RETURNS:
 * 0 if success, -1 if failed.
 *
 * NOMANUAL
 */
IP_STATIC int example_restore_lease_db(void)
{
	int retval   = -1;
	IP_FILE *fd  = IP_NULL;
	struct Ip_stat statbuf;
	void *buf = IP_NULL;

	if(ipcom_stat("/home/jonas/dumpfile", &statbuf) == -1)
		goto leave;

	if((fd = ipcom_fopen("/home/jonas/dumpfile", "r")) == 0)
		goto leave;

	if((buf = ipcom_malloc(statbuf.st_size)) == IP_NULL)
		goto leave;

	if(ipcom_fread(buf, statbuf.st_size, 1, fd) <= 0)
		goto leave;

	ipdhcps_lease_db_restore(buf);

	retval = 0;

leave:

	if(fd)
		ipcom_fclose(fd);

	if(buf != IP_NULL)
		ipcom_free(buf);

	return retval;
}
/****************************************************************************
 *
 * example_do_command - Execute a DHCPS command
 *
 * This routine execute a DHCPS command containing the parameters we're
 * interested in adding to the configuration.
 * 
 * .IP <format> 
 * The format string
 *
 * .IP <...>
 * The arguments for the format string
 * 
 * RETURNS:
 * N/A
 *
 * NOMANUAL
 */
IP_STATIC void
example_do_command(const char *format, ...)
{
    va_list     vargs;
    char        *cmd;
    int         argc;
    char        **argv = IP_NULL;

    if ((cmd = ipcom_malloc(256)) != IP_NULL)
    {
        va_start(vargs, format);
        ipcom_vsnprintf(cmd, 256, format, vargs);        
        va_end(vargs);       

        
        IPCOM_LOG1(INFO,"DHCP Executing '%s'", cmd);
        if(ipcom_parse_argstr(cmd, (int*)&argc, &argv) != IPCOM_SUCCESS)
        {
            IPCOM_LOG1(ERR,"failed to parse command '%s'", cmd);
            goto out;
        }

        if(ipdhcps_cmd_dhcps(argc, argv) != IPCOM_SUCCESS)
        {
            IPCOM_LOG1(ERR,"failed to execute command '%s'", cmd);
            goto out;
        }

out:
        if (argv != IP_NULL)
            ipcom_free(argv);
        if (cmd)
            ipcom_free(cmd);
    }
}
/*
 *===========================================================================
 *                    ipnet_nat_proxy_sip_callidstr
 *===========================================================================
 * Description: Extract the callid string
 * Parameters:  pdata - pointer to message.
 * Returns:     pointer to allocated buffer with callid string or
 *              IP_NULL if wrong format or out of memory.
 */
IP_STATIC char *
ipnet_nat_proxy_sip_callidstr(char *pmsg)
{
    char *pstart;
    char *pcallid;
    int   i;

    SIP_SKIP_SPACES(pmsg);

    pstart = pmsg;
    for (i = 0; i < 200; i++)
    {
        if (*pmsg != '\r')
            pmsg++;
        else
            break;
    }

    /* in case we have a wrong string format */
    if (i >= 200)
    {
        IPCOM_LOG0(ERR, "ipnet_nat_proxy_sip_callidstr() :: ERROR, wrong string format");
        return IP_NULL;
    }

    if ((pcallid = ipcom_malloc((pmsg - pstart) + 1)) == IP_NULL)
        return IP_NULL;

    ipcom_memcpy(pcallid, pstart, pmsg - pstart);
    *(pcallid + (pmsg - pstart)) = 0;

    IPCOM_LOG1(DEBUG, "ipnet_nat_proxy_sip_callidstr() :: callid=%s", pcallid);
    return pcallid;
}
/*
 *===========================================================================
 *                    ipcom_drv_ppp_if_init
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 *
 */
IP_PUBLIC int
ipcom_drv_ppp_if_init(const char *ifname, const char *devname, int unit)
{
    Ipcom_netif         *netif;
    Ipcom_pdrv_ppp      *pdrv;
    Ipcom_drv_ppp_link  *plink;

    /* Allocate memory for the network interface structure */
    netif  = ipcom_if_malloc(IP_IFT_PPP);
    if (netif == IP_NULL)
        return IPCOM_ERR_FAILED;

    /* Set up the driver downcall function pointers */
    netif->drv_ioctl  = ipcom_drv_ppp_ioctl;
    netif->drv_output = ipcom_drv_ppp_output;

    /* Set interface name */
    ipcom_strncpy(netif->name, ifname, sizeof(netif->name) - 1);

    /* Allocate and init memory for the driver structure */
    pdrv = ipcom_malloc(sizeof(*pdrv));
    if (pdrv == IP_NULL)
        goto fail;
    ipcom_memset(pdrv, 0, sizeof(*pdrv));
    netif->pdrv = pdrv;
    plink = &pdrv->plink[unit];
    if (devname == IP_NULL)
    {
        char value[64];
        Ip_size_t value_size = sizeof(value);
        devname = ipcom_sysvar_get_conf("devname", value, &value_size,
                                        IP_NULL, ifname);
    }
    if (devname != IP_NULL)
        plink->devname = ipcom_strdup(devname);
    plink->sv[0] = plink->sv[1] = -1;

    /* Initialize PPP link */
    plink->index    = unit;
    plink->netif    = netif;
    plink->out_q_nr = 0;
    plink->fd       = -1;
    plink->baudrate = ipcom_sysvar_get_conf_as_int("ipppp.baudrate", IP_NULL, netif->name);
    if (plink->baudrate <= 0)
        plink->baudrate = IPCOM_DRV_PPP_BAUDRATE;

    /* Attach the interface. */
    if (ipcom_if_attach(netif) < 0)
        goto fail;

    /* Success. */
    return IPCOM_SUCCESS;

 fail:
    if (pdrv != IP_NULL)
        ipcom_free(pdrv);
    ipcom_if_free(netif);
    return IPCOM_ERR_FAILED;
}
Exemple #13
0
/*
 *===========================================================================
 *                    ipcom_buffer_init
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 *
 */
IP_PUBLIC void
ipcom_buffer_init(Ipcom_buffer *buffer)
{
    buffer->alloc = IPCOM_BUFFER_SIZE;
    buffer->buf = ipcom_malloc(IPCOM_BUFFER_SIZE);
    buffer->offset = 0;
    buffer->end = 0;
}
/*
 *===========================================================================
 *                      ipnet_vrrp_add_addr
 *===========================================================================
 * Description: Adds a virtual router address.
 * Parameters:  netif - The network interface the VRIP will be assigned to.
 *              vrid - The VRID the address will be assigned to.
 * Returns:     0 = success, <0 = error code.
 *
 */
IP_GLOBAL int
ipnet_vrrp_add_addr(Ipnet_netif *netif, Ip_u8 vrid, struct Ip_in_addr addr)
{
    Ipnet_vrrp_addr_t *addr_entry;

    if (ipnet->vrrp_addrs == IP_NULL)
    {
        ipnet->vrrp_addrs = ipcom_hash_new((Ipcom_hash_obj_func) ipnet_vrrp_obj_hash,
                                           (Ipcom_hash_key_func) ipnet_vrrp_obj_hash,
                                           (Ipcom_hash_cmp_func) ipnet_vrrp_hash_cmp);
        if (ipnet->vrrp_addrs == IP_NULL)
            return -IP_ERRNO_ENOMEM;
    }

    addr_entry = ipnet_vrrp_get_addr_entry(netif, vrid);
    if (addr_entry == IP_NULL)
    {
        addr_entry = ipcom_malloc(sizeof(Ipnet_vrrp_addr_t));
        if (addr_entry == IP_NULL)
            return -IP_ERRNO_ENOMEM;
        IPNET_IF_LOCK(netif);
        addr_entry->netif     = netif;
        addr_entry->vrid      = vrid;
        addr_entry->num_addrs = 1;
        addr_entry->addrs[0]  = addr;
    }
    else
    {
        Ipnet_vrrp_addr_t *a;
        int                i;

        i = ipnet_vrrp_addr_index(addr_entry, addr);
        if (i >= 0)
            return -IP_ERRNO_EEXIST;

        (void)ipcom_hash_remove(ipnet->vrrp_addrs, addr_entry);
        a = ipcom_realloc(addr_entry,
                          sizeof(Ipnet_vrrp_addr_t) + addr_entry->num_addrs * sizeof(Ipnet_vrrp_addr_t));
        if (a == IP_NULL)
            return -IP_ERRNO_ENOMEM;
        a->addrs[a->num_addrs++] = addr;
        addr_entry = a;
    }

    if (ipcom_hash_add(ipnet->vrrp_addrs, addr_entry) != IPCOM_SUCCESS)
    {
        ipcom_free(addr_entry);
        return -IP_ERRNO_ENOMEM;
    }

    IPCOM_LOG2(INFO, "VRRP: added address %s on %s",
               ipcom_inet_ntop(IP_AF_INET, &addr, ipnet->log_buf, sizeof(ipnet->log_buf)),
               netif->ipcom.name);

    return 0;
}
IP_PUBLIC char *
ipcom_strdup(const char *s1)
{
    char *s2;

    s2 = ipcom_malloc(ipcom_strlen(s1) + 1);
    if(s2 == IP_NULL)
        return IP_NULL;

    ipcom_strcpy(s2, s1);
    return s2;
}
ZBUF_ID zbufSockRecvfrom
    (
    int              s,         /* socket to receive from */
    int              flags,     /* flags to underlying protocols */
    int *            pLen,      /* number of bytes requested/returned */
    struct sockaddr *from,      /* where to copy sender's addr */
    int *            pFromLen   /* value/result length of <from> */
    )
{
    ZBUF_ID     zbufId;         /* zbuf returned to user */
    ZBUF_SEG    zbufSeg = NULL; /* received zbuf chain */
    int         status;         /* recvfrom() return status */
    char*       buf = NULL;
    int         so_type;
    socklen_t   optlen = sizeof(int);

    if (-1 == getsockopt(s, (int)SOL_SOCKET, (int)SO_TYPE, (char*)&so_type, (int*)&optlen))
        return (ZBUF_ID)NULL;

    ZBUF_ID_CREATE(zbufId);     /* create ID for recv data */
    if (zbufId == (ZBUF_ID)NULL)
        return (ZBUF_ID)NULL;

    if (so_type == SOCK_DGRAM)
    {
        if((status = recvfrom(s, (char*)&zbufSeg, *pLen, flags | IP_MSG_ZBUF, from, pFromLen)) < 0)
            goto cleanup;
    }
    else
    {
        ip_assert(so_type == SOCK_STREAM);
        buf = ipcom_malloc(*pLen);
        if (buf == NULL)
            goto cleanup;
        if ((status = recvfrom(s, buf, *pLen, flags | IP_MSG_ZBUF, from, pFromLen)) < 0)
            goto cleanup;
        if ((zbufSeg = zbufInsertBuf(zbufId, NULL, 0, buf, status, simple_free, 0)) == NULL)
            goto cleanup;
    }

    ZBUF_SETSEG(zbufId, zbufSeg);
    *pLen = status;
    return zbufId;

cleanup:
    if (zbufId)
        ZBUF_ID_DELETE_EMPTY(zbufId);
    if (buf)
        ipcom_free(buf);
    return (ZBUF_ID)NULL;
}
Exemple #17
0
/*
 *===========================================================================
 *                    ipcom_shell_add_cmd
 *===========================================================================
 * Description:     Add a command to the list of available ipcom_shell commands
 * Parameters:      name : command's name
 *                  usage : usage string
 *                  description : description of command
 *                  hook : function to that executes the command
 *                  priority : na
 *                  stack_size : the stack to be used by the process that
 *                               executes the hook.
 *
 * Returns:         IPCOM_SUCCESS : ok
 *                  IPCOM_ERR_DUPLICATE : command already exists
 *                  IPCOM_ERR_NO_MEMORY : out of memory
 *
 *
 */
IP_PUBLIC Ip_err
ipcom_shell_add_cmd(const char *name, const char *usage,
                    const char *description, Ipcom_shell_cmd_type hook,
                    Ip_s32 priority, Ip_s32 stack_size)
{
    Ipcom_shell_cmd *cmd;
    static Ipcom_once_t  once = IPCOM_ONCE_INIT;
    Ip_err  err;

    err = ipcom_once(&once, ipcom_shellcmd_init, IP_NULL);
    if (err != IPCOM_SUCCESS)
        return err;

    /* First check if present */
    cmd = ipcom_shell_find_cmd(name);
    if (cmd != IP_NULL)
        return IPCOM_ERR_DUPLICATE;      /*!!allow duplicates for overlay. */

    /* Add a new entry to the list */
    cmd = (Ipcom_shell_cmd *)ipcom_malloc(sizeof(Ipcom_shell_cmd));
    if (cmd == IP_NULL)
        return IPCOM_ERR_NO_MEMORY;

    ipcom_memset(cmd, 0, sizeof(Ipcom_shell_cmd));

    ipcom_strncpy(cmd->name, name, sizeof(cmd->name)-1);
    ipcom_strncpy(cmd->usage, usage, sizeof(cmd->usage)-1);
    ipcom_strncpy(cmd->description, description, sizeof(cmd->description)-1);

    cmd->hook = hook;
    if (priority == 0 || priority == IPCOM_SHELL_PRIO_SAME)
       cmd->priority = ipcom_proc_getprio(ipcom_getpid());
    else
       cmd->priority = priority;
    cmd->stack_size = stack_size;

    ipcom_list_insert_last(&ipcom_shell_cmd_head, &cmd->cmd_list);

#if defined(WRS_IPNET) && defined(IP_PORT_VXWORKS) && (IP_PORT_VXWORKS >= 65)
    (void)ipcom_vxshell_add_cmd(name,
                                usage,
                                description,
                                hook,
                                priority,
                                stack_size);
#endif

    return IPCOM_SUCCESS;
}
Exemple #18
0
/*
 *===========================================================================
 *                       ipppp_work_alloc
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 *
 */
IP_STATIC struct Ipppp_action_work *
ipppp_work_alloc(Ipcom_netif *netif, int action, void *data)
{
    struct Ipppp_action_work *work;

    work = ipcom_malloc(sizeof(*work));
    if (work)
    {
        ipcom_strcpy(work->ifname, netif->name);
        work->ifindex    = netif->ifindex;
        work->link_index = netif->link_index;
        work->action     = action;
        work->data       = data;
    }

    return work;
}
/*
 *===========================================================================
 *                    ipcom_spinlock_create
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 *
 */
IP_PUBLIC Ip_err
ipcom_spinlock_create(Ipcom_spinlock *sl_handle)
{
#ifdef IPCOM_USE_SMP
    Ipcom_vxworks_spinlock_t *sl;

    *sl_handle = sl = ipcom_malloc(sizeof(*sl));
    if (sl != IP_NULL)
    {
        vxAtomicSet(&sl->count, 1);
        sl->sem = semBCreate(SEM_Q_PRIORITY | SEM_Q_FIFO, SEM_EMPTY);
    }

    return *sl_handle ? IPCOM_SUCCESS : IPCOM_ERR_FAILED;
#else
    *sl_handle = IPCOM_SPINLOCK_TAG;
    return IPCOM_SUCCESS;
#endif
}
/*
 *===========================================================================
 *                    ipdnsc_hostent_insert_alias
 *===========================================================================
 * Description: Inserts an alias name in a hostent structure
 * Parameters:  he - pointer to the hostent structure
 *              name - the name to insert
 * Returns:     0 for OK, -1 for fail.
 */
IP_GLOBAL Ip_s32
ipdnsc_hostent_insert_alias(struct Ip_hostent *he, char *name)
{
    Ip_s32 num_alias, i=0;
    char **tmp;

    if (ipcom_strlen(name) > (IPDNSC_MAXNAME-1))
        return -1;

    /* Find out the current number of aliases */
    num_alias = ipdnsc_hostent_alias_count(he);

    /* Allocate memory for the another alias list entry */
    tmp = ipcom_realloc(he->h_aliases, (num_alias+1) * sizeof(char *));
    if(tmp == IP_NULL)
        return -1;
    he->h_aliases = tmp;

    /* Allocate memory for the alias */
    he->h_aliases[num_alias-1] = ipcom_malloc(ipcom_strlen(name)+1);
    if (he->h_aliases[num_alias-1] == IP_NULL)
    {
        /* We have to free to whole list here */
        while (he->h_aliases[i] != IP_NULL)
        {
		    ipcom_free(he->h_aliases[i]);
            i++;
        }
        /* Free the alias list */
	    ipcom_free(he->h_aliases);
        he->h_aliases = IP_NULL;
        return -1;
    }

    /* Set the alias */
    ipcom_strcpy(he->h_aliases[num_alias-1], name);

    /* Null terminate the list */
    he->h_aliases[num_alias] = IP_NULL;

    return 0;

}
/*
 *===========================================================================
 *                    ipcom_minlock_create
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 *
 */
IP_PUBLIC Ip_err
ipcom_minlock_create(Ipcom_spinlock *sl_handle)
{
#ifdef IPCOM_USE_SMP
    spinlockIsrNd_t *sl;

    sl = ipcom_malloc(sizeof(*sl));
    if (sl != IP_NULL)
    {
        *sl_handle = sl;
        spinlockIsrNdInit (sl);
    }

    return sl ? IPCOM_SUCCESS : IPCOM_ERR_FAILED;
#else
    *sl_handle = (Ipcom_spinlock) 0xabadaba2; /* arbitrary */
    return IPCOM_SUCCESS;
#endif
}
/*
 *===========================================================================
 *                    ipdnsc_hostent_insert_addr
 *===========================================================================
 * Description: Inserts an address in a hostent structure
 * Parameters:  he - pointer to the hostent structure
 *              addr - the addr to insert
 * Returns:     0 for OK, -1 for fail.
 */
IP_GLOBAL Ip_s32
ipdnsc_hostent_insert_addr(struct Ip_hostent *he, char *addr)
{
    Ip_s32 num_addr, i=0;
    char **tmp;

    /* Find out the current number of addresses */
    num_addr = ipdnsc_hostent_addr_count(he);

    /* Allocate memory for the another address list entry */
    tmp = ipcom_realloc(he->h_addr_list, (num_addr+1) * sizeof(char *));
    if(tmp == IP_NULL)
        return -1;
    he->h_addr_list = tmp;

    /* Allocate memory for the address */
    he->h_addr_list[num_addr-1] = ipcom_malloc(he->h_length);
    if (he->h_addr_list[num_addr-1] == IP_NULL)
    {
        /* We have to free to whole list here */
        while (he->h_addr_list[i] != IP_NULL)
        {
		    ipcom_free(he->h_addr_list[i]);
            i++;
        }
        /* Free the address list */
	    ipcom_free(he->h_addr_list);
        he->h_addr_list = IP_NULL;
        return -1;
    }

    /* Set the address */
    ipcom_memcpy(he->h_addr_list[num_addr-1], addr, he->h_length);

    /* Null terminate the list */
    he->h_addr_list[num_addr] = IP_NULL;

    return 0;

}
/*
 *===========================================================================
 *                    ipcom_env_create
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 */
IP_STATIC Ipcom_env_entry *
ipcom_env_create(const char *name, const char *value)
{
    Ip_size_t        name_length;
    Ip_size_t        value_length;
    Ipcom_env_entry *env;

    /* Create environment variable */
    name_length = ipcom_strlen(name) + 1;
    value_length = ipcom_strlen(value) + 1;
    env = ipcom_malloc(sizeof(Ipcom_env_entry) + name_length + value_length);
    if(env == IP_NULL)
        return IP_NULL;

    /* Init environment variable */
    env->name  = (const char *)env + sizeof(Ipcom_env_entry);
    ipcom_memcpy((void *)env->name, name, name_length);
    env->value = env->name + name_length;
    ipcom_memcpy((void *)env->value, value, value_length);

    return env;
}
/*
 *===========================================================================
 *                    ipnet_cmd_sysctl_get
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 *
 */
IP_STATIC Ip_bool
ipnet_cmd_sysctl_get(int            *name,
                     int            namelen,
                     void           **oldp,
                     Ip_size_t      *oldlenp)
{
    *oldlenp = 0;
    if (ipcom_sysctl(name, namelen, IP_NULL, oldlenp, IP_NULL, 0) < 0)
        return IP_FALSE;

    *oldp = ipcom_malloc(*oldlenp);
    if (*oldp == IP_NULL)
        return IP_FALSE;

    if (ipcom_sysctl(name, namelen, *oldp, oldlenp, IP_NULL, 0) < 0)
    {
        ipcom_free(*oldp);
        return IP_FALSE;
    }

    return IP_TRUE;
}
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();
}
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();
}
/*
 *===========================================================================
 *                         ipcom_cmd_ttcp
 *===========================================================================
 */
int
ipcom_cmd_ttcp(int argc, char **argv)
{
    /* Uninitialized variables. */
    union Ip_sockaddr_union     addrme;
    char                        *host = IP_NULL;	/* ptr to name of host */
    int                         c;
    Ip_u32                      msec0, msec1, msecd, bpermsec, kbpersec;
    Ip_fd                       sockfd = -1;
    char                        *buf;		/* ptr to dynamic buffer */
    char                        *orgbuf = 0;     /* the buffer to free. */
    struct Ipcom_cmd_ttcp_data  context;

    /* misc initialized variables. */
#ifdef IPCOM_USE_TCP
    union Ip_sockaddr_union frominet;
    Ip_socklen_t           fromlen;
    int                   one = 1; /* for 4.3 BSD style setsockopt() */
    Ip_fd                  oldfd;	  /* fd of network socket */
#endif
    Ip_u32    nbytes = 0;		  /* bytes on net */
    int    trans = 1;	          /* 0=receive, !0=transmit mode. Default transmit! */

    /* Configuration variables. */
#if defined(IP_SO_X_VR)
    int    vr = 0;
#endif
    int    buflen = 8 * 1024;	/* length of buffer */
    int    nbuf   = 2 * 1024;	/* number of buffers to send in sinkmode */
    int    bufoffset = 0;	/* align buffer to this */
    int    bufalign = 16;	/* modulo this */
    int    options = 0;		/* socket options */
    unsigned short  port = DEFAULT_PORT;	/* TCP port number */
    unsigned short  meport = 0;       	/* local port, default 0. */
    int    sinkmode = 1;		/* 0=normal I/O, !0=sink/source mode */
    int    verbose = 0;		/* 0=print basic info, 1=print cpu rate, proc resource usage. */
    int    sockbufsize = -1;	/* Default socket buffer size to use. */
#ifdef IP_TCP_NODELAY
    int    nodelay = 0;		/* set TCP_NODELAY socket option. */
#endif
    int    enable = 1;
#ifdef TCP_OSERFC2385
    char   *md5opt = IP_NULL;
#endif
#ifdef IP_SO_REUSEPORT
    int     reuse_port = 0;
#endif
#ifdef IPCOM_TTCP_REENTRANT
    union Ip_sockaddr_union  addrhim;
#endif
    int     sock_error;
    int     mev = 0;                /* Use event logging */
    int     nend = 5;               /* Number of UDP end packets */
#ifdef IPCOM_CMD_TTCP_USE_ZEROCOPY_API
    int     zerocopy = 0;
#endif
    int     cpu = -1;
#ifdef IPSCTP
    Ip_bool sctp_type_conflict = IP_FALSE;
#endif

    /* Initialize some static data, default configuration. */
#ifdef IPCOM_USE_TCP
    int     proto = IP_IPPROTO_TCP;
    int     sock_type = IP_SOCK_STREAM;
    const char *proto_as_str = "TCP";
    context.udp         = 0;    /* Default is TCP. */
#else
    int     proto = IP_IPPROTO_UDP;
    int     sock_type = IP_SOCK_DGRAM;
    const char *proto_as_str = "UDP";
    context.udp         = 1;    /* Only UDP. */
#endif
    context.b_flag      = 0;
    context.touchdata   = 0;
    context.numCalls    = 0;
    context.err_no       = 0;
#ifdef IPCOM_USE_INET
    context.family      = IP_AF_INET;  /* default IPv4 */
#else
    context.family      = IP_AF_INET6;  /* default IPv6 */
#endif
    context.addrsize    = sizeof(struct Ip_sockaddr_in);

    (void)ipcom_proc_self();	/* when called from vxworks shell, this prevents a crash */

    (void)options;

    /* Init some more. */
    ipcom_memset(&addrhim, 0, sizeof (addrhim));
    IPCOM_SA_LEN_SET(&addrhim.sin, sizeof(struct Ip_sockaddr_in));
    addrhim.sin.sin_family = IP_AF_INET;

    ipcom_memset(&addrme, 0, sizeof(addrme));
    IPCOM_SA_LEN_SET(&addrme.sin, sizeof(struct Ip_sockaddr_in));
    addrme.sin.sin_family = IP_AF_INET;

#ifdef IP_PORT_INTEGRITY
    ipcom_init_libsocket();
#endif

    if (argc < 2)
        goto usage;
    ipcom_getopt_clear();
    while ((c = ipcom_getopt(argc, argv, "M:xdrstUuvBDTb:f:l:n:p:A:O:V:RP:me:a:cS")) != -1)
    {
        switch (c)
        {
#ifdef TCP_OSERFC2385
        case 'M':			/* MD5 signature option */
            md5opt = ip_optarg;
            break;
#endif
#ifdef IPCOM_USE_INET6
        case 'x':
            context.family = IP_AF_INET6;
            break;
#endif
        case 'm':
            mev = 1;
            break;
        case 'e':
            nend = ipcom_atoi(ip_optarg);
            break;
        case 'B':
            context.b_flag = 1;
            break;
        case 't':
            trans = 1;
            break;
        case 'r':
            trans = 0;
            break;
#ifdef IP_SO_DEBUG
        case 'd':
            options |= IP_SO_DEBUG;
            break;
#endif
        case 'D':
#ifdef IP_TCP_NODELAY
            nodelay = 1;
#else
            ipcom_fprintf(ip_stderr, "ttcp: -D option ignored: IP_TCP_NODELAY socket option not supported"IP_LF);
#endif
            break;
        case 'n':
            nbuf = ipcom_atoi(ip_optarg);
            break;
        case 'l':
            buflen = ipcom_atoi(ip_optarg);
            break;
        case 's':
#ifdef IPCOM_TTCP_USE_STDIOMODE
            sinkmode = !sinkmode;
#endif
            break;
        case 'p':
            port = (unsigned short)ipcom_atoi(ip_optarg);
            break;
        case 'P':
            meport = (unsigned short)ipcom_atoi(ip_optarg);
            break;
#ifdef IPCOM_CMD_TTCP_USE_ZEROCOPY_API
        case 'U':
            zerocopy = 1;
            /* fall through */
#endif
        case 'u':
            proto = IP_IPPROTO_UDP;
            sock_type = IP_SOCK_DGRAM;
            proto_as_str = "UDP";
            context.udp = 1;
            break;
        case 'v':
            verbose = 1;
            break;
        case 'A':
            bufalign = ipcom_atoi(ip_optarg);
            break;
        case 'O':
            bufoffset = ipcom_atoi(ip_optarg);
            break;
        case 'b':
#if defined(IP_SO_SNDBUF) || defined(IP_SO_RCVBUF)
            sockbufsize = ipcom_atoi(ip_optarg);
#else
            ipcom_fprintf(ip_stderr, "ttcp: -b option ignored: IP_SO_SNDBUF/IP_SO_RCVBUF socket options not supported"IP_LF);
#endif
            break;
#ifdef IP_SO_REUSEPORT
        case 'R':
            reuse_port = 1;
            break;
#endif
        case 'T':
            context.touchdata = 1;
            break;
#if defined(IP_SO_X_VR)
        case 'V':
            vr = ipcom_atoi(ip_optarg);
            break;
#endif
        case 'a':
            cpu = ipcom_atoi(ip_optarg);
            break;
#ifdef IPSCTP
        case 'c':
            proto = IP_IPPROTO_SCTP;
            sock_type = IP_SOCK_STREAM;
            proto_as_str = "SCTP";
            if (IP_TRUE == sctp_type_conflict)
            {
                ipcom_fprintf(ip_stderr, "ttcp: c/S conflict in command."IP_LF);
                goto errorout;
            }
            sctp_type_conflict = IP_TRUE;
            break;

        case 'S':
            proto = IP_IPPROTO_SCTP;
            sock_type = IP_SOCK_SEQPACKET;
            proto_as_str = "SCTP";
            if (IP_TRUE == sctp_type_conflict)
            {
                ipcom_fprintf(ip_stderr, "ttcp: c/S conflict in command."IP_LF);
                goto errorout;
            }
            sctp_type_conflict = IP_TRUE;
            break;
#endif
        default:
            goto usage;
        }
    }

#ifndef IP_PORT_LAS
    if (cpu >= 0)
    {
        Ip_cpu_set_t cpuset;

        if (cpu < 0 || cpu >= IP_CPU_SETSIZE)
        {
            ipcom_fprintf(ip_stderr, "ttcp: CPU must be between #0 and #%d"IP_LF, IP_CPU_SETSIZE-1);
            return -1;
        }
        IP_CPU_ZERO(&cpuset);
        IP_CPU_SET(cpu, &cpuset);
        if (ipcom_proc_cpu_affinity_set(0, &cpuset) != IPCOM_SUCCESS)
        {
            ipcom_fprintf(ip_stderr, "ttcp: Failed to set affinity to CPU #%d"IP_LF, cpu);
            return -1;
        }
    }
#endif /* IP_PORT_LAS */

    if(trans)
    {
        host = argv[ip_optind];

        if (host == 0)
            goto usage;
        sock_error = ipcom_getsockaddrbyaddrname(context.family, IP_FALSE, host, (struct Ip_sockaddr *)&addrhim);
        if(sock_error != 0)
        {
            ipcom_fprintf(ip_stderr, "ttcp error: ipcom_getsockaddrbyaddrname failed, errno = %d."IP_LF, sock_error);
            ttcperror(&context, "unknown host");
        }

        addrme.sin.sin_port  = ip_htons(meport);
        addrhim.sin.sin_port = ip_htons(port);   /* same port offset for IPv4 and IPv6 */
    }
    else
    {
        /* rcvr */
        addrme.sin.sin_port = ip_htons(port);
    }

#ifdef IPCOM_USE_INET6
    if(context.family == IP_AF_INET6)
    {
        context.addrsize = sizeof(struct Ip_sockaddr_in6);

        IPCOM_SA_LEN_SET(&addrme.sin6, sizeof(struct Ip_sockaddr_in6));
        addrme.sin6.sin6_family  = IP_AF_INET6;

        IPCOM_SA_LEN_SET(&addrhim.sin6, sizeof(struct Ip_sockaddr_in6));
        addrhim.sin6.sin6_family = IP_AF_INET6;
    }
#endif

    /* Send more than the sentinel size - UDPMINLEN. */
    if(context.udp && buflen <= UDPMINLEN)
        buflen = UDPMINLEN + 1;

    /* Align buffer. */
    if ((buf = (char *) ipcom_malloc(buflen + bufalign)) == (char *) IP_NULL)
        ttcperror(&context, "malloc");
    else
        orgbuf = buf;
    if (bufalign != 0)
        buf += (bufalign - ((Ip_ptrdiff_t) buf % bufalign) + bufoffset) % bufalign;

    /* Get a socket. */
    if ((sockfd = ipcom_socket(context.family, sock_type, proto)) == ERR)
        ttcperror(&context,"socket");

    if (trans)
    {
        if(sockbufsize < 0)
        {
            if(context.udp)
                sockbufsize = DEFAULT_UDP_SNDBUF;
            else
                sockbufsize = DEFAULT_TCP_SNDBUF;
        }
        ipcom_fprintf(ip_stdout, "ttcp-t: fd=%d, buflen=%d, nbuf=%d, align=%d/%d, port=%d",
                      sockfd, buflen, nbuf, bufalign, bufoffset, (int)port);
        if (sockbufsize)
            ipcom_fprintf(ip_stdout, ", sockbufsize=%d", sockbufsize);
        ipcom_fprintf(ip_stdout, "  %s  -> %s"IP_LF, proto_as_str, host);
    }
    else
    {
        if(sockbufsize < 0)
        {
            if(context.udp)
                sockbufsize = DEFAULT_UDP_RCVBUF;
            else
                sockbufsize = DEFAULT_TCP_RCVBUF;
        }
        ipcom_fprintf(ip_stdout, "ttcp-r: fd=%d, buflen=%d, nbuf=%d, align=%d/%d, port=%d",
                      sockfd, buflen, nbuf, bufalign, bufoffset, (int)port);
        if (sockbufsize)
            ipcom_fprintf(ip_stdout, ", sockbufsize=%d", sockbufsize);
        ipcom_fprintf(ip_stdout, "  %s"IP_LF, proto_as_str);
    }

    /* Code to open socket is moved to before the printf to get 'sockfd' right. */
    mes(trans, "socket");

    /* Set REUSE addr */
    if(ipcom_setsockopt(sockfd, IP_SOL_SOCKET, IP_SO_REUSEADDR, (char *)&enable, sizeof (int)) == ERR)
        ttcperror(&context, "setsockopt(IP_SO_REUSEADDR)");
    else
        mes(trans, "setsockopt(IP_SO_REUSEADDR)");

#ifdef IP_SO_REUSEPORT
    /* Set REUSE port */
    if(reuse_port)
    {
        if(ipcom_setsockopt(sockfd, IP_SOL_SOCKET, IP_SO_REUSEPORT, (char *)&reuse_port, sizeof (int)) == ERR)
            ttcperror(&context, "setsockopt(IP_SO_REUSEPORT)");
        else
            mes(trans, "setsockopt(IP_SO_REUSEPORT)");
    }
#endif

#ifdef IPCOM_USE_TCP
#ifdef TCP_OSERFC2385
    if (!udp && md5opt)
    {
        if (ipcom_setsockopt(sockfd, IPPROTO_TCP, TCP_OSERFC2385,
                             md5opt, strlen(md5opt)) == ERR)
        {
            ttcperror(&context, "setsockopt(IP_SO_REUSEADDR)");
        }
        else
        {
            mes(trans, "setsockopt(IP_SO_REUSEADDR)");
        }
    }
#endif
#endif

	/* Set routing table index in socket. */
#if defined(IP_SO_X_VR)
	if(vr != 0)
    {
	    if (ipcom_setsockopt(sockfd, IP_SOL_SOCKET, IP_SO_X_VR, (char *)&vr, 4) == ERR)
            ttcperror(&context, "setsockopt: vr");
	    else
            mes(trans, "setsockopt(vr)");
    }
#endif

    /* Bind the socket. */
    if(ipcom_bind(sockfd, (struct Ip_sockaddr *)&addrme, context.addrsize) == ERR)
        ttcperror(&context, "bind");
    else
#ifdef IPCOM_USE_INET6
        ipcom_fprintf(ip_stderr, "ttcp%s: bind %s %d"IP_LF, trans ? "-t" : "-r",
                      context.family == IP_AF_INET ? "IPv4" : "IPv6",
                      (int)ip_ntohs(addrme.sin.sin_port));
#else
    {
        char   tmpbuf[32];
        ipcom_sprintf(tmpbuf, "bind %d", ip_ntohs(addrme.sin.sin_port));
        mes(trans, tmpbuf);
    }
#endif

    /* Adjust socker buffer size. */
#if defined(IP_SO_SNDBUF) || defined(IP_SO_RCVBUF)
    if(sockbufsize)
    {
        if (trans)
        {
            if (ipcom_setsockopt(sockfd, IP_SOL_SOCKET, IP_SO_SNDBUF, (char *)&sockbufsize, sizeof sockbufsize) == ERR)
                ttcperror(&context,"setsockopt: sndbuf");
            else
                mes(trans, "setsockopt(sndbuf)");
        }
        else
        {
            if (ipcom_setsockopt(sockfd, IP_SOL_SOCKET, IP_SO_RCVBUF, (char *)&sockbufsize, sizeof sockbufsize) == ERR)
                ttcperror(&context,"setsockopt: rcvbuf");
            else
                mes(trans, "setsockopt(rcvbuf)");
        }
    }
#endif

    /* If TCP we need to connect else accept to remote side. */
#ifdef IPCOM_USE_TCP
    if (context.udp)
    {
        mes(trans, "opened");
    }
    else
    {
        /* We are the client if transmitting */
        if(trans)
        {
            if(options)
            {
                if(ipcom_setsockopt(sockfd, IP_SOL_SOCKET, options, (char *)&one, sizeof (one)) == ERR)
                    ttcperror(&context,"setsockopt");
            }
#ifdef IP_TCP_NODELAY
            if(nodelay)
            {
                if(ipcom_setsockopt(sockfd, IP_IPPROTO_TCP, IP_TCP_NODELAY, (char *)&one, sizeof (one)) == ERR)
                    ttcperror(&context,"setsockopt: nodelay");
                mes(trans, "nodelay");
            }
#endif

            if(ipcom_connect(sockfd, (struct Ip_sockaddr *)&addrhim, context.addrsize) == ERR)
                ttcperror(&context,"connect");
            else
                mes(trans, "connect");
        }

        /* Otherwise, we are the TCP server and should listen for the connections.  */
        else
        {
            if(ipcom_listen(sockfd, 0) == ERR)
                ttcperror(&context,"listen");
            else
                mes(trans, "listen");

            if(options)
            {
                if(ipcom_setsockopt(sockfd, IP_SOL_SOCKET, options, (char *)&one, sizeof (one)) == ERR)
                    ttcperror(&context,"setsockopt");
            }

            fromlen = context.addrsize;
            oldfd = sockfd;
#ifdef IPSCTP
            if ((IP_SOCK_SEQPACKET == sock_type)
                && (IP_IPPROTO_SCTP == proto))
            {
                #define TTCP_SCTP_RCV_BUF_LEN 128
                struct Ipsctp_event_subscribe events;
                union Ip_sockaddr_union  local_addr;
                struct Ipsctp_sndrcvinfo sinfo;
                Ip_u32                   len   = 0;
                char                     pbuf[TTCP_SCTP_RCV_BUF_LEN];
                int                      flags = 0;
                int                      ret   = 0;

                /* set data I/O event flag */
                ipcom_memset(&events, 0, sizeof(events));
                events.Ipsctp_data_io_event = 1;
                ret = ipcom_setsockopt(sockfd,
                                       IP_IPPROTO_SCTP,
                                       IPSCTP_EVENTS,
                                       (void *)&events,
                                       sizeof(events));
                if (ERR == ret)
                    ttcperror(&context, "setsockopt events");

                /* get the association identifier */
                ipcom_memset(pbuf, 0, TTCP_SCTP_RCV_BUF_LEN);
                len = sizeof(local_addr);
                /* Wait for connections */
                ret = ipsctp_recvmsg(sockfd,
                                     pbuf,
                                     TTCP_SCTP_RCV_BUF_LEN,
                                     &local_addr.sa,
                                     &len,
                                     &sinfo,
                                     &flags);
                sockfd = ipsctp_peeloff(sockfd, sinfo.sinfo_assoc_id);
                if (IP_SOCKERR == sockfd)
                    ttcperror(&context,"peeloff");
            }
            else
#endif
            {
                if((sockfd = ipcom_accept(sockfd, (struct Ip_sockaddr *)&frominet, &fromlen)) == ERR)
                    ttcperror(&context,"accept");
            }

            {
                union Ip_sockaddr_union peer;
                Ip_socklen_t            peerlen = context.addrsize;

                /* Close the mother socket. */
                if(ipcom_socketclose(oldfd) == ERR)
                    ttcperror(&context,"close of oldfd.");

#if defined(IP_SO_RCVBUF)
                /* Had to add this code in addition to the above because some stacks don't inherit
                 * the receive buffer size from the server socket. /Lennart Bang Enea Ose Systems 980116.
                 */
                if(sockbufsize)
                {
                    if(ipcom_setsockopt(sockfd, IP_SOL_SOCKET, IP_SO_RCVBUF, (char *)&sockbufsize, sizeof sockbufsize) == ERR)
                        ttcperror(&context,"setsockopt: rcvbuf");
                    else
                        mes(trans, "setsockopt(rcvbuf)");
                }
#endif

                if(ipcom_getpeername(sockfd, (struct Ip_sockaddr *) &peer, &peerlen) == ERR)
                    ttcperror(&context, "getpeername");

#ifdef IPCOM_USE_INET
                if(context.family == IP_AF_INET)
                {
                    char addr[16];
                    ipcom_fprintf(ip_stderr, "ttcp-r: accept from %s"IP_LF,
                                  ipcom_inet_ntop(IP_AF_INET, &peer.sin.sin_addr, addr, sizeof(addr)));
                }
#endif
#ifdef IPCOM_USE_INET6
                if(context.family == IP_AF_INET6)
                {
                    char addr[40];
                    ipcom_fprintf(ip_stderr, "ttcp-r: accept from %s"IP_LF,
                                  ipcom_inet_ntop(IP_AF_INET6, &peer.sin6.sin6_addr, addr, sizeof(addr)));
                }
#endif
            }
        }
    }
#endif

    /* Begin the TTCP performance test. */
    msec0 = get_millisec();

    if (mev)
    {
#if defined (IP_PORT_INTEGRITY)
#include "ipcom_integrity.h"
        extern void EventLogOn(void);
#if IP_VER < 500
        extern void EventLogMask(unsigned int newmask);
        EventLogMask(~0);
#endif
        EventLogOn();
#endif
    }

    if(sinkmode)
    {
        register int cnt;

        /* Transmit side. */
        if(trans)
        {
            pattern(buf, buflen);
            if(context.udp)
            {
                (void) NWRITE(sockfd, buf, UDPMINLEN, &context);	/* rcvr start */
                ipcom_millisleep(500);                  /* arp time */
                /* Renew the start time to not include the 500 msec sleep */
                msec0 = get_millisec();
            }
#ifdef IPCOM_CMD_TTCP_USE_ZEROCOPY_API
            if (zerocopy)
            {
                while (nbuf-- && ZERONWRITE(sockfd, buflen, &context) == buflen)
                    nbytes += buflen;
            }
            else
#endif
            {
                while (nbuf-- && NWRITE(sockfd, buf, buflen, &context) == buflen)
                    nbytes += buflen;
            }
            if(context.udp)
                (void) NWRITE(sockfd, buf, UDPMINLEN, &context);	/* rcvr end */
        }

        /* Receive side. */
        else
        {
            if(context.udp)
            {
                int going = 0;

#ifdef IPCOM_CMD_TTCP_USE_ZEROCOPY_API
                if (zerocopy)
                {
                    while ((cnt = ZeroNread(sockfd, &context)) > 0)
                    {
                        if(cnt <= UDPMINLEN)
                        {
                            if(going)
                                break;	/* "EOF" */
                            going = 1;
                            msec0 = get_millisec();
                        }
                        else
                        {
                            nbytes += cnt;
                        }
                    }
                }
                else
#endif
                {
                    while ((cnt = Nread(sockfd, buf, buflen, &context)) > 0)
                    {
                        if(cnt <= UDPMINLEN)
                        {
                            if(going)
                                break;	/* "EOF" */
                            going = 1;
                            msec0 = get_millisec();
                        }
                        else
                        {
                            nbytes += cnt;
                        }
                    }
                }
            }
#ifdef IPCOM_USE_TCP
            else
            {
                while ((cnt = Nread(sockfd, buf, buflen, &context)) > 0)
                {
                    nbytes += cnt;
                }
            }
#endif
        }
    }

#ifdef IPCOM_TTCP_USE_STDIOMODE
    /* non sinkmode. */
    else
    {
        register int cnt;

        if(trans)
        {
            /* Read from standard input and send to other side. */
            while ((cnt = ipcom_fread(buf, buflen, 1, ip_stdin)) > 0 &&
                   NWRITE(sockfd, buf, cnt) == cnt)
                nbytes += cnt;
        }
        else
        {
            /* Read from network and print on stdout. */
            while ((cnt = Nread(sockfd, buf, buflen, &context)) > 0)
            {
                ipcom_fwrite(buf, cnt, 1, ip_stdout);
                nbytes += cnt;
            }
        }
    }
#endif

    if (mev)
    {
#if defined (IP_PORT_INTEGRITY)
        extern void EventLogOff(void);
        EventLogOff();
#elif defined (IP_PORT_RTCORE)
        extern void ip_trace(char *what, char *file, int line, int id, void *data);
        extern void ip_tracedump(void);
        ip_trace("[ASSERT]", __FILE__, __LINE__, ipcom_getpid(), IP_NULL);
        ip_tracedump();
#endif
    }

    /* Read the final time and calculate some statistics. */
    msec1 = get_millisec();
    msecd = msec1 - msec0;
    if (msecd == 0)
        msecd = 1;
    bpermsec = nbytes / msecd;   /* Bytes per millisecond. */
    kbpersec = nbytes / 128;
    kbpersec = kbpersec * 125 / msecd; /* kilobyte per sec. */

    /* End of test assemble statistice. */
    if(context.err_no)
    {
        ipcom_fprintf(ip_stdout, "ttcp%s: socket errno: %d."IP_LF, trans ? "-t" : "-r", context.err_no);
    }

    if(context.udp && trans)
    {
        int j;

        for (j = 0; j < nend; j++)
        {
            ipcom_millisleep(100); /* Let the reading side catch up. */
            (void) NWRITE(sockfd, buf, UDPMINLEN, &context);	/* rcvr end */
        }
    }

    /* Print the statistics. */
    ipcom_fprintf(ip_stdout, "ttcp%s: %lu bytes in %lu milliseconds = %lu KB/sec, %lu B/msec +++"IP_LF,
                  trans ? "-t" : "-r", nbytes, msecd, kbpersec, bpermsec);

    ipcom_fprintf(ip_stdout, "ttcp%s: %lu I/O calls, msec/call = %lu, calls/sec = %lu"IP_LF,
                  trans ? "-t" : "-r",
                  context.numCalls,
                  msecd / context.numCalls,
                  1000 * context.numCalls / msecd);

    if (verbose)
        ipcom_fprintf(ip_stdout, "ttcp%s: buffer address %p"IP_LF, trans ? "-t" : "-r", buf);


    /* Test succeeded, goto errorout to cleanup. */
    goto errorout;

    /* Usage. */
 usage:
    ipcom_fprintf(ip_stderr,
                  "Usage: ttcp -t [-options] host [ < in ]"IP_LF
                  "ttcp -r [-options > out]"IP_LF
                  "Common options:"IP_LF
                  "-x      use IPv6 instead of IPv4"IP_LF
                  "-l ##	length of bufs read from or written to network (default 8192)"IP_LF
#ifdef IPCOM_CMD_TTCP_USE_ZEROCOPY_API
                  "-U	use UDP and interpeak zero copy API instead of TCP"IP_LF
#endif
                  "-u	use UDP (default is TCP)"IP_LF
#ifdef IPSCTP
                  "-c	use SCTP STREAM type(default is TCP)"IP_LF
                  "-S	use SCTP SEQPACKET type(default is TCP)"IP_LF
#endif
                  "-p ##	port number to send to or listen at (default DEFAULT_PORT)"IP_LF);
    ipcom_fprintf(ip_stderr,
                  "-s	-t: source a pattern to network"IP_LF
                  "-r	sink (discard) all data from network"IP_LF
                  "-e ##	number of packets to end UDP transmission"IP_LF
                  "-m	use event logging (not supported on all platforms)"IP_LF
                  "-A	align the start of buffers to this modulus (default 16384)"IP_LF
                  "-O	start buffers at this offset from the modulus (default 0)"IP_LF
                  "-v	verbose: print more statistics"IP_LF
                  "-d	set SO_DEBUG socket option (if supported)"IP_LF);
    ipcom_fprintf(ip_stderr,
                  "-b ##	set socket buffer size (if supported)"IP_LF
                  "Options specific to -t:"IP_LF
                  "-n##	number of source bufs written to network (default 2048)"IP_LF
                  "-D	don't buffer TCP writes (sets TCP_NODELAY socket option)"IP_LF
                  "Options specific to -r:"IP_LF
                  "-B	for -s, only output full blocks as specified by -l (for TAR)"IP_LF
                  "-T	\"touch\": access each byte as it's read"IP_LF
#if defined(IP_SO_X_VR)
                  "-V      virtual router index (if supported)"IP_LF);
#endif
    /* fall through to cleanup...*/

    /* Free buffer and close socket if any error. */
 errorout:
#ifndef IP_PORT_LAS
    if (cpu >= 0)
        ipcom_proc_cpu_affinity_clr(0);
#endif /* IP_PORT_LAS */
    if(orgbuf)
        ipcom_free(orgbuf);
    if(sockfd != -1)
    {
        if(ipcom_socketclose(sockfd) == ERR)
            ipcom_fprintf(ip_stderr, "ttcp error: close of sockfd. (line %d, errno %d)."IP_LF, __LINE__, ipcom_errno);
    }

#ifdef IP_PORT_INTEGRITY
    ipcom_shutdown_libsocket();
#endif

    return 0;
}
Exemple #28
0
/*
 *===========================================================================
 *                    ipcom_sysvar_set_internal
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 */
IP_GLOBAL Ip_err
ipcom_sysvar_set_tree(const char *name, const char *value, int flags, Ipcom_sysvar_tree *tree)
{
    Ip_size_t           name_length;
    Ip_size_t           value_length;
    Ipcom_sysvar_entry  *sysvar;
    Ip_err              retval = IPCOM_SUCCESS;

    /* Check for duplicate. */
    sysvar = ipcom_hash_get(tree->sysvars, name);
    if (sysvar)
    {
        if (IP_BIT_ISSET(sysvar->flags, IPCOM_SYSVAR_FLAG_READONLY))
        {
            retval = IPCOM_ERR_READONLY;
            goto leave;
        }
        else if (IP_BIT_ISFALSE(flags, IPCOM_SYSVAR_FLAG_OVERWRITE))
        {
            retval = IPCOM_ERR_DUPLICATE;
            goto leave;
        }
        else
        {
            flags |= sysvar->flags & IPCOM_SYSVAR_FLAG_KERNEL;
            ipcom_hash_remove(tree->sysvars, sysvar);
            ipcom_free(sysvar);
            goto set;
        }
    }

    /* No current entry found and not allowed to create a new entry. */
    if(IP_BIT_ISSET(flags, IPCOM_SYSVAR_FLAG_NOCREATE))
    {
        retval = IPCOM_ERR_FAILED;
        goto leave;
    }

    /* Add the new sysvar. */
 set:
     name_length = ipcom_strlen(name) + 1;
     value_length = ipcom_strlen(value) + 1;
     sysvar = ipcom_malloc(sizeof(Ipcom_sysvar_entry) + name_length + value_length);

     if(sysvar == IP_NULL)
     {
         retval = IPCOM_ERR_NO_MEMORY;
         goto leave;
     }

     sysvar->refcount = 1;
     sysvar->flags    = flags;
     if (IP_BIT_ISFALSE(flags, IPCOM_SYSVAR_FLAG_INIT))
     {
         tree->modified = IP_TRUE;
         sysvar->flags |= IPCOM_SYSVAR_FLAG_MODIFIED;
     }
     sysvar->name     = (const char *)sysvar + sizeof(Ipcom_sysvar_entry);
     ipcom_memcpy((void *)sysvar->name, name, name_length);
     sysvar->value    = sysvar->name + name_length;
     ipcom_memcpy((void *)sysvar->value, value, value_length);

     retval = ipcom_hash_add(tree->sysvars, sysvar);

 leave:
    return retval; /*lint !e429 Custodial pointer 'sysvar' has not been freed or returned */
}
/*
 *===========================================================================
 *                    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;
}
/*
 *===========================================================================
 *                    ipnet_nat_proxy_sip_payload_parse
 *===========================================================================
 * Description: Parse SIP payload.
 * Parameters:  appdata   - pointer to application data.
 *              applen    - pointer to length of application data.
 *              growspace - space available to extend application data.
 *              param     - pointer to proxy parameters.
 *              newdata   - pointer to pointer to new application data.
 * Returns:     IP_TRUE  = Packet modified.
 *              IP_FALSE = Packet untouched.
 */
IP_STATIC Ip_bool
ipnet_nat_proxy_sip_payload_parse(Ip_u8 *appdata,
                                  int   *applen,
                                  int    growspace,
                                  Ipnet_nat_proxy_param *param,
                                  Ip_u8 **newdata)

{
    char    *psipmsg = (char *)appdata;
    char    *pcallid = IP_NULL;
    char    *pendstr, *pstartstr, *psearch;
    Ip_bool  retcode = IP_FALSE;
    int      pos, sdpdatalen, searchlen, msgtype = 0;
    char     tmpholder[50];
    char     laddrstr[20];
    char     gaddrstr[20];
    char    *pend = (char *)sipbuf + *applen - 1;
    char    *sdplen_start, *sdplen_end, *sdp_end;
    int      newlen, diff;

    if (param->incoming == IP_TRUE)
    {
        /* Incoming message*/
        goto parseFalseExit;
    }

    if (param->inbound == IP_FALSE)
    {
        /* Outbound session */
        if ((psipmsg = ipnet_nat_proxy_sip_outboundmsgtypecheck(psipmsg, &msgtype, *applen)) == IP_NULL)
            return IP_FALSE;   /* not the message we're looking for */
    }
    else
    {
        /* Inbound session */
        if ((psipmsg = ipnet_nat_proxy_sip_inboundmsgtypecheck(psipmsg, &msgtype, *applen)) == IP_NULL)
            return IP_FALSE;   /* not the message we're looking for */
    }

    /* find the call-id field */
    if (ipnet_nat_proxy_sip_keyfind(psipmsg, SIP_CALLID_STR, &pos, *applen - (psipmsg - (char *)appdata)) == IP_FALSE)
    {
        IPCOM_LOG0(ERR, "ipnet_nat_proxy_sip_payload_parse() :: no callid field");
        return IP_FALSE;
    }

    /* get callid string */
    pcallid = ipnet_nat_proxy_sip_callidstr(psipmsg + pos + SIP_TAG_TO_DATAPOS(SIP_CALLID_STR));
    if (pcallid == IP_NULL)
    {
        IPCOM_LOG0(ERR, "ipnet_nat_proxy_sip_payload_parse() :: failed to parse callid string");
        return IP_FALSE;
    }

    if (msgtype == SIP_MSG_TYPE_INVITE)
    {
        if (param->inbound == IP_FALSE)
        {
            /* Update the mapping timeout */
            IPCOM_LOG1(DEBUG, "ipnet_nat_proxy_sip_payload_parse() :: setting mapping timeout to %d seconds",
                       IPNET_NAT_SIP_ENTRY_INVITE_TIMEOUT);
            ipnet_nat_proxy_set_mapping_timeout(IPNET_NAT_SIP_ENTRY_INVITE_TIMEOUT, param->mapping);
        }
        else
        {
            /* ALG will not detect the ACK for inbound calls so use the INVITE response to set established timeout */
            IPCOM_LOG1(DEBUG, "ipnet_nat_proxy_sip_payload_parse() :: setting mapping timeout to %d seconds",
                       IPNET_NAT_SIP_ENTRY_ESTABLISHED_TIMEOUT);
            ipnet_nat_proxy_set_mapping_timeout(IPNET_NAT_SIP_ENTRY_ESTABLISHED_TIMEOUT, param->mapping);
        }
    }
    else if (msgtype == SIP_MSG_TYPE_ACK)
    {
        /* Update the mapping timeout */
        IPCOM_LOG1(DEBUG, "ipnet_nat_proxy_sip_payload_parse() :: setting mapping timeout to %d seconds",
                   IPNET_NAT_SIP_ENTRY_ESTABLISHED_TIMEOUT);
        ipnet_nat_proxy_set_mapping_timeout(IPNET_NAT_SIP_ENTRY_ESTABLISHED_TIMEOUT, param->mapping);
    }

    /* Copy the message to scratch buffer and set pointer */
    if (*applen > (int)sizeof(sipbuf))
    {
        IPCOM_LOG0(ERR, "ipnet_nat_proxy_sip_payload_parse() :: message to long");
        goto parseFalseExit;
    }
    ipcom_memcpy(sipbuf, appdata, *applen);
    psipmsg = (char *)sipbuf + (psipmsg - (char *)appdata);

    /* first the via field
     * For response message, the Via field will not contain the private address.
     * The localAddrProcess() will check if the address is private.
     */

    laddrstr[0] = gaddrstr[0] = 0;
    if (ipnet_nat_proxy_sip_keyfind(psipmsg, SIP_VIA_STR, &pos, (pend - psipmsg) + 1) == IP_TRUE)
	{
        /* advance to IP/Port string */

        psipmsg += (pos + ipcom_strlen(SIP_VIA_STR) + SIP_VIA_FIELD_IPADDR_DIS);

        IPCOM_LOG0(DEBUG, "ipnet_nat_proxy_sip_payload_parse() :: parse via field");

        psipmsg = ipnet_nat_proxy_sip_localaddrprocess(psipmsg, laddrstr, gaddrstr, pcallid,
                                                       SIP_ADDRESS_PORT_STRING, param, &pend);

        if (psipmsg == IP_NULL)
            goto parseFalseExit;

    }

    /* find the contact field */

    if (ipnet_nat_proxy_sip_keyfind (psipmsg, SIP_CONTACT_STR, &pos, (pend - psipmsg) + 1) == IP_TRUE)
    {
        /* advance to IP/Port string */

        psipmsg += (pos + ipcom_strlen(SIP_CONTACT_STR) + SIP_CTAC_FIELD_IPADDR_DIS);

        IPCOM_LOG0(DEBUG, "ipnet_nat_proxy_sip_payload_parse() :: parse contact field");

        psipmsg = ipnet_nat_proxy_sip_localaddrprocess(psipmsg, laddrstr, gaddrstr, pcallid,
                                                       SIP_ADDRESS_PORT_STRING, param, &pend);

        if (psipmsg == IP_NULL)
            goto parseFalseExit;
    }

    /* exit if there isn't any private info in SIP message header */

    if (laddrstr[0] == 0 || gaddrstr[0] == 0)
        goto parseFalseExit;

    /* When program reaches here, it indicates at least one place in the
     * packet should be modified. Use parseFalseExit only if it is an error
     */

    /* find the Content-Type field */

    if (ipnet_nat_proxy_sip_keyfind (psipmsg, SIP_CONTYPE_STR, &pos, (pend - psipmsg) + 1) == IP_FALSE)
        goto parseTrueExit;

    /* advance to start of data field */

    psipmsg += (pos + SIP_TAG_TO_DATAPOS(SIP_CONTYPE_STR));

    SIP_SKIP_SPACES(psipmsg);

    /*check the application/sdp type, if not, exit */

    if (!SIP_IS_STRING_SAME(psipmsg, SIP_APPSDP_STR))
        goto parseTrueExit;

    /* find the content length field */

    if (ipnet_nat_proxy_sip_keyfind (psipmsg, SIP_CONTLEN_STR, &pos, (pend - psipmsg) + 1) == IP_FALSE)
        goto parseTrueExit;

    IPCOM_LOG0(DEBUG, "ipnet_nat_proxy_sip_payload_parse() :: parse Content-Length field");

    /* reach to the content length field, advance to length data */

    psipmsg += (pos + SIP_TAG_TO_DATAPOS(SIP_CONTLEN_STR));

    SIP_SKIP_SPACES(psipmsg);

    sdpdatalen = ipcom_strtol(psipmsg, &pendstr, 10);

    IPCOM_LOG1(DEBUG, "ipnet_nat_proxy_sip_payload_parse() :: data length = %d", sdpdatalen);

    if (sdpdatalen == 0)
        goto parseTrueExit;

    /* store start and end of sdp datalength string as well as end of message */
    sdplen_start = psipmsg;
    sdplen_end   = pendstr;
    sdp_end      = pend;

    /* advance to the start of SDP data */

    if (ipnet_nat_proxy_sip_keyfind (psipmsg, IP_NULL, &pos, (pend - psipmsg) + 1) == IP_FALSE)
    {
        IPCOM_LOG0(DEBUG, "ipnet_nat_proxy_sip_payload_parse() :: Can't find header end mark");
        goto parseTrueExit;
    }

    /* start of the SIP data field */

    psipmsg += pos;
    searchlen = sdpdatalen;

    /* search the local IP address, and replace it with global address */

    pstartstr = psipmsg;
    while (IP_TRUE)
    {
        psearch = ipnet_nat_proxy_sip_faststrsearch(laddrstr, ipcom_strlen(laddrstr),
                                                    pstartstr, searchlen, IP_FALSE);
        if (psearch != IP_NULL)
        {
            IPCOM_LOG1(DEBUG, "ipnet_nat_proxy_sip_payload_parse() :: Local IP address in SDP: %s", laddrstr);

            if (ipnet_nat_proxy_sip_modmsg(gaddrstr, ipcom_strlen(gaddrstr),
                                           psearch, ipcom_strlen(laddrstr), &pend) < 0)
            {
                goto parseFalseExit;
            }

            searchlen = searchlen - (psearch + ipcom_strlen(gaddrstr) - pstartstr);
            pstartstr = psearch + ipcom_strlen(gaddrstr);
        }
        else
            break;
    }

    IPCOM_LOG1(DEBUG, "ipnet_nat_proxy_sip_payload_parse() :: the last search length %d", searchlen);

    /* search for the audio port */

    if (ipnet_nat_proxy_sip_keyfind (psipmsg, SIP_AUDIO_STR, &pos, sdpdatalen) == IP_TRUE)
    {
        /* advance to the port field */

        psipmsg += (pos + SIP_TAG_TO_DATAPOS(SIP_AUDIO_STR));

        SIP_SKIP_SPACES(psipmsg);
        ipnet_nat_proxy_sip_localaddrprocess(psipmsg, laddrstr, gaddrstr, pcallid, SIP_PORT_STRING, param, &pend);
    }

    /* search for the audio control port */

    if (ipnet_nat_proxy_sip_keyfind (psipmsg, SIP_RTCP_STR, &pos, sdpdatalen) == IP_TRUE)
	{
        /* advance to the port field */

        psipmsg += (pos + SIP_TAG_TO_DATAPOS(SIP_RTCP_STR));

        SIP_SKIP_SPACES(psipmsg);
        ipnet_nat_proxy_sip_localaddrprocess(psipmsg, laddrstr, gaddrstr, pcallid, SIP_PORT_STRING, param, &pend);
    }

    /* adjust the length node */

    sdpdatalen += pend - sdp_end;
    ipcom_sprintf(tmpholder, "%d", sdpdatalen);
    if (ipnet_nat_proxy_sip_modmsg(tmpholder, ipcom_strlen(tmpholder),
                                   sdplen_start, sdplen_end - sdplen_start, &pend) < 0)
    {
        goto parseFalseExit;
    }

parseTrueExit:
    /* Update application data with the modified buffer */
    newlen = pend - (char *)sipbuf + 1;
    diff = newlen - *applen;
    if (diff > growspace)
    {
        /* Must allocate a new buffer */
        *newdata = ipcom_malloc(*applen + diff);
        if (*newdata == IP_NULL)
        {
            IPCOM_LOG1(ERR, "ipnet_nat_proxy_sip_payload_parse() :: ipcom_malloc(%d) failed",
                            *applen + diff);
            goto parseFalseExit;
        }
        ipcom_memcpy(*newdata, sipbuf, newlen);
    }
    else
    {
        /* Let the current buffer grow */
        ipcom_memcpy(appdata, sipbuf, newlen);
    }
    *applen = newlen;
    IPCOM_LOG1(DEBUG, "ipnet_nat_proxy_sip_msg() :: the delta length = %d ", diff);
    retcode = IP_TRUE;

parseFalseExit:
    if (msgtype == SIP_MSG_TYPE_BYE)
        ipnet_nat_proxy_sip_endmsgprocess(pcallid, param);
    if (pcallid)
        ipcom_free(pcallid);
    return retcode;
}