void eth_drv_send(void) { LOG6LBR_PRINTF(PACKET, ETH_OUT, "write: %d\n", uip_len + ETHERNET_LLH_LEN); LOG6LBR_COND_FUNC(DUMP, ETH_OUT, int i; #if WIRESHARK_IMPORT_FORMAT printf("0000"); for(i = 0; i < ETHERNET_LLH_LEN; i++) printf(" %02x", ll_header[i]); for(i = 0; i < uip_len; i++) printf(" %02x", uip_buf[i]); #else printf(" "); for(i = 0; i < uip_len + ETHERNET_LLH_LEN; i++) { if ( i < ETHERNET_LLH_LEN ) { printf("%02x", ll_header[i]); } else { printf("%02x", uip_buf[i - ETHERNET_LLH_LEN]); } if((i & 3) == 3) printf(" "); if((i & 15) == 15) printf("\n "); } #endif printf("\n"); )
/*---------------------------------------------------------------------------*/ static void packet_input(void) { LOG6LBR_PRINTF(PACKET, RADIO_IN, "read: %d\n", packetbuf_datalen()); if (LOG6LBR_COND(DUMP, RADIO_IN)) { uint8_t *data = packetbuf_dataptr(); int len = packetbuf_datalen(); int i; #if WIRESHARK_IMPORT_FORMAT printf("0000"); for(i = 0; i < len; i++) printf(" %02x", data[i]); #else printf(" "); for(i = 0; i < len; i++) { printf("%02x", data[i]); if((i & 3) == 3) printf(" "); if((i & 15) == 15) printf("\n "); } #endif printf("\n"); } if(NETSTACK_FRAMER.parse() < 0) { LOG6LBR_ERROR("br-rdc: failed to parse %u\n", packetbuf_datalen()); } else { NETSTACK_MAC.input(); } }
static uint8_t bridge_output(uip_lladdr_t * dest) { int isBroadcast = IS_BROADCAST_ADDR(dest); int wsnDest = 0; if(!isBroadcast) { LOG6LBR_LLADDR_PRINTF(PACKET, PF_OUT, dest, "bridge_output: Sending packet to "); } else { LOG6LBR_PRINTF(PACKET, PF_OUT, "bridge_output: Sending packet to Broadcast\n"); } if(isBroadcast) { //Obviously we can not guess the target segment for a multicast packet //So we have to check the packet source prefix (and match it on the Ethernet segment prefix) //or, in case of link-local packet, check packet type and/or packet data if((UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type == ICMP6_RA) || (UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type == ICMP6_NS && uip_ipaddr_prefixcmp(&wsn_net_prefix, &UIP_ND6_NS_BUF->tgtipaddr, 64)) || uip_ipaddr_prefixcmp(&wsn_net_prefix, &UIP_IP_BUF->srcipaddr, 64)) { wsnDest = 1; } } if(wsnDest || IS_EUI64_ADDR(dest)) { wireless_output(NULL, dest); } else { eth_output(NULL, dest); } return 0; }
uint8_t wireless_output(const uip_lladdr_t * src, const uip_lladdr_t * dest) { int ret; //Packet filtering //---------------- if(uip_len == 0) { LOG6LBR_ERROR("wireless_output: uip_len = 0\n"); return 0; } if(dest && linkaddr_cmp((linkaddr_t *) & dest, (linkaddr_t *) & wsn_mac_addr)) { LOG6LBR_ERROR("wireless_output: sending to self\n"); return 0; } //Packet sending //-------------- if(wireless_outputfunc != NULL) { LOG6LBR_PRINTF(PACKET, PF_OUT, "wireless_output: sending packet\n"); ret = wireless_outputfunc(dest); } else { ret = 0; } return ret; }
void eth_drv_send(uint8_t *packet, uint16_t len) { LOG6LBR_PRINTF(PACKET, ETH_OUT, "write: %d\n", len); LOG6LBR_DUMP_PACKET(ETH_OUT, packet, len); eth_dev_output(packet, len); }
/*---------------------------------------------------------------------------*/ void eth_dev_output(uint8_t * data, int len) { if(write(eth_fd, data, len) != len) { LOG6LBR_FATAL("write() : %s\n", strerror(errno)); exit(1); } LOG6LBR_PRINTF(PACKET, TAP_OUT, "write: %d\n", len); }
/*---------------------------------------------------------------------------*/ static int eth_dev_input(unsigned char *data, int maxlen) { int size; if((size = read(eth_fd, data, maxlen)) == -1) { LOG6LBR_FATAL("read() : %s\n", strerror(errno)); exit(1); } LOG6LBR_PRINTF(PACKET, TAP_IN, "read: %d\n", size); return size; }
/*---------------------------------------------------------------------------*/ static void packet_input(void) { LOG6LBR_PRINTF(PACKET, RADIO_IN, "read: %d\n", packetbuf_datalen()); LOG6LBR_DUMP_PACKET(RADIO_IN, packetbuf_dataptr(), packetbuf_datalen()); if(NETSTACK_FRAMER.parse() < 0) { LOG6LBR_ERROR("br-rdc: failed to parse %u\n", packetbuf_datalen()); native_rdc_parse_error++; } else { NETSTACK_MAC.input(); } }
/*---------------------------------------------------------------------------*/ static void send_packet(mac_callback_t sent, void *ptr) { int size; /* 3 bytes per packet attribute is required for serialization */ uint8_t buf[PACKETBUF_NUM_ATTRS * 3 + PACKETBUF_SIZE + 3]; int sid; packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &linkaddr_node_addr); /* ack or not ? */ packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1); if(NETSTACK_FRAMER.create_and_secure() < 0) { /* Failed to allocate space for headers */ LOG6LBR_ERROR("br-rdc: send failed, too large header\n"); mac_call_sent_callback(sent, ptr, MAC_TX_ERR_FATAL, 1); } else { /* here we send the data over SLIP to the radio-chip */ size = 0; if(sixlbr_config_slip_serialize_tx_attrs) { size = packetutils_serialize_atts(&buf[3], sizeof(buf) - 3); } if(size < 0 || size + packetbuf_totlen() + 3 > sizeof(buf)) { LOG6LBR_ERROR("br-rdc: send failed, too large header\n"); mac_call_sent_callback(sent, ptr, MAC_TX_ERR_FATAL, 1); } else { sid = setup_callback(sent, ptr); if (sid != -1) { LOG6LBR_PRINTF(PACKET, RADIO_OUT, "write: %d (sid: %d, cb: %d)\n", packetbuf_datalen(), sid, callback_count); LOG6LBR_DUMP_PACKET(RADIO_OUT, packetbuf_dataptr(), packetbuf_datalen()); buf[0] = '!'; buf[1] = 'S'; buf[2] = sid; /* sequence or session number for this packet */ /* Copy packet data */ memcpy(&buf[3 + size], packetbuf_hdrptr(), packetbuf_totlen()); callbacks[sid].buf_len = packetbuf_totlen() + size + 3; memcpy(callbacks[sid].buf, buf, callbacks[sid].buf_len); write_to_slip(buf, callbacks[sid].buf_len); } else { LOG6LBR_INFO("native-rdc queue full\n"); mac_call_sent_callback(sent, ptr, MAC_TX_NOACK, 1); } } } }
static int eth_output(const uip_lladdr_t * src, const uip_lladdr_t * dest) { //Packet filtering //---------------- if(uip_len == 0) { LOG6LBR_ERROR("eth_output: uip_len = 0\n"); return 0; } if(dest && linkaddr_cmp((linkaddr_t *) & dest, (linkaddr_t *) & eth_mac64_addr)) { LOG6LBR_ERROR("ethernet_output: sending to self\n"); return 0; } //Create packet header //-------------------- //Packet type BUF->type = uip_htons(UIP_ETHTYPE_IPV6); //Destination address if(IS_BROADCAST_ADDR(dest)) { BUF->dest.addr[0] = 0x33; BUF->dest.addr[1] = 0x33; BUF->dest.addr[2] = UIP_IP_BUF->destipaddr.u8[12]; BUF->dest.addr[3] = UIP_IP_BUF->destipaddr.u8[13]; BUF->dest.addr[4] = UIP_IP_BUF->destipaddr.u8[14]; BUF->dest.addr[5] = UIP_IP_BUF->destipaddr.u8[15]; } else { memcpy(BUF->dest.addr, dest, 6); } //Source address if ( src != NULL ) { memcpy(BUF->src.addr, src, 6); } else { memcpy(BUF->src.addr, eth_mac_addr, 6); } //Sending packet //-------------- LOG6LBR_PRINTF(PACKET, PF_OUT, "eth_output: Sending packet to Ethernet\n"); eth_drv_send(); return 1; }
uint8_t wireless_output(const uip_lladdr_t * src, const uip_lladdr_t * dest) { int ret; //Packet filtering //---------------- if(uip_len == 0) { LOG6LBR_ERROR("wireless_output: uip_len = 0\n"); return 0; } if(dest && linkaddr_cmp((linkaddr_t *) & dest, (linkaddr_t *) & wsn_mac_addr)) { LOG6LBR_ERROR("wireless_output: sending to self\n"); return 0; } #if CETIC_6LBR_WSN_FILTER_RA //Filter out RA/RS towards WSN if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && (UIP_ICMP_BUF->type == ICMP6_RS || UIP_ICMP_BUF->type == ICMP6_RA)) { return 0; } #endif //Packet sending //-------------- if(wireless_outputfunc != NULL) { #if CETIC_6LBR_TRANSPARENTBRIDGE if ( src != NULL ) { platform_set_wsn_mac((linkaddr_t *)src); } #endif LOG6LBR_PRINTF(PACKET, PF_OUT, "wireless_output: sending packet\n"); ret = wireless_outputfunc(dest); #if CETIC_6LBR_TRANSPARENTBRIDGE if ( src != NULL ) { //Restore node address platform_set_wsn_mac((linkaddr_t *) & wsn_mac_addr); } #endif } else { ret = 0; } return ret; }
/*---------------------------------------------------------------------------*/ static void write_to_serial(int outfd, const uint8_t * inbuf, int len) { const uint8_t *p = inbuf; int i; slip_message_sent++; LOG6LBR_PRINTF(PACKET, SLIP_OUT, "write: %d\n", len); if (LOG6LBR_COND(DUMP, SLIP_OUT)) { printf(" "); for(i = 0; i < len; i++) { printf("%02x", p[i]); if((i & 3) == 3) printf(" "); if((i & 15) == 15) printf("\n "); } printf("\n"); } /* It would be ``nice'' to send a SLIP_END here but it's not * really necessary. */ /* slip_send(outfd, SLIP_END); */ for(i = 0; i < len; i++) { switch (p[i]) { case SLIP_END: slip_send(outfd, SLIP_ESC); slip_send(outfd, SLIP_ESC_END); break; case SLIP_ESC: slip_send(outfd, SLIP_ESC); slip_send(outfd, SLIP_ESC_ESC); break; default: slip_send(outfd, p[i]); break; } } slip_send(outfd, SLIP_END); PROGRESS("t"); }
/*---------------------------------------------------------------------------*/ void eth_drv_input(uint8_t *packet, uint16_t len) { LOG6LBR_PRINTF(PACKET, ETH_IN, "read: %d\n", len); LOG6LBR_DUMP_PACKET(ETH_IN, packet, len); #if CETIC_6LBR_IP64 if((nvm_data.global_flags & CETIC_GLOBAL_IP64) != 0 && (((struct uip_eth_hdr *)packet)->type != UIP_HTONS(UIP_ETHTYPE_IPV6))) { IP64_INPUT(packet, len); } else { #endif uip_len = len - UIP_LLH_LEN; memcpy(uip_buf, packet, len); eth_input(); #if CETIC_6LBR_IP64 } #endif }
static uint8_t bridge_output(const uip_lladdr_t * dest) { int isBroadcast = IS_BROADCAST_ADDR(dest); if(!isBroadcast) { LOG6LBR_LLADDR_PRINTF(PACKET, PF_OUT, dest, "bridge_output: Sending packet to "); } else { LOG6LBR_PRINTF(PACKET, PF_OUT, "bridge_output: Sending packet to Broadcast\n"); } //Filter WSN vs Ethernet segment traffic if(IS_EUI48_ADDR(dest)) { eth_output(NULL, dest); } else if(IS_EUI64_ADDR(dest)) { wireless_output(NULL, dest); } else { if (UIP_IP_BUF->proto != UIP_PROTO_ICMP6 || UIP_ICMP_BUF->type != ICMP6_NA) { wireless_output(NULL, dest); } eth_output(NULL, dest); } return 0; }
/*---------------------------------------------------------------------------*/ void packet_sent(uint8_t sessionid, uint8_t status, uint8_t tx) { LOG6LBR_PRINTF(PACKET, RADIO_OUT, "sid ack: %d (%d, %d)\n", sessionid, status, tx); if(sessionid < MAX_CALLBACKS) { struct tx_callback *callback; callback = &callbacks[sessionid]; if (callback->isused) { callback_count--; callback->isused = 0; packetbuf_clear(); packetbuf_attr_copyfrom(callback->attrs, callback->addrs); ctimer_stop(&callback->timeout); mac_call_sent_callback(callback->cback, callback->ptr, status, tx); } else { LOG6LBR_ERROR("br-rdc: ack received for unknown packet (%d)\n", callback->sid); } } else { LOG6LBR_ERROR("*** ERROR: too high session id %d\n", sessionid); } }
static uint8_t bridge_output(uip_lladdr_t * dest) { int ethernetDest = 0; if(uip_len == 0) { LOG6LBR_ERROR("Trying to send empty packet\n"); return 0; } if(!IS_BROADCAST_ADDR(dest)) { LOG6LBR_LLADDR_PRINTF(PACKET, PF_OUT, dest, "bridge_output: Sending packet to "); } else { LOG6LBR_PRINTF(PACKET, PF_OUT, "bridge_output: Sending packet to Broadcast\n"); } if(IS_BROADCAST_ADDR(dest)) { //Obviously we can not guess the target segment for a multicast packet //So we have to check the packet source prefix (and match it on the Ethernet segment prefix) //or, in case of link-local packet, check packet type and/or packet data if((UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type == ICMP6_RA) || (UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type == ICMP6_NS && uip_ipaddr_prefixcmp(ð_net_prefix, &UIP_ND6_NS_BUF->tgtipaddr, 64)) || uip_ipaddr_prefixcmp(ð_net_prefix, &UIP_IP_BUF->srcipaddr, 64)) { ethernetDest = 1; } } if(ethernetDest || IS_EUI48_ADDR(dest)) { eth_output(NULL, dest); } else { #if CETIC_6LBR_ONE_ITF eth_output(&wsn_mac_addr, dest); #else wireless_output(NULL, dest); #endif } return 0; }
static int eth_output(uip_lladdr_t * src, uip_lladdr_t * dest) { if(IS_BROADCAST_ADDR(dest)) { LOG6LBR_PRINTF(PACKET, PF_OUT, "eth_output: broadcast\n"); } else { LOG6LBR_LLADDR_PRINTF(PACKET, PF_OUT, dest, "eth_output: "); } //Packet filtering //---------------- if(uip_len == 0) { LOG6LBR_ERROR("eth_output: uip_len = 0\n"); return 0; } #if CETIC_6LBR_ETH_FILTER_RPL //Filter out RPL (broadcast) traffic if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type == ICMP6_RPL) { //LOG6LBR_PRINTF(PACKET, PF_OUT, "eth_output: Filtering out RPL traffic\n"); return 0; } #endif //IP packet alteration //-------------------- #if CETIC_6LBR_ROUTER //Modify source address if((nvm_data.mode & CETIC_MODE_REWRITE_ADDR_MASK) != 0 && uip_is_addr_link_local(&UIP_IP_BUF->srcipaddr) && uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)) { LOG6LBR_PRINTF(PACKET, PF_OUT, "eth_output: Update src address\n"); uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, ð_ip_local_addr); } #endif #if CETIC_6LBR_SMARTBRIDGE //Reset Hop Limit when in smart-bridge for NDP packets //TODO: Is this still needed after #4467 ? if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && (UIP_ICMP_BUF->type == ICMP6_NS || UIP_ICMP_BUF->type == ICMP6_NA || UIP_ICMP_BUF->type == ICMP6_RS || UIP_ICMP_BUF->type == ICMP6_RA)) { UIP_IP_BUF->ttl = 255; } #endif #if CETIC_6LBR_SMARTBRIDGE || CETIC_6LBR_TRANSPARENTBRIDGE //Remove ROUTER flag when in bridge mode if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type == ICMP6_NA) { //LOG6LBR_PRINTF(PACKET, PF_OUT, "eth_output: Updating NA\n"); UIP_ND6_NA_BUF->flagsreserved &= ~UIP_ND6_NA_FLAG_ROUTER; } #endif //Some IP packets have link layer in them, need to change them around! mac_translateIPLinkLayer(ll_8023_type); //IP header alteration //-------------------- //Remove Hop-by-hop extension header if(uip_ext_len > 0) { extern void remove_ext_hdr(void); uint8_t proto = *((uint8_t *) UIP_IP_BUF + 40); remove_ext_hdr(); UIP_IP_BUF->proto = proto; } //Create packet header //-------------------- //Packet type BUF->type = uip_htons(UIP_ETHTYPE_IPV6); //Destination address if(IS_BROADCAST_ADDR(dest)) { BUF->dest.addr[0] = 0x33; BUF->dest.addr[1] = 0x33; BUF->dest.addr[2] = UIP_IP_BUF->destipaddr.u8[12]; BUF->dest.addr[3] = UIP_IP_BUF->destipaddr.u8[13]; BUF->dest.addr[4] = UIP_IP_BUF->destipaddr.u8[14]; BUF->dest.addr[5] = UIP_IP_BUF->destipaddr.u8[15]; } else { mac_createEthernetAddr(BUF->dest.addr, dest); } //Source address if ( src != NULL ) { mac_createEthernetAddr(BUF->src.addr, src); } else { memcpy(BUF->src.addr, eth_mac_addr, 6); } //Sending packet //-------------- LOG6LBR_PRINTF(PACKET, PF_OUT, "eth_output: Sending packet to Ethernet\n"); eth_drv_send(); return 1; }
void eth_input(void) { #if CETIC_6LBR_TRANSPARENTBRIDGE || CETIC_6LBR_ONE_ITF || CETIC_6LBR_6LR uip_lladdr_t srcAddr; #endif uip_lladdr_t destAddr; int processFrame = 0; int forwardFrame = 0; //Packet type filtering //--------------------- //Keep only IPv6 traffic if(BUF->type != UIP_HTONS(UIP_ETHTYPE_IPV6)) { LOG6LBR_PRINTF(PACKET, PF_IN, "eth_input: Dropping packet type=0x%04x\n", uip_ntohs(BUF->type)); uip_len = 0; return; } //Packet source Filtering //----------------------- /* IPv6 uses 33-33-xx-xx-xx-xx prefix for multicast ND stuff */ if((BUF->dest.addr[0] == 0x33) && (BUF->dest.addr[1] == 0x33)) { forwardFrame = 1; processFrame = 1; rimeaddr_copy((rimeaddr_t *) & destAddr, &rimeaddr_null); } else if((BUF->dest.addr[0] == 0xFF) && (BUF->dest.addr[1] == 0xFF) && (BUF->dest.addr[2] == 0xFF) && (BUF->dest.addr[3] == 0xFF) && (BUF->dest.addr[4] == 0xFF) && (BUF->dest.addr[5] == 0xFF)) { /* IPv6 does not use broadcast addresses, hence this should not happen */ LOG6LBR_PRINTF(PACKET, PF_IN, "eth_input: Dropping broadcast packet\n"); uip_len = 0; return; } else { /* Complex Address Translation */ if(mac_createSicslowpanLongAddr(&(BUF->dest.addr[0]), &destAddr) == 0) { LOG6LBR_WARN("eth_input: Address translation failed\n"); uip_len = 0; return; } } //Packet content rewriting //------------------------ //Some IP packets have link layer in them, need to change them around! uint8_t transReturn = mac_translateIPLinkLayer(ll_802154_type); if(transReturn != 0) { LOG6LBR_WARN("eth_input: IPTranslation returns %d\n", transReturn); } //Destination filtering //--------------------- if(memcmp((uint8_t *) & eth_mac_addr, BUF->dest.addr, 6) == 0) { processFrame = 1; } else { #if CETIC_6LBR_TRANSPARENTBRIDGE //Not for us, forward it directly forwardFrame = 1; #endif } //Handle packet //------------- #if CETIC_6LBR_TRANSPARENTBRIDGE if(forwardFrame) { mac_createSicslowpanLongAddr(&(BUF->src.addr[0]), &srcAddr); #if CETIC_6LBR_LEARN_RPL_MAC if (UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type == ICMP6_RPL) { uint8_t *buffer = UIP_ICMP_PAYLOAD; uint16_t rank = (uint16_t)buffer[2] << 8 | buffer[2 + 1]; if ( rank == RPL_MIN_HOPRANKINC ) { platform_set_wsn_mac((rimeaddr_t *) &srcAddr); rpl_mac_known=1; } } if (!rpl_mac_known) { //Rpl Relay not yet configured, drop packet uip_len = 0; return; } if(rimeaddr_cmp((rimeaddr_t *) &srcAddr, &rimeaddr_node_addr) != 0) { //Only forward RplRoot packets LOG6LBR_LLADDR_PRINTF(PACKET, PF_IN, &destAddr, "eth_input: Forwarding frame to "); wireless_output(NULL, &destAddr); } #else LOG6LBR_LLADDR_PRINTF(PACKET, PF_IN, &destAddr, "eth_input: Forwarding frame to "); wireless_output(&srcAddr, &destAddr); #endif } #endif if(processFrame) { LOG6LBR_PRINTF(PACKET, PF_IN, "eth_input: Processing frame\n"); #if CETIC_6LBR_ONE_ITF || CETIC_6LBR_6LR //RPL uses source packet address to populate its neighbor table //In this two modes RPL packets are incoming from Eth interface mac_createSicslowpanLongAddr(&(BUF->src.addr[0]), &srcAddr); packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (rimeaddr_t *) &srcAddr); #endif send_to_uip(); } else { //Drop packet uip_len = 0; } }
/*---------------------------------------------------------------------------*/ static void send_packet(mac_callback_t sent, void *ptr) { int size; /* 3 bytes per packet attribute is required for serialization */ uint8_t buf[PACKETBUF_NUM_ATTRS * 3 + PACKETBUF_SIZE + 3]; uint8_t sid; packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &rimeaddr_node_addr); /* ack or not ? */ packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1); if(NETSTACK_FRAMER.create() < 0) { /* Failed to allocate space for headers */ LOG6LBR_ERROR("br-rdc: send failed, too large header\n"); mac_call_sent_callback(sent, ptr, MAC_TX_ERR_FATAL, 1); } else { /* here we send the data over SLIP to the radio-chip */ size = 0; #if SERIALIZE_ATTRIBUTES size = packetutils_serialize_atts(&buf[3], sizeof(buf) - 3); #endif if(size < 0 || size + packetbuf_totlen() + 3 > sizeof(buf)) { LOG6LBR_ERROR("br-rdc: send failed, too large header\n"); mac_call_sent_callback(sent, ptr, MAC_TX_ERR_FATAL, 1); } else { LOG6LBR_PRINTF(PACKET, RADIO_OUT, "write: %d\n", packetbuf_datalen()); if (LOG6LBR_COND(DUMP, RADIO_OUT)) { uint8_t *data = packetbuf_dataptr(); int len = packetbuf_datalen(); int i; #if WIRESHARK_IMPORT_FORMAT printf("0000"); for(i = 0; i < len; i++) printf(" %02x", data[i]); #else printf(" "); for(i = 0; i < len; i++) { printf("%02x", data[i]); if((i & 3) == 3) printf(" "); if((i & 15) == 15) printf("\n "); } #endif printf("\n"); } sid = setup_callback(sent, ptr); buf[0] = '!'; buf[1] = 'S'; buf[2] = sid; /* sequence or session number for this packet */ /* Copy packet data */ memcpy(&buf[3 + size], packetbuf_hdrptr(), packetbuf_totlen()); write_to_slip(buf, packetbuf_totlen() + size + 3); } } }
static int eth_output(const uip_lladdr_t * src, const uip_lladdr_t * dest) { if(IS_BROADCAST_ADDR(dest)) { LOG6LBR_PRINTF(PACKET, PF_OUT, "eth_output: broadcast\n"); } else { LOG6LBR_LLADDR_PRINTF(PACKET, PF_OUT, dest, "eth_output: "); } //Packet filtering //---------------- if(uip_len == 0) { LOG6LBR_ERROR("eth_output: uip_len = 0\n"); return 0; } if(dest && linkaddr_cmp((linkaddr_t *) & dest, (linkaddr_t *) & eth_mac64_addr)) { LOG6LBR_ERROR("ethernet_output: sending to self\n"); return 0; } #if CETIC_6LBR_ETH_FILTER_RPL //Filter out RPL (broadcast) traffic if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type == ICMP6_RPL) { //LOG6LBR_PRINTF(PACKET, PF_OUT, "eth_output: Filtering out RPL traffic\n"); return 0; } #endif //IP packet alteration //-------------------- #if CETIC_6LBR_ROUTER //Modify source address if((nvm_data.mode & CETIC_MODE_REWRITE_ADDR_MASK) != 0 && uip_is_addr_link_local(&UIP_IP_BUF->srcipaddr) && uip_ipaddr_cmp(&UIP_IP_BUF->srcipaddr, &wsn_ip_local_addr)) { LOG6LBR_PRINTF(PACKET, PF_OUT, "eth_output: Update src address\n"); uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, ð_ip_local_addr); if(UIP_IP_BUF->proto == UIP_PROTO_UDP) { #if UIP_UDP_CHECKSUMS /* Calculate UDP checksum. */ UIP_UDP_BUF->udpchksum = 0; UIP_UDP_BUF->udpchksum = ~(uip_udpchksum()); if(UIP_UDP_BUF->udpchksum == 0) { UIP_UDP_BUF->udpchksum = 0xffff; } #endif /* UIP_UDP_CHECKSUMS */ } else if(UIP_IP_BUF->proto == UIP_PROTO_TCP) { /* Calculate TCP checksum. */ UIP_TCP_BUF->tcpchksum = 0; UIP_TCP_BUF->tcpchksum = ~(uip_tcpchksum()); } else if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6) { /* Calculate ICMP checksum. */ UIP_ICMP_BUF->icmpchksum = 0; UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); } } #endif #if CETIC_6LBR_SMARTBRIDGE //Reset Hop Limit when in smart-bridge for NDP packets //TODO: Is this still needed after #4467 ? if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && (UIP_ICMP_BUF->type == ICMP6_NS || UIP_ICMP_BUF->type == ICMP6_NA || UIP_ICMP_BUF->type == ICMP6_RS || UIP_ICMP_BUF->type == ICMP6_RA)) { UIP_IP_BUF->ttl = 255; } #endif #if CETIC_6LBR_SMARTBRIDGE || CETIC_6LBR_TRANSPARENTBRIDGE //Remove ROUTER flag when in bridge mode if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type == ICMP6_NA) { //LOG6LBR_PRINTF(PACKET, PF_OUT, "eth_output: Updating NA\n"); UIP_ND6_NA_BUF->flagsreserved &= ~UIP_ND6_NA_FLAG_ROUTER; } #endif //Some IP packets have link layer in them, need to change them around! mac_translateIPLinkLayer(ll_8023_type); //IP header alteration //-------------------- #if UIP_CONF_IPV6_RPL rpl_remove_header(); #endif //Create packet header //-------------------- //Packet type BUF->type = uip_htons(UIP_ETHTYPE_IPV6); //Destination address if(IS_BROADCAST_ADDR(dest)) { BUF->dest.addr[0] = 0x33; BUF->dest.addr[1] = 0x33; BUF->dest.addr[2] = UIP_IP_BUF->destipaddr.u8[12]; BUF->dest.addr[3] = UIP_IP_BUF->destipaddr.u8[13]; BUF->dest.addr[4] = UIP_IP_BUF->destipaddr.u8[14]; BUF->dest.addr[5] = UIP_IP_BUF->destipaddr.u8[15]; } else { mac_createEthernetAddr(BUF->dest.addr, dest); } //Source address if ( src != NULL ) { mac_createEthernetAddr(BUF->src.addr, src); } else { memcpy(BUF->src.addr, eth_mac_addr, 6); } //Sending packet //-------------- LOG6LBR_PRINTF(PACKET, PF_OUT, "eth_output: Sending packet to Ethernet\n"); eth_drv_send(uip_buf, uip_len + UIP_LLH_LEN); return 1; }
static uint8_t bridge_output(const uip_lladdr_t * dest) { int ethernetDest = 0; int wsnDest = 0; if(uip_len == 0) { LOG6LBR_ERROR("Trying to send empty packet\n"); return 0; } if(!IS_BROADCAST_ADDR(dest)) { LOG6LBR_LLADDR_PRINTF(PACKET, PF_OUT, dest, "bridge_output: Sending packet to "); } else { LOG6LBR_PRINTF(PACKET, PF_OUT, "bridge_output: Sending packet to Broadcast\n"); } if(uip_ipaddr_prefixcmp(ð_net_prefix, &UIP_IP_BUF->destipaddr, 64)) { LOG6LBR_6ADDR_PRINTF(PACKET, PF_OUT, ð_net_prefix, "dest prefix eth : "); LOG6LBR_6ADDR_PRINTF(PACKET, PF_OUT, &UIP_IP_BUF->destipaddr, "dest eth : "); //Packet destinated to the Ethernet subnet ethernetDest = 1; } else if(uip_ipaddr_prefixcmp(&wsn_net_prefix, &UIP_IP_BUF->destipaddr, 64)) { LOG6LBR_6ADDR_PRINTF(PACKET, PF_OUT, &wsn_net_prefix, "dest prefix wsn : "); LOG6LBR_6ADDR_PRINTF(PACKET, PF_OUT, &UIP_IP_BUF->destipaddr, "dest prefix wsn : "); //Packet destinated to the WSN subnet wsnDest = 1; } else if(IS_EUI64_ADDR(dest)) { //Destination unknown but next-hop is in WSN subnet wsnDest = 1; } else if (IS_EUI48_ADDR(dest)) { //Destination unknown but next-hop is in Ethernet subnet ethernetDest = 1; } else { //Obviously we can not guess the target segment for a multicast packet //So we have to check the packet source prefix (and match it on the Ethernet segment prefix) //or, in case of link-local packet, check packet type and/or packet data #if UIP_CONF_IPV6_RPL //in RPL mode, RA and RS packets are used to configure the Ethernet subnet if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && (UIP_ICMP_BUF->type == ICMP6_RA || UIP_ICMP_BUF->type == ICMP6_RS)) { ethernetDest = 1; } else if (UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type == ICMP6_NS && uip_ipaddr_prefixcmp(ð_net_prefix, &UIP_ND6_NS_BUF->tgtipaddr, 64)) { ethernetDest = 1; #else //in NDP mode, RA and RS packets are used to configure the WSN subnet if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && (UIP_ICMP_BUF->type == ICMP6_RA || UIP_ICMP_BUF->type == ICMP6_RS)) { wsnDest = 1; } else if (UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type == ICMP6_NS && uip_ipaddr_prefixcmp(&wsn_net_prefix, &UIP_ND6_NS_BUF->tgtipaddr, 64)) { wsnDest = 1; #endif } else if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type == ICMP6_RPL) { //RPL packets are always for WSN subnet wsnDest = 1; } else if(uip_ipaddr_prefixcmp(ð_net_prefix, &UIP_IP_BUF->srcipaddr, 64)) { //Packet type unknown, but source is from Ethernet subnet ethernetDest = 1; } else if(uip_ipaddr_prefixcmp(&wsn_net_prefix, &UIP_IP_BUF->srcipaddr, 64)) { //Packet type unknown, but source is from WSN subnet wsnDest = 1; } else { // We could not guess the destination, forward to both ethernetDest = 1; wsnDest = 1; } } if(wsnDest) { #if CETIC_6LBR_ONE_ITF eth_output(&wsn_mac_addr, dest); #else wireless_output(NULL, dest); #endif } if(ethernetDest) { eth_output(NULL, dest); } return 0; } #endif /*---------------------------------------------------------------------------*/ void packet_filter_init(void) { wireless_outputfunc = tcpip_get_outputfunc(); tcpip_set_outputfunc(bridge_output); tcpip_inputfunc = tcpip_get_inputfunc(); tcpip_set_inputfunc(wireless_input); }
void eth_input(void) { int processFrame = 0; //Packet type filtering //--------------------- //Keep only IPv6 traffic if(BUF->type != UIP_HTONS(UIP_ETHTYPE_IPV6)) { LOG6LBR_PRINTF(PACKET, PF_IN, "eth_input: Dropping packet type=0x%04x\n", uip_ntohs(BUF->type)); uip_len = 0; return; } if((UIP_IP_BUF->len[0] << 8) + UIP_IP_BUF->len[1] + 40 < uip_len) { #if CONTIKI_TARGET_NATIVE if(ethernet_has_fcs) { uip_len = (UIP_IP_BUF->len[0] << 8) + UIP_IP_BUF->len[1] + 40; } else #endif { LOG6LBR_PRINTF(PACKET, PF_IN, "eth_input: packet size different than reported in IPv6 header, %d vs %d\n", uip_len, (UIP_IP_BUF->len[0] << 8) + UIP_IP_BUF->len[1] + 40); } } else if((UIP_IP_BUF->len[0] << 8) + UIP_IP_BUF->len[1] + 40 > uip_len) { LOG6LBR_PRINTF(PACKET, PF_IN, "eth_input: packet shorter than reported in IPv6 header, %d vs %d\n", uip_len, (UIP_IP_BUF->len[0] << 8) + UIP_IP_BUF->len[1] + 40); uip_len = 0; return; } //Packet source Filtering //----------------------- /* IPv6 uses 33-33-xx-xx-xx-xx prefix for multicast ND stuff */ if((BUF->dest.addr[0] == 0x33) && (BUF->dest.addr[1] == 0x33)) { processFrame = 1; } else if((BUF->dest.addr[0] == 0xFF) && (BUF->dest.addr[1] == 0xFF) && (BUF->dest.addr[2] == 0xFF) && (BUF->dest.addr[3] == 0xFF) && (BUF->dest.addr[4] == 0xFF) && (BUF->dest.addr[5] == 0xFF)) { /* IPv6 does not use broadcast addresses, hence this should not happen */ LOG6LBR_PRINTF(PACKET, PF_IN, "eth_input: Dropping broadcast packet\n"); uip_len = 0; return; } //Destination filtering //--------------------- if(memcmp((uint8_t *) & eth_mac_addr, BUF->dest.addr, 6) == 0) { processFrame = 1; } else { if(!processFrame) { // Also search our neighbor list to see if we should accept it if(uip_ds6_nbr_ll_lookup((const uip_lladdr_t*)BUF->dest.addr)) { processFrame = 1; } } } //Handle packet //------------- if(processFrame) { LOG6LBR_PRINTF(PACKET, PF_IN, "eth_input: Processing frame\n"); send_to_uip(); } else { printf("eth_input: Dropping frame, not for us or any known node\n"); //Drop packet uip_len = 0; } }
static void wireless_input(void) { LOG6LBR_PRINTF(PACKET, PF_IN, "wireless_input: processing frame\n"); send_to_uip(); }
static void wireless_input(void) { int processFrame = 0; int forwardFrame = 0; LOG6LBR_PRINTF(PACKET, PF_IN, "wireless_input\n"); //Source filtering //---------------- #if CETIC_6LBR_TRANSPARENTBRIDGE && CETIC_6LBR_LEARN_RPL_MAC if (!rpl_mac_known) { //Rpl Relay not yet configured, drop packet uip_len = 0; return; } if (rimeaddr_cmp (packetbuf_addr(PACKETBUF_ADDR_SENDER), & rimeaddr_node_addr) != 0) { LOG6LBR_WARN("WSN packet received with RplRoot address, another TB is within range, dropping it\n"); //Drop packet uip_len = 0; return; } #endif //Destination filtering //--------------------- if(IS_BROADCAST_ADDR(packetbuf_addr(PACKETBUF_ADDR_RECEIVER))) { //Broadcast LOG6LBR_PRINTF(PACKET, PF_IN, "wireless_input : broadcast\n"); forwardFrame = 1; processFrame = 1; } else { //unicast LOG6LBR_LLADDR_PRINTF(PACKET, PF_IN, (uip_lladdr_t *) packetbuf_addr(PACKETBUF_ADDR_RECEIVER), "wireless_input: dest: "); if(rimeaddr_cmp (packetbuf_addr(PACKETBUF_ADDR_RECEIVER), (rimeaddr_t *) & wsn_mac_addr) != 0) { processFrame = 1; //For us } else { //For another host #if CETIC_6LBR_TRANSPARENTBRIDGE //Not for us, forward it directly forwardFrame = 1; LOG6LBR_PRINTF(PACKET, PF_IN, "wireless_input : to forward\n"); #endif } } //Packet forwarding //----------------- #if CETIC_6LBR_TRANSPARENTBRIDGE if(forwardFrame) { LOG6LBR_PRINTF(PACKET, PF_IN, "wireless_input: forwarding frame\n"); if(eth_output((uip_lladdr_t *) packetbuf_addr(PACKETBUF_ADDR_SENDER), (uip_lladdr_t *) packetbuf_addr(PACKETBUF_ADDR_RECEIVER))) { //Restore packet as eth_output might have converted its content mac_translateIPLinkLayer(ll_802154_type); } } #endif //Handle packet //------------- if(processFrame) { LOG6LBR_PRINTF(PACKET, PF_IN, "wireless_input: processing frame\n"); send_to_uip(); } else { //Drop packet uip_len = 0; } }
/* * Read from serial, when we have a packet call slip_packet_input. No output * buffering, input buffered by stdio. */ void serial_input(FILE * inslip) { static unsigned char inbuf[2048]; static int inbufptr = 0; int ret, i; unsigned char c; #ifdef linux ret = fread(&c, 1, 1, inslip); if(ret == -1 || ret == 0) { LOG6LBR_FATAL("read() : %s\n", strerror(errno)); exit(1); } goto after_fread; #endif read_more: if(inbufptr >= sizeof(inbuf)) { LOG6LBR_ERROR("*** dropping large %d byte packet\n", inbufptr); inbufptr = 0; } ret = fread(&c, 1, 1, inslip); #ifdef linux after_fread: #endif if(ret == -1) { LOG6LBR_FATAL("read() : %s\n", strerror(errno)); exit(1); } if(ret == 0) { clearerr(inslip); return; } slip_received++; switch (c) { case SLIP_END: if(inbufptr > 0) { slip_message_received++; LOG6LBR_PRINTF(PACKET, SLIP_IN, "read: %d\n", inbufptr); if (LOG6LBR_COND(DUMP, SLIP_IN)) { printf(" "); for(i = 0; i < inbufptr; i++) { printf("%02x", inbuf[i]); if((i & 3) == 3) printf(" "); if((i & 15) == 15) printf("\n "); } printf("\n"); } if(inbuf[0] == '!') { command_context = CMD_CONTEXT_RADIO; cmd_input(inbuf, inbufptr); } else if(inbuf[0] == '?') { } else if(inbuf[0] == DEBUG_LINE_MARKER) { LOG6LBR_WRITE(INFO, SLIP_DBG, inbuf + 1, inbufptr - 1); } else if(inbuf[0] == 'E' && is_sensible_string(inbuf, inbufptr) ) { LOG6LBR_WRITE(ERROR, GLOBAL, inbuf + 1, inbufptr - 1); LOG6LBR_APPEND(ERROR, GLOBAL, "\n"); } else if(is_sensible_string(inbuf, inbufptr)) { LOG6LBR_WRITE(INFO, SLIP_DBG, inbuf, inbufptr); } else { slip_packet_input(inbuf, inbufptr); } inbufptr = 0; } break; case SLIP_ESC: if(fread(&c, 1, 1, inslip) != 1) { clearerr(inslip); /* Put ESC back and give up! */ ungetc(SLIP_ESC, inslip); return; } switch (c) { case SLIP_ESC_END: c = SLIP_END; break; case SLIP_ESC_ESC: c = SLIP_ESC; break; } /* FALLTHROUGH */ default: inbuf[inbufptr++] = c; break; } goto read_more; }