예제 #1
0
coap_async_state_t *
coap_find_async(coap_context_t *context, coap_tid_t id)
{
    coap_async_state_t *tmp;
    LL_SEARCH_SCALAR(context->async_state, tmp, id, id);
    return tmp;
}
예제 #2
0
파일: ng_udp.c 프로젝트: anishkt/RIOT
static void _send(ng_pktsnip_t *pkt)
{
    ng_udp_hdr_t *hdr;
    ng_pktsnip_t *udp_snip;
    ng_netreg_entry_t *sendto;

    /* get udp snip and hdr */
    LL_SEARCH_SCALAR(pkt, udp_snip, type, NG_NETTYPE_UDP);
    udp_snip = ng_pktbuf_start_write(udp_snip);
    if (udp_snip == NULL) {
        DEBUG("udp: cannot send packet: unable to allocate packet\n");
        ng_pktbuf_release(pkt);
        return;
    }
    hdr = (ng_udp_hdr_t *)udp_snip->data;
    /* fill in size field */
    hdr->length = byteorder_htons(ng_pkt_len(udp_snip));

    /* and forward packet to the network layer */
    sendto = ng_netreg_lookup(pkt->type, NG_NETREG_DEMUX_CTX_ALL);
    /* throw away packet if no one is interested */
    if (sendto == NULL) {
        DEBUG("udp: cannot send packet: network layer not found\n");
        ng_pktbuf_release(pkt);
        return;
    }
    /* send packet to network layer */
    ng_pktbuf_hold(pkt, ng_netreg_num(pkt->type, NG_NETREG_DEMUX_CTX_ALL) - 1);
    while (sendto != NULL) {
        ng_netapi_send(sendto->pid, pkt);
        sendto = ng_netreg_getnext(sendto);
    }
}
예제 #3
0
파일: gnrc_conn.c 프로젝트: herrfz/RIOT
int gnrc_conn_recvfrom(conn_t *conn, void *data, size_t max_len, void *addr, size_t *addr_len,
                       uint16_t *port)
{
    msg_t msg;
    int timeout = 3;
    while ((timeout--) > 0) {
        gnrc_pktsnip_t *pkt, *l3hdr;
        size_t size = 0;
        msg_receive(&msg);
        switch (msg.type) {
            case GNRC_NETAPI_MSG_TYPE_RCV:
                pkt = (gnrc_pktsnip_t *)msg.content.ptr;
                if (pkt->size > max_len) {
                    return -ENOMEM;
                }
                LL_SEARCH_SCALAR(pkt, l3hdr, type, conn->l3_type);
                if (l3hdr == NULL) {
                    msg_send_to_self(&msg); /* requeue invalid messages */
                    continue;
                }
#if defined(MODULE_CONN_UDP) || defined(MODULE_CONN_TCP)
                if ((conn->l4_type != GNRC_NETTYPE_UNDEF) && (port != NULL)) {
                    gnrc_pktsnip_t *l4hdr;
                    LL_SEARCH_SCALAR(pkt, l4hdr, type, conn->l4_type);
                    if (l4hdr == NULL) {
                        msg_send_to_self(&msg); /* requeue invalid messages */
                        continue;
                    }
                    *port = byteorder_ntohs(((udp_hdr_t *)l4hdr->data)->src_port);
                }
#endif  /* defined(MODULE_CONN_UDP) */
                if (addr != NULL) {
                    memcpy(addr, &((ipv6_hdr_t *)l3hdr->data)->src, sizeof(ipv6_addr_t));
                    *addr_len = sizeof(ipv6_addr_t);
                }
                memcpy(data, pkt->data, pkt->size);
                size = pkt->size;
                gnrc_pktbuf_release(pkt);
                return (int)size;
            default:
                (void)port;
                msg_send_to_self(&msg); /* requeue invalid messages */
                break;
        }
    }
    return -ETIMEDOUT;
}
예제 #4
0
gnrc_netreg_entry_t *gnrc_netreg_lookup(gnrc_nettype_t type, uint32_t demux_ctx)
{
    gnrc_netreg_entry_t *res;

    if (_INVALID_TYPE(type)) {
        return NULL;
    }

    LL_SEARCH_SCALAR(netreg[type], res, demux_ctx, demux_ctx);

    return res;
}
예제 #5
0
파일: test42.c 프로젝트: bitfixer/bitfixer
int main() {
    int i;
    el els[10], *e, *tmp, *tmp2;
    for(i=0;i<10;i++) els[i].id='a'+i;

    /* test LL macros */
    printf("LL macros\n");
    LL_APPEND(head,&els[0]);
    LL_APPEND(head,&els[1]);
    LL_APPEND(head,&els[2]);
    LL_FOREACH(head,e)
        printf("%c ", e->id);
    printf("\n");
    LL_SEARCH_SCALAR(head, e, id, 'b');
    if (e) printf("search scalar found b\n");
    LL_SEARCH(head, e, &els[0], eltcmp);
    if (e) printf("search found %c\n",e->id);
    LL_FOREACH_SAFE(head,e,tmp) LL_DELETE(head,e);

    printf("\n");

    /* test DL macros */
    printf("DL macros\n");
    DL_APPEND(head,&els[0]);
    DL_APPEND(head,&els[1]);
    DL_APPEND(head,&els[2]);
    DL_FOREACH(head,e)
        printf("%c ", e->id);
    printf("\n");
    DL_SEARCH_SCALAR(head, e, id, 'b');
    if (e) printf("search scalar found b\n");
    DL_SEARCH(head, e, &els[0], eltcmp);
    if (e) printf("search found %c\n",e->id);
    DL_FOREACH_SAFE(head,e,tmp) DL_DELETE(head,e);
    printf("\n");

    /* test CDL macros */
    printf("CDL macros\n");
    CDL_PREPEND(head,&els[0]);
    CDL_PREPEND(head,&els[1]);
    CDL_PREPEND(head,&els[2]);
    CDL_FOREACH(head,e)
        printf("%c ", e->id);
    printf("\n");
    CDL_SEARCH_SCALAR(head, e, id, 'b');
    if (e) printf("search scalar found b\n");
    CDL_SEARCH(head, e, &els[0], eltcmp);
    if (e) printf("search found %c\n",e->id);
    CDL_FOREACH_SAFE(head,e,tmp,tmp2) CDL_DELETE(head,e);


    return 0;
}
예제 #6
0
coap_async_state_t *
coap_register_async(coap_context_t *context, coap_address_t *peer, coap_pdu_t *request,
        unsigned char flags, void *data)
{
    coap_async_state_t *s;
    coap_tid_t id;

    coap_transaction_id(peer, request, &id);
    LL_SEARCH_SCALAR(context->async_state, s, id, id);

    if (s != NULL)
    {
        /* We must return NULL here as the caller must know that he is
         * responsible for releasing @p data. */
        debug("asynchronous state for transaction %d already registered\n", id);
        return NULL;
    }

    /* store information for handling the asynchronous task */
    s = (coap_async_state_t *) coap_malloc(sizeof(coap_async_state_t) +
            request->hdr->token_length);
    if (!s)
    {
        coap_log(LOG_CRIT, "coap_register_async: insufficient memory\n");
        return NULL;
    }

    memset(s, 0, sizeof(coap_async_state_t) + request->hdr->token_length);

    /* set COAP_ASYNC_CONFIRM according to request's type */
    s->flags = flags & ~COAP_ASYNC_CONFIRM;
    if (request->hdr->type == COAP_MESSAGE_CON)
        s->flags |= COAP_ASYNC_CONFIRM;

    s->appdata = data;

    memcpy(&s->peer, peer, sizeof(coap_address_t));

    if (request->hdr->token_length)
    {
        s->tokenlen = request->hdr->token_length;
        memcpy(s->token, request->hdr->token, request->hdr->token_length);
    }

    memcpy(&s->id, &id, sizeof(coap_tid_t));

    coap_touch_async(s);

    LL_PREPEND(context->async_state, s);

    return s;
}
예제 #7
0
파일: ng_udp.c 프로젝트: phiros/testci
static void _receive(ng_pktsnip_t *pkt)
{
    ng_pktsnip_t *udp, *ipv6;
    ng_udp_hdr_t *hdr;
    uint32_t port;
    ng_netreg_entry_t *sendto;

    /* mark UDP header */
    udp = ng_pktbuf_start_write(pkt);
    if (udp == NULL) {
        DEBUG("udp: unable to get write access to packet\n");
        ng_pktbuf_release(pkt);
        return;
    }
    pkt = udp;
    udp = ng_pktbuf_add(pkt, pkt->data, sizeof(ng_udp_hdr_t), NG_NETTYPE_UDP);
    if (udp == NULL) {
        DEBUG("udp: error marking UDP header, dropping packet\n");
        ng_pktbuf_release(pkt);
        return;
    }
    /* mark payload as Type: UNDEF */
    pkt->type = NG_NETTYPE_UNDEF;
    /* get explicit pointer to UDP header */
    hdr = (ng_udp_hdr_t *)udp->data;

    LL_SEARCH_SCALAR(pkt, ipv6, type, NG_NETTYPE_IPV6);

    /* validate checksum */
    if (_calc_csum(udp, ipv6, pkt)) {
        DEBUG("udp: received packet with invalid checksum, dropping it\n");
        ng_pktbuf_release(pkt);
        return;
    }

    /* get port (netreg demux context) */
    port = (uint32_t)byteorder_ntohs(hdr->dst_port);

    /* send payload to receivers */
    sendto = ng_netreg_lookup(NG_NETTYPE_UDP, port);
    if (sendto == NULL) {
        DEBUG("udp: unable to forward packet as no one is interested in it\n");
        ng_pktbuf_release(pkt);
        return;
    }
    ng_pktbuf_hold(pkt, ng_netreg_num(NG_NETTYPE_UDP, port) - 1);
    while (sendto != NULL) {
        ng_netapi_receive(sendto->pid, pkt);
        sendto = ng_netreg_getnext(sendto);
    }
}
예제 #8
0
gnrc_netreg_entry_t *gnrc_netreg_getnext(gnrc_netreg_entry_t *entry)
{
    uint32_t demux_ctx;

    if (entry == NULL) {
        return NULL;
    }

    demux_ctx = entry->demux_ctx;

    LL_SEARCH_SCALAR(entry->next, entry, demux_ctx, demux_ctx);

    return entry;
}
예제 #9
0
파일: gnrc_rpl.c 프로젝트: hexanoid/polymcu
static void _receive(gnrc_pktsnip_t *icmpv6)
{
    gnrc_pktsnip_t *ipv6 = NULL;
    ipv6_hdr_t *ipv6_hdr = NULL;
    icmpv6_hdr_t *icmpv6_hdr = NULL;

    LL_SEARCH_SCALAR(icmpv6, ipv6, type, GNRC_NETTYPE_IPV6);

    assert(ipv6 != NULL);

    ipv6_hdr = (ipv6_hdr_t *)ipv6->data;

    icmpv6_hdr = (icmpv6_hdr_t *)icmpv6->data;
    switch (icmpv6_hdr->code) {
        case GNRC_RPL_ICMPV6_CODE_DIS:
            DEBUG("RPL: DIS received\n");
            gnrc_rpl_recv_DIS((gnrc_rpl_dis_t *)(icmpv6_hdr + 1), &ipv6_hdr->src, &ipv6_hdr->dst,
                    byteorder_ntohs(ipv6_hdr->len));
            break;
        case GNRC_RPL_ICMPV6_CODE_DIO:
            DEBUG("RPL: DIO received\n");
            gnrc_rpl_recv_DIO((gnrc_rpl_dio_t *)(icmpv6_hdr + 1), &ipv6_hdr->src,
                    byteorder_ntohs(ipv6_hdr->len));
            break;
        case GNRC_RPL_ICMPV6_CODE_DAO:
            DEBUG("RPL: DAO received\n");
            gnrc_rpl_recv_DAO((gnrc_rpl_dao_t *)(icmpv6_hdr + 1), &ipv6_hdr->src,
                    byteorder_ntohs(ipv6_hdr->len));
            break;
        case GNRC_RPL_ICMPV6_CODE_DAO_ACK:
            DEBUG("RPL: DAO-ACK received\n");
            gnrc_rpl_recv_DAO_ACK((gnrc_rpl_dao_ack_t *)(icmpv6_hdr + 1),
                    byteorder_ntohs(ipv6_hdr->len));
            break;
        default:
            DEBUG("RPL: Unknown ICMPV6 code received\n");
            break;
    }

    gnrc_pktbuf_release(icmpv6);
}
예제 #10
0
gnrc_pktsnip_t *gnrc_ipv6_ext_build(gnrc_pktsnip_t *ipv6, gnrc_pktsnip_t *next,
                                    uint8_t nh, size_t size)
{
    gnrc_pktsnip_t *prev = NULL, *snip;
    ipv6_ext_t *ext;

    if (size < IPV6_EXT_LEN_UNIT) {
        return NULL;
    }

    if (ipv6 != NULL) {
        LL_SEARCH_SCALAR(ipv6, prev, next, next);

        if (prev == NULL) {
            return NULL;
        }
    }

    snip = gnrc_pktbuf_add(next, NULL, size, GNRC_NETTYPE_IPV6);

    if (snip == NULL) {
        return NULL;
    }

    ext = snip->data;

    ext->nh = nh;

    if (size & 0x7) { /* not divisible by eight */
        ext->len = (size / IPV6_EXT_LEN_UNIT);
    }
    else {
        ext->len = (size / IPV6_EXT_LEN_UNIT) - 1;
    }

    if (prev != NULL) {
        prev->next = snip;
    }

    return snip;
}
예제 #11
0
파일: async.c 프로젝트: drashti304/TizenRT
coap_async_state_t *coap_register_async(coap_context_t *context, coap_address_t *peer, coap_pdu_t *request, unsigned char flags, void *data)
{
	coap_async_state_t *s;
	coap_tid_t id;

	coap_transport_t transport = COAP_UDP;

	unsigned char *token;
	unsigned int token_len = 0;

	switch(context->protocol) {
	case COAP_PROTO_UDP:
	case COAP_PROTO_DTLS:
		transport = COAP_UDP;
		break;
	case COAP_PROTO_TCP:
	case COAP_PROTO_TLS:
		transport = coap_get_tcp_header_type_from_initbyte(((unsigned char *)request->transport_hdr)[0] >> 4);
		break;
	default:
		break;
	}

	coap_transaction_id2(peer, request, &id, context->protocol);
	LL_SEARCH_SCALAR(context->async_state, s, id, id);

	coap_get_token2(request->transport_hdr, transport, &token, &token_len);

	if (token_len > 8) {
		debug("coap_register_async : invalied length of token\n");
		return NULL;
	}

	if (s != NULL) {
		/* We must return NULL here as the caller must know that he is
		 * responsible for releasing @p data. */
		debug("coap_register_async : asynchronous state for transaction %d already registered\n", id);
		return NULL;
	}

	/* store information for handling the asynchronous task */
	s = (coap_async_state_t *)coap_malloc(sizeof(coap_async_state_t) + token_len);
	if (!s) {
		coap_log(LOG_CRIT, "coap_register_async : insufficient memory\n");
		return NULL;
	}

	memset(s, 0, sizeof(coap_async_state_t) + token_len);

	/* set COAP_ASYNC_CONFIRM according to request's type */
	s->flags = flags & ~COAP_ASYNC_CONFIRM;
	if (context->protocol == COAP_PROTO_UDP || context->protocol == COAP_PROTO_TCP) {
		if (request->transport_hdr->udp.type == COAP_MESSAGE_CON) {
			s->flags |= COAP_ASYNC_CONFIRM;
		}
	}

	s->appdata = data;

	memcpy(&s->peer, peer, sizeof(coap_address_t));

	if (token_len) {
		s->tokenlen = token_len;
		memcpy(s->token, token, token_len);
	}

	memcpy(&s->id, &id, sizeof(coap_tid_t));

	coap_touch_async(s);

	LL_PREPEND(context->async_state, s);

	return s;
}
예제 #12
0
파일: gnrc_tcp_fsm.c 프로젝트: A-Paul/RIOT
/**
 * @brief FSM handling function for processing of an incomming TCP packet.
 *
 * @param[in,out] tcb      TCB holding the connection information.
 * @param[in]     in_pkt   Incomming packet.
 *
 * @returns   Zero on success.
 *            -ENOMEM if receive buffer could not be allocated.
 */
static int _fsm_rcvd_pkt(gnrc_tcp_tcb_t *tcb, gnrc_pktsnip_t *in_pkt)
{
    gnrc_pktsnip_t *out_pkt = NULL;  /* Outgoing packet */
    uint16_t seq_con = 0;            /* Sequence number consumption of outgoing packet */
    gnrc_pktsnip_t *snp = NULL;      /* Temporary packet snip */
    gnrc_tcp_tcb_t *lst = NULL;      /* Temporary pointer to TCB */
    uint16_t ctl = 0;                /* Control bits of the incomming packet */
    uint32_t seg_seq = 0;            /* Sequence number of the incomming packet*/
    uint32_t seg_ack = 0;            /* Acknowledgment number of the incomming packet */
    uint32_t seg_wnd = 0;            /* Receive window of the incomming packet */
    uint32_t seg_len = 0;            /* Segment length of the incomming packet */
    uint32_t pay_len = 0;            /* Payload length of the incomming packet */

    DEBUG("gnrc_tcp_fsm.c : _fsm_rcvd_pkt()\n");
    /* Search for TCP header. */
    LL_SEARCH_SCALAR(in_pkt, snp, type, GNRC_NETTYPE_TCP);
    tcp_hdr_t *tcp_hdr = (tcp_hdr_t *) snp->data;

    /* Parse packet options, return if they are malformed */
    if (_option_parse(tcb, tcp_hdr) < 0) {
        return 0;
    }

    /* Extract header values */
    ctl = byteorder_ntohs(tcp_hdr->off_ctl);
    seg_seq = byteorder_ntohl(tcp_hdr->seq_num);
    seg_ack = byteorder_ntohl(tcp_hdr->ack_num);
    seg_wnd = byteorder_ntohs(tcp_hdr->window);

    /* Extract network layer header */
#ifdef MODULE_GNRC_IPV6
    LL_SEARCH_SCALAR(in_pkt, snp, type, GNRC_NETTYPE_IPV6);
    if (snp == NULL) {
        DEBUG("gnrc_tcp_fsm.c : _fsm_rcvd_pkt() : incomming packet had no IPv6 header\n");
        return 0;
    }
    void *ip = snp->data;
#endif

    /* Handle state LISTEN */
    if (tcb->state == FSM_STATE_LISTEN) {
        /* 1) Check RST: if RST is set: return */
        if (ctl & MSK_RST) {
            return 0;
        }
        /* 2) Check ACK: if ACK is set: send RST with seq_no = ack_no and return */
        if (ctl & MSK_ACK) {
            _pkt_build_reset_from_pkt(&out_pkt, in_pkt);
            _pkt_send(tcb, out_pkt, 0, false);
            return 0;
        }
        /* 3) Check SYN: if SYN is set prepare for incomming connection */
        if (ctl & MSK_SYN) {
            uint16_t src = byteorder_ntohs(tcp_hdr->src_port);
            uint16_t dst = byteorder_ntohs(tcp_hdr->dst_port);

            /* Check if SYN request is handled by another connection */
            lst = _list_tcb_head;
            while (lst) {
                /* Compare port numbers and network layer adresses */
                if (lst->local_port == dst && lst->peer_port == src) {
#ifdef MODULE_GNRC_IPV6
                    if (snp->type == GNRC_NETTYPE_IPV6 && lst->address_family == AF_INET6) {
                        ipv6_addr_t *dst_addr = &((ipv6_hdr_t *)ip)->dst;
                        ipv6_addr_t *src_addr = &((ipv6_hdr_t *)ip)->src;

                        if (ipv6_addr_equal((ipv6_addr_t *)lst->local_addr, dst_addr) &&
                            ipv6_addr_equal((ipv6_addr_t *)lst->peer_addr, src_addr)) {
                            break;
                        }
                    }
#endif
                }
                lst = lst->next;
            }
            /* Return if connection is already handled (port and addresses match) */
            if (lst != NULL) {
                DEBUG("gnrc_tcp_fsm.c : _fsm_rcvd_pkt() : Connection already handled\n");
                return 0;
            }

            /* SYN request is valid, fill TCB with connection information */
#ifdef MODULE_GNRC_IPV6
            if (snp->type == GNRC_NETTYPE_IPV6 && tcb->address_family == AF_INET6) {
                memcpy(tcb->local_addr, &((ipv6_hdr_t *)ip)->dst, sizeof(ipv6_addr_t));
                memcpy(tcb->peer_addr, &((ipv6_hdr_t *)ip)->src, sizeof(ipv6_addr_t));

                /* In case peer_addr is link local: Store interface Id in tcb */
                if (ipv6_addr_is_link_local((ipv6_addr_t *) tcb->peer_addr)) {
                    gnrc_pktsnip_t *tmp = NULL;
                    LL_SEARCH_SCALAR(in_pkt, tmp, type, GNRC_NETTYPE_NETIF);
                    /* cppcheck-suppress knownConditionTrueFalse
                     * (reason: tmp *can* be != NULL after LL_SEARCH_SCALAR) */
                    if (tmp == NULL) {
                        DEBUG("gnrc_tcp_fsm.c : _fsm_rcvd_pkt() :\
                               incomming packet had no netif header\n");
                        return 0;
                    }
                    tcb->ll_iface = ((gnrc_netif_hdr_t *)tmp->data)->if_pid;
                }
예제 #13
0
파일: ng_icmpv6.c 프로젝트: 4dahalibut/RIOT
void ng_icmpv6_demux(kernel_pid_t iface, ng_pktsnip_t *pkt)
{
    ng_pktsnip_t *icmpv6, *ipv6;
    ng_icmpv6_hdr_t *hdr;
    ng_netreg_entry_t *sendto;

    LL_SEARCH_SCALAR(pkt, icmpv6, type, NG_NETTYPE_ICMPV6);

    /* there can be extension headers between IPv6 and ICMPv6 header so we have
     * to search it */
    LL_SEARCH_SCALAR(icmpv6, ipv6, type, NG_NETTYPE_IPV6);

    hdr = (ng_icmpv6_hdr_t *)icmpv6->data;

    if (_calc_csum(icmpv6, ipv6, pkt)) {
        DEBUG("icmpv6: wrong checksum.\n");
        /* don't release: IPv6 does this */
        return;
    }

    switch (hdr->type) {
        /* TODO: handle ICMPv6 errors */
#ifdef MODULE_NG_ICMPV6_ECHO
        case NG_ICMPV6_ECHO_REQ:
            DEBUG("icmpv6: handle echo request.\n");
            ng_icmpv6_echo_req_handle(iface, (ng_ipv6_hdr_t *)ipv6->data,
                                      (ng_icmpv6_echo_t *)hdr, icmpv6->size);
            break;
#endif

        case NG_ICMPV6_RTR_SOL:
            DEBUG("icmpv6: router solicitation received\n");
            /* TODO */
            break;

        case NG_ICMPV6_RTR_ADV:
            DEBUG("icmpv6: router advertisement received\n");
            /* TODO */
            break;

        case NG_ICMPV6_NBR_SOL:
            DEBUG("icmpv6: neighbor solicitation received\n");
            ng_ndp_nbr_sol_handle(iface, pkt, ipv6->data, (ng_ndp_nbr_sol_t *)hdr,
                                  icmpv6->size);
            break;

        case NG_ICMPV6_NBR_ADV:
            DEBUG("icmpv6: neighbor advertisement received\n");
            ng_ndp_nbr_adv_handle(iface, pkt, ipv6->data, (ng_ndp_nbr_adv_t *)hdr,
                                  icmpv6->size);
            break;

        case NG_ICMPV6_REDIRECT:
            DEBUG("icmpv6: redirect message received\n");
            /* TODO */
            break;

#ifdef MODULE_NG_RPL
        case NG_ICMPV6_RPL_CTRL:
            DEBUG("icmpv6: RPL control message received\n");
            /* TODO */
            break;
#endif

        default:
            DEBUG("icmpv6: unknown type field %" PRIu8 "\n", hdr->type);
            break;
    }

    /* ICMPv6-all will be send in ng_ipv6.c so only dispatch of subtypes is
     * needed */

    sendto = ng_netreg_lookup(NG_NETTYPE_ICMPV6, hdr->type);

    if (sendto == NULL) {
        DEBUG("icmpv6: no receivers for ICMPv6 type %" PRIu8 "\n", hdr->type);
        /* don't release: IPv6 does this */
        return;
    }

    /* ICMPv6 is not interested anymore so `- 1` */
    ng_pktbuf_hold(pkt, ng_netreg_num(NG_NETTYPE_ICMPV6, hdr->type));

    while (sendto != NULL) {
        ng_netapi_receive(sendto->pid, pkt);
        sendto = ng_netreg_getnext(sendto);
    }
}
예제 #14
0
파일: ng_ndp.c 프로젝트: tuyenth/RIOT
void ng_ndp_nbr_adv_handle(kernel_pid_t iface, ng_pktsnip_t *pkt,
                           ng_ipv6_hdr_t *ipv6, ng_ndp_nbr_adv_t *nbr_adv,
                           size_t icmpv6_size)
{
    uint16_t opt_offset = 0;
    uint8_t *buf = ((uint8_t *)nbr_adv) + sizeof(ng_ndp_nbr_adv_t);
    int l2tgt_len = 0;
    uint8_t l2tgt[NG_IPV6_NC_L2_ADDR_MAX];
    int sicmpv6_size = (int)icmpv6_size;
    ng_ipv6_nc_t *nc_entry = ng_ipv6_nc_get(iface, &nbr_adv->tgt);
    ng_pktsnip_t *netif;
    ng_netif_hdr_t *netif_hdr = NULL;

    DEBUG("ndp: received neighbor advertisement (src: %s, ",
          ng_ipv6_addr_to_str(addr_str, &ipv6->src, sizeof(addr_str)));
    DEBUG("dst: %s, ",
          ng_ipv6_addr_to_str(addr_str, &ipv6->dst, sizeof(addr_str)));
    DEBUG("tgt: %s)\n",
          ng_ipv6_addr_to_str(addr_str, &nbr_adv->tgt, sizeof(addr_str)));

    /* check validity */
    if ((ipv6->hl != 255) || (nbr_adv->code != 0) ||
        (icmpv6_size < sizeof(ng_ndp_nbr_adv_t)) ||
        ng_ipv6_addr_is_multicast(&nbr_adv->tgt)) {
        DEBUG("ndp: neighbor advertisement was invalid.\n");
        /* ipv6 releases */
        return;
    }

    if (nc_entry == NULL) {
        /* see https://tools.ietf.org/html/rfc4861#section-7.2.5 */
        DEBUG("ndp: no neighbor cache entry found for advertisement's target\n");
        /* ipv6 releases */
        return;
    }

    sicmpv6_size -= sizeof(ng_ndp_nbr_adv_t);

    while (sicmpv6_size > 0) {
        ng_ndp_opt_t *opt = (ng_ndp_opt_t *)(buf + opt_offset);

        switch (opt->type) {
            case NG_NDP_OPT_TL2A:
                if ((l2tgt_len = _handle_tl2a_opt(pkt, ipv6, nbr_adv->type, opt,
                                                  l2tgt)) < 0) {
                    /* invalid target link-layer address option */
                    return;
                }

                break;

            default:
                /* silently discard all other options */
                break;
        }

        opt_offset += (opt->len * 8);
        sicmpv6_size -= (opt->len * 8);
    }

    LL_SEARCH_SCALAR(pkt, netif, type, NG_NETTYPE_NETIF);

    if (netif != NULL) {
        netif_hdr = netif->data;
    }

    if (ng_ipv6_nc_get_state(nc_entry) == NG_IPV6_NC_STATE_INCOMPLETE) {
        ng_pktqueue_t *queued_pkt;

        if (_pkt_has_l2addr(netif_hdr) && (l2tgt_len == 0)) {
            /* link-layer has addresses, but no TLLAO supplied: discard silently
             * (see https://tools.ietf.org/html/rfc4861#section-7.2.5) */
            return;
        }

        nc_entry->iface = iface;
        nc_entry->l2_addr_len = l2tgt_len;
        memcpy(nc_entry->l2_addr, l2tgt, l2tgt_len);

        if (nbr_adv->flags & NG_NDP_NBR_ADV_FLAGS_S) {
            _set_state(nc_entry, NG_IPV6_NC_STATE_REACHABLE);
        }
        else {
            _set_state(nc_entry, NG_IPV6_NC_STATE_STALE);
        }

        if (nbr_adv->flags & NG_NDP_NBR_ADV_FLAGS_R) {
            nc_entry->flags |= NG_IPV6_NC_IS_ROUTER;
        }
        else {
            nc_entry->flags &= ~NG_IPV6_NC_IS_ROUTER;
            /* TODO: update FIB */
        }

        while ((queued_pkt = ng_pktqueue_remove_head(&nc_entry->pkts)) != NULL) {
            ng_netapi_send(ng_ipv6_pid, queued_pkt->pkt);
            queued_pkt->pkt = NULL;
        }
    }
    else {
        /* first or-term: no link-layer, but nc_entry has l2addr,
         * second or-term: different l2addr cached */
        bool l2tgt_changed = false;

        if ((!_pkt_has_l2addr(netif_hdr)) && (l2tgt_len == 0)) {
            /* there was previously a L2 address registered */
            l2tgt_changed = (nc_entry->l2_addr_len != 0);
        }
        /* link-layer has addresses and TLLAO with different address */
        else if (_pkt_has_l2addr(netif_hdr) && (l2tgt_len != 0)) {
            l2tgt_changed = (!(l2tgt_len == nc_entry->l2_addr_len)) &&
                            (memcmp(nc_entry->l2_addr, l2tgt, l2tgt_len) == 0);
        }

        if ((nbr_adv->flags & NG_NDP_NBR_ADV_FLAGS_O) || !l2tgt_changed ||
            (l2tgt_len == 0)) {
            if (l2tgt_len != 0) {
                nc_entry->iface = iface;
                nc_entry->l2_addr_len = l2tgt_len;
                memcpy(nc_entry->l2_addr, l2tgt, l2tgt_len);
            }

            if (nbr_adv->flags & NG_NDP_NBR_ADV_FLAGS_S) {
                _set_state(nc_entry, NG_IPV6_NC_STATE_REACHABLE);
            }
            else if (l2tgt_changed && (l2tgt_len != 0)) {
                _set_state(nc_entry, NG_IPV6_NC_STATE_STALE);
            }

            if (nbr_adv->flags & NG_NDP_NBR_ADV_FLAGS_R) {
                nc_entry->flags |= NG_IPV6_NC_IS_ROUTER;
            }
            else {
                nc_entry->flags &= ~NG_IPV6_NC_IS_ROUTER;
                /* TODO: update FIB */
            }
        }
        else if (l2tgt_changed) {
            if (ng_ipv6_nc_get_state(nc_entry) == NG_IPV6_NC_STATE_REACHABLE) {
                _set_state(nc_entry, NG_IPV6_NC_STATE_STALE);

            }
        }
    }

    return;
}
예제 #15
0
파일: gnrc_ndp.c 프로젝트: Otmane123/RIOT
void gnrc_ndp_nbr_adv_handle(kernel_pid_t iface, gnrc_pktsnip_t *pkt,
                             ipv6_hdr_t *ipv6, ndp_nbr_adv_t *nbr_adv,
                             size_t icmpv6_size)
{
    uint16_t opt_offset = 0;
    uint8_t *buf = ((uint8_t *)nbr_adv) + sizeof(ndp_nbr_adv_t);
    int l2tgt_len = 0;
    uint8_t l2tgt[GNRC_IPV6_NC_L2_ADDR_MAX];
    int sicmpv6_size = (int)icmpv6_size;
    gnrc_ipv6_nc_t *nc_entry = gnrc_ipv6_nc_get(iface, &nbr_adv->tgt);
    gnrc_pktsnip_t *netif;
    gnrc_netif_hdr_t *netif_hdr = NULL;

    DEBUG("ndp: received neighbor advertisement (src: %s, ",
          ipv6_addr_to_str(addr_str, &ipv6->src, sizeof(addr_str)));
    DEBUG("dst: %s, ",
          ipv6_addr_to_str(addr_str, &ipv6->dst, sizeof(addr_str)));
    DEBUG("tgt: %s)\n",
          ipv6_addr_to_str(addr_str, &nbr_adv->tgt, sizeof(addr_str)));

    /* check validity */
    if ((ipv6->hl != 255) || (nbr_adv->code != 0) ||
        (icmpv6_size < sizeof(ndp_nbr_adv_t)) ||
        ipv6_addr_is_multicast(&nbr_adv->tgt)) {
        DEBUG("ndp: neighbor advertisement was invalid.\n");
        /* ipv6 releases */
        return;
    }

    if (nc_entry == NULL) {
        /* see https://tools.ietf.org/html/rfc4861#section-7.2.5 */
        DEBUG("ndp: no neighbor cache entry found for advertisement's target\n");
        /* ipv6 releases */
        return;
    }

    sicmpv6_size -= sizeof(ndp_nbr_adv_t);

    while (sicmpv6_size > 0) {
        ndp_opt_t *opt = (ndp_opt_t *)(buf + opt_offset);

        switch (opt->type) {
            case NDP_OPT_TL2A:
                if ((l2tgt_len = gnrc_ndp_internal_tl2a_opt_handle(pkt, ipv6, nbr_adv->type, opt, l2tgt)) < 0) {
                    /* invalid target link-layer address option */
                    return;
                }
                break;
#ifdef MODULE_GNRC_SIXLOWPAN_ND
            case NDP_OPT_AR:
                /* address registration option is always ignored when invalid */
                gnrc_sixlowpan_nd_opt_ar_handle(iface, ipv6, nbr_adv->type,
                                                &nbr_adv->tgt,
                                                (sixlowpan_nd_opt_ar_t *)opt,
                                                NULL, 0);
                break;
#endif
            default:
                /* silently discard all other options */
                break;
        }

        opt_offset += (opt->len * 8);
        sicmpv6_size -= (opt->len * 8);

#if ENABLE_DEBUG
        if (sicmpv6_size < 0) {
            DEBUG("ndp: Option parsing out of sync.\n");
        }
#endif
    }

    LL_SEARCH_SCALAR(pkt, netif, type, GNRC_NETTYPE_NETIF);

    if (netif != NULL) {
        netif_hdr = netif->data;
    }

    if (l2tgt_len != -ENOTSUP) {
#ifdef MODULE_GNRC_SIXLOWPAN_ND
        /* check if entry wasn't removed by ARO, ideally there should not be any TL2A in here */
        nc_entry = gnrc_ipv6_nc_get(iface, &nbr_adv->tgt);
        if (nc_entry == NULL) {
            return;
        }
#endif
        if (gnrc_ipv6_nc_get_state(nc_entry) == GNRC_IPV6_NC_STATE_INCOMPLETE) {
            if (_pkt_has_l2addr(netif_hdr) && (l2tgt_len == 0)) {
                /* link-layer has addresses, but no TLLAO supplied: discard silently
                 * (see https://tools.ietf.org/html/rfc4861#section-7.2.5) */
                return;
            }

            nc_entry->iface = iface;
            nc_entry->l2_addr_len = l2tgt_len;
            memcpy(nc_entry->l2_addr, l2tgt, l2tgt_len);

            if (nbr_adv->flags & NDP_NBR_ADV_FLAGS_S) {
                gnrc_ndp_internal_set_state(nc_entry, GNRC_IPV6_NC_STATE_REACHABLE);
            }
            else {
                gnrc_ndp_internal_set_state(nc_entry, GNRC_IPV6_NC_STATE_STALE);
            }

            if (nbr_adv->flags & NDP_NBR_ADV_FLAGS_R) {
                nc_entry->flags |= GNRC_IPV6_NC_IS_ROUTER;
            }
            else {
                nc_entry->flags &= ~GNRC_IPV6_NC_IS_ROUTER;
                /* TODO: update state of neighbor as router in FIB? */
            }
#ifdef MODULE_GNRC_NDP_NODE
            gnrc_pktqueue_t *queued_pkt;
            while ((queued_pkt = gnrc_pktqueue_remove_head(&nc_entry->pkts)) != NULL) {
                if (gnrc_netapi_send(gnrc_ipv6_pid, queued_pkt->pkt) < 1) {
                    DEBUG("ndp: unable to send queued packet\n");
                    gnrc_pktbuf_release(queued_pkt->pkt);
                }
                queued_pkt->pkt = NULL;
            }
#endif
        }
        else {
            /* first or-term: no link-layer, but nc_entry has l2addr,
             * second or-term: different l2addr cached */
            bool l2tgt_changed = false;

            if ((!_pkt_has_l2addr(netif_hdr)) && (l2tgt_len == 0)) {
                /* there was previously a L2 address registered */
                l2tgt_changed = (nc_entry->l2_addr_len != 0);
            }
            /* link-layer has addresses and TLLAO with different address */
            else if (_pkt_has_l2addr(netif_hdr) && (l2tgt_len != 0)) {
                l2tgt_changed = (!(l2tgt_len == nc_entry->l2_addr_len)) &&
                                (memcmp(nc_entry->l2_addr, l2tgt, l2tgt_len) == 0);
            }

            if ((nbr_adv->flags & NDP_NBR_ADV_FLAGS_O) || !l2tgt_changed ||
                (l2tgt_len == 0)) {
                if (l2tgt_len != 0) {
                    nc_entry->iface = iface;
                    nc_entry->l2_addr_len = l2tgt_len;
                    memcpy(nc_entry->l2_addr, l2tgt, l2tgt_len);
                }

                if (nbr_adv->flags & NDP_NBR_ADV_FLAGS_S) {
                    gnrc_ndp_internal_set_state(nc_entry, GNRC_IPV6_NC_STATE_REACHABLE);
                }
                else if (l2tgt_changed) {
                    gnrc_ndp_internal_set_state(nc_entry, GNRC_IPV6_NC_STATE_STALE);
                }

                if (nbr_adv->flags & NDP_NBR_ADV_FLAGS_R) {
                    nc_entry->flags |= GNRC_IPV6_NC_IS_ROUTER;
                }
                else {
                    nc_entry->flags &= ~GNRC_IPV6_NC_IS_ROUTER;
                    /* TODO: update state of neighbor as router in FIB? */
                }
            }
            else if (l2tgt_changed &&
                     gnrc_ipv6_nc_get_state(nc_entry) == GNRC_IPV6_NC_STATE_REACHABLE) {
                gnrc_ndp_internal_set_state(nc_entry, GNRC_IPV6_NC_STATE_STALE);
            }
        }
    }

    return;
}
예제 #16
0
kernel_pid_t gnrc_sixlowpan_nd_next_hop_l2addr(uint8_t *l2addr, uint8_t *l2addr_len,
                                               kernel_pid_t iface, ipv6_addr_t *dst)
{
    ipv6_addr_t *next_hop = NULL;
    gnrc_ipv6_nc_t *nc_entry = NULL;

#ifdef MODULE_GNRC_IPV6_EXT_RH
    ipv6_hdr_t *hdr;
    gnrc_pktsnip_t *ipv6;
    LL_SEARCH_SCALAR(pkt, ipv6, type, GNRC_NETTYPE_IPV6);
    assert(ipv6);
    hdr = ipv6->data;
    next_hop = ipv6_ext_rh_next_hop(hdr);
#endif
#ifdef MODULE_FIB
    ipv6_addr_t next_hop_actual;    /* FIB copies address into this variable */
    /* don't look-up link local addresses in FIB */
    if ((next_hop == NULL) && !ipv6_addr_is_link_local(dst)) {
        size_t next_hop_size = sizeof(ipv6_addr_t);
        uint32_t next_hop_flags = 0;
        if ((next_hop == NULL) &&
            (fib_get_next_hop(&gnrc_ipv6_fib_table, &iface, next_hop_actual.u8, &next_hop_size,
                              &next_hop_flags, (uint8_t *)dst,
                              sizeof(ipv6_addr_t), 0) >= 0) &&
            (next_hop_size == sizeof(ipv6_addr_t))) {
            next_hop = &next_hop_actual;
        }
    }
#endif
#ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER
    /* next hop determination: https://tools.ietf.org/html/rfc6775#section-6.5.4 */
    nc_entry = gnrc_ipv6_nc_get(iface, dst);
    /* if NCE found */
    if (nc_entry != NULL) {
        gnrc_ipv6_netif_t *ipv6_if = gnrc_ipv6_netif_get(nc_entry->iface);
        /* and interface is not 6LoWPAN */
        if (!(ipv6_if->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) ||
                /* or entry is registered */
                (gnrc_ipv6_nc_get_type(nc_entry) == GNRC_IPV6_NC_TYPE_REGISTERED)) {
        next_hop = dst;
        }
    }
#endif
    /* next hop determination according to: https://tools.ietf.org/html/rfc6775#section-5.6 */
    if ((next_hop == NULL) && ipv6_addr_is_link_local(dst)) {   /* prefix is "on-link" */
        /* multicast is not handled here anyway so we don't need to check that */
        next_hop = dst;
    }
    else if (next_hop == NULL) {                                /* prefix is off-link */
        next_hop = gnrc_ndp_internal_default_router();
    }

    /* address resolution of next_hop: https://tools.ietf.org/html/rfc6775#section-5.7 */
    if ((nc_entry == NULL) || (next_hop != dst)) {
        /* get if not gotten from previous check */
        nc_entry = gnrc_ipv6_nc_get(iface, next_hop);
    }
    /* If a NCE for this destination exist, we can use even for link-local
     * addresses. This should be only the case for 6LBRs. */
    if ((ipv6_addr_is_link_local(next_hop)) && (nc_entry == NULL)) {
/* in case of a border router there is no sensible way for address resolution
 * if the interface is not given */
#ifdef MODULE_GNRC_SIXLOWPAN_ND_BORDER_ROUTER
        /* if no interface is specified it is impossible to resolve the
         * link-layer address for a link-local address on a 6LBR */
        if (iface == KERNEL_PID_UNDEF) {
            return KERNEL_PID_UNDEF;
        }
#endif
        kernel_pid_t ifs[GNRC_NETIF_NUMOF];
        size_t ifnum = gnrc_netif_get(ifs);
        /* we don't need address resolution, the EUI-64 is in next_hop's IID */
        *l2addr_len = sizeof(eui64_t);
        memcpy(l2addr, &next_hop->u8[8], sizeof(eui64_t));
        _revert_iid(l2addr);
        if (iface == KERNEL_PID_UNDEF) {
            for (unsigned i = 0; i < ifnum; i++) {
                gnrc_ipv6_netif_t *ipv6_if = gnrc_ipv6_netif_get(ifs[i]);
                if ((ipv6_if != NULL) && (ipv6_if->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN)) {
                    /* always take the first 6LoWPAN interface we can find */
                    return ifs[i];
                }
            }
        }
        return iface;
    }
    if ((nc_entry == NULL) || (!gnrc_ipv6_nc_is_reachable(nc_entry)) ||
        (gnrc_ipv6_nc_get_type(nc_entry) == GNRC_IPV6_NC_TYPE_TENTATIVE)) {
        return KERNEL_PID_UNDEF;
    }
    else {
        if (nc_entry->l2_addr_len > 0) {
            memcpy(l2addr, nc_entry->l2_addr, nc_entry->l2_addr_len);
        }
        *l2addr_len = nc_entry->l2_addr_len;
    }
    return nc_entry->iface;
}
예제 #17
0
파일: gnrc_tcp_fsm.c 프로젝트: A-Paul/RIOT
/**
 * @brief Checks if a given port number is currently used by a TCB as local_port.
 *
 * @note Must be called from a context where the TCB list is locked.
 *
 * @param[in] port_number   Port number that should be checked.
 *
 * @returns   Zero if @p port_number is currently not used.
 *            1 if @p port_number is used by an active connection.
 */
static int _is_local_port_in_use(const uint16_t port_number)
{
    gnrc_tcp_tcb_t *iter = NULL;
    LL_SEARCH_SCALAR(_list_tcb_head, iter, local_port, port_number);
    return (iter != NULL);
}
예제 #18
0
파일: ng_sixlowpan.c 프로젝트: femtoio/RIOT
void _receive(ng_pktsnip_t *pkt)
{
    ng_pktsnip_t *payload;
    uint8_t *dispatch;
    ng_netreg_entry_t *entry;

    LL_SEARCH_SCALAR(pkt, payload, type, NG_NETTYPE_SIXLOWPAN);

    if ((payload == NULL) || (payload->size < 1)) {
        DEBUG("6lo: Received packet has no 6LoWPAN payload\n");
        ng_pktbuf_release(pkt);
    }

    dispatch = payload->data;

    if (dispatch[0] == NG_SIXLOWPAN_UNCOMPRESSED) {
        ng_pktsnip_t *sixlowpan;
        DEBUG("6lo: received uncompressed IPv6 packet\n");
        payload = ng_pktbuf_start_write(payload);

        if (payload == NULL) {
            DEBUG("6lo: can not get write access on received packet\n");
#if defined(DEVELHELP) && defined(ENABLE_DEBUG)
            ng_pktbuf_stats();
#endif
            ng_pktbuf_release(pkt);
            return;
        }

        /* packet is uncompressed: just mark and remove the dispatch */
        sixlowpan = ng_pktbuf_add(payload, payload->data, sizeof(uint8_t),
                                  NG_NETTYPE_SIXLOWPAN);
        LL_DELETE(pkt, sixlowpan);
        ng_pktbuf_release(sixlowpan);
    }
#ifdef MODULE_NG_SIXLOWPAN_FRAG
    else if (ng_sixlowpan_frag_is((ng_sixlowpan_frag_t *)dispatch)) {
        DEBUG("6lo: received 6LoWPAN fragment\n");
        ng_sixlowpan_frag_handle_pkt(pkt);
    }
#endif
    else {
        DEBUG("6lo: dispatch %02x ... is not supported\n",
              dispatch[0]);
        ng_pktbuf_release(pkt);
        return;
    }

    payload->type = NG_NETTYPE_IPV6;

    entry = ng_netreg_lookup(NG_NETTYPE_IPV6, NG_NETREG_DEMUX_CTX_ALL);

    if (entry == NULL) {
        DEBUG("ipv6: No receivers for this packet found\n");
        ng_pktbuf_release(pkt);
        return;
    }

    ng_pktbuf_hold(pkt, ng_netreg_num(NG_NETTYPE_IPV6, NG_NETREG_DEMUX_CTX_ALL) - 1);

    while (entry) {
        DEBUG("6lo: Send receive command for %p to %" PRIu16 "\n",
              (void *)pkt, entry->pid);
        ng_netapi_receive(entry->pid, pkt);
        entry = ng_netreg_getnext(entry);
    }
}
예제 #19
0
파일: ng_ipv6.c 프로젝트: jferreir/RIOT
static void _receive(ng_pktsnip_t *pkt)
{
    kernel_pid_t iface = KERNEL_PID_UNDEF;
    ng_pktsnip_t *ipv6, *netif;
    ng_ipv6_hdr_t *hdr;

    LL_SEARCH_SCALAR(pkt, netif, type, NG_NETTYPE_NETIF);

    if (netif != NULL) {
        iface = ((ng_netif_hdr_t *)netif->data)->if_pid;
    }

    if ((pkt->next != NULL) && (pkt->next->type == NG_NETTYPE_IPV6) &&
        (pkt->next->size == sizeof(ng_ipv6_hdr_t))) {
        /* IP header was already marked. Take it. */
        ipv6 = pkt->next;

        if (!ng_ipv6_hdr_is(ipv6->data)) {
            DEBUG("ipv6: Received packet was not IPv6, dropping packet\n");
            ng_pktbuf_release(pkt);
            return;
        }
    }
    else {
        if (!ng_ipv6_hdr_is(pkt->data)) {
            DEBUG("ipv6: Received packet was not IPv6, dropping packet\n");
            ng_pktbuf_release(pkt);
            return;
        }

        /* seize ipv6 as a temporary variable */
        ipv6 = ng_pktbuf_start_write(pkt);

        if (ipv6 == NULL) {
            DEBUG("ipv6: unable to get write access to packet, drop it\n");
            ng_pktbuf_release(pkt);
            return;
        }

        pkt = ipv6;     /* reset pkt from temporary variable */

        ipv6 = ng_pktbuf_add(pkt, pkt->data, sizeof(ng_ipv6_hdr_t),
                             NG_NETTYPE_IPV6);

        if (ipv6 == NULL) {
            DEBUG("ipv6: error marking IPv6 header, dropping packet\n");
            ng_pktbuf_release(pkt);
            return;
        }
    }

    /* extract header */
    hdr = (ng_ipv6_hdr_t *)ipv6->data;

    DEBUG("ipv6: Received (src = %s, ",
          ng_ipv6_addr_to_str(addr_str, &(hdr->src), sizeof(addr_str)));
    DEBUG("dst = %s, next header = %" PRIu8 ", length = %" PRIu16 ")\n",
          ng_ipv6_addr_to_str(addr_str, &(hdr->dst), sizeof(addr_str)),
          hdr->nh, byteorder_ntohs(hdr->len));

    if (_pkt_not_for_me(&iface, hdr)) { /* if packet is not for me */
        DEBUG("ipv6: packet destination not this host\n");

#ifdef MODULE_NG_IPV6_ROUTER    /* only routers redirect */
        /* redirect to next hop */
        DEBUG("ipv6: decrement hop limit to %" PRIu8 "\n", hdr->hl - 1);

        /* TODO: check if receiving interface is router */
        if (--(hdr->hl) > 0) {  /* drop packets that *reach* Hop Limit 0 */
            ng_pktsnip_t *tmp = pkt;

            DEBUG("ipv6: forward packet to next hop\n");

            /* pkt might not be writable yet, if header was given above */
            pkt = ng_pktbuf_start_write(tmp);
            ipv6 = ng_pktbuf_start_write(ipv6);

            if ((ipv6 == NULL) || (pkt == NULL)) {
                DEBUG("ipv6: unable to get write access to packet: dropping it\n");
                ng_pktbuf_release(tmp);
                return;
            }

            ng_pktbuf_release(ipv6->next);  /* remove headers around IPV6 */
            ipv6->next = pkt;           /* reorder for sending */
            pkt->next = NULL;
            _send(ipv6, false);
        }
        else {
            DEBUG("ipv6: hop limit reached 0: drop packet\n");
            ng_pktbuf_release(pkt);
            return;
        }

#else  /* MODULE_NG_IPV6_ROUTER */
        DEBUG("ipv6: dropping packet\n");
        /* non rounting hosts just drop the packet */
        ng_pktbuf_release(pkt);
        return;
#endif /* MODULE_NG_IPV6_ROUTER */
    }

    /* IPv6 internal demuxing (ICMPv6, Extension headers etc.) */
    ng_ipv6_demux(iface, pkt, hdr->nh);
}
예제 #20
0
static void _receive(ng_pktsnip_t *pkt)
{
    ng_pktsnip_t *payload;
    uint8_t *dispatch;

    /* seize payload as a temporary variable */
    payload = ng_pktbuf_start_write(pkt);   /* need to duplicate since pkt->next
                                             * might get replaced */

    if (payload == NULL) {
        DEBUG("6lo: can not get write access on received packet\n");
#if defined(DEVELHELP) && defined(ENABLE_DEBUG)
        ng_pktbuf_stats();
#endif
        ng_pktbuf_release(pkt);
        return;
    }

    pkt = payload;  /* reset pkt from temporary variable */

    LL_SEARCH_SCALAR(pkt, payload, type, NG_NETTYPE_SIXLOWPAN);

    if ((payload == NULL) || (payload->size < 1)) {
        DEBUG("6lo: Received packet has no 6LoWPAN payload\n");
        ng_pktbuf_release(pkt);
        return;
    }

    dispatch = payload->data;

    if (dispatch[0] == NG_SIXLOWPAN_UNCOMPRESSED) {
        ng_pktsnip_t *sixlowpan;
        DEBUG("6lo: received uncompressed IPv6 packet\n");
        payload = ng_pktbuf_start_write(payload);

        if (payload == NULL) {
            DEBUG("6lo: can not get write access on received packet\n");
#if defined(DEVELHELP) && defined(ENABLE_DEBUG)
            ng_pktbuf_stats();
#endif
            ng_pktbuf_release(pkt);
            return;
        }

        /* packet is uncompressed: just mark and remove the dispatch */
        sixlowpan = ng_pktbuf_add(payload, payload->data, sizeof(uint8_t),
                                  NG_NETTYPE_SIXLOWPAN);

        if (sixlowpan == NULL) {
            DEBUG("6lo: can not mark 6LoWPAN dispatch\n");
            ng_pktbuf_release(pkt);
            return;
        }

        pkt = ng_pktbuf_remove_snip(pkt, sixlowpan);
    }
#ifdef MODULE_NG_SIXLOWPAN_FRAG
    else if (ng_sixlowpan_frag_is((ng_sixlowpan_frag_t *)dispatch)) {
        DEBUG("6lo: received 6LoWPAN fragment\n");
        ng_sixlowpan_frag_handle_pkt(pkt);
        return;
    }
#endif
    else {
        DEBUG("6lo: dispatch %02x ... is not supported\n",
              dispatch[0]);
        ng_pktbuf_release(pkt);
        return;
    }

#ifdef MODULE_NG_SIXLOWPAN_IPHC
    if (ng_sixlowpan_iphc_is(payload->data)) {
        if (!ng_sixlowpan_iphc_decode(pkt)) {
            DEBUG("6lo: error on IPHC decoding\n");
            ng_pktbuf_release(pkt);
            return;
        }
        LL_SEARCH_SCALAR(pkt, payload, type, NG_NETTYPE_IPV6);

    }
#endif

    payload->type = NG_NETTYPE_IPV6;

    if (!ng_netapi_dispatch_receive(NG_NETTYPE_IPV6, NG_NETREG_DEMUX_CTX_ALL, pkt)) {
        DEBUG("ipv6: No receivers for this packet found\n");
        ng_pktbuf_release(pkt);
    }
}
예제 #21
0
파일: gnrc_ipv6.c 프로젝트: nlebang/RIOT
static void _receive(gnrc_pktsnip_t *pkt)
{
    kernel_pid_t iface = KERNEL_PID_UNDEF;
    gnrc_pktsnip_t *ipv6, *netif;
    ipv6_hdr_t *hdr;

    assert(pkt != NULL);

    LL_SEARCH_SCALAR(pkt, netif, type, GNRC_NETTYPE_NETIF);

    if (netif != NULL) {
        iface = ((gnrc_netif_hdr_t *)netif->data)->if_pid;
    }

    if ((pkt->next != NULL) && (pkt->next->type == GNRC_NETTYPE_IPV6) &&
        (pkt->next->size == sizeof(ipv6_hdr_t))) {
        /* IP header was already marked. Take it. */
        ipv6 = pkt->next;

        if (!ipv6_hdr_is(ipv6->data)) {
            DEBUG("ipv6: Received packet was not IPv6, dropping packet\n");
            gnrc_pktbuf_release(pkt);
            return;
        }
    }
    else {
        if (!ipv6_hdr_is(pkt->data)) {
            DEBUG("ipv6: Received packet was not IPv6, dropping packet\n");
            gnrc_pktbuf_release(pkt);
            return;
        }

        /* seize ipv6 as a temporary variable */
        ipv6 = gnrc_pktbuf_start_write(pkt);

        if (ipv6 == NULL) {
            DEBUG("ipv6: unable to get write access to packet, drop it\n");
            gnrc_pktbuf_release(pkt);
            return;
        }

        pkt = ipv6;     /* reset pkt from temporary variable */

        ipv6 = gnrc_pktbuf_mark(pkt, sizeof(ipv6_hdr_t), GNRC_NETTYPE_IPV6);

        if (ipv6 == NULL) {
            DEBUG("ipv6: error marking IPv6 header, dropping packet\n");
            gnrc_pktbuf_release(pkt);
            return;
        }
    }

    /* extract header */
    hdr = (ipv6_hdr_t *)ipv6->data;

    /* if available, remove any padding that was added by lower layers
     * to fulfill their minimum size requirements (e.g. ethernet) */
    if (byteorder_ntohs(hdr->len) < pkt->size) {
        gnrc_pktbuf_realloc_data(pkt, byteorder_ntohs(hdr->len));
    }

    DEBUG("ipv6: Received (src = %s, ",
          ipv6_addr_to_str(addr_str, &(hdr->src), sizeof(addr_str)));
    DEBUG("dst = %s, next header = %" PRIu8 ", length = %" PRIu16 ")\n",
          ipv6_addr_to_str(addr_str, &(hdr->dst), sizeof(addr_str)),
          hdr->nh, byteorder_ntohs(hdr->len));

    if (_pkt_not_for_me(&iface, hdr)) { /* if packet is not for me */
        DEBUG("ipv6: packet destination not this host\n");

#ifdef MODULE_GNRC_IPV6_ROUTER    /* only routers redirect */
        /* redirect to next hop */
        DEBUG("ipv6: decrement hop limit to %" PRIu8 "\n", hdr->hl - 1);

        /* RFC 4291, section 2.5.6 states: "Routers must not forward any
         * packets with Link-Local source or destination addresses to other
         * links."
         */
        if ((ipv6_addr_is_link_local(&(hdr->src))) || (ipv6_addr_is_link_local(&(hdr->dst)))) {
            DEBUG("ipv6: do not forward packets with link-local source or"\
                  " destination address\n");
            gnrc_pktbuf_release(pkt);
            return;
        }
        /* TODO: check if receiving interface is router */
        else if (--(hdr->hl) > 0) {  /* drop packets that *reach* Hop Limit 0 */
            gnrc_pktsnip_t *tmp = pkt;

            DEBUG("ipv6: forward packet to next hop\n");

            /* pkt might not be writable yet, if header was given above */
            pkt = gnrc_pktbuf_start_write(tmp);
            ipv6 = gnrc_pktbuf_start_write(ipv6);

            if ((ipv6 == NULL) || (pkt == NULL)) {
                DEBUG("ipv6: unable to get write access to packet: dropping it\n");
                gnrc_pktbuf_release(tmp);
                return;
            }

            gnrc_pktbuf_release(ipv6->next);    /* remove headers around IPV6 */
            ipv6->next = pkt;                   /* reorder for sending */
            pkt->next = NULL;
            _send(ipv6, false);
            return;
        }
        else {
            DEBUG("ipv6: hop limit reached 0: drop packet\n");
            gnrc_pktbuf_release(pkt);
            return;
        }

#else  /* MODULE_GNRC_IPV6_ROUTER */
        DEBUG("ipv6: dropping packet\n");
        /* non rounting hosts just drop the packet */
        gnrc_pktbuf_release(pkt);
        return;
#endif /* MODULE_GNRC_IPV6_ROUTER */
    }

    /* IPv6 internal demuxing (ICMPv6, Extension headers etc.) */
    gnrc_ipv6_demux(iface, pkt, hdr->nh);
}