Contiki 2.6

tcpip.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2004, Swedish Institute of Computer Science.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the Institute nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  *
00029  * This file is part of the Contiki operating system.
00030  */
00031 
00032 /**
00033  * \file
00034  *         Code for tunnelling uIP packets over the Rime mesh routing module
00035  *
00036  * \author  Adam Dunkels <adam@sics.se>\author
00037  * \author  Mathilde Durvy <mdurvy@cisco.com> (IPv6 related code)
00038  * \author  Julien Abeille <jabeille@cisco.com> (IPv6 related code)
00039  */
00040 
00041 #include "contiki-net.h"
00042 #include "net/uip-split.h"
00043 #include "net/uip-packetqueue.h"
00044 
00045 #if UIP_CONF_IPV6
00046 #include "net/uip-nd6.h"
00047 #include "net/uip-ds6.h"
00048 #endif
00049 
00050 #include <string.h>
00051 
00052 #define DEBUG DEBUG_NONE
00053 #include "net/uip-debug.h"
00054 
00055 #if UIP_LOGGING
00056 #include <stdio.h>
00057 void uip_log(char *msg);
00058 #define UIP_LOG(m) uip_log(m)
00059 #else
00060 #define UIP_LOG(m)
00061 #endif
00062 
00063 #define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[UIP_LLIPH_LEN + uip_ext_len])
00064 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
00065 #define UIP_TCP_BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
00066 
00067 #ifdef UIP_FALLBACK_INTERFACE
00068 extern struct uip_fallback_interface UIP_FALLBACK_INTERFACE;
00069 #endif
00070 
00071 #if UIP_CONF_IPV6_RPL
00072 #include "rpl/rpl.h"
00073 #endif
00074 
00075 process_event_t tcpip_event;
00076 #if UIP_CONF_ICMP6
00077 process_event_t tcpip_icmp6_event;
00078 #endif /* UIP_CONF_ICMP6 */
00079 
00080 /* Periodic check of active connections. */
00081 static struct etimer periodic;
00082 
00083 #if UIP_CONF_IPV6 && UIP_CONF_IPV6_REASSEMBLY
00084 /* Timer for reassembly. */
00085 extern struct etimer uip_reass_timer;
00086 #endif
00087 
00088 #if UIP_TCP
00089 /**
00090  * \internal Structure for holding a TCP port and a process ID.
00091  */
00092 struct listenport {
00093   uint16_t port;
00094   struct process *p;
00095 };
00096 
00097 static struct internal_state {
00098   struct listenport listenports[UIP_LISTENPORTS];
00099   struct process *p;
00100 } s;
00101 #endif
00102 
00103 enum {
00104   TCP_POLL,
00105   UDP_POLL,
00106   PACKET_INPUT
00107 };
00108 
00109 /* Called on IP packet output. */
00110 #if UIP_CONF_IPV6
00111 
00112 static uint8_t (* outputfunc)(uip_lladdr_t *a);
00113 
00114 uint8_t
00115 tcpip_output(uip_lladdr_t *a)
00116 {
00117   int ret;
00118   if(outputfunc != NULL) {
00119     ret = outputfunc(a);
00120     return ret;
00121   }
00122   UIP_LOG("tcpip_output: Use tcpip_set_outputfunc() to set an output function");
00123   return 0;
00124 }
00125 
00126 void
00127 tcpip_set_outputfunc(uint8_t (*f)(uip_lladdr_t *))
00128 {
00129   outputfunc = f;
00130 }
00131 #else
00132 
00133 static uint8_t (* outputfunc)(void);
00134 uint8_t
00135 tcpip_output(void)
00136 {
00137   if(outputfunc != NULL) {
00138     return outputfunc();
00139   }
00140   UIP_LOG("tcpip_output: Use tcpip_set_outputfunc() to set an output function");
00141   return 0;
00142 }
00143 
00144 void
00145 tcpip_set_outputfunc(uint8_t (*f)(void))
00146 {
00147   outputfunc = f;
00148 }
00149 #endif
00150 
00151 #if UIP_CONF_IP_FORWARD
00152 unsigned char tcpip_is_forwarding; /* Forwarding right now? */
00153 #endif /* UIP_CONF_IP_FORWARD */
00154 
00155 PROCESS(tcpip_process, "TCP/IP stack");
00156 
00157 /*---------------------------------------------------------------------------*/
00158 static void
00159 start_periodic_tcp_timer(void)
00160 {
00161   if(etimer_expired(&periodic)) {
00162     etimer_restart(&periodic);
00163   }
00164 }
00165 /*---------------------------------------------------------------------------*/
00166 static void
00167 check_for_tcp_syn(void)
00168 {
00169   /* This is a hack that is needed to start the periodic TCP timer if
00170      an incoming packet contains a SYN: since uIP does not inform the
00171      application if a SYN arrives, we have no other way of starting
00172      this timer.  This function is called for every incoming IP packet
00173      to check for such SYNs. */
00174 #define TCP_SYN 0x02
00175   if(UIP_IP_BUF->proto == UIP_PROTO_TCP &&
00176      (UIP_TCP_BUF->flags & TCP_SYN) == TCP_SYN) {
00177     start_periodic_tcp_timer();
00178   }
00179 }
00180 /*---------------------------------------------------------------------------*/
00181 static void
00182 packet_input(void)
00183 {
00184 #if UIP_CONF_IP_FORWARD
00185   if(uip_len > 0) {
00186     tcpip_is_forwarding = 1;
00187     if(uip_fw_forward() == UIP_FW_LOCAL) {
00188       tcpip_is_forwarding = 0;
00189       check_for_tcp_syn();
00190       uip_input();
00191       if(uip_len > 0) {
00192 #if UIP_CONF_TCP_SPLIT
00193         uip_split_output();
00194 #else /* UIP_CONF_TCP_SPLIT */
00195 #if UIP_CONF_IPV6
00196         tcpip_ipv6_output();
00197 #else
00198         PRINTF("tcpip packet_input forward output len %d\n", uip_len);
00199         tcpip_output();
00200 #endif
00201 #endif /* UIP_CONF_TCP_SPLIT */
00202       }
00203     }
00204     tcpip_is_forwarding = 0;
00205   }
00206 #else /* UIP_CONF_IP_FORWARD */
00207   if(uip_len > 0) {
00208     check_for_tcp_syn();
00209     uip_input();
00210     if(uip_len > 0) {
00211 #if UIP_CONF_TCP_SPLIT
00212       uip_split_output();
00213 #else /* UIP_CONF_TCP_SPLIT */
00214 #if UIP_CONF_IPV6
00215       tcpip_ipv6_output();
00216 #else
00217       PRINTF("tcpip packet_input output len %d\n", uip_len);
00218       tcpip_output();
00219 #endif
00220 #endif /* UIP_CONF_TCP_SPLIT */
00221     }
00222   }
00223 #endif /* UIP_CONF_IP_FORWARD */
00224 }
00225 /*---------------------------------------------------------------------------*/
00226 #if UIP_TCP
00227 #if UIP_ACTIVE_OPEN
00228 struct uip_conn *
00229 tcp_connect(uip_ipaddr_t *ripaddr, uint16_t port, void *appstate)
00230 {
00231   struct uip_conn *c;
00232   
00233   c = uip_connect(ripaddr, port);
00234   if(c == NULL) {
00235     return NULL;
00236   }
00237 
00238   c->appstate.p = PROCESS_CURRENT();
00239   c->appstate.state = appstate;
00240   
00241   tcpip_poll_tcp(c);
00242   
00243   return c;
00244 }
00245 #endif /* UIP_ACTIVE_OPEN */
00246 /*---------------------------------------------------------------------------*/
00247 void
00248 tcp_unlisten(uint16_t port)
00249 {
00250   static unsigned char i;
00251   struct listenport *l;
00252 
00253   l = s.listenports;
00254   for(i = 0; i < UIP_LISTENPORTS; ++i) {
00255     if(l->port == port &&
00256        l->p == PROCESS_CURRENT()) {
00257       l->port = 0;
00258       uip_unlisten(port);
00259       break;
00260     }
00261     ++l;
00262   }
00263 }
00264 /*---------------------------------------------------------------------------*/
00265 void
00266 tcp_listen(uint16_t port)
00267 {
00268   static unsigned char i;
00269   struct listenport *l;
00270 
00271   l = s.listenports;
00272   for(i = 0; i < UIP_LISTENPORTS; ++i) {
00273     if(l->port == 0) {
00274       l->port = port;
00275       l->p = PROCESS_CURRENT();
00276       uip_listen(port);
00277       break;
00278     }
00279     ++l;
00280   }
00281 }
00282 /*---------------------------------------------------------------------------*/
00283 void
00284 tcp_attach(struct uip_conn *conn,
00285            void *appstate)
00286 {
00287   register uip_tcp_appstate_t *s;
00288 
00289   s = &conn->appstate;
00290   s->p = PROCESS_CURRENT();
00291   s->state = appstate;
00292 }
00293 
00294 #endif /* UIP_TCP */
00295 /*---------------------------------------------------------------------------*/
00296 #if UIP_UDP
00297 void
00298 udp_attach(struct uip_udp_conn *conn,
00299            void *appstate)
00300 {
00301   register uip_udp_appstate_t *s;
00302 
00303   s = &conn->appstate;
00304   s->p = PROCESS_CURRENT();
00305   s->state = appstate;
00306 }
00307 /*---------------------------------------------------------------------------*/
00308 struct uip_udp_conn *
00309 udp_new(const uip_ipaddr_t *ripaddr, uint16_t port, void *appstate)
00310 {
00311   struct uip_udp_conn *c;
00312   uip_udp_appstate_t *s;
00313   
00314   c = uip_udp_new(ripaddr, port);
00315   if(c == NULL) {
00316     return NULL;
00317   }
00318 
00319   s = &c->appstate;
00320   s->p = PROCESS_CURRENT();
00321   s->state = appstate;
00322 
00323   return c;
00324 }
00325 /*---------------------------------------------------------------------------*/
00326 struct uip_udp_conn *
00327 udp_broadcast_new(uint16_t port, void *appstate)
00328 {
00329   uip_ipaddr_t addr;
00330   struct uip_udp_conn *conn;
00331 
00332 #if UIP_CONF_IPV6
00333   uip_create_linklocal_allnodes_mcast(&addr);
00334 #else
00335   uip_ipaddr(&addr, 255,255,255,255);
00336 #endif /* UIP_CONF_IPV6 */
00337   conn = udp_new(&addr, port, appstate);
00338   if(conn != NULL) {
00339     udp_bind(conn, port);
00340   }
00341   return conn;
00342 }
00343 #endif /* UIP_UDP */
00344 /*---------------------------------------------------------------------------*/
00345 #if UIP_CONF_ICMP6
00346 uint8_t
00347 icmp6_new(void *appstate) {
00348   if(uip_icmp6_conns.appstate.p == PROCESS_NONE) {
00349     uip_icmp6_conns.appstate.p = PROCESS_CURRENT();
00350     uip_icmp6_conns.appstate.state = appstate;
00351     return 0;
00352   }
00353   return 1;
00354 }
00355 
00356 void
00357 tcpip_icmp6_call(uint8_t type)
00358 {
00359   if(uip_icmp6_conns.appstate.p != PROCESS_NONE) {
00360     /* XXX: This is a hack that needs to be updated. Passing a pointer (&type)
00361        like this only works with process_post_synch. */
00362     process_post_synch(uip_icmp6_conns.appstate.p, tcpip_icmp6_event, &type);
00363   }
00364   return;
00365 }
00366 #endif /* UIP_CONF_ICMP6 */
00367 /*---------------------------------------------------------------------------*/
00368 static void
00369 eventhandler(process_event_t ev, process_data_t data)
00370 {
00371 #if UIP_TCP
00372   static unsigned char i;
00373   register struct listenport *l;
00374 #endif /*UIP_TCP*/
00375   struct process *p;
00376    
00377   switch(ev) {
00378     case PROCESS_EVENT_EXITED:
00379       /* This is the event we get if a process has exited. We go through
00380          the TCP/IP tables to see if this process had any open
00381          connections or listening TCP ports. If so, we'll close those
00382          connections. */
00383 
00384       p = (struct process *)data;
00385 #if UIP_TCP
00386       l = s.listenports;
00387       for(i = 0; i < UIP_LISTENPORTS; ++i) {
00388         if(l->p == p) {
00389           uip_unlisten(l->port);
00390           l->port = 0;
00391           l->p = PROCESS_NONE;
00392         }
00393         ++l;
00394       }
00395          
00396       {
00397         register struct uip_conn *cptr;
00398             
00399         for(cptr = &uip_conns[0]; cptr < &uip_conns[UIP_CONNS]; ++cptr) {
00400           if(cptr->appstate.p == p) {
00401             cptr->appstate.p = PROCESS_NONE;
00402             cptr->tcpstateflags = UIP_CLOSED;
00403           }
00404         }
00405       }
00406 #endif /* UIP_TCP */
00407 #if UIP_UDP
00408       {
00409         register struct uip_udp_conn *cptr;
00410 
00411         for(cptr = &uip_udp_conns[0];
00412             cptr < &uip_udp_conns[UIP_UDP_CONNS]; ++cptr) {
00413           if(cptr->appstate.p == p) {
00414             cptr->lport = 0;
00415           }
00416         }
00417       }
00418 #endif /* UIP_UDP */
00419       break;
00420 
00421     case PROCESS_EVENT_TIMER:
00422       /* We get this event if one of our timers have expired. */
00423       {
00424         /* Check the clock so see if we should call the periodic uIP
00425            processing. */
00426         if(data == &periodic &&
00427            etimer_expired(&periodic)) {
00428 #if UIP_TCP
00429           for(i = 0; i < UIP_CONNS; ++i) {
00430             if(uip_conn_active(i)) {
00431               /* Only restart the timer if there are active
00432                  connections. */
00433               etimer_restart(&periodic);
00434               uip_periodic(i);
00435 #if UIP_CONF_IPV6
00436               tcpip_ipv6_output();
00437 #else
00438               if(uip_len > 0) {
00439                 PRINTF("tcpip_output from periodic len %d\n", uip_len);
00440                 tcpip_output();
00441                 PRINTF("tcpip_output after periodic len %d\n", uip_len);
00442               }
00443 #endif /* UIP_CONF_IPV6 */
00444             }
00445           }
00446 #endif /* UIP_TCP */
00447 #if UIP_CONF_IP_FORWARD
00448           uip_fw_periodic();
00449 #endif /* UIP_CONF_IP_FORWARD */
00450         }
00451         
00452 #if UIP_CONF_IPV6
00453 #if UIP_CONF_IPV6_REASSEMBLY
00454         /*
00455          * check the timer for reassembly
00456          */
00457         if(data == &uip_reass_timer &&
00458            etimer_expired(&uip_reass_timer)) {
00459           uip_reass_over();
00460           tcpip_ipv6_output();
00461         }
00462 #endif /* UIP_CONF_IPV6_REASSEMBLY */
00463         /*
00464          * check the different timers for neighbor discovery and
00465          * stateless autoconfiguration
00466          */
00467         /*if(data == &uip_ds6_timer_periodic &&
00468            etimer_expired(&uip_ds6_timer_periodic)) {
00469           uip_ds6_periodic();
00470           tcpip_ipv6_output();
00471         }*/
00472 #if !UIP_CONF_ROUTER
00473         if(data == &uip_ds6_timer_rs &&
00474            etimer_expired(&uip_ds6_timer_rs)){
00475           uip_ds6_send_rs();
00476           tcpip_ipv6_output();
00477         }
00478 #endif /* !UIP_CONF_ROUTER */
00479         if(data == &uip_ds6_timer_periodic &&
00480            etimer_expired(&uip_ds6_timer_periodic)){
00481           uip_ds6_periodic();
00482           tcpip_ipv6_output();
00483         }
00484 #endif /* UIP_CONF_IPV6 */
00485       }
00486       break;
00487          
00488 #if UIP_TCP
00489     case TCP_POLL:
00490       if(data != NULL) {
00491         uip_poll_conn(data);
00492 #if UIP_CONF_IPV6
00493         tcpip_ipv6_output();
00494 #else /* UIP_CONF_IPV6 */
00495         if(uip_len > 0) {
00496           PRINTF("tcpip_output from tcp poll len %d\n", uip_len);
00497           tcpip_output();
00498         }
00499 #endif /* UIP_CONF_IPV6 */
00500         /* Start the periodic polling, if it isn't already active. */
00501         start_periodic_tcp_timer();
00502       }
00503       break;
00504 #endif /* UIP_TCP */
00505 #if UIP_UDP
00506     case UDP_POLL:
00507       if(data != NULL) {
00508         uip_udp_periodic_conn(data);
00509 #if UIP_CONF_IPV6
00510         tcpip_ipv6_output();
00511 #else
00512         if(uip_len > 0) {
00513           tcpip_output();
00514         }
00515 #endif /* UIP_UDP */
00516       }
00517       break;
00518 #endif /* UIP_UDP */
00519 
00520     case PACKET_INPUT:
00521       packet_input();
00522       break;
00523   };
00524 }
00525 /*---------------------------------------------------------------------------*/
00526 void
00527 tcpip_input(void)
00528 {
00529   process_post_synch(&tcpip_process, PACKET_INPUT, NULL);
00530   uip_len = 0;
00531 #if UIP_CONF_IPV6
00532   uip_ext_len = 0;
00533 #endif /*UIP_CONF_IPV6*/
00534 }
00535 /*---------------------------------------------------------------------------*/
00536 #if UIP_CONF_IPV6
00537 void
00538 tcpip_ipv6_output(void)
00539 {
00540   uip_ds6_nbr_t *nbr = NULL;
00541   uip_ipaddr_t *nexthop;
00542 
00543   if(uip_len == 0) {
00544     return;
00545   }
00546 
00547   if(uip_len > UIP_LINK_MTU) {
00548     UIP_LOG("tcpip_ipv6_output: Packet to big");
00549     uip_len = 0;
00550     return;
00551   }
00552 
00553   if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)){
00554     UIP_LOG("tcpip_ipv6_output: Destination address unspecified");
00555     uip_len = 0;
00556     return;
00557   }
00558 
00559   if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) {
00560     /* Next hop determination */
00561     nbr = NULL;
00562     if(uip_ds6_is_addr_onlink(&UIP_IP_BUF->destipaddr)){
00563       nexthop = &UIP_IP_BUF->destipaddr;
00564     } else {
00565       uip_ds6_route_t* locrt;
00566       locrt = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr);
00567       if(locrt == NULL) {
00568         if((nexthop = uip_ds6_defrt_choose()) == NULL) {
00569 #ifdef UIP_FALLBACK_INTERFACE
00570           PRINTF("FALLBACK: removing ext hdrs & setting proto %d %d\n", 
00571                  uip_ext_len, *((uint8_t *)UIP_IP_BUF + 40));
00572           if(uip_ext_len > 0) {
00573             extern void remove_ext_hdr(void);
00574             uint8_t proto = *((uint8_t *)UIP_IP_BUF + 40);
00575             remove_ext_hdr();
00576             /* This should be copied from the ext header... */
00577             UIP_IP_BUF->proto = proto;
00578           }
00579           UIP_FALLBACK_INTERFACE.output();
00580 #else
00581           PRINTF("tcpip_ipv6_output: Destination off-link but no route\n");
00582 #endif /* !UIP_FALLBACK_INTERFACE */
00583           uip_len = 0;
00584           return;
00585         }
00586       } else {
00587         nexthop = &locrt->nexthop;
00588       }
00589     }
00590     /* End of next hop determination */
00591 #if UIP_CONF_IPV6_RPL
00592     if(rpl_update_header_final(nexthop)) {
00593       uip_len = 0;
00594       return;
00595     }
00596 #endif /* UIP_CONF_IPV6_RPL */
00597     if((nbr = uip_ds6_nbr_lookup(nexthop)) == NULL) {
00598       if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE)) == NULL) {
00599         uip_len = 0;
00600         return;
00601       } else {
00602 #if UIP_CONF_IPV6_QUEUE_PKT
00603         /* Copy outgoing pkt in the queuing buffer for later transmit. */
00604         if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) {
00605           memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len);
00606           uip_packetqueue_set_buflen(&nbr->packethandle, uip_len);
00607         }
00608 #endif
00609       /* RFC4861, 7.2.2:
00610        * "If the source address of the packet prompting the solicitation is the
00611        * same as one of the addresses assigned to the outgoing interface, that
00612        * address SHOULD be placed in the IP Source Address of the outgoing
00613        * solicitation.  Otherwise, any one of the addresses assigned to the
00614        * interface should be used."*/
00615        if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)){
00616           uip_nd6_ns_output(&UIP_IP_BUF->srcipaddr, NULL, &nbr->ipaddr);
00617         } else {
00618           uip_nd6_ns_output(NULL, NULL, &nbr->ipaddr);
00619         }
00620 
00621         stimer_set(&nbr->sendns, uip_ds6_if.retrans_timer / 1000);
00622         nbr->nscount = 1;
00623       }
00624     } else {
00625       if(nbr->state == NBR_INCOMPLETE) {
00626         PRINTF("tcpip_ipv6_output: nbr cache entry incomplete\n");
00627 #if UIP_CONF_IPV6_QUEUE_PKT
00628         /* Copy outgoing pkt in the queuing buffer for later transmit and set
00629            the destination nbr to nbr. */
00630         if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) {
00631           memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len);
00632           uip_packetqueue_set_buflen(&nbr->packethandle, uip_len);
00633         }
00634 #endif /*UIP_CONF_IPV6_QUEUE_PKT*/
00635         uip_len = 0;
00636         return;
00637       }
00638       /* Send in parallel if we are running NUD (nbc state is either STALE,
00639          DELAY, or PROBE). See RFC 4861, section 7.7.3 on node behavior. */
00640       if(nbr->state == NBR_STALE) {
00641         nbr->state = NBR_DELAY;
00642         stimer_set(&nbr->reachable, UIP_ND6_DELAY_FIRST_PROBE_TIME);
00643         nbr->nscount = 0;
00644         PRINTF("tcpip_ipv6_output: nbr cache entry stale moving to delay\n");
00645       }
00646 
00647       tcpip_output(&nbr->lladdr);
00648 
00649 #if UIP_CONF_IPV6_QUEUE_PKT
00650       /*
00651        * Send the queued packets from here, may not be 100% perfect though.
00652        * This happens in a few cases, for example when instead of receiving a
00653        * NA after sendiong a NS, you receive a NS with SLLAO: the entry moves
00654        * to STALE, and you must both send a NA and the queued packet.
00655        */
00656       if(uip_packetqueue_buflen(&nbr->packethandle) != 0) {
00657         uip_len = uip_packetqueue_buflen(&nbr->packethandle);
00658         memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len);
00659         uip_packetqueue_free(&nbr->packethandle);
00660         tcpip_output(&nbr->lladdr);
00661       }
00662 #endif /*UIP_CONF_IPV6_QUEUE_PKT*/
00663 
00664       uip_len = 0;
00665       return;
00666     }
00667   }
00668 
00669   /* Multicast IP destination address. */
00670   tcpip_output(NULL);
00671   uip_len = 0;
00672   uip_ext_len = 0;
00673 }
00674 #endif /* UIP_CONF_IPV6 */
00675 /*---------------------------------------------------------------------------*/
00676 #if UIP_UDP
00677 void
00678 tcpip_poll_udp(struct uip_udp_conn *conn)
00679 {
00680   process_post(&tcpip_process, UDP_POLL, conn);
00681 }
00682 #endif /* UIP_UDP */
00683 /*---------------------------------------------------------------------------*/
00684 #if UIP_TCP
00685 void
00686 tcpip_poll_tcp(struct uip_conn *conn)
00687 {
00688   process_post(&tcpip_process, TCP_POLL, conn);
00689 }
00690 #endif /* UIP_TCP */
00691 /*---------------------------------------------------------------------------*/
00692 void
00693 tcpip_uipcall(void)
00694 {
00695   register uip_udp_appstate_t *ts;
00696   
00697 #if UIP_UDP
00698   if(uip_conn != NULL) {
00699     ts = &uip_conn->appstate;
00700   } else {
00701     ts = &uip_udp_conn->appstate;
00702   }
00703 #else /* UIP_UDP */
00704   ts = &uip_conn->appstate;
00705 #endif /* UIP_UDP */
00706 
00707 #if UIP_TCP
00708  {
00709    static unsigned char i;
00710    register struct listenport *l;
00711    
00712    /* If this is a connection request for a listening port, we must
00713       mark the connection with the right process ID. */
00714    if(uip_connected()) {
00715      l = &s.listenports[0];
00716      for(i = 0; i < UIP_LISTENPORTS; ++i) {
00717        if(l->port == uip_conn->lport &&
00718           l->p != PROCESS_NONE) {
00719          ts->p = l->p;
00720          ts->state = NULL;
00721          break;
00722        }
00723        ++l;
00724      }
00725      
00726      /* Start the periodic polling, if it isn't already active. */
00727      start_periodic_tcp_timer();
00728    }
00729  }
00730 #endif /* UIP_TCP */
00731   
00732   if(ts->p != NULL) {
00733     process_post_synch(ts->p, tcpip_event, ts->state);
00734   }
00735 }
00736 /*---------------------------------------------------------------------------*/
00737 PROCESS_THREAD(tcpip_process, ev, data)
00738 {
00739   PROCESS_BEGIN();
00740   
00741 #if UIP_TCP
00742  {
00743    static unsigned char i;
00744    
00745    for(i = 0; i < UIP_LISTENPORTS; ++i) {
00746      s.listenports[i].port = 0;
00747    }
00748    s.p = PROCESS_CURRENT();
00749  }
00750 #endif
00751 
00752   tcpip_event = process_alloc_event();
00753 #if UIP_CONF_ICMP6
00754   tcpip_icmp6_event = process_alloc_event();
00755 #endif /* UIP_CONF_ICMP6 */
00756   etimer_set(&periodic, CLOCK_SECOND / 2);
00757 
00758   uip_init();
00759 #ifdef UIP_FALLBACK_INTERFACE
00760   UIP_FALLBACK_INTERFACE.init();
00761 #endif
00762 /* initialize RPL if configured for using RPL */
00763 #if UIP_CONF_IPV6_RPL
00764   rpl_init();
00765 #endif /* UIP_CONF_IPV6_RPL */
00766 
00767   while(1) {
00768     PROCESS_YIELD();
00769     eventhandler(ev, data);
00770   }
00771   
00772   PROCESS_END();
00773 }
00774 /*---------------------------------------------------------------------------*/