int main(void) { #ifdef MODULE_LTC4150 ltc4150_start(); #endif #ifdef FEATURE_PERIPH_RTC rtc_init(); #endif #ifdef MODULE_NETIF gnrc_netreg_entry_t dump; dump.pid = gnrc_pktdump_pid; dump.demux_ctx = GNRC_NETREG_DEMUX_CTX_ALL; gnrc_netreg_register(GNRC_NETTYPE_UNDEF, &dump); #endif (void) puts("Welcome to RIOT!"); char line_buf[SHELL_DEFAULT_BUFSIZE]; shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); return 0; }
kernel_pid_t gnrc_rpl_init(kernel_pid_t if_pid) { /* check if RPL was initialized before */ if (gnrc_rpl_pid == KERNEL_PID_UNDEF) { _instance_id = 0; /* start the event loop */ gnrc_rpl_pid = thread_create(_stack, sizeof(_stack), GNRC_RPL_PRIO, THREAD_CREATE_STACKTEST, _event_loop, NULL, "RPL"); if (gnrc_rpl_pid == KERNEL_PID_UNDEF) { DEBUG("RPL: could not start the event loop\n"); return KERNEL_PID_UNDEF; } _me_reg.demux_ctx = ICMPV6_RPL_CTRL; _me_reg.target.pid = gnrc_rpl_pid; /* register interest in all ICMPv6 packets */ gnrc_netreg_register(GNRC_NETTYPE_ICMPV6, &_me_reg); gnrc_rpl_of_manager_init(); xtimer_set_msg(&_lt_timer, _lt_time, &_lt_msg, gnrc_rpl_pid); #ifdef MODULE_NETSTATS_RPL memset(&gnrc_rpl_netstats, 0, sizeof(gnrc_rpl_netstats)); #endif } /* register all_RPL_nodes multicast address */ gnrc_ipv6_netif_add_addr(if_pid, &ipv6_addr_all_rpl_nodes, IPV6_ADDR_BIT_LEN, 0); gnrc_rpl_send_DIS(NULL, (ipv6_addr_t *) &ipv6_addr_all_rpl_nodes); return gnrc_rpl_pid; }
kernel_pid_t gnrc_rpl_init(kernel_pid_t if_pid) { /* check if RPL was initialized before */ if (gnrc_rpl_pid == KERNEL_PID_UNDEF) { /* start the event loop */ gnrc_rpl_pid = thread_create(_stack, sizeof(_stack), GNRC_RPL_PRIO, CREATE_STACKTEST, _event_loop, NULL, "RPL"); if (gnrc_rpl_pid == KERNEL_PID_UNDEF) { DEBUG("RPL: could not start the event loop\n"); return KERNEL_PID_UNDEF; } _me_reg.demux_ctx = ICMPV6_RPL_CTRL; _me_reg.pid = gnrc_rpl_pid; /* register interest in all ICMPv6 packets */ gnrc_netreg_register(GNRC_NETTYPE_ICMPV6, &_me_reg); gnrc_rpl_of_manager_init(); _lt_time = timex_set(GNRC_RPL_LIFETIME_UPDATE_STEP, 0); vtimer_set_msg(&_lt_timer, _lt_time, gnrc_rpl_pid, GNRC_RPL_MSG_TYPE_LIFETIME_UPDATE, NULL); } /* register all_RPL_nodes multicast address */ ipv6_addr_t all_RPL_nodes = GNRC_RPL_ALL_NODES_ADDR; gnrc_ipv6_netif_add_addr(if_pid, &all_RPL_nodes, IPV6_ADDR_BIT_LEN, 0); gnrc_rpl_send_DIS(NULL, &all_RPL_nodes); return gnrc_rpl_pid; }
int _ccnl_interest(int argc, char **argv) { if (argc < 2) { _interest_usage(argv[0]); return -1; } if (argc > 2) { if (_intern_fib_add(argv[1], argv[2]) < 0) { _interest_usage(argv[0]); return -1; } } memset(_int_buf, '\0', BUF_SIZE); memset(_cont_buf, '\0', BUF_SIZE); for (int cnt = 0; cnt < CCNL_INTEREST_RETRIES; cnt++) { gnrc_netreg_entry_t _ne; /* register for content chunks */ _ne.demux_ctx = GNRC_NETREG_DEMUX_CTX_ALL; _ne.pid = sched_active_pid; gnrc_netreg_register(GNRC_NETTYPE_CCN_CHUNK, &_ne); ccnl_send_interest(CCNL_SUITE_NDNTLV, argv[1], NULL, _int_buf, BUF_SIZE); if (ccnl_wait_for_chunk(_cont_buf, BUF_SIZE, 0) > 0) { gnrc_netreg_unregister(GNRC_NETTYPE_CCN_CHUNK, &_ne); printf("Content received: %s\n", _cont_buf); return 0; } gnrc_netreg_unregister(GNRC_NETTYPE_CCN_CHUNK, &_ne); } printf("Timeout! No content received in response to the Interest for %s.\n", argv[1]); return -1; }
int main(void) { gnrc_netreg_entry_t ne; uint8_t cpuid[CPUID_LEN]; cpuid_get(cpuid); conn_test_id = djb2_hash(cpuid, CPUID_LEN); random_init(conn_test_id); ne.pid = thread_create(_stack, sizeof(_stack), THREAD_PRIORITY_MAIN - 1, THREAD_CREATE_STACKTEST, _listener, NULL, "listener"); ne.demux_ctx = GNRC_NETREG_DEMUX_CTX_ALL; gnrc_netreg_register(GNRC_NETTYPE_UNDEF, &ne); puts("Connectivity Test program!"); printf("MY ID: %08lX\n", (unsigned long) conn_test_id); unsigned res = CONN_TEST_CHAN; if (gnrc_netapi_set(CONN_TEST_NETIF, NETOPT_CHANNEL, 0, (uint16_t *)&res, sizeof(uint16_t)) < 0) { puts("main: error setting channel"); } unsigned int addr_len = 8; if (gnrc_netapi_set(CONN_TEST_NETIF, NETOPT_SRC_LEN, 0, (uint16_t *)&addr_len, sizeof(uint16_t)) < 0) { printf("main: error setting addressing mode\n"); } xtimer_set_msg(&ct_timer, (SEC_IN_USEC * 3) + (random_uint32() & 0x001FFFFF), &ct_m, ne.pid); char line_buf[SHELL_DEFAULT_BUFSIZE]; shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); return 0; }
/* start sending beacons */ void beaconing_start(void) { uint8_t remaining_beacons = DOW_BEACONING_COUNT; bool end_beaconing = false; /* register for RX */ gnrc_netreg_entry_t _ne; _ne.target.pid = sched_active_pid; _ne.demux_ctx = GNRC_NETREG_DEMUX_CTX_ALL; gnrc_netreg_register(GNRC_NETTYPE_UNDEF, &_ne); /* schedule beacon */ msg_t beacon_msg; beacon_msg.type = DOW_MSG_BEACON; xtimer_t beacon_timer; beacon_timer.target = beacon_timer.long_target = 0; /* let's delay the first beacon by DOW_BEACONING_WAIT */ uint32_t tmp = DOW_BEACONING_PERIOD + DOW_BEACONING_WAIT; xtimer_set_msg(&beacon_timer, tmp, &beacon_msg, sched_active_pid); tmp -= DOW_BEACONING_WAIT; uint32_t start = xtimer_now().ticks32; while (1) { msg_t m; msg_receive(&m); switch (m.type) { case DOW_MSG_BEACON: LOG_DEBUG("beaconing: ready to send next beacon\n"); beaconing_send(); tmp = DOW_BEACONING_PERIOD; /* check if we need to do further beaconing */ if (--remaining_beacons > 0) { xtimer_set_msg(&beacon_timer, tmp, &beacon_msg, sched_active_pid); } else { beacon_msg.type = DOW_MSG_BEACON_END; tmp = 2 * DOW_BEACONING_WAIT - (xtimer_now().ticks32 - start); LOG_INFO("beaconing: end beaconing period in %" PRIu32 \ " seconds\n", (tmp / US_PER_SEC)); xtimer_set_msg(&beacon_timer, tmp, &beacon_msg, sched_active_pid); } break; case DOW_MSG_BEACON_END: LOG_INFO("beaconing: end beaconing\n"); end_beaconing = true; break; case GNRC_NETAPI_MSG_TYPE_RCV: LOG_DEBUG("beaconing: received packet, assume that it is a beacon\n"); _handle_beacon((gnrc_pktsnip_t *)m.content.ptr); break; default: LOG_WARNING("beaconing: didn't expect message type %X\n", m.type); break; } if (end_beaconing) { break; } } gnrc_netreg_unregister(GNRC_NETTYPE_UNDEF, &_ne); }
static void *_event_loop(void *args) { msg_t msg, reply, msg_q[GNRC_SIXLOWPAN_MSG_QUEUE_SIZE]; gnrc_netreg_entry_t me_reg = GNRC_NETREG_ENTRY_INIT_PID(GNRC_NETREG_DEMUX_CTX_ALL, sched_active_pid); (void)args; msg_init_queue(msg_q, GNRC_SIXLOWPAN_MSG_QUEUE_SIZE); /* register interest in all 6LoWPAN packets */ gnrc_netreg_register(GNRC_NETTYPE_SIXLOWPAN, &me_reg); /* preinitialize ACK */ reply.type = GNRC_NETAPI_MSG_TYPE_ACK; /* start event loop */ while (1) { DEBUG("6lo: waiting for incoming message.\n"); msg_receive(&msg); switch (msg.type) { case GNRC_NETAPI_MSG_TYPE_RCV: DEBUG("6lo: GNRC_NETDEV_MSG_TYPE_RCV received\n"); _receive(msg.content.ptr); break; case GNRC_NETAPI_MSG_TYPE_SND: DEBUG("6lo: GNRC_NETDEV_MSG_TYPE_SND received\n"); _send(msg.content.ptr); break; case GNRC_NETAPI_MSG_TYPE_GET: case GNRC_NETAPI_MSG_TYPE_SET: DEBUG("6lo: reply to unsupported get/set\n"); reply.content.value = -ENOTSUP; msg_reply(&msg, &reply); break; #ifdef MODULE_GNRC_SIXLOWPAN_FRAG case GNRC_SIXLOWPAN_MSG_FRAG_SND: DEBUG("6lo: send fragmented event received\n"); gnrc_sixlowpan_frag_send(msg.content.ptr); break; #endif default: DEBUG("6lo: operation not supported\n"); break; } } return NULL; }
int main(void) { puts("LWMAC test application"); gnrc_netreg_entry_t dump = GNRC_NETREG_ENTRY_INIT_PID(GNRC_NETREG_DEMUX_CTX_ALL, gnrc_pktdump_pid); gnrc_netreg_register(GNRC_NETTYPE_UNDEF, &dump); char line_buf[SHELL_DEFAULT_BUFSIZE]; shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); return 0; }
int main(void) { #ifdef MODULE_NETIF gnrc_netreg_entry_t dump = GNRC_NETREG_ENTRY_INIT_PID(GNRC_NETREG_DEMUX_CTX_ALL, gnrc_pktdump_pid); gnrc_netreg_register(GNRC_NETTYPE_UNDEF, &dump); #endif (void) puts("Welcome to RIOT!"); char line_buf[SHELL_DEFAULT_BUFSIZE]; shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); return 0; }
static void *_ipv6_fwd_eventloop(void *arg) { (void)arg; msg_t msg, msg_q[8]; gnrc_netreg_entry_t me_reg; msg_init_queue(msg_q, 8); me_reg.demux_ctx = GNRC_NETREG_DEMUX_CTX_ALL; me_reg.pid = thread_getpid(); gnrc_netreg_register(GNRC_NETTYPE_SIXLOWPAN, &me_reg); while(1) { msg_receive(&msg); gnrc_pktsnip_t *pkt = msg.content.ptr; if(msg.type == GNRC_NETAPI_MSG_TYPE_SND) { gnrc_pktsnip_t *ipv6 = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_IPV6); ipv6 = ipv6->data; ipv6_hdr_t *ipv6_hdr =(ipv6_hdr_t *)ipv6; /* get the first IPv6 interface and prints its address */ kernel_pid_t ifs[GNRC_NETIF_NUMOF]; gnrc_netif_get(ifs); gnrc_ipv6_netif_t *entry = gnrc_ipv6_netif_get(ifs[0]); for (int i = 0; i < GNRC_IPV6_NETIF_ADDR_NUMOF; i++) { if ( (!ipv6_addr_is_link_local(&entry->addrs[i].addr)) && (!ipv6_addr_is_link_local(&ipv6_hdr->src)) && (!ipv6_addr_is_link_local(&ipv6_hdr->dst)) && !(entry->addrs[i].flags & GNRC_IPV6_NETIF_ADDR_FLAGS_NON_UNICAST) && (!ipv6_addr_is_unspecified(&entry->addrs[i].addr)) ) { if(!ipv6_addr_equal(&entry->addrs[i].addr, &(ipv6_hdr->src))){ char addr_str[IPV6_ADDR_MAX_STR_LEN]; printf("IPv6 ROUTER: forward from src = %s ", ipv6_addr_to_str(addr_str, &(ipv6_hdr->src), sizeof(addr_str)) ); printf("to dst = %s\n",ipv6_addr_to_str(addr_str, &(ipv6_hdr->dst), sizeof(addr_str))); } } } } gnrc_pktbuf_release(pkt); } /* never reached */ return NULL; }
gnrc_nettest_res_t gnrc_nettest_receive(kernel_pid_t pid, gnrc_pktsnip_t *in, unsigned int exp_pkts, const kernel_pid_t *exp_senders, const gnrc_pktsnip_t **exp_out, gnrc_nettype_t exp_type, uint32_t exp_demux_ctx) { gnrc_netreg_entry_t reg_entry = { NULL, exp_demux_ctx, thread_getpid() }; gnrc_nettest_res_t res; gnrc_netreg_register(exp_type, ®_entry); res = _pkt_test(GNRC_NETAPI_MSG_TYPE_RCV, pid, in, exp_pkts, exp_senders, exp_out); gnrc_netreg_unregister(exp_type, ®_entry); return res; }
gnrc_nettest_res_t gnrc_nettest_receive(kernel_pid_t pid, gnrc_pktsnip_t *in, unsigned int exp_pkts, const kernel_pid_t *exp_senders, const gnrc_pktsnip_t **exp_out, gnrc_nettype_t exp_type, uint32_t exp_demux_ctx) { gnrc_netreg_entry_t reg_entry = GNRC_NETREG_ENTRY_INIT_PID(exp_demux_ctx, sched_active_pid); gnrc_nettest_res_t res; gnrc_netreg_register(exp_type, ®_entry); res = _pkt_test(GNRC_NETAPI_MSG_TYPE_RCV, pid, in, exp_pkts, exp_senders, exp_out); gnrc_netreg_unregister(exp_type, ®_entry); return res; }
/** * @brief Maybe you are a golfer?! */ int main(void) { gnrc_netreg_entry_t dump; puts("RIOT sniffer application"); /* start and register rawdump thread */ puts("Run the rawdump thread and register it"); dump.pid = thread_create(rawdmp_stack, sizeof(rawdmp_stack), RAWDUMP_PRIO, CREATE_STACKTEST, rawdump, NULL, "rawdump"); dump.demux_ctx = GNRC_NETREG_DEMUX_CTX_ALL; gnrc_netreg_register(GNRC_NETTYPE_UNDEF, &dump); /* start the shell */ puts("All ok, starting the shell now"); char line_buf[SHELL_DEFAULT_BUFSIZE]; shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); return 0; }
int main(void) { shell_t shell; gnrc_netreg_entry_t dump; puts("KW2XRF device driver test"); /* register the pktdump thread */ puts("Register the packet dump thread for GNRC_NETTYPE_UNDEF packets"); dump.pid = gnrc_pktdump_getpid(); dump.demux_ctx = GNRC_NETREG_DEMUX_CTX_ALL; gnrc_netreg_register(GNRC_NETTYPE_UNDEF, &dump); /* start the shell */ puts("Initialization successful - starting the shell now"); (void) posix_open(uart0_handler_pid, 0); shell_init(&shell, NULL, SHELL_BUFSIZE, uart0_readc, uart0_putc); shell_run(&shell); return 0; }
int _tftp_do_client_transfer(tftp_context_t *ctxt) { msg_t msg; tftp_state ret = TS_BUSY; /* register our DNS response listener */ gnrc_netreg_entry_t entry = GNRC_NETREG_ENTRY_INIT_PID(ctxt->src_port, sched_active_pid); if (gnrc_netreg_register(GNRC_NETTYPE_UDP, &entry)) { DEBUG("tftp: error starting server.\n"); return TS_FAILED; } /* try to start the TFTP transfer */ ret = _tftp_state_processes(ctxt, NULL); if (ret != TS_BUSY) { DEBUG("tftp: transfer failed\n"); /* if the start failed return */ return ret; } /* main processing loop */ while (ret == TS_BUSY) { /* wait for a message */ msg_receive(&msg); DEBUG("tftp: message received\n"); ret = _tftp_state_processes(ctxt, &msg); /* release packet if we received one */ if (msg.type == GNRC_NETAPI_MSG_TYPE_RCV) { gnrc_pktbuf_release(msg.content.ptr); } } /* unregister our UDP listener on this thread */ gnrc_netreg_unregister(GNRC_NETTYPE_UDP, &entry); return ret; }
/** * @brief Maybe you are a golfer?! */ int main(void) { gnrc_netreg_entry_t dump = GNRC_NETREG_ENTRY_INIT_PID(GNRC_NETREG_DEMUX_CTX_ALL, gnrc_pktdump_pid); puts("Xbee S1 device driver test"); /* initialize and register pktdump */ if (gnrc_pktdump_pid <= KERNEL_PID_UNDEF) { puts("Error starting pktdump thread"); return -1; } gnrc_netreg_register(GNRC_NETTYPE_UNDEF, &dump); /* start the shell */ puts("Initialization OK, starting shell now"); char line_buf[SHELL_DEFAULT_BUFSIZE]; shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); return 0; }
static void *_event_loop(void *args) { msg_t msg, reply, msg_q[GNRC_IPV6_MSG_QUEUE_SIZE]; gnrc_netreg_entry_t me_reg; (void)args; msg_init_queue(msg_q, GNRC_IPV6_MSG_QUEUE_SIZE); me_reg.demux_ctx = GNRC_NETREG_DEMUX_CTX_ALL; me_reg.pid = thread_getpid(); /* register interest in all IPv6 packets */ gnrc_netreg_register(GNRC_NETTYPE_IPV6, &me_reg); /* preinitialize ACK */ reply.type = GNRC_NETAPI_MSG_TYPE_ACK; /* start event loop */ while (1) { DEBUG("ipv6: waiting for incoming message.\n"); msg_receive(&msg); switch (msg.type) { case GNRC_NETAPI_MSG_TYPE_RCV: DEBUG("ipv6: GNRC_NETAPI_MSG_TYPE_RCV received\n"); _receive(msg.content.ptr); break; case GNRC_NETAPI_MSG_TYPE_SND: DEBUG("ipv6: GNRC_NETAPI_MSG_TYPE_SND received\n"); _send(msg.content.ptr, true); break; case GNRC_NETAPI_MSG_TYPE_GET: case GNRC_NETAPI_MSG_TYPE_SET: DEBUG("ipv6: reply to unsupported get/set\n"); reply.content.value = -ENOTSUP; msg_reply(&msg, &reply); break; #ifdef MODULE_GNRC_NDP case GNRC_NDP_MSG_RTR_TIMEOUT: DEBUG("ipv6: Router timeout received\n"); ((gnrc_ipv6_nc_t *)msg.content.ptr)->flags &= ~GNRC_IPV6_NC_IS_ROUTER; break; /* XXX reactivate when https://github.com/RIOT-OS/RIOT/issues/5122 is * solved properly */ /* case GNRC_NDP_MSG_ADDR_TIMEOUT: */ /* DEBUG("ipv6: Router advertisement timer event received\n"); */ /* gnrc_ipv6_netif_remove_addr(KERNEL_PID_UNDEF, */ /* msg.content.ptr); */ /* break; */ case GNRC_NDP_MSG_NBR_SOL_RETRANS: DEBUG("ipv6: Neigbor solicitation retransmission timer event received\n"); gnrc_ndp_retrans_nbr_sol(msg.content.ptr); break; case GNRC_NDP_MSG_NC_STATE_TIMEOUT: DEBUG("ipv6: Neigbor cache state timeout received\n"); gnrc_ndp_state_timeout(msg.content.ptr); break; #endif #ifdef MODULE_GNRC_NDP_ROUTER case GNRC_NDP_MSG_RTR_ADV_RETRANS: DEBUG("ipv6: Router advertisement retransmission event received\n"); gnrc_ndp_router_retrans_rtr_adv(msg.content.ptr); break; case GNRC_NDP_MSG_RTR_ADV_DELAY: DEBUG("ipv6: Delayed router advertisement event received\n"); gnrc_ndp_router_send_rtr_adv(msg.content.ptr); break; #endif #ifdef MODULE_GNRC_NDP_HOST case GNRC_NDP_MSG_RTR_SOL_RETRANS: DEBUG("ipv6: Router solicitation retransmission event received\n"); gnrc_ndp_host_retrans_rtr_sol(msg.content.ptr); break; #endif #ifdef MODULE_GNRC_SIXLOWPAN_ND case GNRC_SIXLOWPAN_ND_MSG_MC_RTR_SOL: DEBUG("ipv6: Multicast router solicitation event received\n"); gnrc_sixlowpan_nd_mc_rtr_sol(msg.content.ptr); break; case GNRC_SIXLOWPAN_ND_MSG_UC_RTR_SOL: DEBUG("ipv6: Unicast router solicitation event received\n"); gnrc_sixlowpan_nd_uc_rtr_sol(msg.content.ptr); break; # ifdef MODULE_GNRC_SIXLOWPAN_CTX case GNRC_SIXLOWPAN_ND_MSG_DELETE_CTX: DEBUG("ipv6: Delete 6LoWPAN context event received\n"); gnrc_sixlowpan_ctx_remove(((((gnrc_sixlowpan_ctx_t *)msg.content.ptr)->flags_id) & GNRC_SIXLOWPAN_CTX_FLAGS_CID_MASK)); break; # endif #endif #ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER case GNRC_SIXLOWPAN_ND_MSG_ABR_TIMEOUT: DEBUG("ipv6: border router timeout event received\n"); gnrc_sixlowpan_nd_router_abr_remove(msg.content.ptr); break; /* XXX reactivate when https://github.com/RIOT-OS/RIOT/issues/5122 is * solved properly */ /* case GNRC_SIXLOWPAN_ND_MSG_AR_TIMEOUT: */ /* DEBUG("ipv6: address registration timeout received\n"); */ /* gnrc_sixlowpan_nd_router_gc_nc(msg.content.ptr); */ /* break; */ case GNRC_NDP_MSG_RTR_ADV_SIXLOWPAN_DELAY: DEBUG("ipv6: Delayed router advertisement event received\n"); gnrc_ipv6_nc_t *nc_entry = msg.content.ptr; gnrc_ndp_internal_send_rtr_adv(nc_entry->iface, NULL, &(nc_entry->ipv6_addr), false); break; #endif default: break; } } return NULL; }
tftp_state _tftp_state_processes(tftp_context_t *ctxt, msg_t *m) { gnrc_pktsnip_t *outbuf = gnrc_pktbuf_add(NULL, NULL, TFTP_DEFAULT_DATA_SIZE, GNRC_NETTYPE_UNDEF); /* check if this is an client start */ if (!m) { DEBUG("tftp: starting transaction as client\n"); return _tftp_send_start(ctxt, outbuf); } else if (m->type == TFTP_TIMEOUT_MSG) { DEBUG("tftp: timeout occured\n"); if (++(ctxt->retries) > GNRC_TFTP_MAX_RETRIES) { /* transfer failed due to lost peer */ DEBUG("tftp: peer lost\n"); gnrc_pktbuf_release(outbuf); return TS_FAILED; } /* increase the timeout for congestion control */ ctxt->block_timeout <<= 1; /* the send message timed out, re-sending */ if (ctxt->dst_port == GNRC_TFTP_DEFAULT_DST_PORT) { DEBUG("tftp: sending timed out, re-sending\n"); /* we are still negotiating resent, start */ return _tftp_send_start(ctxt, outbuf); } else { DEBUG("tftp: last data or ack packet lost, resending\n"); /* we are sending / receiving data */ /* if we are reading resent the ACK, if writing the DATA */ return _tftp_send_dack(ctxt, outbuf, (ctxt->op == TO_RRQ) ? TO_ACK : TO_DATA); } } else if (m->type != GNRC_NETAPI_MSG_TYPE_RCV) { DEBUG("tftp: unknown message\n"); gnrc_pktbuf_release(outbuf); return TS_BUSY; } gnrc_pktsnip_t *pkt = m->content.ptr; gnrc_pktsnip_t *tmp; tmp = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_UDP); udp_hdr_t *udp = (udp_hdr_t *)tmp->data; tmp = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_IPV6); ipv6_hdr_t *ip = (ipv6_hdr_t *)tmp->data; uint8_t *data = (uint8_t *)pkt->data; xtimer_remove(&(ctxt->timer)); switch (_tftp_parse_type(data)) { case TO_RRQ: case TO_WRQ: { if (byteorder_ntohs(udp->dst_port) != GNRC_TFTP_DEFAULT_DST_PORT) { /* not a valid start packet */ DEBUG("tftp: incoming packet on port %d dropped\n", byteorder_ntohs(udp->dst_port)); gnrc_pktbuf_release(outbuf); return TS_FAILED; } /* reinitialize the context with the current client */ tftp_opcodes_t op = _tftp_parse_type(data); _tftp_init_ctxt(&(ip->src), NULL, op, TTM_ASCII, CT_SERVER, ctxt->start_cb, ctxt->stop_cb, ctxt->data_cb, ctxt->enable_options, ctxt); /* get the context of the client */ ctxt->dst_port = byteorder_ntohs(udp->src_port); DEBUG("tftp: client's port is %" PRIu16 "\n", ctxt->dst_port); int offset = _tftp_decode_start(ctxt, data, outbuf); DEBUG("tftp: offset after decode start = %i\n", offset); if (offset < 0) { DEBUG("tftp: there is no data?\n"); gnrc_pktbuf_release(outbuf); return TS_FAILED; } /* register a listener for the UDP port */ gnrc_netreg_entry_init_pid(&(ctxt->entry), ctxt->src_port, sched_active_pid); gnrc_netreg_register(GNRC_NETTYPE_UDP, &(ctxt->entry)); /* try to decode the options */ tftp_state state; tftp_opcodes_t opcode; if (ctxt->enable_options && _tftp_decode_options(ctxt, pkt, offset) > offset) { DEBUG("tftp: send option ACK\n"); /* the client send the TFTP options */ opcode = TO_OACK; } else { DEBUG("tftp: send normal ACK\n"); /* the client didn't send options, use ACK and set defaults */ _tftp_set_default_options(ctxt); /* send the first data block */ if (ctxt->op == TO_RRQ) { ++(ctxt->block_nr); opcode = TO_DATA; } else { opcode = TO_ACK; } } /* validate if the application accepts the action, mode, filename and transfer_size */ tftp_action_t action = (ctxt->op == TO_RRQ) ? TFTP_READ : TFTP_WRITE; if (!ctxt->start_cb(action, ctxt->mode, ctxt->file_name, &(ctxt->transfer_size))) { _tftp_send_error(ctxt, outbuf, TE_ACCESS, "Blocked by user application"); DEBUG("tftp: callback not able to handle mode\n"); return TS_FAILED; } /* the client send the TFTP options */ state = _tftp_send_dack(ctxt, outbuf, opcode); /* check if the client negotiation was successful */ if (state != TS_BUSY) { DEBUG("tftp: not able to send ACK\n"); } return state; } break; case TO_DATA: { /* try to process the data */ int proc = _tftp_process_data(ctxt, pkt); if (proc < 0) { DEBUG("tftp: data not accepted\n"); /* the data is not accepted return */ gnrc_pktbuf_release(outbuf); return TS_BUSY; } /* check if this is the first block */ if (!ctxt->block_nr && ctxt->dst_port == GNRC_TFTP_DEFAULT_DST_PORT && !ctxt->use_options) { /* no OACK received, restore default TFTP parameters */ _tftp_set_default_options(ctxt); DEBUG("tftp: restore default TFTP parameters\n"); /* switch the destination port to the src port of the server */ ctxt->dst_port = byteorder_ntohs(udp->src_port); } /* wait for the next data block */ DEBUG("tftp: wait for the next data block\n"); ++(ctxt->block_nr); _tftp_send_dack(ctxt, outbuf, TO_ACK); /* check if the data transfer has finished */ if (proc < ctxt->block_size) { DEBUG("tftp: transfer finished\n"); if (ctxt->stop_cb) { ctxt->stop_cb(TFTP_SUCCESS, NULL); } return TS_FINISHED; } return TS_BUSY; } break; case TO_ACK: { /* validate if this is the ACK we are waiting for */ if (!_tftp_validate_ack(ctxt, data)) { /* invalid packet ACK, drop */ gnrc_pktbuf_release(outbuf); return TS_BUSY; } /* check if the write action is finished */ if (ctxt->write_finished) { gnrc_pktbuf_release(outbuf); if (ctxt->stop_cb) { ctxt->stop_cb(TFTP_SUCCESS, NULL); } return TS_FINISHED; } /* check if this is the first ACK */ if (!ctxt->block_nr && ctxt->dst_port != byteorder_ntohs(udp->src_port)) { /* no OACK received restore default TFTP parameters */ _tftp_set_default_options(ctxt); /* switch the destination port to the src port of the server */ ctxt->dst_port = byteorder_ntohs(udp->src_port); } /* send the next data block */ ++(ctxt->block_nr); return _tftp_send_dack(ctxt, outbuf, TO_DATA); } break; case TO_ERROR: { tftp_err_codes_t err; const char *err_msg; /* decode the received error */ _tftp_decode_error(data, &err, &err_msg); /* inform the user application about the error */ if (ctxt->stop_cb) { ctxt->stop_cb(TFTP_PEER_ERROR, err_msg); } DEBUG("tftp: ERROR: %s\n", err_msg); gnrc_pktbuf_release(outbuf); return TS_FAILED; } break; case TO_OACK: { /* only allow one OACK to be received */ if (ctxt->dst_port != byteorder_ntohs(udp->src_port)) { DEBUG("tftp: TO_OACK received\n"); /* decode the options */ _tftp_decode_options(ctxt, pkt, 0); /* take the new source port */ ctxt->dst_port = byteorder_ntohs(udp->src_port); /* we must send block one to finish the negotiation in send mode */ if (ctxt->op == TO_WRQ) { ++(ctxt->block_nr); } } else { DEBUG("tftp: dropping double TO_OACK\n"); } return _tftp_send_dack(ctxt, outbuf, (ctxt->op == TO_WRQ) ? TO_DATA : TO_ACK); } break; } gnrc_pktbuf_release(outbuf); return TS_FAILED; }
int _tftp_server(tftp_context_t *ctxt) { msg_t msg; bool active = true; gnrc_netreg_entry_t entry = GNRC_NETREG_ENTRY_INIT_PID(GNRC_TFTP_DEFAULT_DST_PORT, sched_active_pid); while (active) { int ret = TS_BUSY; bool got_client = false; /* register the servers main listening port */ if (gnrc_netreg_register(GNRC_NETTYPE_UDP, &entry)) { DEBUG("tftp: error starting server.\n"); return TS_FAILED; } /* main processing loop */ while (ret == TS_BUSY) { /* wait for a message */ msg_receive(&msg); /* check if the server stop message has been received */ if (msg.type == TFTP_STOP_SERVER_MSG) { active = false; ret = TS_FAILED; break; } else { /* continue normal server opration */ DEBUG("tftp: message incoming\n"); ret = _tftp_state_processes(ctxt, &msg); /* release packet if we received one */ if (msg.type == GNRC_NETAPI_MSG_TYPE_RCV) { gnrc_pktbuf_release(msg.content.ptr); } } /* if we just accepted a client, disable the server main listening port */ if (!got_client) { gnrc_netreg_unregister(GNRC_NETTYPE_UDP, &entry); if (ret == TS_BUSY) { got_client = true; DEBUG("tftp: connection established\n"); } } } /* remove any stall timers */ xtimer_remove(&(ctxt->timer)); /* if the server transfer has finished, unregister the client dst port */ gnrc_netreg_unregister(GNRC_NETTYPE_UDP, &(ctxt->entry)); DEBUG("tftp: connection terminated\n"); } /* unregister our UDP listener on this thread */ gnrc_netreg_unregister(GNRC_NETTYPE_UDP, &entry); return 0; }
/* tests receiving */ static int test_receive(void) { ethernet_hdr_t *rcv_mac = (ethernet_hdr_t *)_tmp; uint8_t *rcv_payload = _tmp + sizeof(ethernet_hdr_t); gnrc_pktsnip_t *pkt, *hdr; gnrc_netreg_entry_t me = { NULL, GNRC_NETREG_DEMUX_CTX_ALL, thread_getpid() }; msg_t msg; if (_dev.netdev.event_callback == NULL) { puts("Device's event_callback not set"); return 0; } /* prepare receive buffer */ memcpy(rcv_mac->dst, _dev_addr, sizeof(_dev_addr)); memcpy(rcv_mac->src, _test_src, sizeof(_test_src)); /* no gnrc_ipv6 in compile unit => ETHERTYPE_IPV6 translates to * GNRC_NETTYPE_UNDEF */ rcv_mac->type = byteorder_htons(ETHERTYPE_IPV6); memcpy(rcv_payload, _TEST_PAYLOAD2, sizeof(_TEST_PAYLOAD2) - 1); _tmp_len = sizeof(_TEST_PAYLOAD2) + sizeof(ethernet_hdr_t) - 1; /* register for GNRC_NETTYPE_UNDEF */ gnrc_netreg_register(GNRC_NETTYPE_UNDEF, &me); /* fire ISR event */ _dev.netdev.event_callback((netdev2_t *)&_dev.netdev, NETDEV2_EVENT_ISR); /* wait for packet from MAC layer*/ msg_receive(&msg); /* check message */ if (msg.sender_pid != _mac_pid) { puts("Unexpected sender of netapi receive message"); return 0; } if (msg.type != GNRC_NETAPI_MSG_TYPE_RCV) { puts("Expected netapi receive message"); return 0; } pkt = msg.content.ptr; /* check payload */ if (pkt->size != _tmp_len - sizeof(ethernet_hdr_t)) { puts("Payload of unexpected size"); } if ((pkt->type != GNRC_NETTYPE_UNDEF) || (memcmp(pkt->data, _TEST_PAYLOAD2, pkt->size) != 0)) { puts("Unexpected payload"); puts("==========================================================="); puts("expected"); puts("==========================================================="); od_hex_dump(_TEST_PAYLOAD2, pkt->size, OD_WIDTH_DEFAULT); puts("==========================================================="); puts("send data"); puts("==========================================================="); od_hex_dump(pkt->data, pkt->size, OD_WIDTH_DEFAULT); return 0; } hdr = pkt->next; /* check netif header */ if ((hdr->type != GNRC_NETTYPE_NETIF) || (hdr->next != NULL) || (hdr->size) != (sizeof(gnrc_netif_hdr_t) + (2 * ETHERNET_ADDR_LEN))) { puts("Malformed header received"); return 0; } if (memcmp(gnrc_netif_hdr_get_src_addr(hdr->data), _test_src, ETHERNET_ADDR_LEN) != 0) { char addr_str[ETHERNET_ADDR_LEN * 3]; puts("Unexpected source received"); puts("================="); puts("expected"); puts("================="); puts(gnrc_netif_addr_to_str(addr_str, sizeof(addr_str), _test_src, ETHERNET_ADDR_LEN)); puts("================="); puts("received source"); puts("================="); puts(gnrc_netif_addr_to_str(addr_str, sizeof(addr_str), gnrc_netif_hdr_get_src_addr(hdr->data), ETHERNET_ADDR_LEN)); return 0; } if (memcmp(gnrc_netif_hdr_get_dst_addr(hdr->data), _dev_addr, ETHERNET_ADDR_LEN) != 0) { char addr_str[ETHERNET_ADDR_LEN * 3]; puts("Unexpected destination received"); puts("================="); puts("expected"); puts("================="); puts(gnrc_netif_addr_to_str(addr_str, sizeof(addr_str), _dev_addr, ETHERNET_ADDR_LEN)); puts("===================="); puts("received destination"); puts("===================="); puts(gnrc_netif_addr_to_str(addr_str, sizeof(addr_str), gnrc_netif_hdr_get_dst_addr(hdr->data), ETHERNET_ADDR_LEN)); return 0; } gnrc_pktbuf_release(pkt); gnrc_netreg_unregister(GNRC_NETTYPE_UNDEF, &me); return 1; }
static void _send_packet(void) { gnrc_netif_t *netif = gnrc_netif_iter(NULL); struct { gnrc_netif_hdr_t netif_hdr; uint8_t src[8]; uint8_t dst[8]; } netif_hdr = { .src = IEEE802154_REMOTE_EUI64, .dst = IEEE802154_LOCAL_EUI64, }; gnrc_netif_hdr_init(&(netif_hdr.netif_hdr), 8, 8); netif_hdr.netif_hdr.if_pid = netif->pid; uint8_t data1[] = { /* 6LoWPAN Header */ /* Fragmentation Header (first) */ 0xc0, 0x94, /* 0b11000: frag1, 0b00010010100: datagram_size (148) */ 0x00, 0x01, /* datagram_tag */ /* 0b011: LOWPAN_IPHC */ /* 0b11: Traffic Class and Flow Label are elided */ /* 0b1: Next Header is compressed */ /* 0b11: The Hop Limit field is compressed and the hop limit is 255 */ 0x7f, /* 0b0: No additional 8-bit Context Identifier Extension is used */ /* 0b0: Source address compression uses stateless compression */ /* 0b11: source address mode is 0 bits */ /* 0b0: Destination address is not a multicast address */ /* 0x0: Destination address compression uses stateless compression */ /* 0x00: destination address mode is 128 bits */ 0x30, /* destination address: fd01::1 */ 0xfd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0b11110: UDP LOWPAN_NHC */ /* 0b0: Checksum is carried in-line */ /* 0b11: First 12 bits of both Source Port and Destination Port are 0xf0b and elided */ 0xf3, 0x00, /* Source Port and Destination Port (4 bits each) */ 0x23, 0x2f, /* Checksum */ /* payload */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; uint8_t data2[] = { /* 6LoWPAN Header */ /* Fragmentation Header (rest) */ 0xe0, 0x94, /* 0b11100: frag1, 0b00010010100: datagram_size (148) */ 0x00, 0x01, /* datagram_tag */ 0x0c, /* datagram_offset (12 * 8 = 96) */ /* payload */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; gnrc_netreg_entry_t dump_6lowpan = GNRC_NETREG_ENTRY_INIT_PID(GNRC_NETREG_DEMUX_CTX_ALL, gnrc_pktdump_pid); gnrc_netreg_entry_t dump_ipv6 = GNRC_NETREG_ENTRY_INIT_PID(GNRC_NETREG_DEMUX_CTX_ALL, gnrc_pktdump_pid); gnrc_netreg_entry_t dump_udp = GNRC_NETREG_ENTRY_INIT_PID(GNRC_NETREG_DEMUX_CTX_ALL, gnrc_pktdump_pid); gnrc_netreg_entry_t dump_udp_61616 = GNRC_NETREG_ENTRY_INIT_PID(61616, gnrc_pktdump_pid); gnrc_netreg_register(GNRC_NETTYPE_SIXLOWPAN, &dump_6lowpan); gnrc_netreg_register(GNRC_NETTYPE_IPV6, &dump_ipv6); gnrc_netreg_register(GNRC_NETTYPE_UDP, &dump_udp); gnrc_netreg_register(GNRC_NETTYPE_UDP, &dump_udp_61616); gnrc_pktsnip_t *netif1 = gnrc_pktbuf_add(NULL, &netif_hdr, sizeof(netif_hdr), GNRC_NETTYPE_NETIF); gnrc_pktsnip_t *pkt1 = gnrc_pktbuf_add(netif1, data1, sizeof(data1), GNRC_NETTYPE_SIXLOWPAN); gnrc_netapi_dispatch_receive(GNRC_NETTYPE_SIXLOWPAN, GNRC_NETREG_DEMUX_CTX_ALL, pkt1); gnrc_pktsnip_t *netif2 = gnrc_pktbuf_add(NULL, &netif_hdr, sizeof(netif_hdr), GNRC_NETTYPE_NETIF); gnrc_pktsnip_t *pkt2 = gnrc_pktbuf_add(netif2, data2, sizeof(data2), GNRC_NETTYPE_SIXLOWPAN); gnrc_netapi_dispatch_receive(GNRC_NETTYPE_SIXLOWPAN, GNRC_NETREG_DEMUX_CTX_ALL, pkt2); }
void _prepare_send_checks(void) { gnrc_netreg_register(GNRC_NETTYPE_IPV6, &_ip_handler); }
/* internal functions */ static void *_event_loop(void *args) { msg_t msg, reply, msg_q[GNRC_IPV6_MSG_QUEUE_SIZE]; gnrc_netreg_entry_t me_reg; (void)args; msg_init_queue(msg_q, GNRC_IPV6_MSG_QUEUE_SIZE); me_reg.demux_ctx = GNRC_NETREG_DEMUX_CTX_ALL; me_reg.pid = thread_getpid(); /* register interest in all IPv6 packets */ gnrc_netreg_register(GNRC_NETTYPE_IPV6, &me_reg); /* preinitialize ACK */ reply.type = GNRC_NETAPI_MSG_TYPE_ACK; /* start event loop */ while (1) { DEBUG("ipv6: waiting for incoming message.\n"); msg_receive(&msg); switch (msg.type) { case GNRC_NETAPI_MSG_TYPE_RCV: DEBUG("ipv6: GNRC_NETAPI_MSG_TYPE_RCV received\n"); _receive((gnrc_pktsnip_t *)msg.content.ptr); break; case GNRC_NETAPI_MSG_TYPE_SND: DEBUG("ipv6: GNRC_NETAPI_MSG_TYPE_SND received\n"); _send((gnrc_pktsnip_t *)msg.content.ptr, true); break; case GNRC_NETAPI_MSG_TYPE_GET: case GNRC_NETAPI_MSG_TYPE_SET: DEBUG("ipv6: reply to unsupported get/set\n"); reply.content.value = -ENOTSUP; msg_reply(&msg, &reply); break; #ifdef MODULE_GNRC_NDP case GNRC_NDP_MSG_RTR_TIMEOUT: DEBUG("ipv6: Router timeout received\n"); ((gnrc_ipv6_nc_t *)msg.content.ptr)->flags &= ~GNRC_IPV6_NC_IS_ROUTER; break; case GNRC_NDP_MSG_ADDR_TIMEOUT: DEBUG("ipv6: Router advertisement timer event received\n"); gnrc_ipv6_netif_remove_addr(KERNEL_PID_UNDEF, (ipv6_addr_t *)msg.content.ptr); break; case GNRC_NDP_MSG_NBR_SOL_RETRANS: DEBUG("ipv6: Neigbor solicitation retransmission timer event received\n"); gnrc_ndp_retrans_nbr_sol((gnrc_ipv6_nc_t *)msg.content.ptr); break; case GNRC_NDP_MSG_NC_STATE_TIMEOUT: DEBUG("ipv6: Neigbor cache state timeout received\n"); gnrc_ndp_state_timeout((gnrc_ipv6_nc_t *)msg.content.ptr); break; #endif #ifdef MODULE_GNRC_NDP_ROUTER case GNRC_NDP_MSG_RTR_ADV_RETRANS: DEBUG("ipv6: Router advertisement retransmission event received\n"); gnrc_ndp_router_retrans_rtr_adv((gnrc_ipv6_netif_t *)msg.content.ptr); break; case GNRC_NDP_MSG_RTR_ADV_DELAY: DEBUG("ipv6: Delayed router advertisement event received\n"); gnrc_ndp_router_send_rtr_adv((gnrc_ipv6_nc_t *)msg.content.ptr); break; #endif #ifdef MODULE_GNRC_NDP_HOST case GNRC_NDP_MSG_RTR_SOL_RETRANS: DEBUG("ipv6: Router solicitation retransmission event received\n"); gnrc_ndp_host_retrans_rtr_sol((gnrc_ipv6_netif_t *)msg.content.ptr); break; #endif default: break; } } return NULL; }