Contiki-NG
Loading...
Searching...
No Matches
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/*---------------------------------------------------------------------------*/
97#if UIP_TCP || UIP_UDP
98static void
99init_appstate(uip_tcp_appstate_t *as, void *state)
100{
101 as->p = PROCESS_CURRENT();
102 as->state = state;
103}
104#endif /* UIP_TCP || UIP_UDP */
105/*---------------------------------------------------------------------------*/
106
107uint8_t
108tcpip_output(const uip_lladdr_t *a)
109{
110 int ret;
111
112 /* Tag Traffic Class if we are using TC for variable retrans */
113#if UIP_TAG_TC_WITH_VARIABLE_RETRANSMISSIONS
114 if(uipbuf_get_attr(UIPBUF_ATTR_MAX_MAC_TRANSMISSIONS) !=
116 LOG_INFO("Tagging TC with retrans: %d\n", uipbuf_get_attr(UIPBUF_ATTR_MAX_MAC_TRANSMISSIONS));
117 /* Encapsulate the MAC transmission limit in the Traffic Class field */
119 UIP_IP_BUF->tcflow =
120 uipbuf_get_attr(UIPBUF_ATTR_MAX_MAC_TRANSMISSIONS) << 4;
121 }
122#endif
123
124 if(netstack_process_ip_callback(NETSTACK_IP_OUTPUT, (const linkaddr_t *)a) ==
125 NETSTACK_IP_PROCESS) {
126 ret = NETSTACK_NETWORK.output((const linkaddr_t *) a);
127 return ret;
128 } else {
129 /* Ok, ignore and drop... */
130 uipbuf_clear();
131 return 0;
132 }
133}
134
135PROCESS(tcpip_process, "TCP/IP stack");
136
137/*---------------------------------------------------------------------------*/
138#if UIP_TCP
139static void
140start_periodic_tcp_timer(void)
141{
142 if(etimer_expired(&periodic)) {
143 etimer_restart(&periodic);
144 }
145}
146#endif /* UIP_TCP */
147/*---------------------------------------------------------------------------*/
148static void
149check_for_tcp_syn(void)
150{
151#if UIP_TCP
152 /* This is a hack that is needed to start the periodic TCP timer if
153 an incoming packet contains a SYN: since uIP does not inform the
154 application if a SYN arrives, we have no other way of starting
155 this timer. This function is called for every incoming IP packet
156 to check for such SYNs. */
157#define TCP_SYN 0x02
158 if(uip_len >= UIP_IPTCPH_LEN + uip_ext_len &&
159 UIP_IP_BUF->proto == UIP_PROTO_TCP &&
160 (UIP_TCP_BUF->flags & TCP_SYN) == TCP_SYN) {
161 start_periodic_tcp_timer();
162 }
163#endif /* UIP_TCP */
164}
165/*---------------------------------------------------------------------------*/
166static void
167packet_input(void)
168{
169 if(uip_len > 0) {
170 LOG_INFO("input: received %u bytes\n", uip_len);
171
172 check_for_tcp_syn();
173
174#if UIP_TAG_TC_WITH_VARIABLE_RETRANSMISSIONS
175 if(uip_len >= UIP_IPH_LEN) {
176 uint8_t traffic_class = (UIP_IP_BUF->vtc << 4) | (UIP_IP_BUF->tcflow >> 4);
177 if(traffic_class & UIP_TC_MAC_TRANSMISSION_COUNTER_BIT) {
178 uint8_t max_mac_transmissions = traffic_class & UIP_TC_MAC_TRANSMISSION_COUNTER_MASK;
179 uipbuf_set_attr(UIPBUF_ATTR_MAX_MAC_TRANSMISSIONS, max_mac_transmissions);
180 LOG_INFO("Received packet tagged with TC retrans: %d (%x)",
181 max_mac_transmissions, traffic_class);
182 }
183 }
184#endif /* UIP_TAG_TC_WITH_VARIABLE_RETRANSMISSIONS */
185
186 uip_input();
187 if(uip_len > 0) {
189 }
190 }
191}
192/*---------------------------------------------------------------------------*/
193#if UIP_TCP
194#if UIP_ACTIVE_OPEN
195struct uip_conn *
196tcp_connect(const uip_ipaddr_t *ripaddr, uint16_t port, void *appstate)
197{
198 struct uip_conn *c;
199
200 c = uip_connect(ripaddr, port);
201 if(c == NULL) {
202 return NULL;
203 }
204
205 init_appstate(&c->appstate, appstate);
206
208
209 return c;
210}
211#endif /* UIP_ACTIVE_OPEN */
212/*---------------------------------------------------------------------------*/
213void
214tcp_unlisten(uint16_t port)
215{
216 unsigned char i;
217 struct listenport *l;
218
219 l = s.listenports;
220 for(i = 0; i < UIP_LISTENPORTS; ++i) {
221 if(l->port == port &&
222 l->p == PROCESS_CURRENT()) {
223 l->port = 0;
224 uip_unlisten(port);
225 break;
226 }
227 ++l;
228 }
229}
230/*---------------------------------------------------------------------------*/
231void
232tcp_listen(uint16_t port)
233{
234 unsigned char i;
235 struct listenport *l;
236
237 l = s.listenports;
238 for(i = 0; i < UIP_LISTENPORTS; ++i) {
239 if(l->port == 0) {
240 l->port = port;
241 l->p = PROCESS_CURRENT();
242 uip_listen(port);
243 break;
244 }
245 ++l;
246 }
247}
248/*---------------------------------------------------------------------------*/
249void
250tcp_attach(struct uip_conn *conn, void *appstate)
251{
252 init_appstate(&conn->appstate, appstate);
253}
254#endif /* UIP_TCP */
255/*---------------------------------------------------------------------------*/
256#if UIP_UDP
257void
258udp_attach(struct uip_udp_conn *conn, void *appstate)
259{
260 init_appstate(&conn->appstate, appstate);
261}
262/*---------------------------------------------------------------------------*/
263struct uip_udp_conn *
264udp_new(const uip_ipaddr_t *ripaddr, uint16_t port, void *appstate)
265{
266 struct uip_udp_conn *c = uip_udp_new(ripaddr, port);
267
268 if(c == NULL) {
269 return NULL;
270 }
271
272 init_appstate(&c->appstate, appstate);
273
274 return c;
275}
276/*---------------------------------------------------------------------------*/
277struct uip_udp_conn *
278udp_broadcast_new(uint16_t port, void *appstate)
279{
280 uip_ipaddr_t addr;
281 struct uip_udp_conn *conn;
282
284
285 conn = udp_new(&addr, port, appstate);
286 if(conn != NULL) {
287 udp_bind(conn, port);
288 }
289 return conn;
290}
291#endif /* UIP_UDP */
292/*---------------------------------------------------------------------------*/
293#if UIP_CONF_ICMP6
294uint8_t
296 if(uip_icmp6_conns.appstate.p == PROCESS_NONE) {
297 init_appstate(&uip_icmp6_conns.appstate, appstate);
298 return 0;
299 }
300 return 1;
301}
302
303void
304tcpip_icmp6_call(uint8_t type)
305{
306 if(uip_icmp6_conns.appstate.p != PROCESS_NONE) {
307 /* XXX: This is a hack that needs to be updated. Passing a pointer (&type)
308 like this only works with process_post_synch. */
310 }
311 return;
312}
313#endif /* UIP_CONF_ICMP6 */
314/*---------------------------------------------------------------------------*/
315static void
316eventhandler(process_event_t ev, process_data_t data)
317{
318 switch(ev) {
319#if UIP_TCP || UIP_UDP
320 case PROCESS_EVENT_EXITED:
321 /* This is the event we get if a process has exited. We go through
322 the TCP/IP tables to see if this process had any open
323 connections or listening TCP ports. If so, we'll close those
324 connections. */
325 {
326 struct process *p = (struct process *)data;
327#if UIP_TCP
328 struct listenport *l = s.listenports;
329 for(uint8_t i = 0; i < UIP_LISTENPORTS; ++i) {
330 if(l->p == p) {
331 uip_unlisten(l->port);
332 l->port = 0;
333 l->p = PROCESS_NONE;
334 }
335 ++l;
336 }
337
338 for(struct uip_conn *cptr = &uip_conns[0];
339 cptr < &uip_conns[UIP_TCP_CONNS]; ++cptr) {
340 if(cptr->appstate.p == p) {
341 cptr->appstate.p = PROCESS_NONE;
342 cptr->tcpstateflags = UIP_CLOSED;
343 }
344 }
345#endif /* UIP_TCP */
346#if UIP_UDP
347 for(struct uip_udp_conn *cptr = &uip_udp_conns[0];
348 cptr < &uip_udp_conns[UIP_UDP_CONNS]; ++cptr) {
349 if(cptr->appstate.p == p) {
350 cptr->lport = 0;
351 }
352 }
353#endif /* UIP_UDP */
354 }
355 break;
356#endif /* UIP_TCP || UIP_UDP */
357
358 case PROCESS_EVENT_TIMER:
359 /* We get this event if one of our timers have expired. */
360 {
361 /* Check the clock so see if we should call the periodic uIP
362 processing. */
363 if(data == &periodic &&
364 etimer_expired(&periodic)) {
365#if UIP_TCP
366 for(uint8_t i = 0; i < UIP_TCP_CONNS; ++i) {
367 if(uip_conn_active(i)) {
368 /* Only restart the timer if there are active
369 connections. */
370 etimer_restart(&periodic);
371 uip_periodic(i);
373 }
374 }
375#endif /* UIP_TCP */
376 }
377
378#if UIP_CONF_IPV6_REASSEMBLY
379 /*
380 * check the timer for reassembly
381 */
382 if(data == &uip_reass_timer &&
386 }
387#endif /* UIP_CONF_IPV6_REASSEMBLY */
388 /*
389 * check the different timers for neighbor discovery and
390 * stateless autoconfiguration
391 */
392#if !UIP_CONF_ROUTER
393 if(data == &uip_ds6_timer_rs &&
397 }
398#endif /* !UIP_CONF_ROUTER */
399 if(data == &uip_ds6_timer_periodic &&
403 }
404 }
405 break;
406
407#if UIP_TCP
408 case TCP_POLL:
409 if(data != NULL) {
410 uip_poll_conn(data);
412 /* Start the periodic polling, if it isn't already active. */
413 start_periodic_tcp_timer();
414 }
415 break;
416#endif /* UIP_TCP */
417#if UIP_UDP
418 case UDP_POLL:
419 if(data != NULL) {
422 }
423 break;
424#endif /* UIP_UDP */
425
426 case PACKET_INPUT:
427 packet_input();
428 break;
429 };
430}
431/*---------------------------------------------------------------------------*/
432void
434{
435 if(netstack_process_ip_callback(NETSTACK_IP_INPUT, NULL) ==
436 NETSTACK_IP_PROCESS) {
437 process_post_synch(&tcpip_process, PACKET_INPUT, NULL);
438 } /* else - do nothing and drop */
439 uipbuf_clear();
440}
441/*---------------------------------------------------------------------------*/
442static void
443output_fallback(void)
444{
445#ifdef UIP_FALLBACK_INTERFACE
446 uip_last_proto = *((uint8_t *)UIP_IP_BUF + 40);
447 LOG_INFO("fallback: removing ext hdrs & setting proto %d %d\n",
450 /* Inform the other end that the destination is not reachable. If it's
451 * not informed routes might get lost unexpectedly until there's a need
452 * to send a new packet to the peer */
453 if(UIP_FALLBACK_INTERFACE.output() < 0) {
454 LOG_ERR("fallback: output error. Reporting DST UNREACH\n");
456 uip_flags = 0;
458 return;
459 }
460#else
461 LOG_ERR("output: destination off-link and no default route\n");
462#endif /* !UIP_FALLBACK_INTERFACE */
463}
464/*---------------------------------------------------------------------------*/
465static void
466annotate_transmission(const uip_ipaddr_t *nexthop)
467{
468#if TCPIP_CONF_ANNOTATE_TRANSMISSIONS
469 static uint8_t annotate_last;
470 static uint8_t annotate_has_last = 0;
471
472 if(annotate_has_last) {
473 printf("#L %u 0; red\n", annotate_last);
474 }
475 printf("#L %u 1; red\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]);
476 annotate_last = nexthop->u8[sizeof(uip_ipaddr_t) - 1];
477 annotate_has_last = 1;
478#endif /* TCPIP_CONF_ANNOTATE_TRANSMISSIONS */
479}
480/*---------------------------------------------------------------------------*/
481static const uip_ipaddr_t*
482get_nexthop(uip_ipaddr_t *addr)
483{
484 const uip_ipaddr_t *nexthop;
485 uip_ds6_route_t *route;
486
487 LOG_INFO("output: processing %u bytes packet from ", uip_len);
488 LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
489 LOG_INFO_(" to ");
490 LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
491 LOG_INFO_("\n");
492
493 if(NETSTACK_ROUTING.ext_header_srh_get_next_hop(addr)) {
494 LOG_INFO("output: selected next hop from SRH: ");
495 LOG_INFO_6ADDR(addr);
496 LOG_INFO_("\n");
497 return addr;
498 }
499
500 /* We first check if the destination address is on our immediate
501 link. If so, we simply use the destination address as our
502 nexthop address. */
503 if(uip_ds6_is_addr_onlink(&UIP_IP_BUF->destipaddr)) {
504 LOG_INFO("output: destination is on link\n");
505 return &UIP_IP_BUF->destipaddr;
506 }
507
508 /* Check if we have a route to the destination address. */
509 route = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr);
510
511 /* No route was found - we send to the default route instead. */
512 if(route == NULL) {
513 nexthop = uip_ds6_defrt_choose();
514 if(nexthop == NULL) {
515 output_fallback();
516 } else {
517 LOG_INFO("output: no route found, using default route: ");
518 LOG_INFO_6ADDR(nexthop);
519 LOG_INFO_("\n");
520 }
521
522 } else {
523 /* A route was found, so we look up the nexthop neighbor for
524 the route. */
525 nexthop = uip_ds6_route_nexthop(route);
526
527 /* If the nexthop is dead, for example because the neighbor
528 never responded to link-layer acks, we drop its route. */
529 if(nexthop == NULL) {
530 LOG_ERR("output: found dead route\n");
531 /* Notifiy the routing protocol that we are about to remove the route */
532 NETSTACK_ROUTING.drop_route(route);
533 /* Remove the route */
534 uip_ds6_route_rm(route);
535 /* We don't have a nexthop to send the packet to, so we drop it. */
536 } else {
537 LOG_INFO("output: found next hop from routing table: ");
538 LOG_INFO_6ADDR(nexthop);
539 LOG_INFO_("\n");
540 }
541 }
542
543 return nexthop;
544}
545/*---------------------------------------------------------------------------*/
546#if UIP_ND6_SEND_NS
547static int
548queue_packet(uip_ds6_nbr_t *nbr)
549{
550 /* Copy outgoing pkt in the queuing buffer for later transmit. */
551#if UIP_CONF_IPV6_QUEUE_PKT
552 if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) {
553 memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len);
554 uip_packetqueue_set_buflen(&nbr->packethandle, uip_len);
555 return 0;
556 }
557#endif
558
559 return 1;
560}
561#endif
562/*---------------------------------------------------------------------------*/
563static void
564send_queued(uip_ds6_nbr_t *nbr)
565{
566#if UIP_CONF_IPV6_QUEUE_PKT
567 /*
568 * Send the queued packets from here, may not be 100% perfect though.
569 * This happens in a few cases, for example when instead of receiving a
570 * NA after sendiong a NS, you receive a NS with SLLAO: the entry moves
571 * to STALE, and you must both send a NA and the queued packet.
572 */
573 if(uip_packetqueue_buflen(&nbr->packethandle) != 0) {
574 uip_len = uip_packetqueue_buflen(&nbr->packethandle);
575 memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len);
576 uip_packetqueue_free(&nbr->packethandle);
578 }
579#endif /*UIP_CONF_IPV6_QUEUE_PKT*/
580}
581/*---------------------------------------------------------------------------*/
582static int
583send_nd6_ns(const uip_ipaddr_t *nexthop)
584{
585 int err = 1;
586
587#if UIP_ND6_SEND_NS
588 uip_ds6_nbr_t *nbr = NULL;
589 if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE, NBR_TABLE_REASON_IPV6_ND, NULL)) != NULL) {
590 err = 0;
591
592 queue_packet(nbr);
593 /* RFC4861, 7.2.2:
594 * "If the source address of the packet prompting the solicitation is the
595 * same as one of the addresses assigned to the outgoing interface, that
596 * address SHOULD be placed in the IP Source Address of the outgoing
597 * solicitation. Otherwise, any one of the addresses assigned to the
598 * interface should be used."*/
599 if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)){
600 uip_nd6_ns_output(&UIP_IP_BUF->srcipaddr, NULL, &nbr->ipaddr);
601 } else {
602 uip_nd6_ns_output(NULL, NULL, &nbr->ipaddr);
603 }
604
605 stimer_set(&nbr->sendns, uip_ds6_if.retrans_timer / 1000);
606 nbr->nscount = 1;
607 /* Send the first NS try from here (multicast destination IP address). */
608 }
609#else
610 LOG_ERR("output: neighbor not in cache: ");
611 LOG_ERR_6ADDR(nexthop);
612 LOG_ERR_("\n");
613#endif
614
615 return err;
616}
617/*---------------------------------------------------------------------------*/
618void
620{
621 uip_ipaddr_t ipaddr;
622 uip_ds6_nbr_t *nbr = NULL;
623 const uip_lladdr_t *linkaddr;
624 const uip_ipaddr_t *nexthop;
625
626 if(uip_len == 0) {
627 return;
628 }
629
630 if(uip_len > UIP_LINK_MTU) {
631 LOG_ERR("output: Packet too big");
632 goto exit;
633 }
634
635 if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)){
636 LOG_ERR("output: Destination address unspecified");
637 goto exit;
638 }
639
640
641 if(!NETSTACK_ROUTING.ext_header_update()) {
642 /* Packet can not be forwarded */
643 LOG_ERR("output: routing protocol extension header update error\n");
644 uipbuf_clear();
645 return;
646 }
647
648 if(uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) {
649 linkaddr = NULL;
650 goto send_packet;
651 }
652
653 /* We first check if the destination address is one of ours. There is no
654 * loopback interface -- instead, process this directly as incoming. */
655 if(uip_ds6_is_my_addr(&UIP_IP_BUF->destipaddr)) {
656 LOG_INFO("output: sending to ourself\n");
657 packet_input();
658 return;
659 }
660
661 /* Look for a next hop */
662 if((nexthop = get_nexthop(&ipaddr)) == NULL) {
663 LOG_WARN("output: No next-hop found, dropping packet\n");
664 goto exit;
665 }
666 annotate_transmission(nexthop);
667
668 nbr = uip_ds6_nbr_lookup(nexthop);
669
670#if UIP_ND6_AUTOFILL_NBR_CACHE
671 if(nbr == NULL) {
672 /* Neighbor not found in cache? Derive its link-layer address from it's
673 link-local IPv6, assuming it used autoconfiguration. This is not
674 standard-compliant but this is a convenient way to keep the
675 neighbor cache out of the way in cases ND is not used */
676 uip_lladdr_t lladdr;
677 uip_ds6_set_lladdr_from_iid(&lladdr, nexthop);
678 if((nbr = uip_ds6_nbr_add(nexthop, &lladdr,
679 0, NBR_REACHABLE, NBR_TABLE_REASON_IPV6_ND_AUTOFILL, NULL)) == NULL) {
680 LOG_ERR("output: failed to autofill neighbor cache for host ");
681 LOG_ERR_6ADDR(nexthop);
682 LOG_ERR_(", link-layer addr ");
683 LOG_ERR_LLADDR((linkaddr_t*)&lladdr);
684 LOG_ERR_("\n");
685 goto exit;
686 }
687 }
688#endif /* UIP_ND6_AUTOFILL_NBR_CACHE */
689
690 if(nbr == NULL) {
691 if(send_nd6_ns(nexthop)) {
692 LOG_ERR("output: failed to add neighbor to cache\n");
693 goto exit;
694 } else {
695 /* We're sending NS here instead of original packet */
696 goto send_packet;
697 }
698 }
699
700#if UIP_ND6_SEND_NS
701 if(nbr->state == NBR_INCOMPLETE) {
702 LOG_ERR("output: nbr cache entry incomplete\n");
703 queue_packet(nbr);
704 goto exit;
705 }
706 /* Send in parallel if we are running NUD (nbc state is either STALE,
707 DELAY, or PROBE). See RFC 4861, section 7.3.3 on node behavior. */
708 if(nbr->state == NBR_STALE) {
709 nbr->state = NBR_DELAY;
710 stimer_set(&nbr->reachable, UIP_ND6_DELAY_FIRST_PROBE_TIME);
711 nbr->nscount = 0;
712 LOG_INFO("output: nbr cache entry stale moving to delay\n");
713 }
714#endif /* UIP_ND6_SEND_NS */
715
717 if(nbr) {
718 linkaddr = uip_ds6_nbr_get_ll(nbr);
719 } else {
720 linkaddr = NULL;
721 }
722
723 LOG_INFO("output: sending to ");
724 LOG_INFO_LLADDR((linkaddr_t *)linkaddr);
725 LOG_INFO_("\n");
726 tcpip_output(linkaddr);
727
728 if(nbr) {
729 send_queued(nbr);
730 }
731
732exit:
733 uipbuf_clear();
734 return;
735}
736/*---------------------------------------------------------------------------*/
737#if UIP_UDP
738void
740{
741 process_post(&tcpip_process, UDP_POLL, conn);
742}
743#endif /* UIP_UDP */
744/*---------------------------------------------------------------------------*/
745#if UIP_TCP
746void
748{
749 process_post(&tcpip_process, TCP_POLL, conn);
750}
751#endif /* UIP_TCP */
752/*---------------------------------------------------------------------------*/
753void
754tcpip_uipcall(void)
755{
756 uip_udp_appstate_t *ts;
757
758#if UIP_UDP
759 if(uip_conn != NULL) {
760 ts = &uip_conn->appstate;
761 } else {
762 ts = &uip_udp_conn->appstate;
763 }
764#else /* UIP_UDP */
765 ts = &uip_conn->appstate;
766#endif /* UIP_UDP */
767
768#if UIP_TCP
769 {
770 unsigned char i;
771 struct listenport *l;
772
773 /* If this is a connection request for a listening port, we must
774 mark the connection with the right process ID. */
775 if(uip_connected()) {
776 l = &s.listenports[0];
777 for(i = 0; i < UIP_LISTENPORTS; ++i) {
778 if(l->port == uip_conn->lport &&
779 l->p != PROCESS_NONE) {
780 ts->p = l->p;
781 ts->state = NULL;
782 break;
783 }
784 ++l;
785 }
786
787 /* Start the periodic polling, if it isn't already active. */
788 start_periodic_tcp_timer();
789 }
790 }
791#endif /* UIP_TCP */
792
793 if(ts->p != NULL) {
794 process_post_synch(ts->p, tcpip_event, ts->state);
795 }
796}
797/*---------------------------------------------------------------------------*/
798PROCESS_THREAD(tcpip_process, ev, data)
799{
801
802#if UIP_TCP
803 memset(s.listenports, 0, UIP_LISTENPORTS*sizeof(*(s.listenports)));
804 s.p = PROCESS_CURRENT();
805#endif
806
808#if UIP_CONF_ICMP6
810#endif /* UIP_CONF_ICMP6 */
811 etimer_set(&periodic, CLOCK_SECOND / 2);
812
813 uip_init();
814#ifdef UIP_FALLBACK_INTERFACE
815 UIP_FALLBACK_INTERFACE.init();
816#endif
817 /* Initialize routing protocol */
818 NETSTACK_ROUTING.init();
819
820 while(1) {
822 eventhandler(ev, data);
823 }
824
825 PROCESS_END();
826}
827/*---------------------------------------------------------------------------*/
#define CLOCK_SECOND
A second, measured in system clock time.
Definition clock.h:103
void etimer_restart(struct etimer *et)
Restart an event timer from the current point in time.
Definition etimer.c:199
static bool etimer_expired(struct etimer *et)
Check if an event timer has expired.
Definition etimer.h:201
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:308
int process_post(struct process *p, process_event_t ev, process_data_t data)
Post an asynchronous event.
Definition process.c:325
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:357
#define PROCESS_CURRENT()
Get a pointer to the currently running process.
Definition process.h:404
process_event_t process_alloc_event(void)
Allocate a global event number.
Definition process.c:111
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition process.h:121
#define PROCESS_END()
Define the end of a process.
Definition process.h:132
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
Definition process.h:274
#define PROCESS_YIELD()
Yield the currently running process.
Definition process.h:165
static void send_packet(void)
This function is called by the 6lowpan code to send out a packet.
static void stimer_set(struct stimer *t, unsigned long interval)
Set a timer.
Definition stimer.h:100
void tcp_unlisten(uint16_t port)
Close a listening TCP port.
Definition tcpip.c:214
void udp_attach(struct uip_udp_conn *conn, void *appstate)
Attach the current process to a UDP connection.
Definition tcpip.c:258
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:264
void tcp_attach(struct uip_conn *conn, void *appstate)
Attach a TCP connection to the current process.
Definition tcpip.c:250
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:108
#define udp_bind(conn, port)
Bind a UDP connection to a local port.
Definition tcpip.h:259
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:304
void tcpip_poll_tcp(struct uip_conn *conn)
Cause a specified TCP connection to be polled.
Definition tcpip.c:747
struct uip_udp_conn * udp_broadcast_new(uint16_t port, void *appstate)
Create a new UDP broadcast connection.
Definition tcpip.c:278
uint8_t icmp6_new(void *appstate)
register an ICMPv6 callback
Definition tcpip.c:295
void tcpip_poll_udp(struct uip_udp_conn *conn)
Cause a specified UDP connection to be polled.
Definition tcpip.c:739
void tcpip_ipv6_output(void)
This function does address resolution and then calls tcpip_output.
Definition tcpip.c:619
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:433
void tcp_listen(uint16_t port)
Open a TCP port.
Definition tcpip.c:232
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.
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...
#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:1725
void uip_ds6_send_rs(void)
Send periodic RS to find router.
Definition uip-ds6.c:725
struct etimer uip_reass_timer
Timer for reassembly.
Definition uip6.c:619
#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.
#define uip_is_addr_mcast(a)
is address a multicast address, see RFC 4291 a is of type uip_ipaddr_t*
Definition uip.h:1860
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:491
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:589
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:1774
#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:578
struct uip_udp_conn * uip_udp_new(const uip_ipaddr_t *ripaddr, uint16_t rport)
Set up a new UDP connection.
Definition uip6.c:520
void uip_unlisten(uint16_t port)
Stop listening to the specified port.
Definition uip6.c:566
#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:773
#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
#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:79
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
The default nbr_table entry (when UIP_DS6_NBR_MULTI_IPV6_ADDRS is disabled), that implements nbr cach...
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
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)