Example #1
0
END_TEST
START_TEST(tc_pico_mld_timer_expired)
{
    struct mld_timer *t,*s;
    t = PICO_ZALLOC(sizeof(struct mld_timer));
    t->stopped = MLD_TIMER_STOPPED;
    t->type = 0;
    pico_string_to_ipv6("AAAA::1", t->mcast_link.addr);
    pico_string_to_ipv6("AAAA::1", t->mcast_group.addr);
    //void function, just check for side effects
    pico_mld_timer_expired(NULL, (void *)t);
    pico_tree_insert(&MLDTimers, t);
    s = PICO_ZALLOC(sizeof(struct mld_timer));
    memcpy(s,t,sizeof(struct mld_timer)); // t will be freed next test
    pico_mld_timer_expired(NULL, (void *)t); /* will be freed */
    s->stopped++;
    s->start = PICO_TIME_MS()*2;
    s->type++;
    pico_tree_insert(&MLDTimers, s);
    t = PICO_ZALLOC(sizeof(struct mld_timer));
    memcpy(t,s,sizeof(struct mld_timer)); // s will be freed next test
    pico_mld_timer_expired(NULL, (void *)s); /* s will be freed */
    t->mld_callback = mock_callback;
    pico_mld_timer_expired(NULL, (void *)t); /* t will be freed */
}
Example #2
0
END_TEST

START_TEST(tc_mld_srst) 
{
    struct mld_parameters *p;
    struct pico_device *dev = pico_null_create("dummy3");
    struct pico_ipv6_link *link;
    struct pico_ipv6_mcast_group g; 
    struct mldv2_report *report;
    struct mld_timer t;
    //Building example frame
    
    p = PICO_ZALLOC(sizeof(struct mld_parameters));
    pico_string_to_ipv6("AAAA::1", p->mcast_link.addr);
    pico_string_to_ipv6("FF00::e007:707", p->mcast_group.addr);
    p->MCASTFilter = &_MCASTFilter;
    p->filter_mode = 0;
    g.filter_mode = 0;   
    g.mcast_addr = p->mcast_group;
    g.MCASTSources.root = &LEAF;
    g.MCASTSources.compare = mcast_sources_cmp_ipv6;

    pico_tree_insert(&MLDParameters, p);
    //no link
    fail_if(mld_srst(p) != -1);
    link = pico_ipv6_link_add(dev, p->mcast_link, p->mcast_link);
    link->mcast_compatibility = PICO_MLDV1;
    // invalid proto
    fail_if(mld_srst(p) != -1);
    link->mcast_compatibility = PICO_MLDV2;
    pico_tree_insert(link->MCASTGroups, &g);
    
    fail_if(mld_srst(p) != 0);
}
Example #3
0
END_TEST
START_TEST(tc_pico_mld_process_in) {
    struct mld_parameters *p;
    struct pico_device *dev = pico_null_create("dummy3");
    struct pico_ipv6_link *link;
    struct pico_tree *filter = PICO_ZALLOC(sizeof(struct pico_tree));
    int i,j, _i,_j,result;
    struct pico_ipv6_mcast_group g; 
    struct mldv2_report *report;
    //Building example frame
    p = PICO_ZALLOC(sizeof(struct mld_parameters));
    pico_string_to_ipv6("AAAA::1", p->mcast_link.addr);
    pico_string_to_ipv6("FF00::e007:707", p->mcast_group.addr);
    //no link
    fail_if(pico_mld_generate_report(p) != -1);
    link = pico_ipv6_link_add(dev, p->mcast_link, p->mcast_link);
    pico_string_to_ipv6("AAAA::1", p->mcast_group.addr);
    fail_if(pico_mld_generate_report(p) != -1);
    pico_string_to_ipv6("FF00::e007:707", p->mcast_group.addr);
    link->mcast_compatibility = PICO_MLDV1;
    g.mcast_addr = p->mcast_group;
    g.MCASTSources.root = &LEAF;
    g.MCASTSources.compare = mcast_sources_cmp_ipv6;
    // No mcastsources tree
    link->mcast_compatibility = PICO_MLDV2;
    fail_if(pico_mld_generate_report(p) != -1);
    pico_tree_insert(link->MCASTGroups, &g);
    pico_tree_insert(&MLDParameters, p);
    
    link->mcast_compatibility = 99;
    fail_if(pico_mld_generate_report(p) != -1);
    link->mcast_compatibility = PICO_MLDV1;
    fail_if(pico_mld_generate_report(p) != 0);
    link->mcast_compatibility = PICO_MLDV2;
    for(_j =0; _j<3; _j++) {   //FILTER
        (_j == 2) ? (result = -1) : (result = 0);
        for(_i=0; _i<3; _i++) {  //FILTER
            if(_i == 2) result = -1;
            for(i = 0; i<3; i++) {  //STATES
                for(j = 0; j<6; j++) { //EVENTS
                    p->MCASTFilter = &_MCASTFilter;
                    p->filter_mode = _i;
                    g.filter_mode = _j;
                    if(p->event == MLD_EVENT_DELETE_GROUP || p->event == MLD_EVENT_QUERY_RECV)
                        p->event++;
                    fail_if(pico_mld_generate_report(p) != result);
                    p->state = i;
                    p->event = j;
                    if(result != -1 && p->f) {//in some combinations, no frame is created
                        report = p->f->transport_hdr + MLD_ROUTER_ALERT_LEN;
                        report->crc = short_be(pico_icmp6_checksum(p->f));
                        fail_if(pico_mld_process_in(p->f) != 0);
                    }
                }
            }
        }
    }
}
Example #4
0
static struct pico_dhcp_server_negotiation *pico_dhcp_server_add_negotiation(struct pico_device *dev, struct pico_dhcp_hdr *hdr)
{
    struct pico_dhcp_server_negotiation *dhcpn = NULL;
    struct pico_dhcp_server_setting test = {
        0
    };

    if (pico_dhcp_server_find_negotiation(hdr->xid))
        return NULL;

    dhcpn = PICO_ZALLOC(sizeof(struct pico_dhcp_server_negotiation));
    if (!dhcpn) {
        pico_err = PICO_ERR_ENOMEM;
        return NULL;
    }

    dhcpn->xid = hdr->xid;
    dhcpn->state = PICO_DHCP_STATE_DISCOVER;
    dhcpn->bcast = ((short_be(hdr->flags) & PICO_DHCP_FLAG_BROADCAST) != 0) ? (1) : (0);
    memcpy(dhcpn->hwaddr.addr, hdr->hwaddr, PICO_SIZE_ETH);

    test.dev = dev;
    dhcpn->dhcps = pico_tree_findKey(&DHCPSettings, &test);
    if (!dhcpn->dhcps) {
        dhcps_dbg("DHCP server WARNING: received DHCP message on unconfigured link %s\n", dev->name);
        PICO_FREE(dhcpn);
        return NULL;
    }

    dhcp_negotiation_set_ciaddr(dhcpn);
    pico_tree_insert(&DHCPNegotiations, dhcpn);
    return dhcpn;
}
Example #5
0
static struct pico_dns_query *pico_dns_client_add_query(struct pico_dns_prefix *hdr, uint16_t len, struct pico_dns_query_suffix *suffix,
                                                        void (*callback)(char *, void *), void *arg)
{
    struct pico_dns_query *q = NULL, *found = NULL;

    q = pico_zalloc(sizeof(struct pico_dns_query));
    if (!q)
        return NULL;

    q->query = (char *)hdr;
    q->len = len;
    q->id = short_be(hdr->id);
    q->qtype = short_be(suffix->qtype);
    q->qclass = short_be(suffix->qclass);
    q->retrans = 1;
    q->q_ns = *((struct pico_dns_ns *)pico_tree_first(&NSTable));
    q->callback = callback;
    q->arg = arg;
    q->s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, &pico_dns_client_callback);
    if (!q->s) {
        pico_free(q);
        return NULL;
    }

    found = pico_tree_insert(&DNSTable, q);
    if (found) {
        pico_err = PICO_ERR_EAGAIN;
        pico_socket_close(q->s);
        pico_free(q);
        return NULL;
    }

    return q;
}
Example #6
0
static struct pico_dns_ns *pico_dns_client_add_ns(struct pico_ip4 *ns_addr)
{
    struct pico_dns_ns *dns = NULL, *found = NULL, test = {{0}};

    dns = pico_zalloc(sizeof(struct pico_dns_ns));
    if (!dns) {
        pico_err = PICO_ERR_ENOMEM;
        return NULL;
    }

    dns->ns = *ns_addr;

    found = pico_tree_insert(&NSTable, dns);
    if (found) { /* nameserver already present */
        pico_free(dns);
        return found;
    }

    /* default NS found, remove it */
    pico_string_to_ipv4(PICO_DNS_NS_GOOGLE, &test.ns.addr);
    found = pico_tree_findKey(&NSTable, &test);
    if (found && (found->ns.addr != ns_addr->addr))
        pico_dns_client_del_ns(&found->ns);

    return dns;
}
Example #7
0
static struct pico_dhcp_client_cookie *pico_dhcp_client_add_cookie(uint32_t xid, struct pico_device *dev, void (*cb)(void *dhcpc, int code), uint32_t *uid)
{
    struct pico_dhcp_client_cookie *dhcpc = NULL, *found = NULL, test = {
        0
    };

    test.xid = xid;
    found = pico_tree_findKey(&DHCPCookies, &test);
    if (found) {
        pico_err = PICO_ERR_EAGAIN;
        return NULL;
    }

    dhcpc = pico_zalloc(sizeof(struct pico_dhcp_client_cookie));
    if (!dhcpc) {
        pico_err = PICO_ERR_ENOMEM;
        return NULL;
    }

    dhcpc->state = DHCP_CLIENT_STATE_INIT;
    dhcpc->status = DHCP_CLIENT_STATUS_INIT;
    dhcpc->xid = xid;
    dhcpc->uid = uid;
    *(dhcpc->uid) = 0;
    dhcpc->cb = cb;
    dhcpc->dev = dev;

    pico_tree_insert(&DHCPCookies, dhcpc);
    return dhcpc;
}
Example #8
0
END_TEST
START_TEST(tc_mld_stsdifs) 
{
    struct mld_parameters *p;
    struct pico_device *dev = pico_null_create("dummy3");
    struct pico_ipv6_link *link;
    struct pico_ipv6_mcast_group g; 
    struct mldv2_report *report;
    struct mld_timer t;
    //Building example frame
    p = PICO_ZALLOC(sizeof(struct mld_parameters));
    pico_string_to_ipv6("AAAA::1", p->mcast_link.addr);
    pico_string_to_ipv6("FF00::e007:707", p->mcast_group.addr);
    //no link
    fail_if(mld_stsdifs(p) != -1);
    link = pico_ipv6_link_add(dev, p->mcast_link, p->mcast_link);
    link->mcast_compatibility = PICO_MLDV1;
    // no timer
    fail_if(mld_stsdifs(p) != -1);
    t.type = MLD_TIMER_GROUP_REPORT;
    t.mcast_link = p->mcast_link;
    t.mcast_group = p->mcast_group;
    pico_tree_insert(&MLDTimers, &t);
    fail_if(mld_stsdifs(p) != 0);
    //set flag
    pico_mld_flag = 1;
    fail_if(mld_stsdifs(p) != 0);
}
Example #9
0
static struct pico_dhcp_server_setting *pico_dhcp_server_add_setting(struct pico_dhcp_server_setting *setting)
{
  uint16_t port = PICO_DHCPD_PORT;
  struct pico_dhcp_server_setting *dhcps = NULL, *found = NULL, test = {0};
  struct pico_ipv4_link *link = NULL;
  
  link = pico_ipv4_link_get(&setting->server_ip);
  if (!link) {
    pico_err = PICO_ERR_EINVAL;
    return NULL;
  }
  test.dev = setting->dev;
  found = pico_tree_findKey(&DHCPSettings, &test);
  if (found) {
    pico_err = PICO_ERR_EINVAL;
    return NULL;
  }
  dhcps = pico_zalloc(sizeof(struct pico_dhcp_server_setting));
  if (!dhcps) {
    pico_err = PICO_ERR_ENOMEM;
    return NULL;
  }

  dhcps->lease_time = setting->lease_time;
  dhcps->pool_start = setting->pool_start;
  dhcps->pool_next = setting->pool_next;
  dhcps->pool_end = setting->pool_end;
  dhcps->dev = link->dev;
  dhcps->server_ip = link->address;
  dhcps->netmask = link->netmask;

  /* default values if not provided */
  if (!dhcps->pool_start)
    dhcps->pool_start = (dhcps->server_ip.addr & dhcps->netmask.addr) | DHCP_SERVER_POOL_START;
  if (!dhcps->pool_end)
    dhcps->pool_end = (dhcps->server_ip.addr & dhcps->netmask.addr) | DHCP_SERVER_POOL_END;
  if (!dhcps->lease_time)
    dhcps->lease_time = DHCP_SERVER_LEASE_TIME;
  dhcps->pool_next = dhcps->pool_start;

  dhcps->s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, &pico_dhcpd_wakeup);
  if (!dhcps->s) {
    dhcps_dbg("DHCP server ERROR: failure opening socket (%s)\n", strerror(pico_err));
    pico_free(dhcps);
    return NULL;
  }
  if (pico_socket_bind(dhcps->s, &dhcps->server_ip, &port) < 0) {
    dhcps_dbg("DHCP server ERROR: failure binding socket (%s)\n", strerror(pico_err));
    pico_free(dhcps);
    return NULL;
  }
  
  pico_tree_insert(&DHCPSettings, dhcps);
  return dhcps;
}
Example #10
0
END_TEST
START_TEST(tc_pico_mld_state_change) {
    struct pico_ip6 mcast_link, mcast_group;
    struct mld_parameters p;
    pico_string_to_ipv6("AAAA::1", mcast_link.addr);
    pico_string_to_ipv6("AAAA::1", mcast_group.addr);
    p.mcast_link = mcast_link;
    p.mcast_group = mcast_group;
    
    fail_if(pico_mld_state_change(NULL, &mcast_group, 0,NULL, PICO_MLD_STATE_CREATE) != -1);
    fail_if(pico_mld_state_change(&mcast_link, &mcast_group, 0,NULL, PICO_MLD_STATE_CREATE) != -1);
    fail_if(pico_mld_state_change(&mcast_link, &mcast_group, 0,NULL, 99) != -1);
    pico_tree_insert(&MLDParameters, &p);
    fail_if(pico_mld_state_change(&mcast_link, &mcast_group, 0,NULL, 99) != -1);
}
Example #11
0
END_TEST
START_TEST(tc_pico_mld_find_parameter) {
    struct pico_ip6 mcast_link, mcast_group;
    struct mld_parameters test = {
        0
    };
    fail_if(pico_mld_find_parameter(NULL,NULL) != NULL);
    pico_string_to_ipv6("AAAA::1", mcast_link.addr);
    fail_if(pico_mld_find_parameter(&mcast_link,NULL) != NULL);
    pico_string_to_ipv6("AAAA::2", mcast_group.addr);
    fail_if(pico_mld_find_parameter(&mcast_link,&mcast_group) != NULL);
    test.mcast_link = mcast_link;
    test.mcast_group = mcast_group;
    pico_tree_insert(&MLDParameters, &test);

    fail_if(pico_mld_find_parameter(&mcast_link,&mcast_group) == NULL);
}
Example #12
0
static void next_ping(uint32_t now, void *arg)
{
  struct pico_icmp4_ping_cookie *newcookie, *cookie = (struct pico_icmp4_ping_cookie *)arg;
  IGNORE_PARAMETER(now);

	if(pico_tree_findKey(&Pings,cookie)){
    if (cookie->seq < cookie->count) {
      newcookie = pico_zalloc(sizeof(struct pico_icmp4_ping_cookie));
      if (!newcookie)
        return;
      memcpy(newcookie, cookie, sizeof(struct pico_icmp4_ping_cookie));
      newcookie->seq++;

	    pico_tree_insert(&Pings,newcookie);
      send_ping(newcookie);
    }
  }
}
Example #13
0
static inline struct pico_dhcp_server_setting *dhcps_try_open_socket(struct pico_dhcp_server_setting *dhcps)
{
    uint16_t port = PICO_DHCPD_PORT;
    dhcps->s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, &pico_dhcpd_wakeup);
    if (!dhcps->s) {
        dhcps_dbg("DHCP server ERROR: failure opening socket (%s)\n", strerror(pico_err));
        PICO_FREE(dhcps);
        return NULL;
    }

    if (pico_socket_bind(dhcps->s, &dhcps->server_ip, &port) < 0) {
        dhcps_dbg("DHCP server ERROR: failure binding socket (%s)\n", strerror(pico_err));
        PICO_FREE(dhcps);
        return NULL;
    }

    pico_tree_insert(&DHCPSettings, dhcps);
    return dhcps;
}
Example #14
0
/**************** FILTER API's ****************/
uint32_t pico_ipv4_filter_add(struct pico_device *dev, uint8_t proto,
                              struct pico_ip4 *out_addr, struct pico_ip4 *out_addr_netmask,
                              struct pico_ip4 *in_addr, struct pico_ip4 *in_addr_netmask,
                              uint16_t out_port, uint16_t in_port, int8_t priority,
                              uint8_t tos, enum filter_action action)
{
    static uint32_t filter_id = 1u; /* 0 is a special value used in the binary-tree search for packets being processed */
    struct filter_node *new_filter;

    if (pico_ipv4_filter_add_validate(priority, action) < 0) {
        pico_err = PICO_ERR_EINVAL;
        return 0;
    }

    new_filter = PICO_ZALLOC(sizeof(struct filter_node));
    if (!new_filter) {
        pico_err = PICO_ERR_ENOMEM;
        return 0;
    }

    new_filter->fdev = dev;
    new_filter->proto = proto;
    new_filter->out_addr = (!out_addr) ? (0U) : (out_addr->addr);
    new_filter->out_addr_netmask = (!out_addr_netmask) ? (0U) : (out_addr_netmask->addr);
    new_filter->in_addr = (!in_addr) ? (0U) : (in_addr->addr);
    new_filter->in_addr_netmask = (!in_addr_netmask) ? (0U) : (in_addr_netmask->addr);
    new_filter->out_port = out_port;
    new_filter->in_port = in_port;
    new_filter->priority = priority;
    new_filter->tos = tos;
    new_filter->filter_id = filter_id++;
    new_filter->function_ptr = fp_function[action].fn;

    if(pico_tree_insert(&filter_tree, new_filter))
    {
        PICO_FREE(new_filter);
        filter_id--;
        return 0;
    }

    return new_filter->filter_id;
}
Example #15
0
struct mock_device *pico_mock_create(uint8_t*mac)
{

    struct mock_device*mock = PICO_ZALLOC(sizeof(struct mock_device));
    if(!mock)
        return NULL;

    mock->dev = PICO_ZALLOC(sizeof(struct pico_device));
    if (!mock->dev) {
        PICO_FREE(mock);
        return NULL;
    }

    if(mac != NULL) {
        mock->mac = PICO_ZALLOC(6 * sizeof(uint8_t));
        if(!mock->mac) {
            PICO_FREE(mock->mac);
            PICO_FREE(mock);
            return NULL;
        }

        memcpy(mock->mac, mac, 6);
    }

    if( 0 != pico_device_init((struct pico_device *)mock->dev, "mock", mac)) {
        dbg ("Loop init failed.\n");
        pico_mock_destroy((struct pico_device *)mock->dev);
        if(mock->mac != NULL)
            PICO_FREE(mock->mac);

        PICO_FREE(mock);
        return NULL;
    }

    mock->dev->send = pico_mock_send;
    mock->dev->poll = pico_mock_poll;
    mock->dev->destroy = pico_mock_destroy;
    dbg("Device %s created.\n", mock->dev->name);

    pico_tree_insert(&mock_device_tree, mock);
    return mock;
}
Example #16
0
static struct pico_dhcp_server_negotiation *pico_dhcp_server_add_negotiation(struct pico_device *dev, struct pico_dhcp_hdr *hdr)
{
  struct pico_dhcp_server_negotiation *dhcpn = NULL;
  struct pico_dhcp_server_setting test = {0};
  struct pico_ip4 *ciaddr = NULL;

  if (pico_dhcp_server_find_negotiation(hdr->xid))
    return NULL;

  dhcpn = pico_zalloc(sizeof(struct pico_dhcp_server_negotiation));
  if (!dhcpn) {
    pico_err = PICO_ERR_ENOMEM;
    return NULL;
  }

  dhcpn->xid = hdr->xid;
  dhcpn->state = PICO_DHCP_STATE_DISCOVER;
  memcpy(dhcpn->hwaddr.addr, hdr->hwaddr, PICO_SIZE_ETH);

  test.dev = dev;
  dhcpn->dhcps = pico_tree_findKey(&DHCPSettings, &test);
  if (!dhcpn->dhcps) {
    dhcps_dbg("DHCP server WARNING: received DHCP message on unconfigured link %s\n", dev->name);
    pico_free(dhcpn);
    return NULL;
  }

  ciaddr = pico_arp_reverse_lookup(&dhcpn->hwaddr);
  if (!ciaddr) {
    dhcpn->ciaddr.addr = dhcpn->dhcps->pool_next;
    dhcpn->dhcps->pool_next = long_be(long_be(dhcpn->dhcps->pool_next) + 1);
    pico_arp_create_entry(dhcpn->hwaddr.addr, dhcpn->ciaddr, dhcpn->dhcps->dev);
  } else {
    dhcpn->ciaddr = *ciaddr;
  }

  pico_tree_insert(&DHCPNegotiations, dhcpn);
  return dhcpn; 
}
Example #17
0
int pico_icmp4_ping(char *dst, int count, int interval, int timeout, int size, void (*cb)(struct pico_icmp4_stats *))
{
  static uint16_t next_id = 0x91c0;
  struct pico_icmp4_ping_cookie *cookie;

  if((dst == NULL) || (interval == 0) || (timeout == 0) || (count == 0)){
    pico_err = PICO_ERR_EINVAL;
    return -1;
  }

  cookie = pico_zalloc(sizeof(struct pico_icmp4_ping_cookie));
  if (!cookie) {
    pico_err = PICO_ERR_ENOMEM;
    return -1;
  }

  if (pico_string_to_ipv4(dst, &cookie->dst.addr) < 0) {
    pico_err = PICO_ERR_EINVAL;
    pico_free(cookie);
    return -1;
  }
  cookie->seq = 1;
  cookie->id = next_id++;
  cookie->err = PICO_PING_ERR_PENDING;
  cookie->size = (uint16_t)size;
  cookie->interval = interval;
  cookie->timeout = timeout;
  cookie->cb = cb;
  cookie->count = count;

  pico_tree_insert(&Pings,cookie);
  send_ping(cookie);

  return 0;

}
int pico_dns_client_nameserver(struct pico_ip4 *ns, uint8_t flag)
{
  struct pico_dns_ns test, *key = NULL;

  if (!ns) {
    pico_err = PICO_ERR_EINVAL;
    return -1;
  }

  switch (flag)
  {
    case PICO_DNS_NS_ADD:
      key = pico_zalloc(sizeof(struct pico_dns_ns));
      if (!key) {
        pico_err = PICO_ERR_ENOMEM;
        return -1;
      }
      key->ns = *ns;

      if(pico_tree_insert(&NSTable,key)){
        dns_dbg("DNS WARNING: nameserver %08X already added\n",ns->addr);
        pico_err = PICO_ERR_EINVAL;
        pico_free(key);
        return -1; /* Element key already exists */
      }
      dns_dbg("DNS: nameserver %08X added\n", ns->addr);
      /* If default NS found, remove it */
      pico_string_to_ipv4(PICO_DNS_NS_GOOGLE, &test.ns.addr);
      if (ns->addr != test.ns.addr) {

          key = pico_tree_findKey(&NSTable,&test);
        if (key) {
            if(pico_tree_delete(&NSTable,key)) {
            dns_dbg("DNS: default nameserver %08X removed\n", test.ns.addr);
            pico_free(key);
          } else {
            pico_err = PICO_ERR_EAGAIN;
            return -1;
          }
        }
      }
      break;

    case PICO_DNS_NS_DEL:
      test.ns = *ns;

      key = pico_tree_findKey(&NSTable,&test);
      if (!key) {
        dns_dbg("DNS WARNING: nameserver %08X not found\n", ns->addr);
        pico_err = PICO_ERR_EINVAL;
        return -1;
      }
      /* RB_REMOVE returns pointer to removed element, NULL to indicate error */

            if(pico_tree_delete(&NSTable,key)) {
        dns_dbg("DNS: nameserver %08X removed\n",key->ns.addr);
        pico_free(key);
      } else {
        pico_err = PICO_ERR_EAGAIN;
        return -1;
      }
      /* If no NS left, add default NS */
      if(pico_tree_first(&NSTable) == NULL){
        dns_dbg("DNS: add default nameserver\n");
        return pico_dns_client_init();
      }
      break;

    default:
      pico_err = PICO_ERR_EINVAL;
      return -1;
  }
  return 0;
}