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