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