/*---------------------------------------------------------------------------*/ static struct channel * input(void) { const struct packetbuf_attrlist *a; int byteptr, bitptr, len; uint8_t *hdrptr; struct raw_hdr *hdr; struct channel *c; /* The packet has a header that tells us what channel the packet is for. */ hdr = (struct raw_hdr *)packetbuf_dataptr(); packetbuf_hdrreduce(sizeof(struct raw_hdr)); c = channel_lookup(hdr->channel); if(c == NULL) { PRINTF("chameleon-raw: input: channel %d not found\n", hdr->channel); return NULL; } hdrptr = packetbuf_dataptr(); packetbuf_hdrreduce(c->hdrsize); byteptr = bitptr = 0; for(a = c->attrlist; a->type != PACKETBUF_ATTR_NONE; ++a) { PRINTF("%d.%d: unpack_header type %s, len %d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], packetbuf_attr_strings[a->type], a->len); len = (a->len & 0xf8) + ((a->len & 7) ? 8: 0); if(a->type == PACKETBUF_ADDR_SENDER || a->type == PACKETBUF_ADDR_RECEIVER || a->type == PACKETBUF_ADDR_ESENDER || a->type == PACKETBUF_ADDR_ERECEIVER) { const rimeaddr_t addr; memcpy((uint8_t *)&addr, &hdrptr[byteptr], len / 8); PRINTF("%d.%d: unpack_header type %s, addr %d.%d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], packetbuf_attr_strings[a->type], addr.u8[0], addr.u8[1]); packetbuf_set_addr(a->type, &addr); } else { packetbuf_attr_t val = 0; memcpy((uint8_t *)&val, &hdrptr[byteptr], len / 8); packetbuf_set_attr(a->type, val); PRINTF("%d.%d: unpack_header type %s, val %d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], packetbuf_attr_strings[a->type], val); } byteptr += len / 8; } return c; }
/*---------------------------------------------------------------------------*/ static int parse(void) { int hdr_len; struct hdr *chdr; hdr_len = DECORATED_FRAMER.parse(); if(hdr_len < 0) { return FRAMER_FAILED; } chdr = packetbuf_dataptr(); if(chdr->id != CONTIKIMAC_ID) { PRINTF("contikimac-framer: CONTIKIMAC_ID is missing\n"); return FRAMER_FAILED; } if(!packetbuf_hdrreduce(sizeof(struct hdr))) { PRINTF("contikimac-framer: packetbuf_hdrreduce failed\n"); return FRAMER_FAILED; } packetbuf_set_datalen(chdr->len); chdr->len = 0; return hdr_len + sizeof(struct hdr); }
/*---------------------------------------------------------------------------*/ static int parse(void) { frame802154_t frame; int len; len = packetbuf_datalen(); if(frame802154_parse(packetbuf_dataptr(), len, &frame) && packetbuf_hdrreduce(len - frame.payload_len)) { if(frame.fcf.dest_addr_mode) { if(frame.dest_pid != mac_src_pan_id && frame.dest_pid != FRAME802154_BROADCASTPANDID) { /* Packet to another PAN */ PRINTF("15.4: for another pan %u\n", frame.dest_pid); return FRAMER_FAILED; } if(!is_broadcast_addr(frame.fcf.dest_addr_mode, frame.dest_addr)) { packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, (linkaddr_t *)&frame.dest_addr); } } packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (linkaddr_t *)&frame.src_addr); packetbuf_set_attr(PACKETBUF_ATTR_PENDING, frame.fcf.frame_pending); /* packetbuf_set_attr(PACKETBUF_ATTR_RELIABLE, frame.fcf.ack_required);*/ packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, frame.seq); PRINTF("15.4-IN: %2X", frame.fcf.frame_type); PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER)); PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); PRINTF("%u (%u)\n", packetbuf_datalen(), len); return len - frame.payload_len; } return FRAMER_FAILED; }
/*---------------------------------------------------------------------------*/ static void received(struct runicast_conn *uc, const rimeaddr_t *from, uint8_t seqno) { struct rmh_conn *c = (struct rmh_conn *)uc; struct data_hdr *msg = packetbuf_dataptr(); rimeaddr_t *nexthop; PRINTF("data_packet_received from %d.%d towards %d.%d len %d\n", from->u8[0], from->u8[1], msg->dest.u8[0], msg->dest.u8[1], packetbuf_datalen()); if(rimeaddr_cmp(&msg->dest, &rimeaddr_node_addr)) { PRINTF("for us!\n"); packetbuf_hdrreduce(sizeof(struct data_hdr)); if(c->cb->recv) { c->cb->recv(c, &msg->originator, msg->hops); } } else { nexthop = NULL; if(c->cb->forward) { nexthop = c->cb->forward(c, &msg->originator, &msg->dest, from, msg->hops); } if(nexthop) { PRINTF("forwarding to %d.%d\n", nexthop->u8[0], nexthop->u8[1]); msg->hops++; runicast_send(&c->c, nexthop, c->num_rexmit); } } }
/*---------------------------------------------------------------------------*/ static int parse(struct net_buf *buf) { frame802154_t frame; int hdr_len; hdr_len = frame802154_parse(packetbuf_dataptr(buf), packetbuf_datalen(buf), &frame); if(hdr_len && packetbuf_hdrreduce(buf, hdr_len)) { packetbuf_set_attr(buf, PACKETBUF_ATTR_FRAME_TYPE, frame.fcf.frame_type); if(frame.fcf.dest_addr_mode) { if(frame.dest_pid != mac_src_pan_id && frame.dest_pid != FRAME802154_BROADCASTPANDID) { /* Packet to another PAN */ PRINTF("15.4: for another pan %u (0x%x)\n", frame.dest_pid, frame.dest_pid); return FRAMER_FAILED; } if(!is_broadcast_addr(frame.fcf.dest_addr_mode, frame.dest_addr)) { packetbuf_set_addr(buf, PACKETBUF_ADDR_RECEIVER, (linkaddr_t *)&frame.dest_addr); } } packetbuf_set_addr(buf, PACKETBUF_ADDR_SENDER, (linkaddr_t *)&frame.src_addr); packetbuf_set_attr(buf, PACKETBUF_ATTR_PENDING, frame.fcf.frame_pending); /* packetbuf_set_attr(PACKETBUF_ATTR_RELIABLE, frame.fcf.ack_required);*/ packetbuf_set_attr(buf, PACKETBUF_ATTR_PACKET_ID, frame.seq); #if LLSEC802154_SECURITY_LEVEL if(frame.fcf.security_enabled) { packetbuf_set_attr(buf, PACKETBUF_ATTR_SECURITY_LEVEL, frame.aux_hdr.security_control.security_level); packetbuf_set_attr(buf, PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1, frame.aux_hdr.frame_counter.u16[0]); packetbuf_set_attr(buf, PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3, frame.aux_hdr.frame_counter.u16[1]); #if LLSEC802154_USES_EXPLICIT_KEYS packetbuf_set_attr(buf, PACKETBUF_ATTR_KEY_ID_MODE, frame.aux_hdr.security_control.key_id_mode); packetbuf_set_attr(buf, PACKETBUF_ATTR_KEY_INDEX, frame.aux_hdr.key_index); packetbuf_set_attr(buf, PACKETBUF_ATTR_KEY_SOURCE_BYTES_0_1, frame.aux_hdr.key_source.u16[0]); #endif /* LLSEC802154_USES_EXPLICIT_KEYS */ } #endif /* LLSEC802154_SECURITY_LEVEL */ PRINTF("15.4-IN: %2X ", frame.fcf.frame_type); PRINTLLADDR((const uip_lladdr_t *)packetbuf_addr(buf, PACKETBUF_ADDR_SENDER)); PRINTF(" "); PRINTLLADDR((const uip_lladdr_t *)packetbuf_addr(buf, PACKETBUF_ADDR_RECEIVER)); PRINTF(" %d %u (%u)\n", hdr_len, packetbuf_datalen(buf), packetbuf_totlen(buf)); #ifdef FRAMER_802154_HANDLER if(FRAMER_802154_HANDLER(&frame)) { return FRAMER_FRAME_HANDLED; } #endif return hdr_len; } return FRAMER_FAILED; }
/*---------------------------------------------------------------------------*/ static int parse(void) { frame802154_t frame; int hdr_len; hdr_len = frame802154_parse(packetbuf_dataptr(), packetbuf_datalen(), &frame); if(hdr_len && packetbuf_hdrreduce(hdr_len)) { packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, frame.fcf.frame_type); if(frame.fcf.dest_addr_mode) { if(frame.dest_pid != frame802154_get_pan_id() && frame.dest_pid != FRAME802154_BROADCASTPANDID) { /* Packet to another PAN */ PRINTF("15.4: for another pan %u\n", frame.dest_pid); return FRAMER_FAILED; } if(!frame802154_is_broadcast_addr(frame.fcf.dest_addr_mode, frame.dest_addr)) { packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, (linkaddr_t *)&frame.dest_addr); } } packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (linkaddr_t *)&frame.src_addr); packetbuf_set_attr(PACKETBUF_ATTR_PENDING, frame.fcf.frame_pending); if(frame.fcf.sequence_number_suppression == 0) { packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, frame.seq); } else { packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, 0xffff); } #if NETSTACK_CONF_WITH_RIME packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, frame.seq); #endif #if LLSEC802154_USES_AUX_HEADER if(frame.fcf.security_enabled) { packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, frame.aux_hdr.security_control.security_level); #if LLSEC802154_USES_FRAME_COUNTER packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1, frame.aux_hdr.frame_counter.u16[0]); packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3, frame.aux_hdr.frame_counter.u16[1]); #endif /* LLSEC802154_USES_FRAME_COUNTER */ #if LLSEC802154_USES_EXPLICIT_KEYS packetbuf_set_attr(PACKETBUF_ATTR_KEY_ID_MODE, frame.aux_hdr.security_control.key_id_mode); packetbuf_set_attr(PACKETBUF_ATTR_KEY_INDEX, frame.aux_hdr.key_index); packetbuf_set_attr(PACKETBUF_ATTR_KEY_SOURCE_BYTES_0_1, frame.aux_hdr.key_source.u16[0]); #endif /* LLSEC802154_USES_EXPLICIT_KEYS */ } #endif /* LLSEC802154_USES_AUX_HEADER */ PRINTF("15.4-IN: %2X", frame.fcf.frame_type); PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER)); PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); PRINTF("%d %u (%u)\n", hdr_len, packetbuf_datalen(), packetbuf_totlen()); return hdr_len; } return FRAMER_FAILED; }
/*---------------------------------------------------------------------------*/ static void recv_from_ipolite(struct ipolite_conn *ipolite, const rimeaddr_t *from) { PRINTF("%d.%d: netflood recv_from_ipolite\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]); struct netflood_conn *c = (struct netflood_conn *)ipolite; struct netflood_hdr hdr; uint8_t hops; struct queuebuf *queuebuf; memcpy(&hdr, packetbuf_dataptr(), sizeof(struct netflood_hdr)); hops = hdr.hops; /* Remember packet if we need to forward it. */ queuebuf = queuebuf_new_from_packetbuf(); packetbuf_hdrreduce(sizeof(struct netflood_hdr)); if(c->u->recv != NULL) { if(!(rimeaddr_cmp(&hdr.originator, &c->last_originator) && hdr.originator_seqno <= c->last_originator_seqno)) { if(c->u->recv(c, from, &hdr.originator, hdr.originator_seqno, hops)) { if(queuebuf != NULL) { queuebuf_to_packetbuf(queuebuf); queuebuf_free(queuebuf); queuebuf = NULL; memcpy(&hdr, packetbuf_dataptr(), sizeof(struct netflood_hdr)); /* Rebroadcast received packet. */ if(hops < HOPS_MAX) { PRINTF("%d.%d: netflood rebroadcasting %d.%d/%d (%d.%d/%d) hops %d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr.originator.u8[0], hdr.originator.u8[1], hdr.originator_seqno, c->last_originator.u8[0], c->last_originator.u8[1], c->last_originator_seqno, hops); hdr.hops++; memcpy(packetbuf_dataptr(), &hdr, sizeof(struct netflood_hdr)); send(c); rimeaddr_copy(&c->last_originator, &hdr.originator); c->last_originator_seqno = hdr.originator_seqno; } } } } } if(queuebuf != NULL) { queuebuf_free(queuebuf); } }
/*---------------------------------------------------------------------------*/ static int read_packet(void) { frame802154_t frame; int len; packetbuf_clear(); len = radio->read(packetbuf_dataptr(), PACKETBUF_SIZE); if(len > 0) { packetbuf_set_datalen(len); if(frame802154_parse(packetbuf_dataptr(), len, &frame) && packetbuf_hdrreduce(len - frame.payload_len)) { if(frame.fcf.dest_addr_mode) { if(frame.dest_pid != mac_src_pan_id && frame.dest_pid != FRAME802154_BROADCASTPANDID) { /* Not broadcast or for our PAN */ PRINTF("6MAC: for another pan %u\n", frame.dest_pid); return 0; } if(!is_broadcast_addr(frame.fcf.dest_addr_mode, frame.dest_addr.u8)) { packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &frame.dest_addr); if(!rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_node_addr)) { /* Not for this node */ PRINTF("6MAC: not for us\n"); return 0; } } } packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &frame.src_addr); #if MAC_FILTER if(mac_filter()){ PRINTF("Filter dropped a packet!"); return -1; } #endif PRINTF("6MAC-IN: %2X", frame.fcf.frame_type); PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER)); PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); PRINTF("%u\n", packetbuf_datalen()); return packetbuf_datalen(); } else { PRINTF("6MAC: failed to parse hdr\n"); } } return 0; }
/*---------------------------------------------------------------------------*/ static uint8_t input_packet(struct net_buf *buf) { frame802154_t frame; int len; len = packetbuf_datalen(buf); PRINTF("6MAC: received %d bytes\n", len); if(frame802154_parse(packetbuf_dataptr(buf), len, &frame) && packetbuf_hdrreduce(buf, len - frame.payload_len)) { if(frame.fcf.dest_addr_mode) { if(frame.dest_pid != mac_src_pan_id && frame.dest_pid != FRAME802154_BROADCASTPANDID) { /* Not broadcast or for our PAN */ PRINTF("6MAC: for another pan %u (0x%x)\n", frame.dest_pid, frame.dest_pid); goto error; } if(!is_broadcast_addr(frame.fcf.dest_addr_mode, frame.dest_addr)) { packetbuf_set_addr(buf, PACKETBUF_ADDR_RECEIVER, (linkaddr_t *)&frame.dest_addr); #if !NETSTACK_CONF_BRIDGE_MODE if(!linkaddr_cmp(packetbuf_addr(buf, PACKETBUF_ADDR_RECEIVER), &linkaddr_node_addr)) { /* Not for this node */ PRINTF("6MAC: not for us, we are "); PRINTLLADDR((uip_lladdr_t *)&linkaddr_node_addr); PRINTF(" recipient is "); PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(buf, PACKETBUF_ADDR_RECEIVER)); PRINTF("\n"); goto error; } #endif } } packetbuf_set_addr(buf, PACKETBUF_ADDR_SENDER, (linkaddr_t *)&frame.src_addr); PRINTF("6MAC-IN: type 0x%X sender ", frame.fcf.frame_type); PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(buf, PACKETBUF_ADDR_SENDER)); PRINTF(" receiver "); PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(buf, PACKETBUF_ADDR_RECEIVER)); PRINTF(" len %u\n", packetbuf_datalen(buf)); return NETSTACK_MAC.input(buf); } else { PRINTF("6MAC: failed to parse hdr\n"); } error: return 0; }
/*---------------------------------------------------------------------------*/ static int parse(void) { struct nullmac_hdr *hdr; hdr = packetbuf_dataptr(); if(packetbuf_hdrreduce(sizeof(struct nullmac_hdr))) { packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &(hdr->sender)); packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &(hdr->receiver)); PRINTF("PNULLMAC-IN: "); PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER)); PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); PRINTF("%u (%u)\n", packetbuf_datalen(), sizeof(struct nullmac_hdr)); return sizeof(struct nullmac_hdr); } return FRAMER_FAILED; }
/* Test vector C.2.1.2 from IEEE 802.15.4-2006 */ static void test_sec_lvl_2() { uint8_t key[16] = { 0xC0 , 0xC1 , 0xC2 , 0xC3 , 0xC4 , 0xC5 , 0xC6 , 0xC7 , 0xC8 , 0xC9 , 0xCA , 0xCB , 0xCC , 0xCD , 0xCE , 0xCF }; uint8_t extended_source_address[8] = { 0xAC , 0xDE , 0x48 , 0x00 , 0x00 , 0x00 , 0x00 , 0x01 }; uint8_t data[26] = { 0x08 , 0xD0 , 0x84 , 0x21 , 0x43 , /* Source Address */ 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x48 , 0xDE , 0xAC , /* Security Level*/ 0x02 , /* Frame Counter */ 0x05 , 0x00 , 0x00 , 0x00 , /* Payload */ 0x55 , 0xCF , 0x00 , 0x00 , 0x51 , 0x52 , 0x53 , 0x54 }; uint8_t oracle[LLSEC802154_MIC_LENGTH] = { 0x22 , 0x3B , 0xC1 , 0xEC , 0x84 , 0x1A , 0xB5 , 0x53 }; frame802154_frame_counter_t counter; uint8_t mic[LLSEC802154_MIC_LENGTH]; printf("Testing verification ... "); packetbuf_clear(); packetbuf_set_datalen(26); memcpy(packetbuf_hdrptr(), data, 26); counter.u32 = 5; packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1, counter.u16[0]); packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3, counter.u16[1]); packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, LLSEC802154_SECURITY_LEVEL); packetbuf_hdrreduce(18); AES_128.set_key(key); CCM.mic(extended_source_address, mic, LLSEC802154_MIC_LENGTH); if(memcmp(mic, oracle, LLSEC802154_MIC_LENGTH) == 0) { printf("Success\n"); } else { printf("Failure\n"); } }
/*---------------------------------------------------------------------------*/ static void input_packet(void) { frame802154_t frame; int len; len = packetbuf_datalen(); if(frame802154_parse(packetbuf_dataptr(), len, &frame) && packetbuf_hdrreduce(len - frame.payload_len)) { if(frame.fcf.dest_addr_mode) { if(frame.dest_pid != mac_src_pan_id && frame.dest_pid != FRAME802154_BROADCASTPANDID) { /* Not broadcast or for our PAN */ PRINTF("6MAC: for another pan %u\n", frame.dest_pid); return; } if(!is_broadcast_addr(frame.fcf.dest_addr_mode, frame.dest_addr)) { packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, (rimeaddr_t *)&frame.dest_addr); if(!rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_node_addr)) { /* Not for this node */ PRINTF("6MAC: not for us\n"); return; } } } packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (rimeaddr_t *)&frame.src_addr); PRINTF("6MAC-IN: %2X", frame.fcf.frame_type); PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER)); PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); printf("\n\n!Incoming Data %u!\n\n", packetbuf_datalen()); NETSTACK_MAC.input(); } else { PRINTF("6MAC: failed to parse hdr\n"); } }
/*---------------------------------------------------------------------------*/ static int parse(void) { struct ccmac_hdr *hdr; int deco_hdr_len; deco_hdr_len = DECORATED_FRAMER.parse(); if (deco_hdr_len < 0) { PRINTF("framer-ccmac: decorated parse failed\n"); return FRAMER_FAILED; } hdr = packetbuf_dataptr(); if(packetbuf_hdrreduce(sizeof(struct ccmac_hdr))) { packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE, hdr->packet_type); PRINTF("framer-ccmac: "); PRINTF(" Type %d ", packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE)); PRINTF("%u (%u)\n", packetbuf_datalen(), sizeof(struct ccmac_hdr)); return deco_hdr_len + sizeof(struct ccmac_hdr); } PRINTF("framer-ccmac: parse failed\n"); return FRAMER_FAILED; }
/*---------------------------------------------------------------------------*/ static void input_packet(void) { struct xmac_hdr *hdr; printf("input packet!\n"); if(NETSTACK_FRAMER.parse() >= 0) { hdr = packetbuf_dataptr(); if(hdr->dispatch != DISPATCH) { someone_is_sending = 0; if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_node_addr) || rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) { /* This is a regular packet that is destined to us or to the broadcast address. */ /* We have received the final packet, so we can go back to being asleep. */ off(); /* Check for duplicate packet by comparing the sequence number of the incoming packet with the last few ones we saw. */ { int i; for(i = 0; i < MAX_SEQNOS; ++i) { if(packetbuf_attr(PACKETBUF_ATTR_PACKET_ID) == received_seqnos[i].seqno && rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_SENDER), &received_seqnos[i].sender)) { /* Drop the packet. */ return; } } for(i = MAX_SEQNOS - 1; i > 0; --i) { memcpy(&received_seqnos[i], &received_seqnos[i - 1], sizeof(struct seqno)); } received_seqnos[0].seqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID); rimeaddr_copy(&received_seqnos[0].sender, packetbuf_addr(PACKETBUF_ADDR_SENDER)); } #if XMAC_CONF_COMPOWER /* Accumulate the power consumption for the packet reception. */ compower_accumulate(¤t_packet); /* Convert the accumulated power consumption for the received packet to packet attributes so that the higher levels can keep track of the amount of energy spent on receiving the packet. */ compower_attrconv(¤t_packet); /* Clear the accumulated power consumption so that it is ready for the next packet. */ compower_clear(¤t_packet); #endif /* XMAC_CONF_COMPOWER */ waiting_for_packet = 0; PRINTDEBUG("xmac: data(%u)\n", packetbuf_datalen()); NETSTACK_MAC.input(); return; } else { PRINTDEBUG("xmac: data not for us\n"); } } else if(hdr->type == TYPE_STROBE) { someone_is_sending = 2; if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_node_addr)) { /* This is a strobe packet for us. */ /* If the sender address is someone else, we should acknowledge the strobe and wait for the packet. By using the same address as both sender and receiver, we flag the message is a strobe ack. */ waiting_for_packet = 1; #if 0 hdr->type = TYPE_STROBE_ACK; packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, packetbuf_addr(PACKETBUF_ADDR_SENDER)); packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &rimeaddr_node_addr); packetbuf_compact(); if(NETSTACK_FRAMER.create() >= 0) { /* We turn on the radio in anticipation of the incoming packet. */ someone_is_sending = 1; waiting_for_packet = 1; on(); NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen()); PRINTDEBUG("xmac: send strobe ack %u\n", packetbuf_totlen()); } else { PRINTF("xmac: failed to send strobe ack\n"); } #endif /* 0 */ } else if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) { /* If the receiver address is null, the strobe is sent to prepare for an incoming broadcast packet. If this is the case, we turn on the radio and wait for the incoming broadcast packet. */ waiting_for_packet = 1; on(); } else { PRINTDEBUG("xmac: strobe not for us\n"); } /* We are done processing the strobe and we therefore return to the caller. */ return; #if XMAC_CONF_ANNOUNCEMENTS } else if(hdr->type == TYPE_ANNOUNCEMENT) { packetbuf_hdrreduce(sizeof(struct xmac_hdr)); parse_announcements(packetbuf_addr(PACKETBUF_ADDR_SENDER)); #endif /* XMAC_CONF_ANNOUNCEMENTS */ } else if(hdr->type == TYPE_STROBE_ACK) { PRINTDEBUG("xmac: stray strobe ack\n"); } else { PRINTF("xmac: unknown type %u (%u/%u)\n", hdr->type, packetbuf_datalen(), len); } } else { PRINTF("xmac: failed to parse (%u)\n", packetbuf_totlen()); } }
/** * Read a packet from the underlying radio driver. If the incoming * packet is a probe packet and the sender of the probe matches the * destination address of the queued packet (if any), the queued packet * is sent. */ static void input_packet(void) { struct lpp_hdr hdr; clock_time_t reception_time; reception_time = clock_time(); if(!NETSTACK_FRAMER.parse()) { printf("lpp input_packet framer error\n"); } memcpy(&hdr, packetbuf_dataptr(), sizeof(struct lpp_hdr));; packetbuf_hdrreduce(sizeof(struct lpp_hdr)); /* PRINTF("got packet type %d\n", hdr->type);*/ if(hdr.type == TYPE_PROBE) { struct announcement_msg adata; /* Register the encounter with the sending node. We now know the neighbor's phase. */ register_encounter(&hdr.sender, reception_time); /* Parse incoming announcements */ memcpy(&adata, packetbuf_dataptr(), MIN(packetbuf_datalen(), sizeof(adata))); #if 0 PRINTF("%d.%d: probe from %d.%d with %d announcements\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr.sender.u8[0], hdr.sender.u8[1], adata->num); if(adata.num / sizeof(struct announcement_data) > sizeof(struct announcement_msg)) { /* Sanity check. The number of announcements is too large - corrupt packet has been received. */ return 0; } for(i = 0; i < adata.num; ++i) { /* PRINTF("%d.%d: announcement %d: %d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], adata->data[i].id, adata->data[i].value);*/ announcement_heard(&hdr.sender, adata.data[i].id, adata.data[i].value); } #endif /* 0 */ /* Go through the list of packets to be sent to see if any of them match the sender of the probe, or if they are a broadcast packet that should be sent. */ if(list_length(queued_packets_list) > 0) { struct queue_list_item *i; for(i = list_head(queued_packets_list); i != NULL; i = list_item_next(i)) { const rimeaddr_t *receiver; uint8_t sent; sent = 0; receiver = queuebuf_addr(i->packet, PACKETBUF_ADDR_RECEIVER); if(rimeaddr_cmp(receiver, &hdr.sender) || rimeaddr_cmp(receiver, &rimeaddr_null)) { queuebuf_to_packetbuf(i->packet); #if WITH_PENDING_BROADCAST if(i->broadcast_flag == BROADCAST_FLAG_NONE || i->broadcast_flag == BROADCAST_FLAG_SEND) { i->num_transmissions = 1; NETSTACK_RADIO.send(queuebuf_dataptr(i->packet), queuebuf_datalen(i->packet)); sent = 1; PRINTF("%d.%d: got a probe from %d.%d, sent packet to %d.%d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr.sender.u8[0], hdr.sender.u8[1], receiver->u8[0], receiver->u8[1]); } else { PRINTF("%d.%d: got a probe from %d.%d, did not send packet\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr.sender.u8[0], hdr.sender.u8[1]); } #else /* WITH_PENDING_BROADCAST */ i->num_transmissions = 1; NETSTACK_RADIO.send(queuebuf_dataptr(i->packet), queuebuf_datalen(i->packet)); PRINTF("%d.%d: got a probe from %d.%d, sent packet to %d.%d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr.sender.u8[0], hdr.sender.u8[1], receiver->u8[0], receiver->u8[1]); #endif /* WITH_PENDING_BROADCAST */ /* off();*/ /* Attribute the energy spent on listening for the probe to this packet transmission. */ compower_accumulate(&i->compower); /* If the packet was not a broadcast packet, we dequeue it now. Broadcast packets should be transmitted to all neighbors, and are dequeued by the dutycycling function instead, after the appropriate time. */ if(!rimeaddr_cmp(receiver, &rimeaddr_null)) { if(detect_ack()) { remove_queued_packet(i, 1); } else { remove_queued_packet(i, 0); } #if WITH_PROBE_AFTER_TRANSMISSION /* Send a probe packet to catch any reply from the other node. */ restart_dutycycle(PROBE_AFTER_TRANSMISSION_TIME); #endif /* WITH_PROBE_AFTER_TRANSMISSION */ #if WITH_STREAMING if(is_streaming) { ctimer_set(&stream_probe_timer, STREAM_PROBE_TIME, send_stream_probe, NULL); } #endif /* WITH_STREAMING */ } if(sent) { turn_radio_off(); } #if WITH_ACK_OPTIMIZATION if(packetbuf_attr(PACKETBUF_ATTR_RELIABLE) || packetbuf_attr(PACKETBUF_ATTR_ERELIABLE)) { /* We're sending a packet that needs an ACK, so we keep the radio on in anticipation of the ACK. */ turn_radio_on(); } #endif /* WITH_ACK_OPTIMIZATION */ } } } } else if(hdr.type == TYPE_DATA) { turn_radio_off(); if(!rimeaddr_cmp(&hdr.receiver, &rimeaddr_null)) { if(!rimeaddr_cmp(&hdr.receiver, &rimeaddr_node_addr)) { /* Not broadcast or for us */ PRINTF("%d.%d: data not for us from %d.%d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr.sender.u8[0], hdr.sender.u8[1]); return; } packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &hdr.receiver); } packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &hdr.sender); PRINTF("%d.%d: got data from %d.%d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], hdr.sender.u8[0], hdr.sender.u8[1]); /* Accumulate the power consumption for the packet reception. */ compower_accumulate(¤t_packet); /* Convert the accumulated power consumption for the received packet to packet attributes so that the higher levels can keep track of the amount of energy spent on receiving the packet. */ compower_attrconv(¤t_packet); /* Clear the accumulated power consumption so that it is ready for the next packet. */ compower_clear(¤t_packet); #if WITH_PENDING_BROADCAST if(rimeaddr_cmp(&hdr.receiver, &rimeaddr_null)) { /* This is a broadcast packet. Check the list of pending packets to see if we are currently sending a broadcast. If so, we refrain from sending our broadcast until one sleep cycle period, so that the other broadcaster will have finished sending. */ struct queue_list_item *i; for(i = list_head(queued_packets_list); i != NULL; i = list_item_next(i)) { /* If the packet is a broadcast packet that is not yet ready to be sent, we do not send it. */ if(i->broadcast_flag == BROADCAST_FLAG_PENDING) { PRINTF("Someone else is sending, pending -> waiting\n"); set_broadcast_flag(i, BROADCAST_FLAG_WAITING); } } } #endif /* WITH_PENDING_BROADCAST */ #if WITH_PROBE_AFTER_RECEPTION /* XXX send probe after receiving a packet to facilitate data streaming. We must first copy the contents of the packetbuf into a queuebuf to avoid overwriting the data with the probe packet. */ if(rimeaddr_cmp(&hdr.receiver, &rimeaddr_node_addr)) { struct queuebuf *q; q = queuebuf_new_from_packetbuf(); if(q != NULL) { send_probe(); queuebuf_to_packetbuf(q); queuebuf_free(q); } } #endif /* WITH_PROBE_AFTER_RECEPTION */ #if WITH_ADAPTIVE_OFF_TIME off_time = LOWEST_OFF_TIME; restart_dutycycle(off_time); #endif /* WITH_ADAPTIVE_OFF_TIME */ NETSTACK_MAC.input(); } }
/*---------------------------------------------------------------------------*/ static void mac_frame_input(void) { #if IEEE80211_DRIVER_DEBUG_DEEP PRINTF("IEEE80211driver: mac_frame_input.\n"); #endif /* Theoretically, now is the time where the framer goes on * with the frame parsing. This has, however, been done in * earlier implementation steps. So now the "parsing" will * just remove the MAC header, leaving the network layer * payload for the NETSTACK_NETWORK driver. */ uint8_t hdr_length = sizeof(struct ieee80211_hdr_3addr) + 2 + 6; int hdr = packetbuf_hdrreduce(hdr_length); if (!hdr) { printf("ERROR: Could not remove MAC header from the packet buffer.\n"); return; } int j; uint8_t* pkt_data = packetbuf_dataptr(); #if IEEE80211_DRIVER_DEBUG_DEEP PRINTF("IEEE80211_drv: [%u].\n", packetbuf_datalen()); #endif /* We do not need to check whether the packet is destined * for us, since this has been done by the ieee80211_rx.c * implementation. So we just do sanity checks here. */ if (packetbuf_totlen() > 0 && packetbuf_datalen() > 0) { /* Check for duplicate packet by comparing the sequence number * of the incoming packet with the last few ones we saw. This * is the same as in Contiki MAC. */ int i; for (i=0; i< MAX_SEQNOS; i++) { if(packetbuf_attr(PACKETBUF_ATTR_PACKET_ID) == received_seqnos[i].seqno && rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_SENDER),&received_seqnos[i].sender)) { /* Drop the packet. */ PRINTF("Dropping MAC Duplicate.\n"); return; } } /* It seems that this is not a duplicate. So we update the history for * the received packet sequence numbers, dropping the oldest one and * adding the current packet sequence number and sender address. */ for(i=MAX_SEQNOS-1; i>0; --i) { memcpy(&received_seqnos[i], &received_seqnos[i - 1],sizeof(struct seqno)); } received_seqnos[MAX_SEQNOS-1].seqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID); rimeaddr_copy(&received_seqnos[MAX_SEQNOS-1].sender, packetbuf_addr(PACKETBUF_ADDR_SENDER)); } /* Finally, the input function of the Network Driver shall be called. Note * that the packet we send up to the network layer contains only the layer * 3 payload; all MAC layer content has been removed. */ NETSTACK_NETWORK.input(); }
/*---------------------------------------------------------------------------*/ static int parse(void) { frame802154_t frame; int hdr_len; hdr_len = frame_emmac_parse(packetbuf_dataptr(), packetbuf_datalen(), &frame); if(hdr_len && packetbuf_hdrreduce(hdr_len)) { packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, frame.fcf.frame_type); if(frame.fcf.dest_addr_mode) { if(frame.dest_pid != mac_src_pan_id && frame.dest_pid != FRAME802154_BROADCASTPANDID) { /* Packet to another PAN */ PRINTF("15.4: for another pan %u\n", frame.dest_pid); return FRAMER_FAILED; } if(!is_broadcast_addr(frame.fcf.dest_addr_mode, frame.dest_addr)) { packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, (linkaddr_t *)&frame.dest_addr); } } if(frame.fcf.timestamp_flag){ packetbuf_set_attr(PACKETBUF_ATTR_NODE_TIMESTAMP, frame.timestamp); packetbuf_set_attr(PACKETBUF_ATTR_NODE_CLOCK_TIME, frame.clock_time); } if(frame.fcf.rand_seed_flag) packetbuf_set_attr(PACKETBUF_ATTR_NODE_RAND_SEED, frame.random_seed); if(frame.fcf.frame_type==0) packetbuf_set_attr(PACKETBUF_ATTR_NODE_BLACKLIST, frame.blacklist); packetbuf_set_attr(PACKETBUF_ATTR_NODE_TIMESTAMP_FLAG, frame.fcf.timestamp_flag); packetbuf_set_attr(PACKETBUF_ATTR_NODE_RAND_SEED_FLAG, frame.fcf.rand_seed_flag); packetbuf_set_attr(PACKETBUF_ATTR_NODE_STATE_FLAG, frame.fcf.state_flag); packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (linkaddr_t *)&frame.src_addr); packetbuf_set_attr(PACKETBUF_ATTR_PENDING, frame.fcf.frame_pending); /* packetbuf_set_attr(PACKETBUF_ATTR_RELIABLE, frame.fcf.ack_required);*/ packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, frame.seq); #if LLSEC802154_SECURITY_LEVEL if(frame.fcf.security_enabled) { packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, frame.aux_hdr.security_control.security_level); packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1, frame.aux_hdr.frame_counter.u16[0]); packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3, frame.aux_hdr.frame_counter.u16[1]); #if LLSEC802154_USES_EXPLICIT_KEYS packetbuf_set_attr(PACKETBUF_ATTR_KEY_ID_MODE, frame.aux_hdr.security_control.key_id_mode); packetbuf_set_attr(PACKETBUF_ATTR_KEY_INDEX, frame.aux_hdr.key_index); packetbuf_set_attr(PACKETBUF_ATTR_KEY_SOURCE_BYTES_0_1, frame.aux_hdr.key_source.u16[0]); #endif /* LLSEC802154_USES_EXPLICIT_KEYS */ } #endif /* LLSEC802154_SECURITY_LEVEL */ PRINTF("15.4-IN: %2X", frame.fcf.frame_type); PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER)); PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); PRINTF("%d %u (%u)\n", hdr_len, packetbuf_datalen(), packetbuf_totlen()); return hdr_len; } return FRAMER_FAILED; }
/*---------------------------------------------------------------------------*/ static int parse_80211(void) { int len; uint16_t pan_id; rimeaddr_t* dst_mac_address; rimeaddr_t* src_mac_address; len = packetbuf_datalen(); /* The first 8 bytes are the destination address * of the remote node [IEEE 802.11 MAC address] * and it can well be an Ethernet broadcast one. */ dst_mac_address = (rimeaddr_t*)(packetbuf_dataptr()); packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, (rimeaddr_t *)dst_mac_address); /* We now need to remove these bytes from the * packet buffer so the plain IPv6 packet can * be sent properly. */ if(packetbuf_hdrreduce(RIMEADDR_SIZE) == 0) { PRINTF("SLIP_FRAMER: ERROR; Could not remove MAC address info from incoming slip frame.\n"); return -1; } /* The following 8 bytes contain the source address * of the local [host] interface. */ src_mac_address = (rimeaddr_t*)(packetbuf_dataptr()); packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (rimeaddr_t *)src_mac_address); /* TODO Sanity check; this address should be the local node. */ if (!ether_addr_equal((uint8_t*)src_mac_address, uip_lladdr.addr)) { PRINTF("SLIP_FRAMER; Packet coming from UART has a wrong source MAC Address!\n"); PRINTADDR(src_mac_address); return -1; } /* We now need to remove these bytes from the * packet buffer so the plain IPv6 packet can * be sent properly. */ if(packetbuf_hdrreduce(RIMEADDR_SIZE) == 0) { PRINTF("SLIP_FRAMER: ERROR; Could not remove MAC address info from incoming slip frame.\n"); return -1; } /* The next 2 bytes contain the PAN ID. We should drop * the packet if it does not carry the selected PAN ID */ pan_id = *((uint16_t*)(packetbuf_dataptr())); if (pan_id != mac_src_pan_id && pan_id != FRAME802154_BROADCASTPANDID) { /* Packet to another PAN */ PRINTF("15.4: for another pan %04x\n", pan_id); return -1; } /* We now need to remove these bytes from the * packet buffer so the plain IPv6 packet can * be sent properly. */ if(packetbuf_hdrreduce(sizeof(uint16_t)) == 0) { PRINTF("SLIP_FRAMER: ERROR; Could not remove PAN ID info from incoming slip frame.\n"); return -1; } /* We would like to print some log information. */ PRINTF("802.11-framer-IN: %02x%02x ",(uint8_t)pan_id,(uint8_t)(pan_id>>8)); PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); PRINTF(" After parse: %u (%u)\n", packetbuf_datalen(), len); /* We are now ready to send the packet down. */ return 0; }
/*---------------------------------------------------------------------------*/ static struct channel * input(void) { const struct packetbuf_attrlist *a; int byteptr, bitptr, len; uint8_t *hdrptr; struct raw_hdr *hdr; struct channel *c; /* The packet has a header that tells us what channel the packet is for. */ hdr = (struct raw_hdr *)packetbuf_dataptr(); if(packetbuf_hdrreduce(sizeof(struct raw_hdr)) == 0) { PRINTF("chameleon-raw: too short packet\n"); return NULL; } c = channel_lookup((hdr->channel[1] << 8) + hdr->channel[0]); if(c == NULL) { PRINTF("chameleon-raw: input: channel %u not found\n", (hdr->channel[1] << 8) + hdr->channel[0]); return NULL; } hdrptr = packetbuf_dataptr(); if(packetbuf_hdrreduce(c->hdrsize) == 0) { PRINTF("chameleon-raw: too short packet\n"); return NULL; } byteptr = bitptr = 0; for(a = c->attrlist; a->type != PACKETBUF_ATTR_NONE; ++a) { #if CHAMELEON_WITH_MAC_LINK_ADDRESSES if(a->type == PACKETBUF_ADDR_SENDER || a->type == PACKETBUF_ADDR_RECEIVER) { /* Let the link layer handle sender and receiver */ continue; } #endif /* CHAMELEON_WITH_MAC_LINK_ADDRESSES */ PRINTF("%d.%d: unpack_header type %d, len %d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], a->type, a->len); len = (a->len & 0xf8) + ((a->len & 7) ? 8: 0); if(PACKETBUF_IS_ADDR(a->type)) { const rimeaddr_t addr; memcpy((uint8_t *)&addr, &hdrptr[byteptr], len / 8); PRINTF("%d.%d: unpack_header type %d, addr %d.%d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], a->type, addr.u8[0], addr.u8[1]); packetbuf_set_addr(a->type, &addr); } else { packetbuf_attr_t val = 0; memcpy((uint8_t *)&val, &hdrptr[byteptr], len / 8); packetbuf_set_attr(a->type, val); PRINTF("%d.%d: unpack_header type %d, val %d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], a->type, val); } byteptr += len / 8; } return c; }
/*---------------------------------------------------------------------------*/ static void input_packet(void) { /* We have received the packet, so we can go back to being asleep. */ off(); /* printf("cycle_start 0x%02x 0x%02x\n", cycle_start, cycle_start % CYCLE_TIME);*/ if(packetbuf_totlen() > 0 && NETSTACK_FRAMER.parse()) { #if WITH_CONTIKIMAC_HEADER struct hdr *chdr; chdr = packetbuf_dataptr(); if(chdr->id != CONTIKIMAC_ID) { PRINTF("contikimac: failed to parse hdr (%u)\n", packetbuf_totlen()); return; } packetbuf_hdrreduce(sizeof(struct hdr)); packetbuf_set_datalen(chdr->len); #endif /* WITH_CONTIKIMAC_HEADER */ if(packetbuf_datalen() > 0 && packetbuf_totlen() > 0 && (rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_node_addr) || rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null))) { /* This is a regular packet that is destined to us or to the broadcast address. */ #if WITH_PHASE_OPTIMIZATION /* If the sender has set its pending flag, it has its radio turned on and we should drop the phase estimation that we have from before. */ if(packetbuf_attr(PACKETBUF_ATTR_PENDING)) { phase_remove(&phase_list, packetbuf_addr(PACKETBUF_ADDR_SENDER)); } #endif /* WITH_PHASE_OPTIMIZATION */ /* Check for duplicate packet by comparing the sequence number of the incoming packet with the last few ones we saw. */ { int i; for(i = 0; i < MAX_SEQNOS; ++i) { if(packetbuf_attr(PACKETBUF_ATTR_PACKET_ID) == received_seqnos[i].seqno && rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_SENDER), &received_seqnos[i].sender)) { /* Drop the packet. */ /* printf("Drop duplicate ContikiMAC layer packet\n");*/ return; } } for(i = MAX_SEQNOS - 1; i > 0; --i) { memcpy(&received_seqnos[i], &received_seqnos[i - 1], sizeof(struct seqno)); } received_seqnos[0].seqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID); rimeaddr_copy(&received_seqnos[0].sender, packetbuf_addr(PACKETBUF_ADDR_SENDER)); } #if CONTIKIMAC_CONF_COMPOWER /* Accumulate the power consumption for the packet reception. */ compower_accumulate(¤t_packet); /* Convert the accumulated power consumption for the received packet to packet attributes so that the higher levels can keep track of the amount of energy spent on receiving the packet. */ compower_attrconv(¤t_packet); /* Clear the accumulated power consumption so that it is ready for the next packet. */ compower_clear(¤t_packet); #endif /* CONTIKIMAC_CONF_COMPOWER */ PRINTDEBUG("contikimac: data (%u)\n", packetbuf_datalen()); NETSTACK_MAC.input(); return; } else { PRINTDEBUG("contikimac: data not for us\n"); } } else { PRINTF("contikimac: failed to parse (%u)\n", packetbuf_totlen()); } }
/* Test vector C.2.1.2 from IEEE 802.15.4-2006 */ static void test_sec_lvl_6() { uint8_t key[16] = { 0xC0 , 0xC1 , 0xC2 , 0xC3 , 0xC4 , 0xC5 , 0xC6 , 0xC7 , 0xC8 , 0xC9 , 0xCA , 0xCB , 0xCC , 0xCD , 0xCE , 0xCF }; uint8_t extended_source_address[8] = { 0xAC , 0xDE , 0x48 , 0x00 , 0x00 , 0x00 , 0x00 , 0x01 }; uint8_t data[30] = { 0x2B , 0xDC , 0x84 , 0x21 , 0x43 , /* Destination Address */ 0x02 , 0x00 , 0x00 , 0x00 , 0x00 , 0x48 , 0xDE , 0xAC , /* PAN-ID */ 0xFF , 0xFF , /* Source Address */ 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x48 , 0xDE , 0xAC , /* Security Level */ 0x06 , /* Frame Counter */ 0x05 , 0x00 , 0x00 , 0x00 , 0x01 , 0xCE }; uint8_t oracle[LLSEC802154_MIC_LENGTH] = { 0x4F , 0xDE , 0x52 , 0x90 , 0x61 , 0xF9 , 0xC6 , 0xF1 }; frame802154_frame_counter_t counter; uint8_t mic[LLSEC802154_MIC_LENGTH]; printf("Testing verification ... "); packetbuf_clear(); packetbuf_set_datalen(30); memcpy(packetbuf_hdrptr(), data, 30); counter.u32 = 5; packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1, counter.u16[0]); packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3, counter.u16[1]); packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, LLSEC802154_SECURITY_LEVEL); packetbuf_hdrreduce(29); CCM_STAR.set_key(key); ccm_star_mic_packetbuf(extended_source_address, mic, LLSEC802154_MIC_LENGTH); if(memcmp(mic, oracle, LLSEC802154_MIC_LENGTH) == 0) { printf("Success\n"); } else { printf("Failure\n"); } printf("Testing encryption ... "); ccm_star_ctr_packetbuf(extended_source_address); if(((uint8_t *) packetbuf_hdrptr())[29] == 0xD8) { printf("Success\n"); } else { printf("Failure\n"); } printf("Testing decryption ... "); ccm_star_ctr_packetbuf(extended_source_address); if(((uint8_t *) packetbuf_hdrptr())[29] == 0xCE) { printf("Success\n"); } else { printf("Failure\n"); } }
/*---------------------------------------------------------------------------*/ static void input_packet(void) { static struct ctimer ct; if(!we_are_receiving_burst) { off(); } /* printf("cycle_start 0x%02x 0x%02x\n", cycle_start, cycle_start % CYCLE_TIME);*/ #ifdef NETSTACK_DECRYPT NETSTACK_DECRYPT(); #endif /* NETSTACK_DECRYPT */ if(packetbuf_totlen() > 0 && NETSTACK_FRAMER.parse() >= 0) { #if WITH_CONTIKIMAC_HEADER struct hdr *chdr; chdr = packetbuf_dataptr(); if(chdr->id != CONTIKIMAC_ID) { PRINTF("contikimac: failed to parse hdr (%u)\n", packetbuf_totlen()); return; } packetbuf_hdrreduce(sizeof(struct hdr)); packetbuf_set_datalen(chdr->len); #endif /* WITH_CONTIKIMAC_HEADER */ if(packetbuf_datalen() > 0 && packetbuf_totlen() > 0 && (rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_node_addr) || rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null))) { /* This is a regular packet that is destined to us or to the broadcast address. */ #if !RDC_CONF_HARDWARE_SEND_ACK if (rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_node_addr)) { we_are_acking = 1; /* need to send an ack */ static uint8_t ackbuf[ACK_LEN] = { 0 }; ackbuf[ACK_LEN - 1] = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID); NETSTACK_RADIO.send(ackbuf, ACK_LEN); we_are_acking = 0; } #endif /* If FRAME_PENDING is set, we are receiving a packets in a burst */ we_are_receiving_burst = packetbuf_attr(PACKETBUF_ATTR_PENDING); if(we_are_receiving_burst) { on(); /* Set a timer to turn the radio off in case we do not receive a next packet */ ctimer_set(&ct, INTER_PACKET_DEADLINE, recv_burst_off, NULL); } else { off(); ctimer_stop(&ct); } /* Check for duplicate packet. */ if(mac_sequence_is_duplicate()) { /* Drop the packet. */ /* printf("Drop duplicate ContikiMAC layer packet\n");*/ return; } mac_sequence_register_seqno(); #if CONTIKIMAC_CONF_COMPOWER /* Accumulate the power consumption for the packet reception. */ compower_accumulate(¤t_packet); /* Convert the accumulated power consumption for the received packet to packet attributes so that the higher levels can keep track of the amount of energy spent on receiving the packet. */ compower_attrconv(¤t_packet); /* Clear the accumulated power consumption so that it is ready for the next packet. */ compower_clear(¤t_packet); #endif /* CONTIKIMAC_CONF_COMPOWER */ PRINTDEBUG("contikimac: data (%u)\n", packetbuf_datalen()); NETSTACK_MAC.input(); return; } else { PRINTDEBUG("contikimac: data not for us\n"); } } else { PRINTF("contikimac: failed to parse (%u)\n", packetbuf_totlen()); } }
/*---------------------------------------------------------------------------*/ static void input_packet(void) { struct cxmac_hdr *hdr; if(NETSTACK_FRAMER.parse() >= 0) { hdr = packetbuf_dataptr(); if(hdr->dispatch != DISPATCH) { someone_is_sending = 0; if(linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &linkaddr_node_addr) || linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &linkaddr_null)) { /* This is a regular packet that is destined to us or to the broadcast address. */ /* We have received the final packet, so we can go back to being asleep. */ off(); #if CXMAC_CONF_COMPOWER /* Accumulate the power consumption for the packet reception. */ compower_accumulate(¤t_packet); /* Convert the accumulated power consumption for the received packet to packet attributes so that the higher levels can keep track of the amount of energy spent on receiving the packet. */ compower_attrconv(¤t_packet); /* Clear the accumulated power consumption so that it is ready for the next packet. */ compower_clear(¤t_packet); #endif /* CXMAC_CONF_COMPOWER */ waiting_for_packet = 0; PRINTDEBUG("cxmac: data(%u)\n", packetbuf_datalen()); NETSTACK_MAC.input(); return; } else { PRINTDEBUG("cxmac: data not for us\n"); } } else if(hdr->type == TYPE_STROBE) { someone_is_sending = 2; if(linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &linkaddr_node_addr)) { /* This is a strobe packet for us. */ /* If the sender address is someone else, we should acknowledge the strobe and wait for the packet. By using the same address as both sender and receiver, we flag the message is a strobe ack. */ hdr->type = TYPE_STROBE_ACK; packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, packetbuf_addr(PACKETBUF_ADDR_SENDER)); packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &linkaddr_node_addr); packetbuf_compact(); if(NETSTACK_FRAMER.create() >= 0) { /* We turn on the radio in anticipation of the incoming packet. */ someone_is_sending = 1; waiting_for_packet = 1; on(); NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen()); PRINTDEBUG("cxmac: send strobe ack %u\n", packetbuf_totlen()); } else { PRINTF("cxmac: failed to send strobe ack\n"); } } else if(linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &linkaddr_null)) { /* If the receiver address is null, the strobe is sent to prepare for an incoming broadcast packet. If this is the case, we turn on the radio and wait for the incoming broadcast packet. */ waiting_for_packet = 1; on(); } else { PRINTDEBUG("cxmac: strobe not for us\n"); } /* We are done processing the strobe and we therefore return to the caller. */ return; #if CXMAC_CONF_ANNOUNCEMENTS } else if(hdr->type == TYPE_ANNOUNCEMENT) { packetbuf_hdrreduce(sizeof(struct cxmac_hdr)); parse_announcements(packetbuf_addr(PACKETBUF_ADDR_SENDER)); #endif /* CXMAC_CONF_ANNOUNCEMENTS */ } else if(hdr->type == TYPE_STROBE_ACK) { PRINTDEBUG("cxmac: stray strobe ack\n"); } else { PRINTF("cxmac: unknown type %u (%u)\n", hdr->type, packetbuf_datalen()); } } else { PRINTF("cxmac: failed to parse (%u)\n", packetbuf_totlen()); } }
/*---------------------------------------------------------------------------*/ static void input_packet(void) { static struct ctimer ct; if(!we_are_receiving_burst) { off(); } /* printf("cycle_start 0x%02x 0x%02x\n", cycle_start, cycle_start % CYCLE_TIME);*/ #ifdef NETSTACK_DECRYPT NETSTACK_DECRYPT(); #endif /* NETSTACK_DECRYPT */ if(packetbuf_totlen() > 0 && NETSTACK_FRAMER.parse() >= 0) { #if WITH_CONTIKIMAC_HEADER struct hdr *chdr; chdr = packetbuf_dataptr(); if(chdr->id != CONTIKIMAC_ID) { PRINTF("contikimac: failed to parse hdr (%u)\n", packetbuf_totlen()); return; } packetbuf_hdrreduce(sizeof(struct hdr)); packetbuf_set_datalen(chdr->len); #endif /* WITH_CONTIKIMAC_HEADER */ if(packetbuf_datalen() > 0 && packetbuf_totlen() > 0 && (rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_node_addr) || rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null))) { /* This is a regular packet that is destined to us or to the broadcast address. */ /* If FRAME_PENDING is set, we are receiving a packets in a burst */ we_are_receiving_burst = packetbuf_attr(PACKETBUF_ATTR_PENDING); if(we_are_receiving_burst) { on(); /* Set a timer to turn the radio off in case we do not receive a next packet */ ctimer_set(&ct, INTER_PACKET_DEADLINE, recv_burst_off, NULL); } else { off(); ctimer_stop(&ct); } /* Check for duplicate packet by comparing the sequence number of the incoming packet with the last few ones we saw. */ { int i; for(i = 0; i < MAX_SEQNOS; ++i) { if(packetbuf_attr(PACKETBUF_ATTR_PACKET_ID) == received_seqnos[i].seqno && rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_SENDER), &received_seqnos[i].sender)) { /* Drop the packet. */ /* printf("Drop duplicate ContikiMAC layer packet\n");*/ return; } } for(i = MAX_SEQNOS - 1; i > 0; --i) { memcpy(&received_seqnos[i], &received_seqnos[i - 1], sizeof(struct seqno)); } received_seqnos[0].seqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID); rimeaddr_copy(&received_seqnos[0].sender, packetbuf_addr(PACKETBUF_ADDR_SENDER)); } #if CONTIKIMAC_CONF_COMPOWER /* Accumulate the power consumption for the packet reception. */ compower_accumulate(¤t_packet); /* Convert the accumulated power consumption for the received packet to packet attributes so that the higher levels can keep track of the amount of energy spent on receiving the packet. */ compower_attrconv(¤t_packet); /* Clear the accumulated power consumption so that it is ready for the next packet. */ compower_clear(¤t_packet); #endif /* CONTIKIMAC_CONF_COMPOWER */ PRINTDEBUG("contikimac: data (%u)\n", packetbuf_datalen()); NETSTACK_MAC.input(); return; } else { PRINTDEBUG("contikimac: data not for us\n"); } } else { PRINTF("contikimac: failed to parse (%u)\n", packetbuf_totlen()); } }
/*---------------------------------------------------------------------------*/ static void recv(struct polite_conn *polite) { struct rudolph2_conn *c = (struct rudolph2_conn *)polite; struct rudolph2_hdr *hdr = packetbuf_dataptr(); /* Only accept NACKs from nodes that are farther away from the base than us. */ if(hdr->type == TYPE_NACK && hdr->hops_from_base > c->hops_from_base) { c->nacks++; PRINTF("%d.%d: Got NACK for %d:%d (%d:%d)\n", rimeaddr_node_addr.u8[RIMEADDR_SIZE-2], rimeaddr_node_addr.u8[RIMEADDR_SIZE-1], hdr->version, hdr->chunk, c->version, c->rcv_nxt); if(hdr->version == c->version) { if(hdr->chunk < c->rcv_nxt) { c->snd_nxt = hdr->chunk; send_data(c, SEND_INTERVAL); } } else if(LT(hdr->version, c->version)) { c->snd_nxt = 0; send_data(c, SEND_INTERVAL); } } else if(hdr->type == TYPE_DATA) { if(hdr->hops_from_base < c->hops_from_base) { /* Only accept data from nodes that are closer to the base than us. */ c->hops_from_base = hdr->hops_from_base + 1; if(LT(c->version, hdr->version)) { PRINTF("%d.%d: rudolph2 new version %d, chunk %d\n", rimeaddr_node_addr.u8[RIMEADDR_SIZE-2], rimeaddr_node_addr.u8[RIMEADDR_SIZE-1], hdr->version, hdr->chunk); c->version = hdr->version; c->snd_nxt = c->rcv_nxt = 0; c->flags &= ~FLAG_LAST_RECEIVED; c->flags &= ~FLAG_LAST_SENT; if(hdr->chunk != 0) { send_nack(c); } else { packetbuf_hdrreduce(sizeof(struct rudolph2_hdr)); write_data(c, 0, packetbuf_dataptr(), packetbuf_totlen()); } } else if(hdr->version == c->version) { PRINTF("%d.%d: got chunk %d snd_nxt %d rcv_nxt %d\n", rimeaddr_node_addr.u8[RIMEADDR_SIZE-2], rimeaddr_node_addr.u8[RIMEADDR_SIZE-1], hdr->chunk, c->snd_nxt, c->rcv_nxt); if(hdr->chunk == c->rcv_nxt) { int len; packetbuf_hdrreduce(sizeof(struct rudolph2_hdr)); PRINTF("%d.%d: received chunk %d len %d\n", rimeaddr_node_addr.u8[RIMEADDR_SIZE-2], rimeaddr_node_addr.u8[RIMEADDR_SIZE-1], hdr->chunk, packetbuf_totlen()); len = packetbuf_totlen(); write_data(c, hdr->chunk, packetbuf_dataptr(), packetbuf_totlen()); c->rcv_nxt++; if(len < RUDOLPH2_DATASIZE) { c->flags |= FLAG_LAST_RECEIVED; send_data(c, RESEND_INTERVAL); ctimer_set(&c->t, RESEND_INTERVAL, timed_send, c); } } else if(hdr->chunk > c->rcv_nxt) { PRINTF("%d.%d: received chunk %d > %d, sending NACK\n", rimeaddr_node_addr.u8[RIMEADDR_SIZE-2], rimeaddr_node_addr.u8[RIMEADDR_SIZE-1], hdr->chunk, c->rcv_nxt); send_nack(c); } else if(hdr->chunk < c->rcv_nxt) { /* Ignore packets with a lower chunk number */ } } } } }