Contiki-Inga 3.x
tcpip.c
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 Code for tunnelling uIP packets over the Rime mesh routing module
34  *
35  * \author Adam Dunkels <adam@sics.se>
36  * \author Mathilde Durvy <mdurvy@cisco.com> (IPv6 related code)
37  * \author Julien Abeille <jabeille@cisco.com> (IPv6 related code)
38  */
39 
40 #include "contiki-net.h"
41 #include "net/ip/uip-split.h"
42 #include "net/ip/uip-packetqueue.h"
43 
44 #if UIP_CONF_IPV6
45 #include "net/ipv6/uip-nd6.h"
46 #include "net/ipv6/uip-ds6.h"
47 #endif
48 
49 #include <string.h>
50 
51 #define DEBUG DEBUG_PRINT
52 #include "net/ip/uip-debug.h"
53 
54 #if UIP_LOGGING
55 #include <stdio.h>
56 void uip_log(char *msg);
57 #define UIP_LOG(m) uip_log(m)
58 #else
59 #define UIP_LOG(m)
60 #endif
61 
62 #define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[UIP_LLIPH_LEN + uip_ext_len])
63 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
64 #define UIP_TCP_BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
65 
66 #ifdef UIP_FALLBACK_INTERFACE
67 extern struct uip_fallback_interface UIP_FALLBACK_INTERFACE;
68 #endif
69 
70 #if UIP_CONF_IPV6_RPL
71 #include "rpl/rpl.h"
72 #endif
73 
74 process_event_t tcpip_event;
75 #if UIP_CONF_ICMP6
76 process_event_t tcpip_icmp6_event;
77 #endif /* UIP_CONF_ICMP6 */
78 
79 /* Periodic check of active connections. */
80 static struct etimer periodic;
81 
82 #if UIP_CONF_IPV6 && UIP_CONF_IPV6_REASSEMBLY
83 /* Timer for reassembly. */
84 extern struct etimer uip_reass_timer;
85 #endif
86 
87 #if UIP_TCP
88 /**
89  * \internal Structure for holding a TCP port and a process ID.
90  */
91 struct listenport {
92  uint16_t port;
93  struct process *p;
94 };
95 
96 static struct internal_state {
97  struct listenport listenports[UIP_LISTENPORTS];
98  struct process *p;
99 } s;
100 #endif
101 
102 enum {
103  TCP_POLL,
104  UDP_POLL,
105  PACKET_INPUT
106 };
107 
108 /* Called on IP packet output. */
109 #if UIP_CONF_IPV6
110 
111 static uint8_t (* outputfunc)(const uip_lladdr_t *a);
112 
113 uint8_t
115 {
116  int ret;
117  if(outputfunc != NULL) {
118  ret = outputfunc(a);
119  return ret;
120  }
121  UIP_LOG("tcpip_output: Use tcpip_set_outputfunc() to set an output function");
122  return 0;
123 }
124 
125 void
126 tcpip_set_outputfunc(uint8_t (*f)(const uip_lladdr_t *))
127 {
128  outputfunc = f;
129 }
130 #else
131 
132 static uint8_t (* outputfunc)(void);
133 uint8_t
134 tcpip_output(void)
135 {
136  if(outputfunc != NULL) {
137  return outputfunc();
138  }
139  UIP_LOG("tcpip_output: Use tcpip_set_outputfunc() to set an output function");
140  return 0;
141 }
142 
143 void
144 tcpip_set_outputfunc(uint8_t (*f)(void))
145 {
146  outputfunc = f;
147 }
148 #endif
149 
150 #if UIP_CONF_IP_FORWARD
151 unsigned char tcpip_is_forwarding; /* Forwarding right now? */
152 #endif /* UIP_CONF_IP_FORWARD */
153 
154 PROCESS(tcpip_process, "TCP/IP stack");
155 
156 /*---------------------------------------------------------------------------*/
157 static void
158 start_periodic_tcp_timer(void)
159 {
160  if(etimer_expired(&periodic)) {
161  etimer_restart(&periodic);
162  }
163 }
164 /*---------------------------------------------------------------------------*/
165 static void
166 check_for_tcp_syn(void)
167 {
168 #if UIP_TCP || UIP_CONF_IP_FORWARD
169  /* This is a hack that is needed to start the periodic TCP timer if
170  an incoming packet contains a SYN: since uIP does not inform the
171  application if a SYN arrives, we have no other way of starting
172  this timer. This function is called for every incoming IP packet
173  to check for such SYNs. */
174 #define TCP_SYN 0x02
175  if(UIP_IP_BUF->proto == UIP_PROTO_TCP &&
176  (UIP_TCP_BUF->flags & TCP_SYN) == TCP_SYN) {
177  start_periodic_tcp_timer();
178  }
179 #endif /* UIP_TCP || UIP_CONF_IP_FORWARD */
180 }
181 /*---------------------------------------------------------------------------*/
182 static void
183 packet_input(void)
184 {
185 #if UIP_CONF_IP_FORWARD
186  if(uip_len > 0) {
187  tcpip_is_forwarding = 1;
188  if(uip_fw_forward() == UIP_FW_LOCAL) {
189  tcpip_is_forwarding = 0;
190  check_for_tcp_syn();
191  uip_input();
192  if(uip_len > 0) {
193 #if UIP_CONF_TCP_SPLIT
195 #else /* UIP_CONF_TCP_SPLIT */
196 #if UIP_CONF_IPV6
198 #else
199  PRINTF("tcpip packet_input forward output len %d\n", uip_len);
200  tcpip_output();
201 #endif
202 #endif /* UIP_CONF_TCP_SPLIT */
203  }
204  }
205  tcpip_is_forwarding = 0;
206  }
207 #else /* UIP_CONF_IP_FORWARD */
208  if(uip_len > 0) {
209  check_for_tcp_syn();
210  uip_input();
211  if(uip_len > 0) {
212 #if UIP_CONF_TCP_SPLIT
214 #else /* UIP_CONF_TCP_SPLIT */
215 #if UIP_CONF_IPV6
217 #else
218  PRINTF("tcpip packet_input output len %d\n", uip_len);
219  tcpip_output();
220 #endif
221 #endif /* UIP_CONF_TCP_SPLIT */
222  }
223  }
224 #endif /* UIP_CONF_IP_FORWARD */
225 }
226 /*---------------------------------------------------------------------------*/
227 #if UIP_TCP
228 #if UIP_ACTIVE_OPEN
229 struct uip_conn *
230 tcp_connect(uip_ipaddr_t *ripaddr, uint16_t port, void *appstate)
231 {
232  struct uip_conn *c;
233 
234  c = uip_connect(ripaddr, port);
235  if(c == NULL) {
236  return NULL;
237  }
238 
239  c->appstate.p = PROCESS_CURRENT();
240  c->appstate.state = appstate;
241 
242  tcpip_poll_tcp(c);
243 
244  return c;
245 }
246 #endif /* UIP_ACTIVE_OPEN */
247 /*---------------------------------------------------------------------------*/
248 void
249 tcp_unlisten(uint16_t port)
250 {
251  static unsigned char i;
252  struct listenport *l;
253 
254  l = s.listenports;
255  for(i = 0; i < UIP_LISTENPORTS; ++i) {
256  if(l->port == port &&
257  l->p == PROCESS_CURRENT()) {
258  l->port = 0;
259  uip_unlisten(port);
260  break;
261  }
262  ++l;
263  }
264 }
265 /*---------------------------------------------------------------------------*/
266 void
267 tcp_listen(uint16_t port)
268 {
269  static unsigned char i;
270  struct listenport *l;
271 
272  l = s.listenports;
273  for(i = 0; i < UIP_LISTENPORTS; ++i) {
274  if(l->port == 0) {
275  l->port = port;
276  l->p = PROCESS_CURRENT();
277  uip_listen(port);
278  break;
279  }
280  ++l;
281  }
282 }
283 /*---------------------------------------------------------------------------*/
284 void
285 tcp_attach(struct uip_conn *conn,
286  void *appstate)
287 {
289 
290  s = &conn->appstate;
291  s->p = PROCESS_CURRENT();
292  s->state = appstate;
293 }
294 
295 #endif /* UIP_TCP */
296 /*---------------------------------------------------------------------------*/
297 #if UIP_UDP
298 void
299 udp_attach(struct uip_udp_conn *conn,
300  void *appstate)
301 {
303 
304  s = &conn->appstate;
305  s->p = PROCESS_CURRENT();
306  s->state = appstate;
307 }
308 /*---------------------------------------------------------------------------*/
309 struct uip_udp_conn *
310 udp_new(const uip_ipaddr_t *ripaddr, uint16_t port, void *appstate)
311 {
312  struct uip_udp_conn *c;
314 
315  c = uip_udp_new(ripaddr, port);
316  if(c == NULL) {
317  return NULL;
318  }
319 
320  s = &c->appstate;
321  s->p = PROCESS_CURRENT();
322  s->state = appstate;
323 
324  return c;
325 }
326 /*---------------------------------------------------------------------------*/
327 struct uip_udp_conn *
328 udp_broadcast_new(uint16_t port, void *appstate)
329 {
330  uip_ipaddr_t addr;
331  struct uip_udp_conn *conn;
332 
333 #if UIP_CONF_IPV6
335 #else
336  uip_ipaddr(&addr, 255,255,255,255);
337 #endif /* UIP_CONF_IPV6 */
338  conn = udp_new(&addr, port, appstate);
339  if(conn != NULL) {
340  udp_bind(conn, port);
341  }
342  return conn;
343 }
344 #endif /* UIP_UDP */
345 /*---------------------------------------------------------------------------*/
346 #if UIP_CONF_ICMP6
347 uint8_t
348 icmp6_new(void *appstate) {
349  if(uip_icmp6_conns.appstate.p == PROCESS_NONE) {
350  uip_icmp6_conns.appstate.p = PROCESS_CURRENT();
351  uip_icmp6_conns.appstate.state = appstate;
352  return 0;
353  }
354  return 1;
355 }
356 
357 void
358 tcpip_icmp6_call(uint8_t type)
359 {
360  if(uip_icmp6_conns.appstate.p != PROCESS_NONE) {
361  /* XXX: This is a hack that needs to be updated. Passing a pointer (&type)
362  like this only works with process_post_synch. */
363  process_post_synch(uip_icmp6_conns.appstate.p, tcpip_icmp6_event, &type);
364  }
365  return;
366 }
367 #endif /* UIP_CONF_ICMP6 */
368 /*---------------------------------------------------------------------------*/
369 static void
370 eventhandler(process_event_t ev, process_data_t data)
371 {
372 #if UIP_TCP
373  static unsigned char i;
374  register struct listenport *l;
375 #endif /*UIP_TCP*/
376  struct process *p;
377 
378  switch(ev) {
379  case PROCESS_EVENT_EXITED:
380  /* This is the event we get if a process has exited. We go through
381  the TCP/IP tables to see if this process had any open
382  connections or listening TCP ports. If so, we'll close those
383  connections. */
384 
385  p = (struct process *)data;
386 #if UIP_TCP
387  l = s.listenports;
388  for(i = 0; i < UIP_LISTENPORTS; ++i) {
389  if(l->p == p) {
390  uip_unlisten(l->port);
391  l->port = 0;
392  l->p = PROCESS_NONE;
393  }
394  ++l;
395  }
396 
397  {
398  struct uip_conn *cptr;
399 
400  for(cptr = &uip_conns[0]; cptr < &uip_conns[UIP_CONNS]; ++cptr) {
401  if(cptr->appstate.p == p) {
402  cptr->appstate.p = PROCESS_NONE;
403  cptr->tcpstateflags = UIP_CLOSED;
404  }
405  }
406  }
407 #endif /* UIP_TCP */
408 #if UIP_UDP
409  {
410  struct uip_udp_conn *cptr;
411 
412  for(cptr = &uip_udp_conns[0];
413  cptr < &uip_udp_conns[UIP_UDP_CONNS]; ++cptr) {
414  if(cptr->appstate.p == p) {
415  cptr->lport = 0;
416  }
417  }
418  }
419 #endif /* UIP_UDP */
420  break;
421 
422  case PROCESS_EVENT_TIMER:
423  /* We get this event if one of our timers have expired. */
424  {
425  /* Check the clock so see if we should call the periodic uIP
426  processing. */
427  if(data == &periodic &&
428  etimer_expired(&periodic)) {
429 #if UIP_TCP
430  for(i = 0; i < UIP_CONNS; ++i) {
431  if(uip_conn_active(i)) {
432  /* Only restart the timer if there are active
433  connections. */
434  etimer_restart(&periodic);
435  uip_periodic(i);
436 #if UIP_CONF_IPV6
438 #else
439  if(uip_len > 0) {
440  PRINTF("tcpip_output from periodic len %d\n", uip_len);
441  tcpip_output();
442  PRINTF("tcpip_output after periodic len %d\n", uip_len);
443  }
444 #endif /* UIP_CONF_IPV6 */
445  }
446  }
447 #endif /* UIP_TCP */
448 #if UIP_CONF_IP_FORWARD
449  uip_fw_periodic();
450 #endif /* UIP_CONF_IP_FORWARD */
451  }
452 
453 #if UIP_CONF_IPV6
454 #if UIP_CONF_IPV6_REASSEMBLY
455  /*
456  * check the timer for reassembly
457  */
458  if(data == &uip_reass_timer &&
459  etimer_expired(&uip_reass_timer)) {
460  uip_reass_over();
462  }
463 #endif /* UIP_CONF_IPV6_REASSEMBLY */
464  /*
465  * check the different timers for neighbor discovery and
466  * stateless autoconfiguration
467  */
468  /*if(data == &uip_ds6_timer_periodic &&
469  etimer_expired(&uip_ds6_timer_periodic)) {
470  uip_ds6_periodic();
471  tcpip_ipv6_output();
472  }*/
473 #if !UIP_CONF_ROUTER
474  if(data == &uip_ds6_timer_rs &&
476  uip_ds6_send_rs();
478  }
479 #endif /* !UIP_CONF_ROUTER */
480  if(data == &uip_ds6_timer_periodic &&
481  etimer_expired(&uip_ds6_timer_periodic)) {
484  }
485 #endif /* UIP_CONF_IPV6 */
486  }
487  break;
488 
489 #if UIP_TCP
490  case TCP_POLL:
491  if(data != NULL) {
492  uip_poll_conn(data);
493 #if UIP_CONF_IPV6
495 #else /* UIP_CONF_IPV6 */
496  if(uip_len > 0) {
497  PRINTF("tcpip_output from tcp poll len %d\n", uip_len);
498  tcpip_output();
499  }
500 #endif /* UIP_CONF_IPV6 */
501  /* Start the periodic polling, if it isn't already active. */
502  start_periodic_tcp_timer();
503  }
504  break;
505 #endif /* UIP_TCP */
506 #if UIP_UDP
507  case UDP_POLL:
508  if(data != NULL) {
509  uip_udp_periodic_conn(data);
510 #if UIP_CONF_IPV6
512 #else
513  if(uip_len > 0) {
514  tcpip_output();
515  }
516 #endif /* UIP_UDP */
517  }
518  break;
519 #endif /* UIP_UDP */
520 
521  case PACKET_INPUT:
522  packet_input();
523  break;
524  };
525 }
526 /*---------------------------------------------------------------------------*/
527 void
529 {
530  process_post_synch(&tcpip_process, PACKET_INPUT, NULL);
531  uip_len = 0;
532 #if UIP_CONF_IPV6
533  uip_ext_len = 0;
534 #endif /*UIP_CONF_IPV6*/
535 }
536 /*---------------------------------------------------------------------------*/
537 #if UIP_CONF_IPV6
538 void
540 {
541  uip_ds6_nbr_t *nbr = NULL;
542  uip_ipaddr_t *nexthop;
543 
544  if(uip_len == 0) {
545  return;
546  }
547 
548  if(uip_len > UIP_LINK_MTU) {
549  UIP_LOG("tcpip_ipv6_output: Packet to big");
550  uip_len = 0;
551  return;
552  }
553 
554  if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)){
555  UIP_LOG("tcpip_ipv6_output: Destination address unspecified");
556  uip_len = 0;
557  return;
558  }
559 
560  if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) {
561  /* Next hop determination */
562  nbr = NULL;
563 
564  /* We first check if the destination address is on our immediate
565  link. If so, we simply use the destination address as our
566  nexthop address. */
567  if(uip_ds6_is_addr_onlink(&UIP_IP_BUF->destipaddr)){
568  nexthop = &UIP_IP_BUF->destipaddr;
569  } else {
570  uip_ds6_route_t *route;
571  /* Check if we have a route to the destination address. */
572  route = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr);
573 
574  /* No route was found - we send to the default route instead. */
575  if(route == NULL) {
576  PRINTF("tcpip_ipv6_output: no route found, using default route\n");
577  nexthop = uip_ds6_defrt_choose();
578  if(nexthop == NULL) {
579 #ifdef UIP_FALLBACK_INTERFACE
580  PRINTF("FALLBACK: removing ext hdrs & setting proto %d %d\n",
581  uip_ext_len, *((uint8_t *)UIP_IP_BUF + 40));
582  if(uip_ext_len > 0) {
583  extern void remove_ext_hdr(void);
584  uint8_t proto = *((uint8_t *)UIP_IP_BUF + 40);
585  remove_ext_hdr();
586  /* This should be copied from the ext header... */
587  UIP_IP_BUF->proto = proto;
588  }
589  UIP_FALLBACK_INTERFACE.output();
590 #else
591  PRINTF("tcpip_ipv6_output: Destination off-link but no route\n");
592 #endif /* !UIP_FALLBACK_INTERFACE */
593  uip_len = 0;
594  return;
595  }
596 
597  } else {
598  /* A route was found, so we look up the nexthop neighbor for
599  the route. */
600  nexthop = uip_ds6_route_nexthop(route);
601 
602  /* If the nexthop is dead, for example because the neighbor
603  never responded to link-layer acks, we drop its route. */
604  if(nexthop == NULL) {
605 #if UIP_CONF_IPV6_RPL
606  /* If we are running RPL, and if we are the root of the
607  network, we'll trigger a global repair berfore we remove
608  the route. */
609  rpl_dag_t *dag;
610  rpl_instance_t *instance;
611 
612  dag = (rpl_dag_t *)route->state.dag;
613  if(dag != NULL) {
614  instance = dag->instance;
615 
616  rpl_repair_root(instance->instance_id);
617  }
618 #endif /* UIP_CONF_RPL */
619  uip_ds6_route_rm(route);
620 
621  /* We don't have a nexthop to send the packet to, so we drop
622  it. */
623  return;
624  }
625  }
626 #if TCPIP_CONF_ANNOTATE_TRANSMISSIONS
627  if(nexthop != NULL) {
628  static uint8_t annotate_last;
629  static uint8_t annotate_has_last = 0;
630 
631  if(annotate_has_last) {
632  printf("#L %u 0; red\n", annotate_last);
633  }
634  printf("#L %u 1; red\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]);
635  annotate_last = nexthop->u8[sizeof(uip_ipaddr_t) - 1];
636  annotate_has_last = 1;
637  }
638 #endif /* TCPIP_CONF_ANNOTATE_TRANSMISSIONS */
639  }
640 
641  /* End of next hop determination */
642 
643 #if UIP_CONF_IPV6_RPL
644  if(rpl_update_header_final(nexthop)) {
645  uip_len = 0;
646  return;
647  }
648 #endif /* UIP_CONF_IPV6_RPL */
649  nbr = uip_ds6_nbr_lookup(nexthop);
650  if(nbr == NULL) {
651 #if UIP_ND6_SEND_NA
652  if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE)) == NULL) {
653  uip_len = 0;
654  return;
655  } else {
656 #if UIP_CONF_IPV6_QUEUE_PKT
657  /* Copy outgoing pkt in the queuing buffer for later transmit. */
658  if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) {
659  memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len);
660  uip_packetqueue_set_buflen(&nbr->packethandle, uip_len);
661  }
662 #endif
663  /* RFC4861, 7.2.2:
664  * "If the source address of the packet prompting the solicitation is the
665  * same as one of the addresses assigned to the outgoing interface, that
666  * address SHOULD be placed in the IP Source Address of the outgoing
667  * solicitation. Otherwise, any one of the addresses assigned to the
668  * interface should be used."*/
669  if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)){
670  uip_nd6_ns_output(&UIP_IP_BUF->srcipaddr, NULL, &nbr->ipaddr);
671  } else {
672  uip_nd6_ns_output(NULL, NULL, &nbr->ipaddr);
673  }
674 
675  stimer_set(&nbr->sendns, uip_ds6_if.retrans_timer / 1000);
676  nbr->nscount = 1;
677  }
678 #endif /* UIP_ND6_SEND_NA */
679  } else {
680 #if UIP_ND6_SEND_NA
681  if(nbr->state == NBR_INCOMPLETE) {
682  PRINTF("tcpip_ipv6_output: nbr cache entry incomplete\n");
683 #if UIP_CONF_IPV6_QUEUE_PKT
684  /* Copy outgoing pkt in the queuing buffer for later transmit and set
685  the destination nbr to nbr. */
686  if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) {
687  memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len);
688  uip_packetqueue_set_buflen(&nbr->packethandle, uip_len);
689  }
690 #endif /*UIP_CONF_IPV6_QUEUE_PKT*/
691  uip_len = 0;
692  return;
693  }
694  /* Send in parallel if we are running NUD (nbc state is either STALE,
695  DELAY, or PROBE). See RFC 4861, section 7.3.3 on node behavior. */
696  if(nbr->state == NBR_STALE) {
697  nbr->state = NBR_DELAY;
698  stimer_set(&nbr->reachable, UIP_ND6_DELAY_FIRST_PROBE_TIME);
699  nbr->nscount = 0;
700  PRINTF("tcpip_ipv6_output: nbr cache entry stale moving to delay\n");
701  }
702 #endif /* UIP_ND6_SEND_NA */
703 
705 
706 #if UIP_CONF_IPV6_QUEUE_PKT
707  /*
708  * Send the queued packets from here, may not be 100% perfect though.
709  * This happens in a few cases, for example when instead of receiving a
710  * NA after sendiong a NS, you receive a NS with SLLAO: the entry moves
711  * to STALE, and you must both send a NA and the queued packet.
712  */
713  if(uip_packetqueue_buflen(&nbr->packethandle) != 0) {
714  uip_len = uip_packetqueue_buflen(&nbr->packethandle);
715  memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len);
716  uip_packetqueue_free(&nbr->packethandle);
718  }
719 #endif /*UIP_CONF_IPV6_QUEUE_PKT*/
720 
721  uip_len = 0;
722  return;
723  }
724  return;
725  }
726  /* Multicast IP destination address. */
728  uip_len = 0;
729  uip_ext_len = 0;
730 }
731 #endif /* UIP_CONF_IPV6 */
732 /*---------------------------------------------------------------------------*/
733 #if UIP_UDP
734 void
735 tcpip_poll_udp(struct uip_udp_conn *conn)
736 {
737  process_post(&tcpip_process, UDP_POLL, conn);
738 }
739 #endif /* UIP_UDP */
740 /*---------------------------------------------------------------------------*/
741 #if UIP_TCP
742 void
743 tcpip_poll_tcp(struct uip_conn *conn)
744 {
745  process_post(&tcpip_process, TCP_POLL, conn);
746 }
747 #endif /* UIP_TCP */
748 /*---------------------------------------------------------------------------*/
749 void
750 tcpip_uipcall(void)
751 {
752  uip_udp_appstate_t *ts;
753 
754 #if UIP_UDP
755  if(uip_conn != NULL) {
756  ts = &uip_conn->appstate;
757  } else {
758  ts = &uip_udp_conn->appstate;
759  }
760 #else /* UIP_UDP */
761  ts = &uip_conn->appstate;
762 #endif /* UIP_UDP */
763 
764 #if UIP_TCP
765  {
766  static unsigned char i;
767  struct listenport *l;
768 
769  /* If this is a connection request for a listening port, we must
770  mark the connection with the right process ID. */
771  if(uip_connected()) {
772  l = &s.listenports[0];
773  for(i = 0; i < UIP_LISTENPORTS; ++i) {
774  if(l->port == uip_conn->lport &&
775  l->p != PROCESS_NONE) {
776  ts->p = l->p;
777  ts->state = NULL;
778  break;
779  }
780  ++l;
781  }
782 
783  /* Start the periodic polling, if it isn't already active. */
784  start_periodic_tcp_timer();
785  }
786  }
787 #endif /* UIP_TCP */
788 
789  if(ts->p != NULL) {
790  process_post_synch(ts->p, tcpip_event, ts->state);
791  }
792 }
793 /*---------------------------------------------------------------------------*/
794 PROCESS_THREAD(tcpip_process, ev, data)
795 {
796  PROCESS_BEGIN();
797 
798 #if UIP_TCP
799  {
800  static unsigned char i;
801 
802  for(i = 0; i < UIP_LISTENPORTS; ++i) {
803  s.listenports[i].port = 0;
804  }
805  s.p = PROCESS_CURRENT();
806  }
807 #endif
808 
810 #if UIP_CONF_ICMP6
811  tcpip_icmp6_event = process_alloc_event();
812 #endif /* UIP_CONF_ICMP6 */
813  etimer_set(&periodic, CLOCK_SECOND / 2);
814 
815  uip_init();
816 #ifdef UIP_FALLBACK_INTERFACE
817  UIP_FALLBACK_INTERFACE.init();
818 #endif
819 /* initialize RPL if configured for using RPL */
820 #if UIP_CONF_IPV6 && UIP_CONF_IPV6_RPL
821  rpl_init();
822 #endif /* UIP_CONF_IPV6_RPL */
823 
824  while(1) {
825  PROCESS_YIELD();
826  eventhandler(ev, data);
827  }
828 
829  PROCESS_END();
830 }
831 /*---------------------------------------------------------------------------*/