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