void gnrc_netif_ipv6_addr_remove_internal(gnrc_netif_t *netif, const ipv6_addr_t *addr) { bool remove_sol_nodes = true; ipv6_addr_t sol_nodes; assert((netif != NULL) && (addr != NULL)); ipv6_addr_set_solicited_nodes(&sol_nodes, addr); gnrc_netif_acquire(netif); for (unsigned i = 0; i < GNRC_NETIF_IPV6_ADDRS_NUMOF; i++) { if (ipv6_addr_equal(&netif->ipv6.addrs[i], addr)) { netif->ipv6.addrs_flags[i] = 0; ipv6_addr_set_unspecified(&netif->ipv6.addrs[i]); } else { ipv6_addr_t tmp; ipv6_addr_set_solicited_nodes(&tmp, &netif->ipv6.addrs[i]); /* there is still an address on the interface with the same * solicited nodes address */ if (ipv6_addr_equal(&tmp, &sol_nodes)) { remove_sol_nodes = false; } } } if (remove_sol_nodes) { gnrc_netif_ipv6_group_leave_internal(netif, &sol_nodes); } gnrc_netif_release(netif); }
static void _remove_addr_from_entry(gnrc_ipv6_netif_t *entry, ipv6_addr_t *addr) { mutex_lock(&entry->mutex); for (int i = 0; i < GNRC_IPV6_NETIF_ADDR_NUMOF; i++) { if (ipv6_addr_equal(&(entry->addrs[i].addr), addr)) { DEBUG("ipv6 netif: Remove %s to interface %" PRIkernel_pid "\n", ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)), entry->pid); ipv6_addr_set_unspecified(&(entry->addrs[i].addr)); entry->addrs[i].flags = 0; #ifdef MODULE_GNRC_NDP_ROUTER /* Removal of prefixes MAY allow the router to retransmit up to * GNRC_NDP_MAX_INIT_RTR_ADV_NUMOF unsolicited RA * (see https://tools.ietf.org/html/rfc4861#section-6.2.4) */ if ((entry->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER) && (entry->flags & GNRC_IPV6_NETIF_FLAGS_RTR_ADV) && (!ipv6_addr_is_multicast(addr) && !ipv6_addr_is_link_local(addr))) { entry->rtr_adv_count = GNRC_NDP_MAX_INIT_RTR_ADV_NUMOF; mutex_unlock(&entry->mutex); /* function below relocks the mutex */ gnrc_ndp_router_retrans_rtr_adv(entry); return; } #endif mutex_unlock(&entry->mutex); return; } } mutex_unlock(&entry->mutex); }
void gnrc_ipv6_nc_remove(kernel_pid_t iface, const ipv6_addr_t *ipv6_addr) { gnrc_ipv6_nc_t *entry = gnrc_ipv6_nc_get(iface, ipv6_addr); if (entry != NULL) { DEBUG("ipv6_nc: Remove %s for interface %" PRIkernel_pid "\n", ipv6_addr_to_str(addr_str, ipv6_addr, sizeof(addr_str)), iface); #ifdef MODULE_GNRC_NDP_NODE while (entry->pkts != NULL) { gnrc_pktbuf_release(entry->pkts->pkt); entry->pkts->pkt = NULL; gnrc_pktqueue_remove_head(&entry->pkts); } #endif #ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER xtimer_remove(&entry->type_timeout); #endif #if defined(MODULE_GNRC_NDP_ROUTER) || defined(MODULE_GNRC_SIXLOWPAN_ND_BORDER_ROUTER) xtimer_remove(&entry->rtr_adv_timer); #endif ipv6_addr_set_unspecified(&(entry->ipv6_addr)); entry->iface = KERNEL_PID_UNDEF; entry->flags = 0; } }
void gnrc_netif_ipv6_group_leave_internal(gnrc_netif_t *netif, const ipv6_addr_t *addr) { int idx; assert((netif != NULL) && (addr != NULL)); gnrc_netif_acquire(netif); idx = _group_idx(netif, addr); if (idx >= 0) { ipv6_addr_set_unspecified(&netif->ipv6.groups[idx]); /* TODO: * - MLD action */ } gnrc_netif_release(netif); }
bool gnrc_conn6_set_local_addr(uint8_t *conn_addr, const ipv6_addr_t *addr) { ipv6_addr_t *tmp; if (!ipv6_addr_is_unspecified(addr) && !ipv6_addr_is_loopback(addr) && gnrc_ipv6_netif_find_by_addr(&tmp, addr) == KERNEL_PID_UNDEF) { return false; } else if (ipv6_addr_is_loopback(addr) || ipv6_addr_is_unspecified(addr)) { ipv6_addr_set_unspecified((ipv6_addr_t *)conn_addr); } else { memcpy(conn_addr, addr, sizeof(ipv6_addr_t)); } return true; }
static void _remove_addr_from_entry(gnrc_ipv6_netif_t *entry, ipv6_addr_t *addr) { mutex_lock(&entry->mutex); for (int i = 0; i < GNRC_IPV6_NETIF_ADDR_NUMOF; i++) { if (ipv6_addr_equal(&(entry->addrs[i].addr), addr)) { DEBUG("ipv6 netif: Remove %s to interface %" PRIkernel_pid "\n", ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)), entry->pid); ipv6_addr_set_unspecified(&(entry->addrs[i].addr)); entry->addrs[i].flags = 0; mutex_unlock(&entry->mutex); return; } } mutex_unlock(&entry->mutex); }
void gnrc_sixlowpan_nd_router_abr_remove(gnrc_sixlowpan_nd_router_abr_t *abr) { for (int i = 0; i < GNRC_SIXLOWPAN_CTX_SIZE; i++) { if (bf_isset(abr->ctxs, i)) { gnrc_sixlowpan_ctx_remove(i); bf_unset(abr->ctxs, i); } } while (abr->prfs != NULL) { gnrc_sixlowpan_nd_router_prf_t *prefix = abr->prfs; LL_DELETE(abr->prfs, prefix); gnrc_ipv6_netif_remove_addr(prefix->iface->pid, &prefix->prefix->addr); prefix->next = NULL; prefix->iface = NULL; prefix->prefix = NULL; } ipv6_addr_set_unspecified(&abr->addr); abr->version = 0; }
static void _nc_remove(kernel_pid_t iface, gnrc_ipv6_nc_t *entry) { (void) iface; if (entry == NULL) { return; } DEBUG("ipv6_nc: Remove %s for interface %" PRIkernel_pid "\n", ipv6_addr_to_str(addr_str, &(entry->ipv6_addr), sizeof(addr_str)), iface); #ifdef MODULE_GNRC_NDP_NODE while (entry->pkts != NULL) { gnrc_pktbuf_release(entry->pkts->pkt); entry->pkts->pkt = NULL; gnrc_pktqueue_remove_head(&entry->pkts); } #endif #ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER xtimer_remove(&entry->type_timeout); gnrc_ipv6_netif_t *if_entry = gnrc_ipv6_netif_get(iface); if ((if_entry != NULL) && (if_entry->rtr_adv_msg.content.ptr == (char *) entry)) { /* cancel timer set by gnrc_ndp_rtr_sol_handle */ xtimer_remove(&if_entry->rtr_adv_timer); } #endif #if defined(MODULE_GNRC_NDP_ROUTER) || defined(MODULE_GNRC_SIXLOWPAN_ND_BORDER_ROUTER) xtimer_remove(&entry->rtr_adv_timer); #endif xtimer_remove(&entry->rtr_timeout); xtimer_remove(&entry->nbr_sol_timer); xtimer_remove(&entry->nbr_adv_timer); ipv6_addr_set_unspecified(&(entry->ipv6_addr)); entry->iface = KERNEL_PID_UNDEF; entry->flags = 0; }
static int _implicit_bind(socket_t *s, void *addr) { ipv6_addr_t unspec; ipv6_addr_t *best_match; int res; /* TODO: ensure that this port hasn't been used yet */ s->src_port = (uint16_t)genrand_uint32_range(1LU << 10U, 1LU << 16U); /* find the best matching source address */ if ((best_match = conn_find_best_source(addr)) == NULL) { ipv6_addr_set_unspecified(&unspec); best_match = &unspec; } switch (s->type) { #ifdef MODULE_CONN_TCP case SOCK_STREAM: res = conn_tcp_create(&s->conn.udp, best_match, sizeof(unspec), s->domain, s->src_port); break; #endif #ifdef MODULE_CONN_UDP case SOCK_DGRAM: res = conn_udp_create(&s->conn.udp, best_match, sizeof(unspec), s->domain, s->src_port); break; #endif default: res = -1; break; } if (res < 0) { errno = -res; } else { s->bound = true; } return res; }
gnrc_sixlowpan_ctx_t *gnrc_sixlowpan_ctx_update(uint8_t id, const ipv6_addr_t *prefix, uint8_t prefix_len, uint16_t ltime, bool comp) { if ((id >= GNRC_SIXLOWPAN_CTX_SIZE) || (prefix_len == 0)) { return NULL; } mutex_lock(&_ctx_mutex); _ctxs[id].ltime = ltime; if (ltime == 0) { comp = false; } if (prefix_len > IPV6_ADDR_BIT_LEN) { _ctxs[id].prefix_len = IPV6_ADDR_BIT_LEN; } else { _ctxs[id].prefix_len = prefix_len; } _ctxs[id].flags_id = (comp) ? (GNRC_SIXLOWPAN_CTX_FLAGS_COMP | id) : id; if (!ipv6_addr_equal(&(_ctxs[id].prefix), prefix)) { ipv6_addr_set_unspecified(&(_ctxs[id].prefix)); ipv6_addr_init_prefix(&(_ctxs[id].prefix), prefix, _ctxs[id].prefix_len); } DEBUG("6lo ctx: update context (%u, %s/%" PRIu8 "), lifetime: %" PRIu16 " min\n", id, ipv6_addr_to_str(ipv6str, &_ctxs[id].prefix, sizeof(ipv6str)), _ctxs[id].prefix_len, _ctxs[id].ltime); _ctx_inval_times[id] = ltime + _current_minute(); mutex_unlock(&_ctx_mutex); return &(_ctxs[id]); }
/** * @brief Transition from current FSM state into another state. * * @param[in,out] tcb TCB holding the FSM state. * @param[in] state State to transition in. * * @return Zero on success. */ static int _transition_to(gnrc_tcp_tcb_t *tcb, fsm_state_t state) { DEBUG("_transition_to: %d\n", state); gnrc_tcp_tcb_t *iter = NULL; switch (state) { case FSM_STATE_CLOSED: /* Clear retransmit queue */ _clear_retransmit(tcb); /* Remove connection from active connections */ mutex_lock(&_list_tcb_lock); LL_DELETE(_list_tcb_head, tcb); mutex_unlock(&_list_tcb_lock); /* Free potencially allocated receive buffer */ _rcvbuf_release_buffer(tcb); tcb->status |= STATUS_NOTIFY_USER; break; case FSM_STATE_LISTEN: /* Clear address info */ #ifdef MODULE_GNRC_IPV6 if (tcb->address_family == AF_INET6) { if (tcb->status & STATUS_ALLOW_ANY_ADDR) { ipv6_addr_set_unspecified((ipv6_addr_t *) tcb->local_addr); } ipv6_addr_set_unspecified((ipv6_addr_t *) tcb->peer_addr); } #endif tcb->peer_port = PORT_UNSPEC; /* Allocate receive buffer */ if (_rcvbuf_get_buffer(tcb) == -ENOMEM) { return -ENOMEM; } /* Add connection to active connections (if not already active) */ mutex_lock(&_list_tcb_lock); LL_SEARCH(_list_tcb_head, iter, tcb, TCB_EQUAL); if (iter == NULL) { LL_PREPEND(_list_tcb_head, tcb); } mutex_unlock(&_list_tcb_lock); break; case FSM_STATE_SYN_SENT: /* Allocate rceveive buffer */ if (_rcvbuf_get_buffer(tcb) == -ENOMEM) { return -ENOMEM; } /* Add connection to active connections (if not already active) */ mutex_lock(&_list_tcb_lock); LL_SEARCH(_list_tcb_head, iter, tcb, TCB_EQUAL); /* If connection is not already active: Check port number, append TCB */ if (iter == NULL) { /* Check if port number was specified */ if (tcb->local_port != PORT_UNSPEC) { /* Check if given port number is use: return error and release buffer */ if (_is_local_port_in_use(tcb->local_port)) { mutex_unlock(&_list_tcb_lock); _rcvbuf_release_buffer(tcb); return -EADDRINUSE; } } /* Pick random port */ else { tcb->local_port = _get_random_local_port(); } LL_PREPEND(_list_tcb_head, tcb); } mutex_unlock(&_list_tcb_lock); break; case FSM_STATE_SYN_RCVD: case FSM_STATE_ESTABLISHED: case FSM_STATE_CLOSE_WAIT: tcb->status |= STATUS_NOTIFY_USER; break; case FSM_STATE_TIME_WAIT: _restart_timewait_timer(tcb); break; default: break; } tcb->state = state; return 0; }