Contiki-NG
tcpip.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2004, Swedish Institute of Computer Science.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the Institute nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * This file is part of the Contiki operating system.
30 */
31
32/**
33 * \file
34 * Core of the TCP/IP stack, handles input/output/routing
35 *
36 * \author Adam Dunkels <adam@sics.se>\author
37 * \author Mathilde Durvy <mdurvy@cisco.com> (IPv6 related code)
38 * \author Julien Abeille <jabeille@cisco.com> (IPv6 related code)
39 */
40
41#include "contiki.h"
42#include "contiki-net.h"
43#include "net/ipv6/uip-packetqueue.h"
44
45#include "net/ipv6/uip-nd6.h"
46#include "net/ipv6/uip-ds6.h"
48#include "net/linkaddr.h"
49#include "net/routing/routing.h"
50
51#include <string.h>
52
53/* Log configuration */
54#include "sys/log.h"
55#define LOG_MODULE "TCP/IP"
56#define LOG_LEVEL LOG_LEVEL_TCPIP
57
58#ifdef UIP_FALLBACK_INTERFACE
59extern struct uip_fallback_interface UIP_FALLBACK_INTERFACE;
60#endif
61
62process_event_t tcpip_event;
63#if UIP_CONF_ICMP6
64process_event_t tcpip_icmp6_event;
65#endif /* UIP_CONF_ICMP6 */
66
67/* Periodic check of active connections. */
68static struct etimer periodic;
69
70#if UIP_CONF_IPV6_REASSEMBLY
71/* Timer for reassembly. */
72extern struct etimer uip_reass_timer;
73#endif
74
75#if UIP_TCP
76/**
77 * \internal Structure for holding a TCP port and a process ID.
78 */
79struct listenport {
80 uint16_t port;
81 struct process *p;
82};
83
84static struct internal_state {
85 struct listenport listenports[UIP_LISTENPORTS];
86 struct process *p;
87} s;
88#endif
89
90enum {
91 TCP_POLL,
92 UDP_POLL,
93 PACKET_INPUT
94};
95
96/*---------------------------------------------------------------------------*/
97static void
98init_appstate(uip_tcp_appstate_t *as, void *state)
99{
100 as->p = PROCESS_CURRENT();
101 as->state = state;
102}
103/*---------------------------------------------------------------------------*/
104
105uint8_t
106tcpip_output(const uip_lladdr_t *a)
107{
108 int ret;
109
110 /* Tag Traffic Class if we are using TC for variable retrans */
111#if UIP_TAG_TC_WITH_VARIABLE_RETRANSMISSIONS
112 if(uipbuf_get_attr(UIPBUF_ATTR_MAX_MAC_TRANSMISSIONS) !=
114 LOG_INFO("Tagging TC with retrans: %d\n", uipbuf_get_attr(UIPBUF_ATTR_MAX_MAC_TRANSMISSIONS));
115 /* Encapsulate the MAC transmission limit in the Traffic Class field */
117 UIP_IP_BUF->tcflow =
118 uipbuf_get_attr(UIPBUF_ATTR_MAX_MAC_TRANSMISSIONS) << 4;
119 }
120#endif
121
122 if(netstack_process_ip_callback(NETSTACK_IP_OUTPUT, (const linkaddr_t *)a) ==
123 NETSTACK_IP_PROCESS) {
124 ret = NETSTACK_NETWORK.output((const linkaddr_t *) a);
125 return ret;
126 } else {
127 /* Ok, ignore and drop... */
128 uipbuf_clear();
129 return 0;
130 }
131}
132
133PROCESS(tcpip_process, "TCP/IP stack");
134
135/*---------------------------------------------------------------------------*/
136#if UIP_TCP
137static void
138start_periodic_tcp_timer(void)
139{
140 if(etimer_expired(&periodic)) {
141 etimer_restart(&periodic);
142 }
143}
144#endif /* UIP_TCP */
145/*---------------------------------------------------------------------------*/
146static void
147check_for_tcp_syn(void)
148{
149#if UIP_TCP
150 /* This is a hack that is needed to start the periodic TCP timer if
151 an incoming packet contains a SYN: since uIP does not inform the
152 application if a SYN arrives, we have no other way of starting
153 this timer. This function is called for every incoming IP packet
154 to check for such SYNs. */
155#define TCP_SYN 0x02
156 if(UIP_IP_BUF->proto == UIP_PROTO_TCP &&
157 (UIP_TCP_BUF->flags & TCP_SYN) == TCP_SYN) {
158 start_periodic_tcp_timer();
159 }
160#endif /* UIP_TCP */
161}
162/*---------------------------------------------------------------------------*/
163static void
164packet_input(void)
165{
166 if(uip_len > 0) {
167 LOG_INFO("input: received %u bytes\n", uip_len);
168
169 check_for_tcp_syn();
170
171#if UIP_TAG_TC_WITH_VARIABLE_RETRANSMISSIONS
172 {
173 uint8_t traffic_class = (UIP_IP_BUF->vtc << 4) | (UIP_IP_BUF->tcflow >> 4);
174 if(traffic_class & UIP_TC_MAC_TRANSMISSION_COUNTER_BIT) {
175 uint8_t max_mac_transmissions = traffic_class & UIP_TC_MAC_TRANSMISSION_COUNTER_MASK;
176 uipbuf_set_attr(UIPBUF_ATTR_MAX_MAC_TRANSMISSIONS, max_mac_transmissions);
177 LOG_INFO("Received packet tagged with TC retrans: %d (%x)",
178 max_mac_transmissions, traffic_class);
179 }
180 }
181#endif /* UIP_TAG_TC_WITH_VARIABLE_RETRANSMISSIONS */
182
183 uip_input();
184 if(uip_len > 0) {
186 }
187 }
188}
189/*---------------------------------------------------------------------------*/
190#if UIP_TCP
191#if UIP_ACTIVE_OPEN
192struct uip_conn *
193tcp_connect(const uip_ipaddr_t *ripaddr, uint16_t port, void *appstate)
194{
195 struct uip_conn *c;
196
197 c = uip_connect(ripaddr, port);
198 if(c == NULL) {
199 return NULL;
200 }
201
202 init_appstate(&c->appstate, appstate);
203
205
206 return c;
207}
208#endif /* UIP_ACTIVE_OPEN */
209/*---------------------------------------------------------------------------*/
210void
211tcp_unlisten(uint16_t port)
212{
213 unsigned char i;
214 struct listenport *l;
215
216 l = s.listenports;
217 for(i = 0; i < UIP_LISTENPORTS; ++i) {
218 if(l->port == port &&
219 l->p == PROCESS_CURRENT()) {
220 l->port = 0;
221 uip_unlisten(port);
222 break;
223 }
224 ++l;
225 }
226}
227/*---------------------------------------------------------------------------*/
228void
229tcp_listen(uint16_t port)
230{
231 unsigned char i;
232 struct listenport *l;
233
234 l = s.listenports;
235 for(i = 0; i < UIP_LISTENPORTS; ++i) {
236 if(l->port == 0) {
237 l->port = port;
238 l->p = PROCESS_CURRENT();
239 uip_listen(port);
240 break;
241 }
242 ++l;
243 }
244}
245/*---------------------------------------------------------------------------*/
246void
247tcp_attach(struct uip_conn *conn, void *appstate)
248{
249 init_appstate(&conn->appstate, appstate);
250}
251#endif /* UIP_TCP */
252/*---------------------------------------------------------------------------*/
253#if UIP_UDP
254void
255udp_attach(struct uip_udp_conn *conn, void *appstate)
256{
257 init_appstate(&conn->appstate, appstate);
258}
259/*---------------------------------------------------------------------------*/
260struct uip_udp_conn *
261udp_new(const uip_ipaddr_t *ripaddr, uint16_t port, void *appstate)
262{
263 struct uip_udp_conn *c = uip_udp_new(ripaddr, port);
264
265 if(c == NULL) {
266 return NULL;
267 }
268
269 init_appstate(&c->appstate, appstate);
270
271 return c;
272}
273/*---------------------------------------------------------------------------*/
274struct uip_udp_conn *
275udp_broadcast_new(uint16_t port, void *appstate)
276{
277 uip_ipaddr_t addr;
278 struct uip_udp_conn *conn;
279
281
282 conn = udp_new(&addr, port, appstate);
283 if(conn != NULL) {
284 udp_bind(conn, port);
285 }
286 return conn;
287}
288#endif /* UIP_UDP */
289/*---------------------------------------------------------------------------*/
290#if UIP_CONF_ICMP6
291uint8_t
293 if(uip_icmp6_conns.appstate.p == PROCESS_NONE) {
294 init_appstate(&uip_icmp6_conns.appstate, appstate);
295 return 0;
296 }
297 return 1;
298}
299
300void
301tcpip_icmp6_call(uint8_t type)
302{
303 if(uip_icmp6_conns.appstate.p != PROCESS_NONE) {
304 /* XXX: This is a hack that needs to be updated. Passing a pointer (&type)
305 like this only works with process_post_synch. */
307 }
308 return;
309}
310#endif /* UIP_CONF_ICMP6 */
311/*---------------------------------------------------------------------------*/
312static void
313eventhandler(process_event_t ev, process_data_t data)
314{
315#if UIP_TCP
316 unsigned char i;
317 register struct listenport *l;
318#endif /*UIP_TCP*/
319 struct process *p;
320
321 switch(ev) {
322 case PROCESS_EVENT_EXITED:
323 /* This is the event we get if a process has exited. We go through
324 the TCP/IP tables to see if this process had any open
325 connections or listening TCP ports. If so, we'll close those
326 connections. */
327
328 p = (struct process *)data;
329#if UIP_TCP
330 l = s.listenports;
331 for(i = 0; i < UIP_LISTENPORTS; ++i) {
332 if(l->p == p) {
333 uip_unlisten(l->port);
334 l->port = 0;
335 l->p = PROCESS_NONE;
336 }
337 ++l;
338 }
339
340 {
341 struct uip_conn *cptr;
342
343 for(cptr = &uip_conns[0]; cptr < &uip_conns[UIP_TCP_CONNS]; ++cptr) {
344 if(cptr->appstate.p == p) {
345 cptr->appstate.p = PROCESS_NONE;
346 cptr->tcpstateflags = UIP_CLOSED;
347 }
348 }
349 }
350#endif /* UIP_TCP */
351#if UIP_UDP
352 {
353 struct uip_udp_conn *cptr;
354
355 for(cptr = &uip_udp_conns[0];
356 cptr < &uip_udp_conns[UIP_UDP_CONNS]; ++cptr) {
357 if(cptr->appstate.p == p) {
358 cptr->lport = 0;
359 }
360 }
361 }
362#endif /* UIP_UDP */
363 break;
364
365 case PROCESS_EVENT_TIMER:
366 /* We get this event if one of our timers have expired. */
367 {
368 /* Check the clock so see if we should call the periodic uIP
369 processing. */
370 if(data == &periodic &&
371 etimer_expired(&periodic)) {
372#if UIP_TCP
373 for(i = 0; i < UIP_TCP_CONNS; ++i) {
374 if(uip_conn_active(i)) {
375 /* Only restart the timer if there are active
376 connections. */
377 etimer_restart(&periodic);
378 uip_periodic(i);
380 }
381 }
382#endif /* UIP_TCP */
383 }
384
385#if UIP_CONF_IPV6_REASSEMBLY
386 /*
387 * check the timer for reassembly
388 */
389 if(data == &uip_reass_timer &&
393 }
394#endif /* UIP_CONF_IPV6_REASSEMBLY */
395 /*
396 * check the different timers for neighbor discovery and
397 * stateless autoconfiguration
398 */
399 /*if(data == &uip_ds6_timer_periodic &&
400 etimer_expired(&uip_ds6_timer_periodic)) {
401 uip_ds6_periodic();
402 tcpip_ipv6_output();
403 }*/
404#if !UIP_CONF_ROUTER
405 if(data == &uip_ds6_timer_rs &&
409 }
410#endif /* !UIP_CONF_ROUTER */
411 if(data == &uip_ds6_timer_periodic &&
415 }
416 }
417 break;
418
419#if UIP_TCP
420 case TCP_POLL:
421 if(data != NULL) {
422 uip_poll_conn(data);
424 /* Start the periodic polling, if it isn't already active. */
425 start_periodic_tcp_timer();
426 }
427 break;
428#endif /* UIP_TCP */
429#if UIP_UDP
430 case UDP_POLL:
431 if(data != NULL) {
434 }
435 break;
436#endif /* UIP_UDP */
437
438 case PACKET_INPUT:
439 packet_input();
440 break;
441 };
442}
443/*---------------------------------------------------------------------------*/
444void
446{
447 if(netstack_process_ip_callback(NETSTACK_IP_INPUT, NULL) ==
448 NETSTACK_IP_PROCESS) {
449 process_post_synch(&tcpip_process, PACKET_INPUT, NULL);
450 } /* else - do nothing and drop */
451 uipbuf_clear();
452}
453/*---------------------------------------------------------------------------*/
454static void
455output_fallback(void)
456{
457#ifdef UIP_FALLBACK_INTERFACE
458 uip_last_proto = *((uint8_t *)UIP_IP_BUF + 40);
459 LOG_INFO("fallback: removing ext hdrs & setting proto %d %d\n",
462 /* Inform the other end that the destination is not reachable. If it's
463 * not informed routes might get lost unexpectedly until there's a need
464 * to send a new packet to the peer */
465 if(UIP_FALLBACK_INTERFACE.output() < 0) {
466 LOG_ERR("fallback: output error. Reporting DST UNREACH\n");
468 uip_flags = 0;
470 return;
471 }
472#else
473 LOG_ERR("output: destination off-link and no default route\n");
474#endif /* !UIP_FALLBACK_INTERFACE */
475}
476/*---------------------------------------------------------------------------*/
477static void
478annotate_transmission(const uip_ipaddr_t *nexthop)
479{
480#if TCPIP_CONF_ANNOTATE_TRANSMISSIONS
481 static uint8_t annotate_last;
482 static uint8_t annotate_has_last = 0;
483
484 if(annotate_has_last) {
485 printf("#L %u 0; red\n", annotate_last);
486 }
487 printf("#L %u 1; red\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]);
488 annotate_last = nexthop->u8[sizeof(uip_ipaddr_t) - 1];
489 annotate_has_last = 1;
490#endif /* TCPIP_CONF_ANNOTATE_TRANSMISSIONS */
491}
492/*---------------------------------------------------------------------------*/
493static const uip_ipaddr_t*
494get_nexthop(uip_ipaddr_t *addr)
495{
496 const uip_ipaddr_t *nexthop;
497 uip_ds6_route_t *route;
498
499 LOG_INFO("output: processing %u bytes packet from ", uip_len);
500 LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
501 LOG_INFO_(" to ");
502 LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
503 LOG_INFO_("\n");
504
505 if(NETSTACK_ROUTING.ext_header_srh_get_next_hop(addr)) {
506 LOG_INFO("output: selected next hop from SRH: ");
507 LOG_INFO_6ADDR(addr);
508 LOG_INFO_("\n");
509 return addr;
510 }
511
512 /* We first check if the destination address is on our immediate
513 link. If so, we simply use the destination address as our
514 nexthop address. */
515 if(uip_ds6_is_addr_onlink(&UIP_IP_BUF->destipaddr)) {
516 LOG_INFO("output: destination is on link\n");
517 return &UIP_IP_BUF->destipaddr;
518 }
519
520 /* Check if we have a route to the destination address. */
521 route = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr);
522
523 /* No route was found - we send to the default route instead. */
524 if(route == NULL) {
525 nexthop = uip_ds6_defrt_choose();
526 if(nexthop == NULL) {
527 output_fallback();
528 } else {
529 LOG_INFO("output: no route found, using default route: ");
530 LOG_INFO_6ADDR(nexthop);
531 LOG_INFO_("\n");
532 }
533
534 } else {
535 /* A route was found, so we look up the nexthop neighbor for
536 the route. */
537 nexthop = uip_ds6_route_nexthop(route);
538
539 /* If the nexthop is dead, for example because the neighbor
540 never responded to link-layer acks, we drop its route. */
541 if(nexthop == NULL) {
542 LOG_ERR("output: found dead route\n");
543 /* Notifiy the routing protocol that we are about to remove the route */
544 NETSTACK_ROUTING.drop_route(route);
545 /* Remove the route */
546 uip_ds6_route_rm(route);
547 /* We don't have a nexthop to send the packet to, so we drop it. */
548 } else {
549 LOG_INFO("output: found next hop from routing table: ");
550 LOG_INFO_6ADDR(nexthop);
551 LOG_INFO_("\n");
552 }
553 }
554
555 return nexthop;
556}
557/*---------------------------------------------------------------------------*/
558#if UIP_ND6_SEND_NS
559static int
560queue_packet(uip_ds6_nbr_t *nbr)
561{
562 /* Copy outgoing pkt in the queuing buffer for later transmit. */
563#if UIP_CONF_IPV6_QUEUE_PKT
564 if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) {
565 memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len);
566 uip_packetqueue_set_buflen(&nbr->packethandle, uip_len);
567 return 0;
568 }
569#endif
570
571 return 1;
572}
573#endif
574/*---------------------------------------------------------------------------*/
575static void
576send_queued(uip_ds6_nbr_t *nbr)
577{
578#if UIP_CONF_IPV6_QUEUE_PKT
579 /*
580 * Send the queued packets from here, may not be 100% perfect though.
581 * This happens in a few cases, for example when instead of receiving a
582 * NA after sendiong a NS, you receive a NS with SLLAO: the entry moves
583 * to STALE, and you must both send a NA and the queued packet.
584 */
585 if(uip_packetqueue_buflen(&nbr->packethandle) != 0) {
586 uip_len = uip_packetqueue_buflen(&nbr->packethandle);
587 memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len);
588 uip_packetqueue_free(&nbr->packethandle);
590 }
591#endif /*UIP_CONF_IPV6_QUEUE_PKT*/
592}
593/*---------------------------------------------------------------------------*/
594static int
595send_nd6_ns(const uip_ipaddr_t *nexthop)
596{
597 int err = 1;
598
599#if UIP_ND6_SEND_NS
600 uip_ds6_nbr_t *nbr = NULL;
601 if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE, NBR_TABLE_REASON_IPV6_ND, NULL)) != NULL) {
602 err = 0;
603
604 queue_packet(nbr);
605 /* RFC4861, 7.2.2:
606 * "If the source address of the packet prompting the solicitation is the
607 * same as one of the addresses assigned to the outgoing interface, that
608 * address SHOULD be placed in the IP Source Address of the outgoing
609 * solicitation. Otherwise, any one of the addresses assigned to the
610 * interface should be used."*/
611 if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)){
612 uip_nd6_ns_output(&UIP_IP_BUF->srcipaddr, NULL, &nbr->ipaddr);
613 } else {
614 uip_nd6_ns_output(NULL, NULL, &nbr->ipaddr);
615 }
616
617 stimer_set(&nbr->sendns, uip_ds6_if.retrans_timer / 1000);
618 nbr->nscount = 1;
619 /* Send the first NS try from here (multicast destination IP address). */
620 }
621#else
622 LOG_ERR("output: neighbor not in cache: ");
623 LOG_ERR_6ADDR(nexthop);
624 LOG_ERR_("\n");
625#endif
626
627 return err;
628}
629/*---------------------------------------------------------------------------*/
630void
632{
633 uip_ipaddr_t ipaddr;
634 uip_ds6_nbr_t *nbr = NULL;
635 const uip_lladdr_t *linkaddr;
636 const uip_ipaddr_t *nexthop;
637
638 if(uip_len == 0) {
639 return;
640 }
641
642 if(uip_len > UIP_LINK_MTU) {
643 LOG_ERR("output: Packet too big");
644 goto exit;
645 }
646
647 if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)){
648 LOG_ERR("output: Destination address unspecified");
649 goto exit;
650 }
651
652
653 if(!NETSTACK_ROUTING.ext_header_update()) {
654 /* Packet can not be forwarded */
655 LOG_ERR("output: routing protocol extension header update error\n");
656 uipbuf_clear();
657 return;
658 }
659
660 if(uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) {
661 linkaddr = NULL;
662 goto send_packet;
663 }
664
665 /* We first check if the destination address is one of ours. There is no
666 * loopback interface -- instead, process this directly as incoming. */
667 if(uip_ds6_is_my_addr(&UIP_IP_BUF->destipaddr)) {
668 LOG_INFO("output: sending to ourself\n");
669 packet_input();
670 return;
671 }
672
673 /* Look for a next hop */
674 if((nexthop = get_nexthop(&ipaddr)) == NULL) {
675 LOG_WARN("output: No next-hop found, dropping packet\n");
676 goto exit;
677 }
678 annotate_transmission(nexthop);
679
680 nbr = uip_ds6_nbr_lookup(nexthop);
681
682#if UIP_ND6_AUTOFILL_NBR_CACHE
683 if(nbr == NULL) {
684 /* Neighbor not found in cache? Derive its link-layer address from it's
685 link-local IPv6, assuming it used autoconfiguration. This is not
686 standard-compliant but this is a convenient way to keep the
687 neighbor cache out of the way in cases ND is not used */
688 uip_lladdr_t lladdr;
689 uip_ds6_set_lladdr_from_iid(&lladdr, nexthop);
690 if((nbr = uip_ds6_nbr_add(nexthop, &lladdr,
691 0, NBR_REACHABLE, NBR_TABLE_REASON_IPV6_ND_AUTOFILL, NULL)) == NULL) {
692 LOG_ERR("output: failed to autofill neighbor cache for host ");
693 LOG_ERR_6ADDR(nexthop);
694 LOG_ERR_(", link-layer addr ");
695 LOG_ERR_LLADDR((linkaddr_t*)&lladdr);
696 LOG_ERR_("\n");
697 goto exit;
698 }
699 }
700#endif /* UIP_ND6_AUTOFILL_NBR_CACHE */
701
702 if(nbr == NULL) {
703 if(send_nd6_ns(nexthop)) {
704 LOG_ERR("output: failed to add neighbor to cache\n");
705 goto exit;
706 } else {
707 /* We're sending NS here instead of original packet */
708 goto send_packet;
709 }
710 }
711
712#if UIP_ND6_SEND_NS
713 if(nbr->state == NBR_INCOMPLETE) {
714 LOG_ERR("output: nbr cache entry incomplete\n");
715 queue_packet(nbr);
716 goto exit;
717 }
718 /* Send in parallel if we are running NUD (nbc state is either STALE,
719 DELAY, or PROBE). See RFC 4861, section 7.3.3 on node behavior. */
720 if(nbr->state == NBR_STALE) {
721 nbr->state = NBR_DELAY;
722 stimer_set(&nbr->reachable, UIP_ND6_DELAY_FIRST_PROBE_TIME);
723 nbr->nscount = 0;
724 LOG_INFO("output: nbr cache entry stale moving to delay\n");
725 }
726#endif /* UIP_ND6_SEND_NS */
727
729 if(nbr) {
730 linkaddr = uip_ds6_nbr_get_ll(nbr);
731 } else {
732 linkaddr = NULL;
733 }
734
735 LOG_INFO("output: sending to ");
736 LOG_INFO_LLADDR((linkaddr_t *)linkaddr);
737 LOG_INFO_("\n");
738 tcpip_output(linkaddr);
739
740 if(nbr) {
741 send_queued(nbr);
742 }
743
744exit:
745 uipbuf_clear();
746 return;
747}
748/*---------------------------------------------------------------------------*/
749#if UIP_UDP
750void
752{
753 process_post(&tcpip_process, UDP_POLL, conn);
754}
755#endif /* UIP_UDP */
756/*---------------------------------------------------------------------------*/
757#if UIP_TCP
758void
760{
761 process_post(&tcpip_process, TCP_POLL, conn);
762}
763#endif /* UIP_TCP */
764/*---------------------------------------------------------------------------*/
765void
766tcpip_uipcall(void)
767{
769
770#if UIP_UDP
771 if(uip_conn != NULL) {
772 ts = &uip_conn->appstate;
773 } else {
774 ts = &uip_udp_conn->appstate;
775 }
776#else /* UIP_UDP */
777 ts = &uip_conn->appstate;
778#endif /* UIP_UDP */
779
780#if UIP_TCP
781 {
782 unsigned char i;
783 struct listenport *l;
784
785 /* If this is a connection request for a listening port, we must
786 mark the connection with the right process ID. */
787 if(uip_connected()) {
788 l = &s.listenports[0];
789 for(i = 0; i < UIP_LISTENPORTS; ++i) {
790 if(l->port == uip_conn->lport &&
791 l->p != PROCESS_NONE) {
792 ts->p = l->p;
793 ts->state = NULL;
794 break;
795 }
796 ++l;
797 }
798
799 /* Start the periodic polling, if it isn't already active. */
800 start_periodic_tcp_timer();
801 }
802 }
803#endif /* UIP_TCP */
804
805 if(ts->p != NULL) {
806 process_post_synch(ts->p, tcpip_event, ts->state);
807 }
808}
809/*---------------------------------------------------------------------------*/
810PROCESS_THREAD(tcpip_process, ev, data)
811{
813
814#if UIP_TCP
815 memset(s.listenports, 0, UIP_LISTENPORTS*sizeof(*(s.listenports)));
816 s.p = PROCESS_CURRENT();
817#endif
818
820#if UIP_CONF_ICMP6
822#endif /* UIP_CONF_ICMP6 */
823 etimer_set(&periodic, CLOCK_SECOND / 2);
824
825 uip_init();
826#ifdef UIP_FALLBACK_INTERFACE
827 UIP_FALLBACK_INTERFACE.init();
828#endif
829 /* Initialize routing protocol */
830 NETSTACK_ROUTING.init();
831
832 while(1) {
834 eventhandler(ev, data);
835 }
836
837 PROCESS_END();
838}
839/*---------------------------------------------------------------------------*/
PROCESS_THREAD(cc2538_rf_process, ev, data)
Implementation of the cc2538 RF driver process.
Definition: cc2538-rf.c:1154
#define CLOCK_SECOND
A second, measured in system clock time.
Definition: clock.h:82
void etimer_restart(struct etimer *et)
Restart an event timer from the current point in time.
Definition: etimer.c:199
int etimer_expired(struct etimer *et)
Check if an event timer has expired.
Definition: etimer.c:213
void etimer_set(struct etimer *et, clock_time_t interval)
Set an event timer.
Definition: etimer.c:177
#define PROCESS(name, strname)
Declare a process.
Definition: process.h:307
int process_post(struct process *p, process_event_t ev, process_data_t data)
Post an asynchronous event.
Definition: process.c:322
void process_post_synch(struct process *p, process_event_t ev, process_data_t data)
Post a synchronous event to a process.
Definition: process.c:362
#define PROCESS_CURRENT()
Get a pointer to the currently running process.
Definition: process.h:402
process_event_t process_alloc_event(void)
Allocate a global event number.
Definition: process.c:93
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition: process.h:120
#define PROCESS_END()
Define the end of a process.
Definition: process.h:131
#define PROCESS_YIELD()
Yield the currently running process.
Definition: process.h:164
static void send_packet(void)
This function is called by the 6lowpan code to send out a packet.
Definition: sicslowpan.c:1543
void stimer_set(struct stimer *t, unsigned long interval)
Set a timer.
Definition: stimer.c:67
void tcp_unlisten(uint16_t port)
Close a listening TCP port.
Definition: tcpip.c:211
void udp_attach(struct uip_udp_conn *conn, void *appstate)
Attach the current process to a UDP connection.
Definition: tcpip.c:255
process_event_t tcpip_event
The uIP event.
Definition: tcpip.c:62
struct uip_conn * tcp_connect(const uip_ipaddr_t *ripaddr, uint16_t port, void *appstate)
Open a TCP connection to the specified IP address and port.
struct uip_udp_conn * udp_new(const uip_ipaddr_t *ripaddr, uint16_t port, void *appstate)
Create a new UDP connection.
Definition: tcpip.c:261
void tcp_attach(struct uip_conn *conn, void *appstate)
Attach a TCP connection to the current process.
Definition: tcpip.c:247
uint8_t tcpip_output(const uip_lladdr_t *a)
Output packet to layer 2 The eventual parameter is the MAC address of the destination.
Definition: tcpip.c:106
#define udp_bind(conn, port)
Bind a UDP connection to a local port.
Definition: tcpip.h:261
void tcpip_icmp6_call(uint8_t type)
This function is called at reception of an ICMPv6 packet If an application registered as an ICMPv6 li...
Definition: tcpip.c:301
void tcpip_poll_tcp(struct uip_conn *conn)
Cause a specified TCP connection to be polled.
Definition: tcpip.c:759
struct uip_udp_conn * udp_broadcast_new(uint16_t port, void *appstate)
Create a new UDP broadcast connection.
Definition: tcpip.c:275
uint8_t icmp6_new(void *appstate)
register an ICMPv6 callback
Definition: tcpip.c:292
void tcpip_poll_udp(struct uip_udp_conn *conn)
Cause a specified UDP connection to be polled.
Definition: tcpip.c:751
void tcpip_ipv6_output(void)
This function does address resolution and then calls tcpip_output.
Definition: tcpip.c:631
process_event_t tcpip_icmp6_event
The ICMP6 event.
Definition: tcpip.c:64
void tcpip_input(void)
Deliver an incoming packet to the TCP/IP stack.
Definition: tcpip.c:445
void tcp_listen(uint16_t port)
Open a TCP port.
Definition: tcpip.c:229
void uip_nd6_ns_output(const uip_ipaddr_t *src, const uip_ipaddr_t *dest, uip_ipaddr_t *tgt)
Send a neighbor solicitation, send a Neighbor Advertisement.
const uip_lladdr_t * uip_ds6_nbr_get_ll(const uip_ds6_nbr_t *nbr)
Get the link-layer address associated with a specified nbr cache.
Definition: uip-ds6-nbr.c:422
void uip_icmp6_error_output(uint8_t type, uint8_t code, uint32_t param)
Send an icmpv6 error message.
Definition: uip-icmp6.c:155
uip_ds6_nbr_t * uip_ds6_nbr_add(const uip_ipaddr_t *ipaddr, const uip_lladdr_t *lladdr, uint8_t isrouter, uint8_t state, nbr_table_reason_t reason, void *data)
Add a neighbor cache for a specified IPv6 address, which is associated with a specified link-layer ad...
Definition: uip-ds6-nbr.c:132
#define ICMP6_DST_UNREACH
dest unreachable
Definition: uip-icmp6.h:53
void uip_ds6_periodic(void)
Periodic processing of data structures.
Definition: uip-ds6.c:177
#define uip_is_addr_unspecified(a)
Is IPv6 address a the unspecified address a is of type uip_ipaddr_t.
Definition: uip.h:1734
void uip_ds6_send_rs(void)
Send periodic RS to find router.
Definition: uip-ds6.c:733
struct etimer uip_reass_timer
Timer for reassembly.
Definition: uip6.c:621
#define NBR_INCOMPLETE
Possible states for the nbr cache entries.
Definition: uip-ds6-nbr.h:64
struct uip_icmp6_conn uip_icmp6_conns
single possible icmpv6 "connection"
Definition: uip6.c:243
#define ICMP6_DST_UNREACH_ADDR
address unreachable
Definition: uip-icmp6.h:83
struct etimer uip_ds6_timer_periodic
Timer for maintenance of data structures.
Definition: uip-ds6.c:60
uip_ds6_nbr_t * uip_ds6_nbr_lookup(const uip_ipaddr_t *ipaddr)
Get the neighbor cache associated with a specified IPv6 address.
Definition: uip-ds6-nbr.c:497
#define uip_is_addr_mcast(a)
is address a multicast address, see RFC 4291 a is of type uip_ipaddr_t*
Definition: uip.h:1869
bool uip_remove_ext_hdr(void)
Removes all IPv6 extension headers from uip_buf, updates length fields (uip_len and uip_ext_len)
Definition: uip6.c:493
struct etimer uip_ds6_timer_rs
RS timer, to schedule RS sending.
Definition: uip-ds6.c:69
void uip_ds6_set_lladdr_from_iid(uip_lladdr_t *lladdr, const uip_ipaddr_t *ipaddr)
Build a link-layer address from an IPv6 address based on its UUID64.
Definition: uip-ds6.c:597
uip_ds6_netif_t uip_ds6_if
The single interface.
Definition: uip-ds6.c:75
#define uip_create_linklocal_allnodes_mcast(a)
set IP address a to the link local all-nodes multicast address
Definition: uip.h:1783
#define UIP_IP_BUF
Direct access to IPv6 header.
Definition: uip.h:71
struct uip_conn * uip_connect(const uip_ipaddr_t *ripaddr, uint16_t port)
Connect to a remote host using TCP.
void uip_listen(uint16_t port)
Start listening to the specified port.
Definition: uip6.c:580
struct uip_udp_conn * uip_udp_new(const uip_ipaddr_t *ripaddr, uint16_t rport)
Set up a new UDP connection.
Definition: uip6.c:522
void uip_unlisten(uint16_t port)
Stop listening to the specified port.
Definition: uip6.c:568
#define uip_connected()
Has the connection just been connected?
Definition: uip.h:703
#define uip_periodic(conn)
Periodic processing for a connection identified by its number.
Definition: uip.h:349
#define uip_input()
Process an incoming packet.
Definition: uip.h:303
#define uip_poll_conn(conn)
Request that a particular connection should be polled.
Definition: uip.h:387
#define uip_udp_periodic_conn(conn)
Periodic processing for a UDP connection identified by a pointer to its structure.
Definition: uip.h:441
void uip_reass_over(void)
Abandon the reassembly of the current packet.
Definition: uip6.c:775
#define uip_conn_active(conn)
Macro to determine whether a specific uIP connection is active.
Definition: uip.h:358
uint16_t uip_ext_len
The length of the extension headers.
Definition: uip6.c:122
uint16_t uip_len
The length of the packet in the uip_buf buffer.
Definition: uip6.c:159
uint8_t uip_last_proto
The final protocol after IPv6 extension headers: UIP_PROTO_TCP, UIP_PROTO_UDP or UIP_PROTO_ICMP6.
Definition: uip6.c:125
void uip_init(void)
uIP initialization function.
Definition: uip6.c:387
struct tcpip_uipstate uip_tcp_appstate_t
The type of the application state that is to be stored in the uip_conn structure.
Definition: tcpip.h:86
struct tcpip_uipstate uip_udp_appstate_t
The type of the application state that is to be stored in the uip_conn structure.
Definition: tcpip.h:85
#define UIP_LINK_MTU
The maximum transmission unit at the IP Layer.
Definition: uipopt.h:154
#define UIP_TC_MAC_TRANSMISSION_COUNTER_BIT
The MAC-layer transmissons limit is encapslated in "Traffic Class" field.
Definition: uipopt.h:427
#define UIP_MAX_MAC_TRANSMISSIONS_UNDEFINED
This is the default value of MAC-layer transmissons for uIPv6.
Definition: uipopt.h:445
#define UIP_TC_MAC_TRANSMISSION_COUNTER_MASK
The bits in the "Traffic Class" field that describe the MAC transmission limit.
Definition: uipopt.h:432
#define UIP_LISTENPORTS
The maximum number of simultaneously listening TCP ports.
Definition: uipopt.h:299
#define UIP_TCP_CONNS
The maximum number of simultaneously open TCP connections.
Definition: uipopt.h:285
#define UIP_UDP_CONNS
The maximum amount of concurrent UDP connections.
Definition: uipopt.h:231
Header file for the link-layer address representation.
Header file for the logging system.
Routing driver header file.
A timer.
Definition: etimer.h:76
int(* ext_header_srh_get_next_hop)(uip_ipaddr_t *ipaddr)
Look for next hop from SRH of current uIP packet.
Definition: routing.h:162
void(* init)(void)
Initialize the routing protocol.
Definition: routing.h:63
int(* ext_header_update)(void)
Adds/updates routing protocol extension headers to current uIP packet.
Definition: routing.h:138
void(* drop_route)(uip_ds6_route_t *route)
Called by uIP if it has decided to drop a route because.
Definition: routing.h:182
Representation of a uIP TCP connection.
Definition: uip.h:1258
uint16_t lport
The local TCP port, in network byte order.
Definition: uip.h:1261
uip_ipaddr_t ripaddr
The IP address of the remote host.
Definition: uip.h:1259
uint8_t tcpstateflags
TCP state and flags.
Definition: uip.h:1274
The default nbr_table entry (when UIP_DS6_NBR_MULTI_IPV6_ADDRS is disabled), that implements nbr cach...
Definition: uip-ds6-nbr.h:105
An entry in the routing table.
Representation of a uIP UDP connection.
Definition: uip.h:1309
uip_ipaddr_t ripaddr
The IP address of the remote peer.
Definition: uip.h:1310
uip_udp_appstate_t appstate
The application state.
Definition: uip.h:1315
uint16_t lport
The local port number in network byte order.
Definition: uip.h:1311
IPv6 Neighbor cache (link-layer/IPv6 address mapping)
Header file for IPv6-related data structures.
static uip_ds6_nbr_t * nbr
Pointer to llao option in uip_buf.
Definition: uip-nd6.c:106
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
Definition: uip-nd6.c:116
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Definition: uip-nd6.c:107
Header file for IPv6 Neighbor discovery (RFC 4861)