/*---------------------------------------------------------------------------*/ uint8_t sprint_ip6addr(struct in6_addr addr, char * result) { unsigned char i = 0; unsigned char zerocnt = 0; unsigned char numprinted = 0; char * starting = result; *result++='['; while (numprinted < 8) { if ((addr.s6_addr16[i] == 0) && (zerocnt == 0)) { while(addr.s6_addr16[zerocnt + i] == 0) zerocnt++; if (zerocnt == 1) { *result++ = '0'; numprinted++; break; } i += zerocnt; numprinted += zerocnt; } else { result += sprintf(result, "%x", (unsigned int) uip_ntohs(addr.s6_addr16[i])); i++; numprinted++; } if (numprinted != 8) *result++ = ':'; } *result++=']'; *result=0; return (result - starting); }
/*---------------------------------------------------------------------------*/ void sprint_ip6(uip_ip6addr_t addr) { unsigned char i = 0; unsigned char zerocnt = 0; unsigned char numprinted = 0; char thestring[40]; char * result = thestring; *result++='['; while (numprinted < 8) { if ((addr.u16[i] == 0) && (zerocnt == 0)) { while(addr.u16[zerocnt + i] == 0) zerocnt++; if (zerocnt == 1) { *result++ = '0'; numprinted++; break; } i += zerocnt; numprinted += zerocnt; } else { result += sprintf(result, "%x", (unsigned int)(uip_ntohs(addr.u16[i]))); i++; numprinted++; } if (numprinted != 8) *result++ = ':'; } *result++=']'; *result=0; printf("%s",thestring); }
void init_dtls(session_t *dst) { PRINTF("DTLS client started\n"); print_local_addresses(); dst->size = sizeof(dst->addr) + sizeof(dst->port); dst->port = UIP_HTONS(20220); set_connection_address(&dst->addr); client_conn = udp_new(&dst->addr, 0, NULL); udp_bind(client_conn, dst->port); PRINTF("set connection address to "); PRINT6ADDR(&dst->addr); PRINTF(":%d\n", uip_ntohs(dst->port)); set_log_level(LOG_DEBUG); dtls_context = dtls_new_context(client_conn); if (dtls_context) { dtls_set_psk(dtls_context, (unsigned char *)"secretPSK", 9, (unsigned char *)"Client_identity", 15); dtls_set_cb(dtls_context, read_from_peer, read); dtls_set_cb(dtls_context, send_to_peer, write); } }
uint8_t httpd_sprint_ip6(const uip_ip6addr_t *addr, char *result) { unsigned char i = 0; unsigned char zerocnt = 0; unsigned char numprinted = 0; char *starting = result; *result++ = '['; while(numprinted < 8) { if((addr->u16[i] == 0) && (zerocnt == 0)) { while(addr->u16[zerocnt + i] == 0) { zerocnt++; } if(zerocnt == 1) { *result++ = '0'; numprinted++; break; } i += zerocnt; numprinted += zerocnt; } else { result += sprintf(result, "%x", (unsigned int)(uip_ntohs(addr->u16[i]))); i++; numprinted++; } if(numprinted != 8) { *result++ = ':'; } } *result++ = ']'; *result = 0; return (result - starting); }
void init_dtls(session_t *dst) { static dtls_handler_t cb = { .write = send_to_peer, .read = read_from_peer, .event = NULL, .get_key = get_key }; PRINTF("DTLS client started\n"); print_local_addresses(); dst->size = sizeof(dst->addr) + sizeof(dst->port); dst->port = UIP_HTONS(20220); set_connection_address(&dst->addr); client_conn = udp_new(&dst->addr, 0, NULL); udp_bind(client_conn, dst->port); PRINTF("set connection address to "); PRINT6ADDR(&dst->addr); PRINTF(":%d\n", uip_ntohs(dst->port)); set_log_level(LOG_DEBUG); dtls_context = dtls_new_context(client_conn); if (dtls_context) dtls_set_handler(dtls_context, &cb); }
static void tcpdump(uint8_t *pkt, uint16_t len) { char prt[41]; if (((struct uip_eth_hdr *)pkt)->type == UIP_HTONS(UIP_ETHTYPE_IP)) { tcpdump_format(pkt + 14, len - 14, prt, sizeof(prt)); printf_P(PSTR("%s\n"), prt); } else if (((struct uip_eth_hdr *)pkt)->type == UIP_HTONS(UIP_ETHTYPE_ARP)) { printf_P(PSTR("ARP\n")); } else { printf_P(PSTR("Ethertype: %04x\n"), uip_ntohs(((struct uip_eth_hdr *)pkt)->type)); } #if TCPDUMP_RAWPKT for (uint8_t i = 0; i < 64; i++) { if (i >= len) { printf_P(PSTR("**")); break; } printf("%02x ", *(pkt + i)); if ((i > 0) && !((i + 1) % 4)) { printf_P(PSTR(" ")); } } printf("\n"); #endif }
coap_pdu_t * coap_new_pdu(coap_transport_type transport, unsigned int size) { coap_pdu_t *pdu; #ifndef WITH_CONTIKI pdu = coap_pdu_init(0, 0, ntohs(COAP_INVALID_TID), #ifndef WITH_TCP COAP_MAX_PDU_SIZE, #else size, #endif transport); #else /* WITH_CONTIKI */ pdu = coap_pdu_init(0, 0, uip_ntohs(COAP_INVALID_TID), #ifndef WITH_TCP COAP_MAX_PDU_SIZE, #else size, #endif transport); #endif /* WITH_CONTIKI */ #ifndef NDEBUG if (!pdu) coap_log(LOG_CRIT, "coap_new_pdu: cannot allocate memory for new PDU\n"); #endif return pdu; }
void network_handler(ev, data){ char buf[UIP_BUFSIZE]; // packet data buffer unsigned short cmd; // DataPayload *dp; ChannelState *state = NULL; uint16_t len = uip_datalen(); PRINTF("ipaddr=%d.%d.%d.%d\n", uip_ipaddr_to_quad(&(UDP_HDR->srcipaddr))); PRINTF("Packet is %d bytes long\n",len); memcpy(buf, uip_appdata, len); buf[len] = '\0'; dp = (DataPayload *)buf; PRINTF("Data is %d bytes long\n",uip_ntohs(dp->dhdr.tlen)); cmd = dp->hdr.cmd; // only a byte so no reordering :) PRINTF("Received a %s command.\n", cmdnames[cmd]); PRINTF("Message for channel %d\n",dp->hdr.dst_chan_num); if (dp->hdr.dst_chan_num == HOMECHANNEL || cmd == DISCONNECT){ if (cmd == QACK){ state = &home_channel_state; copy_link_address(state); } else if (cmd == DISCONNECT){ state = get_channel_state(dp->hdr.dst_chan_num); if (state){ remove_channel(state->chan_num); } state = &home_channel_state; copy_link_address(state); } } else{ state = get_channel_state(dp->hdr.dst_chan_num); if (state == NULL){ PRINTF("Channel %d doesn't exist\n", dp->hdr.dst_chan_num); return; } if (check_seqno(state, dp) == 0) { printf("OH NOES\n"); return; }else { //CHECK IF RIGHT CONNECTION //copy_link_address(state); } } // Received a message so reset pingOUT state->pingOUT = 0; if (cmd == QUERY) PRINTF("I'm a controller, Ignoring QUERY\n"); else if (cmd == CONNECT) PRINTF("I'm a controller, Ignoring CONNECT\n"); else if (cmd == QACK) qack_handler(state, dp); else if (cmd == CACK) cack_handler(state, dp); else if (cmd == RESPONSE) response_handler(state, dp); else if (cmd == CMDACK) command_ack_handler(state,dp); else if (cmd == PING) ping_handler(state, dp); else if (cmd == PACK) pack_handler(state, dp); else if (cmd == DISCONNECT) close_handler(state,dp); }
/*---------------------------------------------------------------------------*/ static int prepare_and_send_buf(coap_context_t *ctx, session_t *session, uint8_t *data, size_t len) { struct net_buf *buf; int max_data_len; /* This net_buf gets sent to network, so it is not released * by this function unless there was an error and buf was * not actually sent. */ buf = ip_buf_get_tx(ctx->net_ctx); if (!buf) { len = -ENOBUFS; goto out; } max_data_len = IP_BUF_MAX_DATA - UIP_IPUDPH_LEN; PRINTF("%s: reply to peer data %p len %d\n", __FUNCTION__, data, len); if (len > max_data_len) { PRINTF("%s: too much (%d bytes) data to send (max %d bytes)\n", __FUNCTION__, len, max_data_len); ip_buf_unref(buf); len = -EINVAL; goto out; } /* Note that we have reversed the addresses here * because net_reply() will reverse them again. */ #ifdef CONFIG_NETWORKING_WITH_IPV6 uip_ip6addr_copy(&NET_BUF_IP(buf)->destipaddr, (uip_ip6addr_t *)&ctx->my_addr.in6_addr); uip_ip6addr_copy(&NET_BUF_IP(buf)->srcipaddr, (uip_ip6addr_t *)&session->addr.ipaddr); #else uip_ip4addr_copy(&NET_BUF_IP(buf)->destipaddr, (uip_ip4addr_t *)&ctx->my_addr.in_addr); uip_ip4addr_copy(&NET_BUF_IP(buf)->srcipaddr, (uip_ip4addr_t *)&session->addr.ipaddr); #endif NET_BUF_UDP(buf)->destport = uip_ntohs(ctx->my_port); NET_BUF_UDP(buf)->srcport = session->addr.port; uip_set_udp_conn(buf) = net_context_get_udp_connection(ctx->net_ctx); memcpy(net_buf_add(buf, len), data, len); ip_buf_appdatalen(buf) = len; ip_buf_appdata(buf) = buf->data + ip_buf_reserve(buf); if (net_reply(ctx->net_ctx, buf)) { ip_buf_unref(buf); } out: return len; }
int get_key(struct dtls_context_t *ctx, const session_t *session, const unsigned char *id, size_t id_len, const dtls_key_t **result) { static const dtls_key_t psk = { .type = DTLS_KEY_PSK, .key.psk.id = (unsigned char *)"Client_identity", .key.psk.id_length = 15, .key.psk.key = (unsigned char *)"secretPSK", .key.psk.key_length = 9 }; *result = &psk; return 0; } PROCESS(udp_server_process, "UDP server process"); AUTOSTART_PROCESSES(&udp_server_process); /*---------------------------------------------------------------------------*/ static void dtls_handle_read(dtls_context_t *ctx) { static session_t session; if(uip_newdata()) { uip_ipaddr_copy(&session.addr, &UIP_IP_BUF->srcipaddr); session.port = UIP_UDP_BUF->srcport; session.size = sizeof(session.addr) + sizeof(session.port); ((char *)uip_appdata)[uip_datalen()] = 0; PRINTF("Client received message from "); PRINT6ADDR(&session.addr); PRINTF(":%d\n", uip_ntohs(session.port)); dtls_handle_message(ctx, &session, uip_appdata, uip_datalen()); } } /*---------------------------------------------------------------------------*/ static void print_local_addresses(void) { int i; uint8_t state; PRINTF("Client IPv6 addresses: "); for(i = 0; i < UIP_DS6_ADDR_NB; i++) { state = uip_ds6_if.addr_list[i].state; if(uip_ds6_if.addr_list[i].isused && (state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) { PRINT6ADDR(&uip_ds6_if.addr_list[i].ipaddr); PRINTF("\n"); } } }
void response_handler(ChannelState *state, DataPayload *dp){ if (state->state != STATE_CONNECTED && state->state != STATE_PING){ PRINTF("Not connected to device!\n"); return; } state->ticks = 100; ResponseMsg *rmsg = (ResponseMsg *)dp->data; PRINTF("%s %d\n", rmsg->name, uip_ntohs(rmsg->data)); /*RESET PING TIMER*/ ctimer_restart(&(state->timer)); process_post_synch(state->ccb.client_process, KNOT_EVENT_DATA_READY, rmsg); }
/*---------------------------------------------------------------------------*/ void ip64_dhcpc_configured(const struct ip64_dhcpc_state *s) { uip_ip6addr_t ip6dnsaddr; PRINTF("DHCP Configured with %d.%d.%d.%d\n", s->ipaddr.u8[0], s->ipaddr.u8[1], s->ipaddr.u8[2], s->ipaddr.u8[3]); ip64_set_hostaddr((uip_ip4addr_t *)&s->ipaddr); ip64_set_netmask((uip_ip4addr_t *)&s->netmask); ip64_set_draddr((uip_ip4addr_t *)&s->default_router); if(!uip_ip4addr_cmp((uip_ip4addr_t *)&s->dnsaddr, &uip_all_zeroes_addr)) { //Note: Currently we assume only one DNS server uip_ipaddr_t * dns = uip_nameserver_get(0); //Only update DNS entry if it is empty or already IPv4 if(uip_is_addr_unspecified(dns) || ip64_addr_is_ip64(dns)) { ip64_addr_4to6((uip_ip4addr_t *)&s->dnsaddr, &ip6dnsaddr); uip_nameserver_update(&ip6dnsaddr, uip_ntohs(s->lease_time[0])*65536ul + uip_ntohs(s->lease_time[1])); } } #if CETIC_6LBR cetic_6lbr_ip64_dhcpc_configured(s); #endif }
coap_pdu_t * coap_new_pdu(void) { coap_pdu_t *pdu; #ifndef WITH_CONTIKI pdu = coap_pdu_init(0, 0, ntohs((unsigned short)COAP_INVALID_TID), COAP_MAX_PDU_SIZE); #else /* WITH_CONTIKI */ pdu = coap_pdu_init(0, 0, uip_ntohs(COAP_INVALID_TID), COAP_MAX_PDU_SIZE); #endif /* WITH_CONTIKI */ #ifndef NDEBUG if (!pdu) coap_log(LOG_CRIT, "coap_new_pdu: cannot allocate memory for new PDU\n"); #endif return pdu; }
void callback(void * data){ ResponseMsg * r = data; int value = uip_ntohs((int)r->data); printf(">>APP: %s sensor = %d\n", r->name, value); if (actuator == 0) return; //NO actuator connected if (value > 75 && lighton){ printf("It's too bright - Turning off light\n"); command_actuator(&actuator); lighton = 0; } else if (value <75 && !lighton){ printf("It's too dark - Turning on light\n"); command_actuator(&actuator); lighton = 1; } }
/*---------------------------------------------------------------------------*/ uint8_t httpd_cgi_sprint_ip6(uip_ip6addr_t addr, char * result) { unsigned char zerocnt = 0; unsigned char numprinted = 0; char * starting = result; unsigned char i = 0; while (numprinted < 8) { //Address is zero, have we used our ability to //replace a bunch with : yet? if ((addr.u16[i] == 0) && (zerocnt == 0)) { //How mant zeros? zerocnt = 0; while(addr.u16[zerocnt + i] == 0) zerocnt++; //just one, don't waste our zeros... if (zerocnt == 1) { *result++ = '0'; numprinted++; break; } //Cool - can replace a bunch of zeros i += zerocnt; numprinted += zerocnt; //all zeroes ? if (zerocnt > 7) {*result++ = ':';*result++ = ':';} } //Normal address, just print it else { result += sprintf(result, "%x", (unsigned int)(uip_ntohs(addr.u16[i]))); i++; numprinted++; } //Don't print : on last one if (numprinted != 8) *result++ = ':'; } return (result - starting); }
/*---------------------------------------------------------------------------*/ static void dtls_handle_read(dtls_context_t *ctx) { static session_t session; if(uip_newdata()) { uip_ipaddr_copy(&session.addr, &UIP_IP_BUF->srcipaddr); session.port = UIP_UDP_BUF->srcport; session.size = sizeof(session.addr) + sizeof(session.port); ((char *)uip_appdata)[uip_datalen()] = 0; PRINTF("Client received message from "); PRINT6ADDR(&session.addr); PRINTF(":%d\n", uip_ntohs(session.port)); dtls_handle_message(ctx, &session, uip_appdata, uip_datalen()); } }
/*---------------------------------------------------------------------------*/ PROCESS_THREAD(ledsUDPServer_process, ev, data) { static struct uip_udp_conn *localconn; PROCESS_BEGIN(); /* Create a local connection structure : * - Remote IP: 0.0.0.0 (all accepted). * - Remote port: 0 (all accepted). */ localconn = udp_new(&uip_all_zeroes_addr, 0, NULL); /* Bind to the local port. */ udp_bind(localconn,uip_htons(local_port)); PRINTF("I listen the UDP port %u\n",uip_ntohs(localconn->lport)); while (1) { PRINTF("I wait a new request\n"); PROCESS_WAIT_EVENT_UNTIL(ev == tcpip_event); /* Here, a new TCP/IP event occurred ! */ /* A good packet is : * - With data. * - With at least "preambleSize + 1" bytes. * - Packet start with the good preamble. */ if(uip_newdata() && uip_datalen() >= (preambleSize + 1) && !strncmp(uip_appdata,preamble,preambleSize)) { PRINTF("I received a LED toggling request.\n"); { char *data = (char *)uip_appdata; int led = 0; switch (data[4]) { case '1': led = LEDS_BLUE; break; case '2': led = LEDS_GREEN; break; case '3': led = LEDS_RED; break; default : PRINTF("I can't find the good LED...\n"); continue; } leds_toggle(led); } } } PROCESS_END(); }
/*---------------------------------------------------------------------------*/ static void multicast_send(void) { uint32_t id; id = uip_htonl(seq_id); memset(buf, 0, MAX_PAYLOAD_LEN); memcpy(buf, &id, sizeof(seq_id)); PRINTF("Send to: "); PRINT6ADDR(&mcast_conn->ripaddr); PRINTF(" Remote Port %u,", uip_ntohs(mcast_conn->rport)); PRINTF(" (msg=0x%08lx)", (unsigned long)uip_ntohl(*((uint32_t *)buf))); PRINTF(" %lu bytes\n", (unsigned long)sizeof(id)); seq_id++; uip_udp_packet_send(mcast_conn, buf, sizeof(id)); }
/*---------------------------------------------------------------------------*/ int coap_context_connect(coap_context_t *coap_ctx, uip_ipaddr_t *addr, uint16_t port) { session_t session; if(coap_ctx == NULL || coap_ctx->is_used == 0) { return 0; } #ifdef NETSTACK_CONF_WITH_IPV6 memcpy(&coap_ctx->addr.in6_addr, addr, sizeof(coap_ctx->addr.in6_addr)); coap_ctx->addr.family = AF_INET6; #else memcpy(&coap_ctx->addr.in_addr, addr, sizeof(coap_ctx->addr.in_addr)); coap_ctx->addr.family = AF_INET; #endif coap_ctx->port = port; coap_ctx->net_ctx = net_context_get(IPPROTO_UDP, (const struct net_addr *)&coap_ctx->addr, coap_ctx->port, (const struct net_addr *)&coap_ctx->my_addr, coap_ctx->my_port); if (!coap_ctx->net_ctx) { PRINTF("%s: Cannot get network context\n", __FUNCTION__); return 0; } uip_ipaddr_copy(&session.addr.ipaddr, addr); session.addr.port = UIP_HTONS(port); session.size = sizeof(session.addr); session.ifindex = 1; coap_ctx->status = STATUS_CONNECTING; PRINTF("coap-context: DTLS CONNECT TO ["); PRINT6ADDR(addr); PRINTF("]:%u\n", uip_ntohs(port)); if(dtls_connect(coap_ctx->dtls_context, &session) >= 0) { return 1; } /* Failed to initiate connection */ coap_ctx->status = STATUS_ALERT; return 0; }
void service_search(ChannelState* state, uint8_t type){ DataPayload *new_dp = &(state->packet); clean_packet(new_dp); //dp_complete(new_dp,10,QACK,1); set_broadcast(&(home_channel_state.remote_addr)); new_dp->hdr.src_chan_num = state->chan_num; new_dp->hdr.dst_chan_num = 0; (new_dp)->hdr.cmd = QUERY; (new_dp)->dhdr.tlen = uip_htons(sizeof(QueryMsg)); PRINTF("%d\n", uip_ntohs((new_dp)->dhdr.tlen)); QueryMsg *q = (QueryMsg *) new_dp->data; q->type = type; strcpy(q->name, controller_name); knot_broadcast(state,new_dp); state->state = STATE_QUERY; state->ticks = 100; }
static int send_to_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) { struct uip_udp_conn *conn = (struct uip_udp_conn *)dtls_get_app_data(ctx); uip_ipaddr_copy(&conn->ripaddr, &session->addr); conn->rport = session->port; PRINTF("send to "); PRINT6ADDR(&conn->ripaddr); PRINTF(":%u\n", uip_ntohs(conn->rport)); uip_udp_packet_send(conn, data, len); /* Restore server connection to allow data from any node */ memset(&conn->ripaddr, 0, sizeof(conn->ripaddr)); memset(&conn->rport, 0, sizeof(conn->rport)); return len; }
/*---------------------------------------------------------------------------*/ int coap_context_wait_data(coap_context_t *coap_ctx, int32_t ticks) { struct net_buf *buf; buf = net_receive(coap_ctx->net_ctx, ticks); if (buf) { session_t session; int ret; uip_ipaddr_copy(&session.addr.ipaddr, &UIP_IP_BUF(buf)->srcipaddr); session.addr.port = UIP_UDP_BUF(buf)->srcport; session.size = sizeof(session.addr); session.ifindex = 1; PRINTF("coap-context: got dtls message from "); PRINT6ADDR(&session.addr.ipaddr); PRINTF(":%d %u bytes\n", uip_ntohs(session.addr.port), uip_appdatalen(buf)); PRINTF("Received appdata %p appdatalen %d\n", ip_buf_appdata(buf), ip_buf_appdatalen(buf)); coap_ctx->buf = buf; ret = dtls_handle_message(coap_ctx->dtls_context, &session, ip_buf_appdata(buf), ip_buf_appdatalen(buf)); /* We always release the buffer here as this buffer is never sent * to network anyway. */ if (coap_ctx->buf) { ip_buf_unref(coap_ctx->buf); coap_ctx->buf = NULL; } return ret; } return 0; }
/*---------------------------------------------------------------------------*/ int coap_context_wait_data(coap_context_t *coap_ctx, int32_t ticks) { struct net_buf *buf; buf = net_receive(coap_ctx->net_ctx, ticks); if (buf) { PRINTF("coap-context: got message from "); PRINT6ADDR(&UIP_IP_BUF(buf)->srcipaddr); PRINTF(":%d %u bytes\n", uip_ntohs(UIP_UDP_BUF(buf)->srcport), uip_appdatalen(buf)); PRINTF("Received data appdata %p appdatalen %d\n", ip_buf_appdata(buf), ip_buf_appdatalen(buf)); coap_ctx->buf = buf; coap_engine_receive(coap_ctx); return 1; } return 0; }
/*---------------------------------------------------------------------------*/ static void sprint_ip6(uip_ip6addr_t addr) { unsigned char i = 0; unsigned char zerocnt = 0; unsigned char numprinted = 0; unsigned char notskipped = 0; char thestring[40]; char *result = thestring; *result++ = '['; while(numprinted < 8) { if((addr.u16[i] == 0) && (zerocnt == 0)) { while(addr.u16[zerocnt + i] == 0) { zerocnt++; } if(zerocnt == 1 && notskipped) { *result++ = '0'; numprinted++; notskipped = 1; continue; } i += zerocnt; numprinted += zerocnt; } else { result += sprintf(result, "%x", (unsigned int)(uip_ntohs(addr.u16[i]))); i++; numprinted++; } if(numprinted != 8) { *result++ = ':'; } } *result++=']'; *result=0; PRINTF("%s", thestring); }
/** * \brief Adds a context to the Context Table * * \param length Length of the prefix * * \param context_id Context Id * * \param prefix Context prefix * * \param compression Is context valid for compression? * * \returns A pointer to the newly created context if the * creation was successfull, otherwise NULL. * */ uip_ds6_addr_context_t* uip_ds6_context_add(uip_nd6_opt_6co *context_option, u16_t defrt_lifetime) { uip_ds6_addr_context_t* context; context = &uip_ds6_addr_context_table[context_option->res1_c_cid & UIP_ND6_RA_CID]; if(context->state != NOT_IN_USE) { /* Context aready exists */ return NULL; } context->length = context_option->preflen; context->context_id = context_option->res1_c_cid & UIP_ND6_RA_CID; uip_ipaddr_copy(&context->prefix, &context_option->prefix); if (context_option->res1_c_cid & UIP_ND6_RA_FLAG_COMPRESSION) { context->state = IN_USE_COMPRESS; } else { context->state = IN_USE_UNCOMPRESS_ONLY; } /* Prevent overflow in case we need to set the lifetime to "twice the * Default Router Lifetime" */ stimer_set(&context->vlifetime, uip_ntohs(context_option->lifetime)); context->defrt_lifetime = defrt_lifetime < 0x7FFF ? defrt_lifetime : 0x7FFF; return context; }
/* Switch the ports and addresses and set route and neighbor cache. * Returns 1 if packet was sent properly, in this case it is the caller * that needs to release the net_buf. If 0 is returned, then uIP stack * has released the net_buf already because there was an some net related * error when sending the buffer. */ static inline int udp_prepare_and_send(struct net_context *context, struct net_buf *buf) { #ifdef CONFIG_NETWORKING_WITH_IPV6 uip_ds6_route_t *route_old, *route_new = NULL; uip_ds6_nbr_t *nbr; #endif uip_ipaddr_t tmp; uint16_t port; uint8_t ret; if (uip_len(buf) == 0) { /* This is expected as uIP will typically set the * packet length to 0 after receiving it. So we need * to fix the length here. The protocol specific * part is added also here. */ uip_len(buf) = uip_slen(buf) = uip_appdatalen(buf); buf->data = buf->buf + UIP_IPUDPH_LEN; } port = UIP_UDP_BUF(buf)->srcport; UIP_UDP_BUF(buf)->srcport = UIP_UDP_BUF(buf)->destport; UIP_UDP_BUF(buf)->destport = port; uip_ipaddr_copy(&tmp, &UIP_IP_BUF(buf)->srcipaddr); uip_ipaddr_copy(&UIP_IP_BUF(buf)->srcipaddr, &UIP_IP_BUF(buf)->destipaddr); uip_ipaddr_copy(&UIP_IP_BUF(buf)->destipaddr, &tmp); #ifdef CONFIG_NETWORKING_WITH_IPV6 /* The peer needs to be in neighbor cache before route can be added. */ nbr = uip_ds6_nbr_lookup((uip_ipaddr_t *)&UIP_IP_BUF(buf)->destipaddr); if (!nbr) { const uip_lladdr_t *lladdr = (const uip_lladdr_t *)&buf->src; nbr = uip_ds6_nbr_add( (uip_ipaddr_t *)&UIP_IP_BUF(buf)->destipaddr, lladdr, 0, NBR_REACHABLE); if (!nbr) { NET_DBG("Cannot add peer "); PRINT6ADDR(&UIP_IP_BUF(buf)->destipaddr); PRINT(" to neighbor cache\n"); } } /* Temporarily add route to peer, delete the route after * sending the packet. Check if there was already a * route and do not remove it if there was existing * route to this peer. */ route_old = uip_ds6_route_lookup(&UIP_IP_BUF(buf)->destipaddr); if (!route_old) { route_new = uip_ds6_route_add(&UIP_IP_BUF(buf)->destipaddr, 128, &UIP_IP_BUF(buf)->destipaddr); if (!route_new) { NET_DBG("Cannot add route to peer "); PRINT6ADDR(&UIP_IP_BUF(buf)->destipaddr); PRINT("\n"); } } #endif ret = simple_udp_sendto_port(buf, net_context_get_udp_connection(context), buf->data, buf->len, &UIP_IP_BUF(buf)->destipaddr, uip_ntohs(UIP_UDP_BUF(buf)->destport)); if (!ret) { NET_DBG("Packet could not be sent properly.\n"); } #ifdef CONFIG_NETWORKING_WITH_IPV6 if (!route_old && route_new) { /* This will also remove the neighbor cache entry */ uip_ds6_route_rm(route_new); } #endif return ret; }
/** * \brief Take a packet received over the ethernet link, and send it * out over 802.15.4 */ void mac_ethernetToLowpan(uint8_t * ethHeader) { //Dest address uip_lladdr_t destAddr; uip_lladdr_t *destAddrPtr = NULL; PRINTF("Packet type: 0x%04x\n\r", uip_ntohs(((struct uip_eth_hdr *) ethHeader)->type)); //RUM doesn't support sending data #if UIP_CONF_USE_RUM return; #endif /* In sniffer or sneezr mode we don't ever send anything */ if ((usbstick_mode.sendToRf == 0) || (usbstick_mode.sneeze != 0)) { uip_len = 0; return; } /* If not IPv6 we don't do anything. Disable ipv4 on the interface to prevent possible hangs from discovery packet flooding */ if (((struct uip_eth_hdr *) ethHeader)->type != UIP_HTONS(UIP_ETHTYPE_IPV6)) { PRINTF("eth2low: Dropping packet w/type=0x%04x\n",uip_ntohs(((struct uip_eth_hdr *) ethHeader)->type)); // printf("!ipv6"); #if !RF230BB && !RF212BB usb_eth_stat.txbad++; #endif uip_len = 0; return; } /* IPv6 uses 33-33-xx-xx-xx-xx prefix for multicast ND stuff */ if ( (((struct uip_eth_hdr *) ethHeader)->dest.addr[0] == 0x33) && (((struct uip_eth_hdr *) ethHeader)->dest.addr[1] == 0x33) ) { PRINTF("eth2low: Ethernet multicast packet received\n\r"); ;//Do Nothing } else if ( (((struct uip_eth_hdr *) ethHeader)->dest.addr[0] == 0xFF) && (((struct uip_eth_hdr *) ethHeader)->dest.addr[1] == 0xFF) && (((struct uip_eth_hdr *) ethHeader)->dest.addr[2] == 0xFF) && (((struct uip_eth_hdr *) ethHeader)->dest.addr[3] == 0xFF) && (((struct uip_eth_hdr *) ethHeader)->dest.addr[4] == 0xFF) && (((struct uip_eth_hdr *) ethHeader)->dest.addr[5] == 0xFF) ) { /* IPv6 does not use broadcast addresses, hence this should not happen */ PRINTF("eth2low: Dropping broadcast packet\n\r"); #if !RF230BB && !RF212BB usb_eth_stat.txbad++; #endif uip_len = 0; return; } else { /* Simple Address Translation */ if(memcmp((uint8_t *)&simple_trans_ethernet_addr, &(((struct uip_eth_hdr *) ethHeader)->dest.addr[0]), 6) == 0) { #if UIP_CONF_IPV6 //Addressed to us: make 802.15.4 address from IPv6 Address destAddr.addr[0] = UIP_IP_BUF->destipaddr.u8[8] ^ 0x02; destAddr.addr[1] = UIP_IP_BUF->destipaddr.u8[9]; destAddr.addr[2] = UIP_IP_BUF->destipaddr.u8[10]; destAddr.addr[3] = UIP_IP_BUF->destipaddr.u8[11]; destAddr.addr[4] = UIP_IP_BUF->destipaddr.u8[12]; destAddr.addr[5] = UIP_IP_BUF->destipaddr.u8[13]; destAddr.addr[6] = UIP_IP_BUF->destipaddr.u8[14]; destAddr.addr[7] = UIP_IP_BUF->destipaddr.u8[15]; #else //Not intended to be functional, but allows ip4 build without errors. destAddr.addr[0] = UIP_IP_BUF->destipaddr.u8[0] ^ 0x02; destAddr.addr[1] = UIP_IP_BUF->destipaddr.u8[1]; destAddr.addr[2] = UIP_IP_BUF->destipaddr.u8[2]; destAddr.addr[3] = UIP_IP_BUF->destipaddr.u8[3]; destAddr.addr[4] = UIP_IP_BUF->destipaddr.u8[0]; destAddr.addr[5] = UIP_IP_BUF->destipaddr.u8[1]; destAddr.addr[6] = UIP_IP_BUF->destipaddr.u8[2]; destAddr.addr[7] = UIP_IP_BUF->destipaddr.u8[3]; #endif destAddrPtr = &destAddr; } #if UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS else { //Not addressed to us uip_len = 0; return; } #else /* Complex Address Translation */ PRINTF("eth2low: Addressed packet received... "); //Check this returns OK if (mac_createSicslowpanLongAddr( &(((struct uip_eth_hdr *) ethHeader)->dest.addr[0]), &destAddr) == 0) { PRINTF(" translation failed\n\r"); #if !RF230BB && !RF212BB usb_eth_stat.txbad++; #endif uip_len = 0; return; } PRINTF(" translated OK\n\r"); destAddrPtr = &destAddr; #endif /* UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS */ } //Remove header from length before passing onward uip_len -= UIP_LLH_LEN; //Some IP packets have link layer in them, need to change them around! if (usbstick_mode.translate) { #if DEBUG uint8_t transReturn = mac_translateIPLinkLayer(ll_802154_type); PRINTF("IPTranslation: returns %d\n\r", transReturn); #else mac_translateIPLinkLayer(ll_802154_type); #endif } #if UIP_CONF_IPV6 /* Send the packet to the uip6 stack if it exists, else send to 6lowpan */ #if UIP_CONF_IPV6_RPL /* Save the destination address, to trap ponging it back to the interface */ uip_ipaddr_copy(&last_sender, &UIP_IP_BUF->srcipaddr); tcpip_input(); tcpip_output(destAddrPtr); #else // PRINTF("Input from %x %x %x %x %x %x %x %x\n",UIP_IP_BUF->srcipaddr.u8[0],UIP_IP_BUF->srcipaddr.u8[1],UIP_IP_BUF->srcipaddr.u8[2],UIP_IP_BUF->srcipaddr.u8[3],UIP_IP_BUF->srcipaddr.u8[4],UIP_IP_BUF->srcipaddr.u8[5],UIP_IP_BUF->srcipaddr.u8[6],UIP_IP_BUF->srcipaddr.u8[7]); // PRINTF("Output to %x %x %x %x %x %x %x %x\n",destAddr.addr[0],destAddr.addr[1],destAddr.addr[2],destAddr.addr[3],destAddr.addr[4],destAddr.addr[5],destAddr.addr[6],destAddr.addr[7]); tcpip_output(destAddrPtr); #endif #else /* UIP_CONF_IPV6 */ tcpip_output(); //Allow non-ipv6 builds (Hello World) #endif /* UIP_CONF_IPV6 */ #if !RF230BB && !RF212BB usb_eth_stat.txok++; #endif uip_len = 0; }
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 int coap_receive(void) { coap_error_code = NO_ERROR; PRINTF("handle_incoming_data(): received uip_datalen=%u \n",(uint16_t)uip_datalen()); /* Static declaration reduces stack peaks and program code size. */ static coap_packet_t message[1]; /* This way the packet can be treated as pointer as usual. */ static coap_packet_t response[1]; static coap_transaction_t *transaction = NULL; if (uip_newdata()) { PRINTF("receiving UDP datagram from: "); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF(":%u\n Length: %u\n Data: ", uip_ntohs(UIP_UDP_BUF->srcport), uip_datalen() ); PRINTBITS(uip_appdata, uip_datalen()); PRINTF("\n"); coap_error_code = coap_parse_message(message, uip_appdata, uip_datalen()); if (coap_error_code==NO_ERROR) { /*TODO duplicates suppression, if required by application */ PRINTF(" Parsed: v %u, t %u, oc %u, c %u, mid %u\n", message->version, message->type, message->option_count, message->code, message->mid); PRINTF(" URL: %.*s\n", message->uri_path_len, message->uri_path); PRINTF(" Payload: %.*s\n", message->payload_len, message->payload); /* Handle requests. */ if (message->code >= COAP_GET && message->code <= COAP_DELETE) { /* Use transaction buffer for response to confirmable request. */ if ( (transaction = coap_new_transaction(message->mid, &UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport)) ) { uint32_t block_num = 0; uint16_t block_size = REST_MAX_CHUNK_SIZE; uint32_t block_offset = 0; int32_t new_offset = 0; /* prepare response */ if (message->type==COAP_TYPE_CON) { /* Reliable CON requests are answered with an ACK. */ coap_init_message(response, COAP_TYPE_ACK, CONTENT_2_05, message->mid); } else { /* Unreliable NON requests are answered with a NON as well. */ coap_init_message(response, COAP_TYPE_NON, CONTENT_2_05, coap_get_mid()); } /* resource handlers must take care of different handling (e.g., TOKEN_OPTION_REQUIRED_240) */ if (IS_OPTION(message, COAP_OPTION_TOKEN)) { coap_set_header_token(response, message->token, message->token_len); SET_OPTION(response, COAP_OPTION_TOKEN); } /* get offset for blockwise transfers */ if (coap_get_header_block2(message, &block_num, NULL, &block_size, &block_offset)) { PRINTF("Blockwise: block request %lu (%u/%u) @ %lu bytes\n", block_num, block_size, REST_MAX_CHUNK_SIZE, block_offset); block_size = MIN(block_size, REST_MAX_CHUNK_SIZE); new_offset = block_offset; } /* Invoke resource handler. */ if (service_cbk) { /* Call REST framework and check if found and allowed. */ if (service_cbk(message, response, transaction->packet+COAP_MAX_HEADER_SIZE, block_size, &new_offset)) { if (coap_error_code==NO_ERROR) { /* Apply blockwise transfers. */ if ( IS_OPTION(message, COAP_OPTION_BLOCK1) && response->code<BAD_REQUEST_4_00 && !IS_OPTION(response, COAP_OPTION_BLOCK1) ) { PRINTF("Block1 NOT IMPLEMENTED\n"); coap_error_code = NOT_IMPLEMENTED_5_01; coap_error_message = "NoBlock1Support"; } else if ( IS_OPTION(message, COAP_OPTION_BLOCK2) ) { /* unchanged new_offset indicates that resource is unaware of blockwise transfer */ if (new_offset==block_offset) { PRINTF("Blockwise: unaware resource with payload length %u/%u\n", response->payload_len, block_size); if (block_offset >= response->payload_len) { PRINTF("handle_incoming_data(): block_offset >= response->payload_len\n"); response->code = BAD_OPTION_4_02; coap_set_payload(response, "BlockOutOfScope", 15); /* a const char str[] and sizeof(str) produces larger code size */ } else { coap_set_header_block2(response, block_num, response->payload_len - block_offset > block_size, block_size); coap_set_payload(response, response->payload+block_offset, MIN(response->payload_len - block_offset, block_size)); } /* if (valid offset) */ } else { /* resource provides chunk-wise data */ PRINTF("Blockwise: blockwise resource, new offset %ld\n", new_offset); coap_set_header_block2(response, block_num, new_offset!=-1 || response->payload_len > block_size, block_size); if (response->payload_len > block_size) coap_set_payload(response, response->payload, block_size); } /* if (resource aware of blockwise) */ } else if (new_offset!=0) { PRINTF("Blockwise: no block option for blockwise resource, using block size %u\n", REST_MAX_CHUNK_SIZE); coap_set_header_block2(response, 0, new_offset!=-1, REST_MAX_CHUNK_SIZE); coap_set_payload(response, response->payload, MIN(response->payload_len, REST_MAX_CHUNK_SIZE)); } /* if (blockwise request) */ } /* no errors/hooks */ } /* successful service callback */ /* Serialize response. */ if (coap_error_code==NO_ERROR) { if ((transaction->packet_len = coap_serialize_message(response, transaction->packet))==0) { coap_error_code = PACKET_SERIALIZATION_ERROR; } } } else { coap_error_code = NOT_IMPLEMENTED_5_01; coap_error_message = "NoServiceCallbck"; // no a to fit 16 bytes } /* if (service callback) */ } else { coap_error_code = SERVICE_UNAVAILABLE_5_03; coap_error_message = "NoFreeTraBuffer"; } /* if (transaction buffer) */ } else { /* Responses */ if (message->type==COAP_TYPE_ACK) { PRINTF("Received ACK\n"); } else if (message->type==COAP_TYPE_RST) { PRINTF("Received RST\n"); /* Cancel possible subscriptions. */ coap_remove_observer_by_mid(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, message->mid); } transaction = coap_get_transaction_by_mid(message->mid); if (message->type != COAP_TYPE_CON && transaction) { /* Free transaction memory before callback, as it may create a new transaction. */ restful_response_handler callback = transaction->callback; void *callback_data = transaction->callback_data; coap_clear_transaction(transaction); /* Check if someone registered for the response */ if (callback) { callback(callback_data, message); } } /* if (ACKed transaction) */ /* Observe notification */ if ((message->type == COAP_TYPE_CON || message->type == COAP_TYPE_NON) \ && IS_OPTION(message, COAP_OPTION_OBSERVE)) { PRINTF("Observe [%u]\n", message->observe); coap_handle_notification(&UIP_IP_BUF->srcipaddr, \ UIP_UDP_BUF->srcport, message); } transaction = NULL; } /* Request or Response */ } /* if (parsed correctly) */ if (coap_error_code==NO_ERROR) { if (transaction) coap_send_transaction(transaction); } else if (coap_error_code==MANUAL_RESPONSE) { PRINTF("Clearing transaction for manual response"); coap_clear_transaction(transaction); } else { PRINTF("ERROR %u: %s\n", coap_error_code, coap_error_message); coap_clear_transaction(transaction); /* Set to sendable error code. */ if (coap_error_code >= 192) { coap_error_code = INTERNAL_SERVER_ERROR_5_00; } /* Reuse input buffer for error message. */ coap_init_message(message, COAP_TYPE_ACK, coap_error_code, message->mid); coap_set_payload(message, coap_error_message, strlen(coap_error_message)); coap_send_message(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, uip_appdata, coap_serialize_message(message, uip_appdata)); } } /* if (new data) */ return coap_error_code; }
static void dhcpTask(void* arg) { int wait; init: xid++; s.state = STATE_SENDING; wait = 1; while (1) { send_discover(); if (readResponse(DHCPOFFER, wait) != -1) { s.state = STATE_OFFER_RECEIVED; goto selecting; } if(wait < 60) wait = wait * 2; } selecting: xid++; wait = 1; do { send_request(); if (readResponse(DHCPACK, wait) != -1) { s.state = STATE_CONFIG_RECEIVED; goto bound; } if(wait < 10) { wait++; } else { goto init; } } while(s.state != STATE_CONFIG_RECEIVED); bound: #if 0 nosPrintf("Got IP address %d.%d.%d.%d\n", uip_ipaddr_to_quad(&s.ipaddr)); nosPrintf("Got netmask %d.%d.%d.%d\n", uip_ipaddr_to_quad(&s.netmask)); nosPrintf("Got DNS server %d.%d.%d.%d\n", uip_ipaddr_to_quad(&s.dnsaddr)); nosPrintf("Got default router %d.%d.%d.%d\n", uip_ipaddr_to_quad(&s.default_router)); nosPrintf("Lease expires in %ld seconds\n", uip_ntohs(s.lease_time[0])*65536ul + uip_ntohs(s.lease_time[1])); #endif dhcpc_configured(&s); uint32_t leaseLeft = uip_ntohs(s.lease_time[0])*65536ul + uip_ntohs(s.lease_time[1]); uint32_t sleepLeft = leaseLeft / 2; #define MAX_SECS ((INFINITE - 1) / HZ) while (sleepLeft > 0) { if (sleepLeft > MAX_SECS) { wait = MAX_SECS * HZ; sleepLeft -= MAX_SECS; } else { wait = sleepLeft * HZ; sleepLeft = 0; } posTaskSleep(wait); } leaseLeft = leaseLeft / 2; /* renewing: */ xid++; do { send_request(); if (leaseLeft / 2 > MAX_SECS) wait = MAX_SECS; else wait = (leaseLeft / 2); if (readResponse(DHCPACK, wait) != -1) { s.state = STATE_CONFIG_RECEIVED; goto bound; } leaseLeft -= wait; } while (leaseLeft > 3); /* rebinding: */ /* lease_expired: */ dhcpc_unconfigured(&s); goto init; }