/*
 *===========================================================================
 *                    ipcom_hash_new
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 *
 */
IP_PUBLIC Ipcom_hash *
ipcom_hash_new(Ipcom_hash_obj_func obj_hash_func,
               Ipcom_hash_key_func key_hash_func,
               Ipcom_hash_cmp_func obj_key_cmp)
{
    Ipcom_hash *head;

    ip_assert(obj_hash_func != IP_NULL);
    ip_assert(key_hash_func != IP_NULL);
    ip_assert(obj_key_cmp != IP_NULL);

    head = IPCOM_MALLOC_STATIC(sizeof(*head));
    if (head == IP_NULL)
        return IP_NULL;
    head->table = IPCOM_CALLOC_STATIC(IPCOM_HASH_INITIAL_SIZE, sizeof(*head->table));
    if (head->table == IP_NULL)
    {
        IPCOM_FREE_STATIC(head);
        return IP_NULL;
    }

    head->obj_hash_func = obj_hash_func;
    head->key_hash_func = key_hash_func;
    head->obj_key_cmp = obj_key_cmp;
    head->size = IPCOM_HASH_INITIAL_SIZE;
    head->elem = 0;
    return head;
}
/*
 *===========================================================================
 *                    ipcom_proc_copyenv
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 *
 */
IP_GLOBAL void
ipcom_proc_copyenv(Ipcom_proc *proc_c)
{
    Ipcom_proc         *proc_p;
    Ip_err              retval;

    proc_p = ipcom_proc_self();
    ip_assert(proc_p != IP_NULL);
    ip_assert(proc_c != IP_NULL);

    if (proc_p->env_tree == IP_NULL)
        /* Parent process has no environment variables */
        return;

    /* Create child environment semaphore and tree */
    retval = ipcom_once(&proc_c->env_once, ipcom_env_init, proc_c);
    if (retval != IPCOM_SUCCESS)
    {
        IP_PANIC();
        return;
    }

    ipcom_mutex_lock(proc_p->env_mutex);

    ipcom_hash_for_each(proc_p->env_tree,
                        (Ipcom_hash_foreach_cb_func) ipcom_env_clone,
                        proc_c->env_tree);

    ipcom_mutex_unlock(proc_p->env_mutex);
}
/*
 *===========================================================================
 *                    ipnet_netlink_register_ops
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 *
 */
IP_GLOBAL void
ipnet_rtnetlink_register_family_event(int                             family,
                                      int                             cmd,
                                      Ip_size_t                       maxattr,
                                      Ip_size_t                       min_size,
                                      Ipnet_rtnetlink_do_t            doit,
                                      Ipnet_netlink_dump_t           dumpit)
{
    Ipnet_rtnetlink_table_t   *table;

    /**/
    if (ipnet->rtnetlink_links[family] == IP_NULL)
    {
        ipnet->rtnetlink_links[family] = ipcom_calloc(IP_RTM_NR_MSGTYPES, sizeof(Ipnet_rtnetlink_table_t *));
        ip_assert(ipnet->rtnetlink_links[family] != IP_NULL);
    }

    ip_assert(ipnet->rtnetlink_links[family][cmd - IP_RTM_BASE] == IP_NULL);

    ipnet->rtnetlink_links[family][cmd - IP_RTM_BASE] = ipcom_calloc(1, sizeof(Ipnet_rtnetlink_table_t));

    ip_assert(ipnet->rtnetlink_links[family][cmd - IP_RTM_BASE] != IP_NULL);

    table = ipnet->rtnetlink_links[family][cmd - IP_RTM_BASE];

    table->nl_cmd                       = cmd;
    table->nl_func_table.nl_rta_max     = maxattr;
    table->nl_func_table.nl_size_min    = IP_NLMSG_LENGTH(min_size);
    table->nl_func_table.nl_do          = doit;
    table->nl_func_table.nl_dump        = dumpit;
}
/*
 *===========================================================================
 *                    ipcom_hash_add
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 *
 */
IP_PUBLIC Ip_err
ipcom_hash_add(Ipcom_hash *head, void *obj)
{
    unsigned hash_index;
    Ip_err   err;

    ip_assert(head->size > 0);
    if ((head->elem + 1) * 100 / head->size > IPCOM_HASH_HIGH_WATER_MARK)
    {
        err = ipcom_hash_resize(head, IP_TRUE);
        if (err != IPCOM_SUCCESS)
            return err;
    }

    if (head->size / 2 <= head->elem)
        /* The size of the hash table is locked and it has reached
           the capacity limit */
        return IPCOM_ERR_REACHED_MAX;

    hash_index = head->obj_hash_func(obj) % head->size;
    /* Find an empty slot at the hash index or after it if another
       object hash:ed to the same value */
    while (head->table[hash_index % head->size] != IP_NULL)
    {
        if (head->table[hash_index % head->size] == obj)
            return IPCOM_ERR_DUPLICATE;
        hash_index++;
    }
    head->table[hash_index % head->size] = obj;
    head->elem++;
    return IPCOM_SUCCESS;
}
/*
 *===========================================================================
 *                    ipcom_clearenv
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 *
 */
IP_PUBLIC int
ipcom_clearenv(void)
{
#if IPCOM_USE_ENV == IPCOM_ENV_IPCOM
    Ip_err      retval;
    Ipcom_proc *proc;

    proc = ipcom_proc_self();
    ip_assert(proc != IP_NULL);

    retval = ipcom_once(&proc->env_once, ipcom_env_init, proc);
    if (retval != IPCOM_SUCCESS)
    {
        IP_PANIC();
        return -1;
    }

    ipcom_proc_clearenv(proc);
    return 0;

#elif IPCOM_USE_ENV == IPCOM_ENV_NATIVE && (defined(IP_PORT_OSE) || defined(IP_PORT_OSE5))
    /*!! Are all environment variables cleaned up by OS automatically? */
    return 0;

#elif defined(IPCOM_USE_SYSVAR) && IPCOM_VR_MAX == 1
    /*! Hmmmm */
    return -1;

#else
    return -1;

#endif /* #if IPCOM_USE_ENV == IPCOM_ENV_IPCOM */
}
/*
 *===========================================================================
 *                    ipcom_hash_for_each
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 *
 */
IP_PUBLIC void
ipcom_hash_for_each(Ipcom_hash *head, Ipcom_hash_foreach_cb_func cb_func, void *data)
{
    unsigned  i;
    unsigned  x;
    void    **elems;

    if (head->elem == 0)
        return;

    elems = IPCOM_MALLOC_DYNAMIC(head->elem * sizeof(void*)); /*lint !e647 */
    if (elems == IP_NULL)
    {
        IP_PANIC();
        return;
    }

    for (i = 0, x = 0; i < head->size; i++)
        if (head->table[i] != IP_NULL)
            elems[x++] = head->table[i];

    ip_assert(x == head->elem);
    for (i = 0; i < x; i++)
        cb_func(elems[i], data);

    IPCOM_FREE_DYNAMIC(elems);
}
/*
 *===========================================================================
 *                    ipcom_env_init
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 */
IP_STATIC Ip_err
ipcom_env_init(void *procptr)
{
    Ipcom_proc   *proc = procptr;

    ip_assert(proc != IP_NULL);

    (void)ipcom_mutex_create(&proc->env_mutex);

    proc->env_tree = ipcom_hash_new((Ipcom_hash_obj_func)ipcom_env_hash_obj,
                                    (Ipcom_hash_key_func)ipcom_env_hash_key,
                                    (Ipcom_hash_cmp_func)ipcom_env_hash_cmp);
    ip_assert(proc->env_tree != IP_NULL);

    return IPCOM_SUCCESS;
}
/*
 *===========================================================================
 *                     ipnet_cmd_qc_next_arg
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 *
 */
IP_STATIC void
ipnet_cmd_qc_next_arg(Ipnet_cmd_qc *p)
{
    ip_assert(p->argc > 0);
    p->argv++;
    p->argc--;
}
예제 #9
0
/*
 *===========================================================================
 *                    ipnet_nat_proxy_sip_modmsg
 *===========================================================================
 * Description: Modify message and adjust length
 * Parameters:  newdata    - pointer to new data
 *              newlen     - length of new data
 *              olddata    - pointer to old data
 *              oldlen     - length of old data
 *              ppend      - pointer to pointer to last byte of message
 * Returns:     0  = ok
 *              -1 = message too long
 */
IP_STATIC int
ipnet_nat_proxy_sip_modmsg(char *newdata, int newlen,
                           char *olddata, int oldlen,
                           char **ppend)
{
    char *pmax  = (char *)sipbuf + sizeof(sipbuf) - 1;
    int diff    = newlen - oldlen;
    int movelen = (*ppend  + 1) - (olddata + oldlen);

    ip_assert(movelen >= 0);
    if (pmax - *ppend < diff)
    {
        IPCOM_LOG0(ERR, "ipnet_nat_proxy_sip_modmsg() :: message to long");
        return -1;
    }

    /* Make space for new data */
    ipcom_memmove(olddata + newlen, olddata + oldlen, movelen);
    *ppend += diff;

    /* Copy in new data */
    ipcom_memcpy(olddata, newdata, newlen);

    return 0;
}
예제 #10
0
/*
 *===========================================================================
 *                     ipnet_sock_tcp_append_send_data
 *===========================================================================
 * Description: Append data to the last packet in the send queue up to
 *              a full MSS segment.
 * Parameters:  send_tail - The last element of the send queue.
 *              pbuf - Pointer to the data buffer pointer. The buffer
 *                     pointer (*pbuf) will point to the first byte
 *                     that has not been copied.
 *              plen - A pointer to the length length of *pbuf, will
 *                     contain the number of bytes not copied when this
 *                     function returns.
 *              mss - The maximum segment size for this segment.
 * Returns:     Number of bytes appended.
 *
 */
IP_STATIC int
ipnet_sock_tcp_append_send_data(Ipcom_pkt *send_tail,
                                Ip_u8 **pbuf,
                                int *plen,
                                int mss)
{
    int bytes_appended;
    int len = *plen;

    if (mss <= send_tail->end - send_tail->start)
        /* mss must have been decresed after the send_tail was created */
        return 0;

    bytes_appended = IP_MIN(mss - (send_tail->end - send_tail->start), len);
    ip_assert(bytes_appended >= 0);

    if (send_tail->chk != 0 && (send_tail->end & 0x1) == 0)
    {
        /* End is even, just add the checksum of the appended data to
           the current checksum */
        send_tail->chk += ipnet_in_checksum_memcpy(&send_tail->data[send_tail->end],
                                                   *pbuf,
                                                   bytes_appended);
    }
    else
    {
        /* The checksum will be wrong unless the last odd byte is
           included in the new checksum, since odd bytes is handled as
           if the byte behind it is 0 (which is probably false now
           when more data is appended) */
        ipnet_copy_from_user(&send_tail->data[send_tail->end],
                             *pbuf,
                             bytes_appended);
        /* Calculate the checksum when sending instead */
        send_tail->chk = 0;
    }

    send_tail->end += bytes_appended;

    ip_assert(send_tail->end <= send_tail->maxlen);

    *pbuf = *pbuf + bytes_appended;
    *plen -= bytes_appended;

    return bytes_appended;
}
/*
 *===========================================================================
 *                    ipcom_getenv
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 *
 */
IP_PUBLIC char *
ipcom_getenv(const char *name)
{
#if IPCOM_USE_ENV == IPCOM_ENV_IPCOM
    Ip_err           retval;
    Ipcom_proc      *proc;
    Ipcom_env_entry *env;
    char            *value = IP_NULL;

    proc = ipcom_proc_self();
    ip_assert(proc != IP_NULL);

    retval = ipcom_once(&proc->env_once, ipcom_env_init, proc);
    if (retval != IPCOM_SUCCESS)
    {
        IP_PANIC();
        return IP_NULL;
    }

    ipcom_mutex_lock(proc->env_mutex);

    env = ipcom_hash_get(proc->env_tree, name);
    if (env != IP_NULL)
        value = (char *)env->value;

    ipcom_mutex_unlock(proc->env_mutex);

    return value;

#elif IPCOM_USE_ENV == IPCOM_ENV_NATIVE && (defined(IP_PORT_OSE) || defined(IP_PORT_OSE5))
    char *env;
    static char buf[256];

    env = get_env(current_process(), name);
    if (env != IP_NULL)
    {
        ipcom_strncpy(buf, env, sizeof(buf));
        free_buf((union SIGNAL **)&env);
        return (char *)buf;
    }
    return IP_NULL;

#elif IPCOM_USE_ENV == IPCOM_ENV_NATIVE
    return getenv(name);

#elif defined(IPCOM_USE_SYSVAR) && IPCOM_VR_MAX == 1
    static char buf[256];
    Ip_size_t  buf_size = sizeof(buf);

    return ipcom_sysvar_get(name, buf, &buf_size);

#else
    return IP_NULL;

#endif /* #if IPCOM_USE_ENV == IPCOM_ENV_IPCOM */
}
예제 #12
0
/*
 *===========================================================================
 *                    ipcom_buffer_free
 *===========================================================================
 * Description: Frees any memory used for the buffer.
 * Parameters:
 * Returns:
 *
 */
IP_PUBLIC void
ipcom_buffer_free(Ipcom_buffer *buffer)
{
#ifdef IP_DEBUG
    ipcom_memset(buffer->buf, 0xdd, buffer->alloc);
#endif
    ip_assert( buffer->buf && buffer );
    ipcom_free(buffer->buf);
    ipcom_free(buffer);
}
예제 #13
0
/*
 *===========================================================================
 *                    ipnet_gre_tmo
 *===========================================================================
 * Description: Reassembly timeout handler.
 * Parameters:  netif - A GRE tunnel interface.
 * Returns:     0 = success, <0 = error code.
 *
 */
IP_STATIC void
ipnet_gre_seq_tmo(Ipnet_netif *netif)
{
    Ipnet_pkt_gre *gre_hdr;
    Ipcom_pkt     *pkt;
    Ipnet_gre_t   *gre = netif->ipcom.pdrv;

    /* RFC 2890, chapter 2.2
       ...
       Under no circumstances should a packet wait more that
       OUTOFORDER_TIMER milliseconds in the buffer.  If a packet has been
       waiting that long, the receiver MUST immediately traverse the buffer
       in sorted order, decapsulating packets (and ignoring any sequence
       number gaps) until there are no more packets in the buffer that have
       been waiting longer than OUTOFORDER_TIMER milliseconds. The "last
       successfully decapsulated sequence number" should then be set to the
       last packet so decapsulated.
       ...
    */
    pkt = ipcom_pqueue_get_next(gre->reassembly_queue);
    ip_assert(pkt != IP_NULL);
    gre->recv_seqnum = IP_GET_NTOHL(&pkt->data[pkt->start]);

    do
    {
        pkt = ipcom_pqueue_remove_next(gre->reassembly_queue);
        /* Discard the sequence number option and make place for a GRE header */
        pkt->start += IPNET_GRE_OPT_SEQNUM_SIZE - IPNET_GRE_HDR_SIZE;

        gre_hdr = (Ipnet_pkt_gre *)&pkt->data[pkt->start];
        gre_hdr->flags_reserved0_ver = 0;
        if (IP_BIT_ISSET(pkt->flags, IPCOM_PKT_FLAG_IPV4))
            gre_hdr->protocol_type = ip_htons(0x0800);
        else if (IP_BIT_ISSET(pkt->flags, IPCOM_PKT_FLAG_IPV6))
            gre_hdr->protocol_type = ip_htons(0x86DD);

        (void) ipnet_gre_input(netif, pkt);
        ++gre->recv_seqnum;
    } while (IP_NULL != (pkt = ipcom_pqueue_get_next(gre->reassembly_queue))
             && gre->recv_seqnum == IP_GET_NTOHL(&pkt->data[pkt->start]));

    if (pkt != IP_NULL)
    {
        Ip_u32 timeout = IPNET_PKT_GET_TIMEOUT_ABS(pkt);

        /* More out of order packets waiting, schedule a timeout of
           the time remaining until this packet sequence timer timeouts */
        (void) ipnet_timeout_schedule((timeout < ipnet->msec_now
                                       ? 0
                                       : timeout - ipnet->msec_now),
                                      (Ipnet_timeout_handler) ipnet_gre_seq_tmo,
                                      netif,
                                      &gre->reassembly_tmo);
    }
}
예제 #14
0
/*
 *===========================================================================
 *                    ipcom_list_remove
 *===========================================================================
 * Description:   Remove list entry pointer to by 'entry' from its list.
 * Parameters:    entry - Pointer to the list entry to remove.
 * Returns:       .
 *
 */
IP_PUBLIC void
ipcom_list_remove(Ipcom_list *entry)
{
    ipcom_list_assert(IP_NULL, entry);
    ip_assert(entry->head->size > 0);

    entry->next->prev = entry->prev;
    entry->prev->next = entry->next;

    entry->head->size--;
    entry->head = IP_NULL;
}
/*
 *===========================================================================
 *                    ipcom_unsetenv
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 *
 */
IP_PUBLIC int
ipcom_unsetenv(const char *name)
{
#if IPCOM_USE_ENV == IPCOM_ENV_IPCOM
    Ip_err           retval;
    Ipcom_proc      *proc;
    Ipcom_env_entry *env;

    proc = ipcom_proc_self();
    ip_assert(proc != IP_NULL);

    retval = ipcom_once(&proc->env_once, ipcom_env_init, proc);
    if (retval != IPCOM_SUCCESS)
    {
        IP_PANIC();
        return -1;
    }

    ipcom_mutex_lock(proc->env_mutex);

    env = ipcom_hash_get(proc->env_tree, name);
    if (env != IP_NULL)
        ipcom_env_delete(env, proc->env_tree);

    ipcom_mutex_unlock(proc->env_mutex);

    return 0;

#elif IPCOM_USE_ENV == IPCOM_ENV_NATIVE && (defined(IP_PORT_OSE) || defined(IP_PORT_OSE5))
    set_env(current_process(), name, NULL);
    return 0;

#elif IPCOM_USE_ENV == IPCOM_ENV_NATIVE && defined(IP_PORT_VXWORKS)
    {
        char buf[256];
        int  ret;
        ipcom_snprintf(buf, sizeof(buf), "%s=", name);
        ret = (int)putenv(buf);
        return ret == 0 ? 0 : -1;
    }

#elif IPCOM_USE_ENV == IPCOM_ENV_NATIVE
    return unsetenv(name);

#elif defined(IPCOM_USE_SYSVAR) && IPCOM_VR_MAX == 1
    (void)ipcom_sysvar_unset(name);
    return 0;

#else
    return 0;

#endif /* #if IPCOM_USE_ENV == IPCOM_ENV_IPCOM */
}
예제 #16
0
/*
 *===========================================================================
 *                    ipcom_buffer_get
 *===========================================================================
 * Description: Gets data from the beginning of the buffer.
 * Parameters:
 * Returns:
 *
 */
IP_PUBLIC Ip_err
ipcom_buffer_get(Ipcom_buffer *buffer, Ip_u8 *buf, Ip_u32 len)
{
    ip_assert(len <= (buffer->end - buffer->offset));

    if(len > (buffer->end - buffer->offset))
        return IPCOM_ERR_FAILED;

    ipcom_memcpy(buf, buffer->buf + buffer->offset, len);
    buffer->offset += len;
    return IPCOM_SUCCESS;
}
예제 #17
0
/*
 *===========================================================================
 *                    ipcom_freeaddrinfo
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 *
 */
IP_PUBLIC void
ipcom_freeaddrinfo(struct Ip_addrinfo *ai)
{
#if defined(IP_PORT_OSE5)
    ip_assert(ipcom_getaddrinfo_fallback > 0);
    if (ipcom_getaddrinfo_fallback == 1)
        freeaddrinfo((struct addrinfo *)ai);
    else
        ipcom_freeaddrinfo2(ai);
#else
    ipcom_freeaddrinfo2(ai);
#endif
}
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;
}
/*
 *===========================================================================
 *                    ipcom_clearenv
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 *
 */
IP_GLOBAL void
ipcom_proc_clearenv(Ipcom_proc *proc)
{
    ip_assert(proc != IP_NULL);

    ipcom_mutex_lock(proc->env_mutex);

    /* Remove all environment variable entries */
    ipcom_hash_for_each(proc->env_tree,
                        (Ipcom_hash_foreach_cb_func) ipcom_env_delete,
                        proc->env_tree);

    ipcom_mutex_unlock(proc->env_mutex);
}
예제 #20
0
/*
 *===========================================================================
 *                    ipcom_buffer_decr_cap
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 *
 */
IP_PUBLIC Ip_err
ipcom_buffer_decr_cap(Ipcom_buffer *buffer, Ip_u32 len)
{
    ip_assert( len <= ipcom_buffer_capacity(buffer) );
    if(len > ipcom_buffer_capacity(buffer))
        return IPCOM_ERR_FAILED;

    IPCOM_LOG4(DEBUG2,
               "ipcom_buffer_decr_cap :: buf=%x, len=%d, end=%d, offset=%d",
               buffer, len, buffer->end, buffer->offset);

    buffer->end += len;
    return IPCOM_SUCCESS;
}
예제 #21
0
/*
 *===========================================================================
 *                    ipcom_buffer_consume_end
 *===========================================================================
 * Description: Consumes the given number of bytes from the end of the buffer.
 * Parameters:
 * Returns:
 *
 */
IP_PUBLIC Ip_err
ipcom_buffer_consume_end(Ipcom_buffer *buffer, Ip_u32 bytes)
{
    ip_assert( bytes <= (buffer->end - buffer->offset) );
    if(bytes > (buffer->end - buffer->offset))
        return IPCOM_ERR_FAILED;

    IPCOM_LOG4(DEBUG2,
               "ipcom_buffer_consume_end :: buf=%x, bytes=%d, end=%d, offset=%d",
               buffer, bytes, buffer->end, buffer->offset);

    buffer->end -= bytes;
    return IPCOM_SUCCESS;
}
예제 #22
0
/*
 *===========================================================================
 *                    ipnet_wlan_ioctl
 *===========================================================================
 * Description: WLAN IO control.
 * Parameters:  netif - The network interface to operate on.
 *              command -
 *              data - Depends on command.
 * Returns:     0 = success, < 0 = error code
 *
 */
IP_STATIC int
ipnet_wlan_ioctl(Ipnet_netif *netif, Ip_u32 command, void *data)
{
    int             ret = 0;
    Ipcom_iwreq    *iw = data;
    Ipcom_wlan_func wlan_if;

    ip_assert(netif->ipcom.link_addr_size == IPNET_WLAN_ADDR_SIZE);

    switch(command)
    {
    case IP_SIOCSIWATTACHFUNC:
    case IP_SIOCSIWREMOVEFUNC:

        if(command == IP_SIOCSIWATTACHFUNC)
        {
            netif->wlan->aux_link_ioctl = (int (*)(Ipnet_netif *, Ip_u32, void *))iw->u.data.pointer;
        }

        if(netif->wlan->aux_link_ioctl != IP_NULL)
        {
            wlan_if.link_input = (int (*)(Ipcom_netif *, Ipcom_pkt *))netif->link_input;
            ret = netif->wlan->aux_link_ioctl(netif, command, &wlan_if);
            netif->link_input = (Ipnet_link_input)wlan_if.link_input;
        }

        if(command == IP_SIOCSIWREMOVEFUNC)
        {
            netif->wlan->aux_link_ioctl = IP_NULL;
        }

        break;

    default:

        if(netif->wlan->aux_link_ioctl)
        {
            ret = netif->wlan->aux_link_ioctl(netif, command, data);
            if(ret <= 0)
            {
                break;
            }
        }
        ret = netif->wlan->eth_link_ioctl(netif, command, data);
    }

    return ret;
}
/*
 *===========================================================================
 *                    ipcom_spinlock_unlock
 *===========================================================================
 * Description:
 * Parameters:
 * Returns:
 *
 */
IP_FASTTEXT IP_PUBLIC void
ipcom_spinlock_unlock(Ipcom_spinlock sl_handle)
{
#ifdef IPCOM_USE_SMP
    Ipcom_vxworks_spinlock_t *sl = (Ipcom_vxworks_spinlock_t*) sl_handle;

    VX_MEM_BARRIER_RW();  /* build a memory fence for load and store */

    if (vxAtomicInc(&sl->count) < 0)
        /* Contention for this lock, let's wakeup one of the tasks
           that is blocked on this lock */
        semGive(sl->sem);
#else
    IPCOM_UNUSED_ARG(sl_handle);
    ip_assert(sl_handle == IPCOM_SPINLOCK_TAG);
    taskUnlock();
#endif
}
/*
 *===========================================================================
 *                    ipnet_loopback_drv_output
 *===========================================================================
 * Description: Loops back the packet.
 * Parameters:  netif - The interface the packet was sent to.
 *              pkt - The packet to loopback. pkt->start is the offset to the
 *              IP header.
 * Returns:     0 = success, 0< = error code.
 *
 */
IP_STATIC int
ipnet_loopback_drv_output(Ipcom_netif *netif, Ipcom_pkt *pkt)
{
    int ret = 0;

    /* The ipcom_pkt_input_queue() frees the packet if it cannot be queued,
       add a reference so that packet is still allocated if that happens */
    IPCOM_PKT_ADD_REF(pkt);
    IPCOM_PKT_TRACE(pkt, IPCOM_PKT_ID_RX);
    IP_BIT_SET(pkt->flags, IPCOM_PKT_FLAG_LOOPED_BACK);
    ret = ipcom_pkt_input_queue(netif, pkt);
    if (IP_UNLIKELY(ret != -IP_ERRNO_EWOULDBLOCK))
    {
        ip_assert(IPCOM_PKT_HAS_MULTIPLE_OWNERS(pkt));
        ipcom_pkt_free(pkt);
    }
    return ret;
}
/*
 *===========================================================================
 *                    ipcom_cmd_smptest_server
 *===========================================================================
 * Description: This is the server part of the smptest command
 * Parameters:  The address we should listen to, and info about how many sockets
 *              we should use.
 * Returns:     0 on success. -1 on failure.
 */
IP_STATIC int
ipcom_cmd_smptest_server()
{
    Ipcom_proc_attr    attr;
    unsigned int i;
    Ipcom_proc *proc;
    int retval;

    spawn_number_server     = 0;

    if ( 0 != ipcom_sem_create( &sem_wait_server, 0 ) )
    {
        ipcom_printf("ipcom_sem_create failed: %s"IP_LF, ipcom_strerror(ipcom_errno));
        return -1;
    }
    ipcom_atomic_set( &num_wait_server, smp_opt_server.num_sock );
    ipcom_atomic_set( &listen_wait, smp_opt_server.num_sock );

    ipcom_proc_attr_init(&attr);
    attr.priority   = IPCOM_PRIORITY_DEFAULT;


    /* Hacky hacky way to write from a task.. copied from ipcom_mshell.c */
    proc = ipcom_proc_self();
    ip_assert( proc != 0 );
    server_out = proc->shell_fd;

    for ( i = 0;i < smp_opt_server.num_sock;++i )
    {
        retval = ipcom_proc_acreate("ipcom_cmd_smptest_server_spawn",
                                        (Ipcom_proc_func)ipcom_cmd_smptest_server_spawn, &attr, 0 );
        if (retval != 0)
        {
            ipcom_printf( "Error spawning smptest server"IP_LF );
            return retval;
        }
    }

    ipcom_sem_wait( sem_wait_server );

    ipcom_sem_delete( &sem_wait_server );

    return 0;
}
예제 #26
0
/*
 *===========================================================================
 *                    ipcom_hash_resize
 *===========================================================================
 * Description:   Doubles the size or cuts the size in half.
 * Parameters:    head - The head of the hash table.
 *                increase - Set to IP_TRUE to double the size, IP_FALSE
 *                to half the size.
 * Returns:       IPCOM_SUCCESS or IPCOM_ERR_NO_MEMORY if not enough memory
 *                could be allocated.
 *
 */
IP_STATIC Ip_err
ipcom_hash_resize(Ipcom_hash *head, Ip_bool increase)
{
    void **old_hash_table;
    int    old_size;
    int    i;
    Ip_err err;

    old_hash_table = head->table;
    old_size = head->size;

    /* Keep the size odd since that will increase the chance of the high
       bits of the hash value to affect the low bits which is used as
       index in the hash table */
    if (increase)
        head->size = (head->size << 1) + 3;
    else
        head->size = (head->size >> 1) - 1;

    head->table = IPCOM_CALLOC_STATIC(head->size, sizeof(*head->table));
    if (head->table == IP_NULL)
    {
        IPCOM_LOG2(ERR, "ipcom_hash_resize :: ipcom_calloc(%d, %d) failed",
                   head->size,
                   sizeof(*head->table));
        head->size = old_size;
        head->table = old_hash_table;
        return IPCOM_ERR_NO_MEMORY;
    }

    head->elem = 0;
    for (i = 0; i < old_size; i++)
        if (old_hash_table[i] != IP_NULL)
        {
            err = ipcom_hash_add(head, old_hash_table[i]);
            ip_assert(err == IPCOM_SUCCESS);
            (void)err;
        }

    IPCOM_FREE_STATIC(old_hash_table);
    return IPCOM_SUCCESS;
}
/*
 *===========================================================================
 *                  ipnet_pkt_queue_mbc_remove
 *===========================================================================
 * Description: Removes an queue from a container queue and put pack a
 *              default queue type.
 * Parameters:  c - The MBC parent queue for 'q'.
 *              q - The queue to remove.
 * Returns:     0 = success, <0 = error code (-IP_ERRNO_xxx)
 *
 */
IP_STATIC int
ipnet_pkt_queue_mbc_remove(Ipnet_pkt_queue_mbc *c, Ipnet_pkt_queue *q)
{
    Ip_u32           band;

    ip_assert(c->hdr.id == q->parent_id);
    for (band = 0; band < c->number_of_bands; band++)
    {
        if (q == c->bands[band])
        {
            int ret = ipnet_pkt_queue_mbc_insert_default_queue(c, band);
            if (ret < 0)
                IPCOM_LOG3(WARNING, "MBC: Failed to replace %s:%d with a fifo in remove(): %s",
                           q->type, q->id, ipcom_strerror(-ret));
            return ret;
        }
    }

    return -IP_ERRNO_ESRCH;
}
IP_FASTTEXT IP_PUBLIC void
ipcom_spinlock_lock(Ipcom_spinlock sl_handle)
{
#ifdef IPCOM_USE_SMP
    Ipcom_vxworks_spinlock_t *sl = (Ipcom_vxworks_spinlock_t*) sl_handle;
#ifdef IPCOM_SPINLOCK_BUSY_PERSIST
    int i;
    atomicVal_t count;

 try_again:

    if (vxCas(&sl->count, 1, 0))
        goto got_it;

    for (i = IPCOM_SPINLOCK_BUSY_PERSIST; i > 0; --i)
    {
        count = vxAtomicGet(&sl->count);
        if (count < 0)
            break;
        if (count == 1)
            goto try_again;
    }
#endif /* IPCOM_SPINLOCK_BUSY_PERSIST */
    if (vxAtomicDec(&sl->count) <= 0)
        /* Contention for this lock, let's sleep until the lock gets
           available */
        semTake(sl->sem, WAIT_FOREVER);
    else
    {
#ifdef IPCOM_SPINLOCK_BUSY_PERSIST
    got_it:
#endif
        /* prevent load/store re-ordering beyond this point */
        VX_MEM_BARRIER_RW();
    }
#else
    IPCOM_UNUSED_ARG(sl_handle);
    ip_assert(sl_handle == IPCOM_SPINLOCK_TAG);
    taskLock();
#endif
}
예제 #29
0
/*
 *===========================================================================
 *                    ipcom_list_insert_last
 *===========================================================================
 * Description:   Insert list 'entry' last in the list 'head'.
 * Parameters:    head  - Pointer to the list header to insert 'entry' in.
 *                entry - Pointer to the list entry to insert last.
 * Returns:       .
 *
 */
IP_PUBLIC void
ipcom_list_insert_last(Ipcom_list *head, Ipcom_list *entry)
{
#ifdef IP_ASSERT
    {
        Ipcom_list *tmp;
        for(tmp = head->next; tmp != head; tmp = tmp->next)
            ip_assert(entry != tmp);
    }
#endif

    entry->prev = head->prev;
    entry->next = head;
    entry->next->prev = entry;
    entry->prev->next = entry;

    entry->head = head;
    head->size++;

    ipcom_list_assert(head, entry);
}
예제 #30
0
/*
 *===========================================================================
 *                      ipnet_vrrp_del_addr
 *===========================================================================
 * Description: Deletes a virtual router address.
 * Parameters:  netif - The network interface the VRIP was assigned to.
 *              vrid - The VRID the address was assigned to.
 * Returns:     0 = success, <0 = error code.
 *
 */
IP_GLOBAL int
ipnet_vrrp_del_addr(Ipnet_netif *netif, Ip_u8 vrid, struct Ip_in_addr addr)
{
    Ipnet_vrrp_addr_t *addr_entry;
    int                i;

    ip_assert(ipnet->vrrp_addrs != IP_NULL);

    addr_entry = ipnet_vrrp_get_addr_entry(netif, vrid);
    if (addr_entry == IP_NULL)
        return -IP_ERRNO_ESRCH;

    i = ipnet_vrrp_addr_index(addr_entry, addr);
    if (i < 0)
        return -IP_ERRNO_ESRCH;

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

    if (--addr_entry->num_addrs > 0)
    {
        for (;i < addr_entry->num_addrs; i++)
            addr_entry->addrs[i] = addr_entry->addrs[i + 1];
    }
    else
    {
        (void)ipcom_hash_remove(ipnet->vrrp_addrs, addr_entry);
        ipcom_free(addr_entry);

        if (ipnet->vrrp_addrs->elem == 0)
        {
            ipcom_hash_delete(ipnet->vrrp_addrs);
            ipnet->vrrp_addrs = IP_NULL;
        }
    }

    return 0;
}