/*---------------------------------------------------------------------------*/ void uip_netif_sched_dad(struct uip_netif_addr *ifaddr) { if(ifaddr->state != TENTATIVE){ UIP_LOG("DAD called with non tentative address"); return; } /* * check dad is not running */ if(dad_ifaddr != NULL){ UIP_LOG("DAD already running"); return; } /* * Set the interface address that is going through DAD */ dad_ifaddr = ifaddr; PRINTF("Scheduling DAD for ipaddr:"); PRINT6ADDR(&dad_ifaddr->ipaddr); PRINTF("\n"); etimer_set(&uip_netif_timer_dad, random_rand()%(UIP_ND6_MAX_RTR_SOLICITATION_DELAY * CLOCK_SECOND)); }
/*---------------------------------------------------------------------------*/ void uip_netif_addr_add(uip_ipaddr_t *ipaddr, u8_t length, unsigned long vlifetime, uip_netif_type type) { /* check prefix has the right length if we are doing autoconf */ if((type == AUTOCONF) && (length != UIP_DEFAULT_PREFIX_LEN)) { UIP_LOG("Error: UNSUPPORTED PREFIX LENGTH"); return; } /* check if addr does not already exist and find a free entry */ for(i = 0; i < UIP_CONF_NETIF_MAX_ADDRESSES; ++i) { if(uip_netif_physical_if.addresses[i].state == NOT_USED){ /* * Copying address * If we are doing autoconf, ipaddr is a prefix, we copy the 128 bits * of it, then overwrite the last 64 bits with the interface ID at * next if statement. * Otherwise ipaddr is an address, we just copy it */ uip_ipaddr_copy(&uip_netif_physical_if.addresses[i].ipaddr, ipaddr); if(type == AUTOCONF) { /* construct address from prefix and layer2 id */ uip_netif_addr_autoconf_set(&uip_netif_physical_if.addresses[i].ipaddr, &uip_lladdr); } /* setting state, type */ uip_netif_physical_if.addresses[i].state = TENTATIVE; uip_netif_physical_if.addresses[i].type = type; /* setting lifetime timer if lieftime is not infinite */ if(vlifetime != 0) { stimer_set(&(uip_netif_physical_if.addresses[i].vlifetime), vlifetime); uip_netif_physical_if.addresses[i].is_infinite = 0; } else { uip_netif_physical_if.addresses[i].is_infinite = 1; } PRINTF("Created new address"); PRINT6ADDR(&uip_netif_physical_if.addresses[i].ipaddr); PRINTF("for interface\n"); /* schedule DAD */ uip_netif_sched_dad(&uip_netif_physical_if.addresses[i]); return; } } /* If we did not find space, log */ UIP_LOG("ADDRESS LIST FULL"); return; }
static s8_t tcpip_accept_func(void *arg,struct uip_tcp_pcb *newpcb,s8_t err) { s32_t s; struct tcpip_sock *ptr,*newsock = NULL; struct tcpip_sock *sock = (struct tcpip_sock*)arg; UIP_LOG("tcpip_accept_func()"); if(!sock) return UIP_ERR_ABRT; s = tcpip_allocsocket(newpcb); if(s<0) { uip_tcp_close(newpcb); return UIP_ERR_ABRT; } newsock = tcpip_getsocket(s); newsock->pcb->flags |= UIP_TF_NODELAY; ptr = tcpip_accepted_sockets; while(ptr && ptr->next) ptr = ptr->next; if(!ptr) tcpip_accepted_sockets = newsock; else ptr->next = newsock; uip_tcp_arg(newpcb,newsock); uip_tcp_recv(newpcb,tcpip_recved); uip_tcp_sent(newpcb,tcpip_sent); uip_tcp_err(newpcb,tcpip_err); uip_tcp_poll(newpcb,tcpip_poll,4); return UIP_ERR_OK; }
void DEBUG_Init(s32 device_type,s32 channel_port) { u32 level; struct uip_ip_addr localip,netmask,gateway; UIP_LOG("DEBUG_Init()\n"); __lwp_thread_dispatchdisable(); bp_init(); if(device_type==GDBSTUB_DEVICE_USB) { current_device = usb_init(channel_port); } else { localip.addr = uip_ipaddr((const u8_t*)tcp_localip); netmask.addr = uip_ipaddr((const u8_t*)tcp_netmask); gateway.addr = uip_ipaddr((const u8_t*)tcp_gateway); current_device = tcpip_init(&localip,&netmask,&gateway,(u16)channel_port); } if(current_device!=NULL) { _CPU_ISR_Disable(level); __exception_sethandler(EX_DSI,dbg_exceptionhandler); __exception_sethandler(EX_PRG,dbg_exceptionhandler); __exception_sethandler(EX_TRACE,dbg_exceptionhandler); __exception_sethandler(EX_IABR,dbg_exceptionhandler); _CPU_ISR_Restore(level); dbg_initialized = 1; } __lwp_thread_dispatchenable(); }
void tcpip_input(void) { if(inputfunc != NULL) { inputfunc(); } UIP_LOG("tcpip_input: Use tcpip_set_inputfunc() to set an input function"); }
/*---------------------------------------------------------------------------*/ void uip_netif_dad_failed(uip_ipaddr_t *ipaddr) { UIP_LOG("DAD FAILED"); UIP_LOG("THE STACK IS GOING TO SHUT DOWN"); UIP_LOG("THE HOST WILL BE UNREACHABLE"); if(uip_ipaddr_cmp(&dad_ifaddr->ipaddr, ipaddr)){ etimer_stop(&uip_netif_timer_dad); dad_ifaddr->state = NOT_USED; dad_ifaddr = NULL; dad_ns = 0; } exit(-1); }
uint8_t tcpip_output(void) { if(outputfunc != NULL) { return outputfunc(); } UIP_LOG("tcpip_output: Use tcpip_set_outputfunc() to set an output function"); return 0; }
uint8_t tcpip_output(struct net_buf *buf, const uip_lladdr_t *a) { if(outputfunc != NULL) { return outputfunc(buf, a); } UIP_LOG("tcpip_output: Use tcpip_set_outputfunc() to set an output function"); return 0; }
u8_t tcpip_output(uip_lladdr_t *a) { if(outputfunc != NULL) { return outputfunc(a); } UIP_LOG("tcpip_output: Use tcpip_set_outputfunc() to set an output function"); return 0; }
uint8_t tcpip_output(const uip_lladdr_t *a) { int ret; if(outputfunc != NULL) { ret = outputfunc(a); return ret; } UIP_LOG("tcpip_output: Use tcpip_set_outputfunc() to set an output function"); return 0; }
/*---------------------------------------------------------------------------*/ void uip_netif_addr_autoconf_set(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr) { /* We consider only links with IEEE EUI-64 identifier or IEEE 48-bit MAC addresses */ #if (UIP_LLADDR_LEN == 8) memcpy(ipaddr->u8 + 8, lladdr, UIP_LLADDR_LEN); ipaddr->u8[8] ^= 0x02; #elif (UIP_LLADDR_LEN == 6) memcpy(ipaddr->u8 + 8, lladdr, 3); ipaddr->u8[11] = 0xff; ipaddr->u8[12] = 0xfe; memcpy(ipaddr->u8 + 13, (u8_t*)lladdr + 3, 3); ipaddr->u8[8] ^= 0x02; #else UIP_LOG("CAN NOT BUIL INTERFACE IDENTIFIER"); UIP_LOG("THE STACK IS GOING TO SHUT DOWN"); UIP_LOG("THE HOST WILL BE UNREACHABLE"); exit(-1); #endif }
uint8_t tcpip_output(const uip_lladdr_t *a) { PRINTF("TCP IP OUTPUT.\n"); int ret; if(outputfunc != NULL) { ret = outputfunc(a); return ret; } PRINTF("TCP IP OUTPUT. NO Func\n"); UIP_LOG("tcpip_output: Use tcpip_set_outputfunc() to set an output function"); return 0; }
s8_t uip_ipinput(struct uip_pbuf *p,struct uip_netif *inp) { u16_t iphdr_len; struct uip_ip_hdr *iphdr; struct uip_netif *netif; iphdr = p->payload; if(UIP_IPH_V(iphdr)!=4) { UIP_ERROR("uip_ipinput: ip packet dropped due to bad version number.\n"); uip_pbuf_free(p); return 0; } iphdr_len = UIP_IPH_HL(iphdr); iphdr_len *= 4; if(iphdr_len>p->len) { UIP_ERROR("uip_ipinput: ip packet dropped due to too small packet size.\n"); uip_pbuf_free(p); return 0; } if(uip_ipchksum(iphdr,iphdr_len)!=0) { UIP_STAT(++uip_stat.ip.drop); UIP_STAT(++uip_stat.ip.chkerr); UIP_ERROR("uip_ipinput: bad checksum.\n"); uip_pbuf_free(p); return 0; } uip_pbuf_realloc(p,ntohs(UIP_IPH_LEN(iphdr))); for(netif=uip_netif_list;netif!=NULL;netif=netif->next) { if(uip_netif_isup(netif) && !ip_addr_isany(&netif->ip_addr)) { if(ip_addr_cmp(&iphdr->dst,&netif->ip_addr) || ip_addr_isbroadcast(&iphdr->dst,netif)) break; } } if(!netif) { UIP_ERROR("uip_ipinput: no route found.\n"); uip_pbuf_free(p); return 0; } if((UIP_IPH_OFFSET(iphdr)&htons(UIP_IP_OFFMASK|UIP_IP_MF))!=0) { #if UIP_IP_REASSEMBLY p = uip_ipreass(p); if(p==NULL) return UIP_ERR_OK; iphdr = (struct uip_ip_hdr*)p->payload; #else uip_pbuf_free(p); UIP_STAT(++uip_stat.ip.drop); UIP_ERROR("ip: fragment dropped.\n"); return 0; #endif } switch(UIP_IPH_PROTO(iphdr)) { case UIP_PROTO_TCP: uip_tcpinput(p,inp); break; case UIP_PROTO_ICMP: uip_icmpinput(p,inp); break; default: UIP_LOG("uip_ipinput: Unsupported protocol.\n"); if(!ip_addr_isbroadcast(&(iphdr->dst),inp) && !ip_addr_ismulticast(&(iphdr->dst))) { p->payload = iphdr; uip_icmp_destunreach(p,UIP_ICMP_DUR_PROTO); } uip_pbuf_free(p); break; } return 0; }
void tcpip_ipv6_output(void) { uip_ds6_nbr_t *nbr = NULL; uip_ipaddr_t* nexthop; if(uip_len == 0) { return; } if(uip_len > UIP_LINK_MTU) { UIP_LOG("tcpip_ipv6_output: Packet to big"); uip_len = 0; return; } if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)){ UIP_LOG("tcpip_ipv6_output: Destination address unspecified"); uip_len = 0; return; } if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { /* Next hop determination */ nbr = NULL; if(uip_ds6_is_addr_onlink(&UIP_IP_BUF->destipaddr)){ nexthop = &UIP_IP_BUF->destipaddr; } else { uip_ds6_route_t* locrt; locrt = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr); if(locrt == NULL) { if((nexthop = uip_ds6_defrt_choose()) == NULL) { #ifdef UIP_FALLBACK_INTERFACE UIP_FALLBACK_INTERFACE.output(); #else PRINTF("tcpip_ipv6_output: Destination off-link but no route\n"); #endif uip_len = 0; return; } } else { nexthop = &locrt->nexthop; } } /* end of next hop determination */ // if((nbr = uip_ds6_nbr_lookup(nexthop)) == NULL) { if(0){ /* * I-D.ietf.6lowpan-nd 5.7: As all prefixes but the link-local prefix are * always assumed to be off-link, multicast-based address resolution between * neighbors is not needed. * In addition, there are neither INCOMPLETE, STALE, DELAY, nor PROBE NCEs * in 6LoWPAN-ND. */ return; } else { tcpip_output(&(nbr->lladdr)); uip_len = 0; return; } } /*multicast IP destination address */ tcpip_output(NULL); uip_len = 0; uip_ext_len = 0; }
void tcpip_ipv6_output(void) { uip_ds6_nbr_t *nbr = NULL; uip_ipaddr_t *nexthop; if(uip_len == 0) { return; } if(uip_len > UIP_LINK_MTU) { UIP_LOG("tcpip_ipv6_output: Packet to big"); uip_clear_buf(); return; } if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)){ UIP_LOG("tcpip_ipv6_output: Destination address unspecified"); uip_clear_buf(); return; } if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { /* Next hop determination */ nbr = NULL; /* We first check if the destination address is on our immediate link. If so, we simply use the destination address as our nexthop address. */ if(uip_ds6_is_addr_onlink(&UIP_IP_BUF->destipaddr)){ nexthop = &UIP_IP_BUF->destipaddr; } else { uip_ds6_route_t *route; /* Check if we have a route to the destination address. */ route = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr); /* No route was found - we send to the default route instead. */ if(route == NULL) { PRINTF("tcpip_ipv6_output: no route found, using default route\n"); nexthop = uip_ds6_defrt_choose(); if(nexthop == NULL) { #ifdef UIP_FALLBACK_INTERFACE PRINTF("FALLBACK: removing ext hdrs & setting proto %d %d\n", uip_ext_len, *((uint8_t *)UIP_IP_BUF + 40)); if(uip_ext_len > 0) { extern void remove_ext_hdr(void); uint8_t proto = *((uint8_t *)UIP_IP_BUF + 40); remove_ext_hdr(); /* This should be copied from the ext header... */ UIP_IP_BUF->proto = proto; } /* Inform the other end that the destination is not reachable. If it's * not informed routes might get lost unexpectedly until there's a need * to send a new packet to the peer */ if(UIP_FALLBACK_INTERFACE.output() < 0) { PRINTF("FALLBACK: output error. Reporting DST UNREACH\n"); uip_icmp6_error_output(ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR, 0); uip_flags = 0; tcpip_ipv6_output(); return; } #else PRINTF("tcpip_ipv6_output: Destination off-link but no route\n"); #endif /* !UIP_FALLBACK_INTERFACE */ uip_clear_buf(); return; } } else { /* A route was found, so we look up the nexthop neighbor for the route. */ nexthop = uip_ds6_route_nexthop(route); /* If the nexthop is dead, for example because the neighbor never responded to link-layer acks, we drop its route. */ if(nexthop == NULL) { #if UIP_CONF_IPV6_RPL /* If we are running RPL, and if we are the root of the network, we'll trigger a global repair berfore we remove the route. */ rpl_dag_t *dag; rpl_instance_t *instance; dag = (rpl_dag_t *)route->state.dag; if(dag != NULL) { instance = dag->instance; rpl_repair_root(instance->instance_id); } #endif /* UIP_CONF_IPV6_RPL */ uip_ds6_route_rm(route); /* We don't have a nexthop to send the packet to, so we drop it. */ return; } } #if TCPIP_CONF_ANNOTATE_TRANSMISSIONS if(nexthop != NULL) { static uint8_t annotate_last; static uint8_t annotate_has_last = 0; if(annotate_has_last) { printf("#L %u 0; red\n", annotate_last); } printf("#L %u 1; red\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]); annotate_last = nexthop->u8[sizeof(uip_ipaddr_t) - 1]; annotate_has_last = 1; } #endif /* TCPIP_CONF_ANNOTATE_TRANSMISSIONS */ } /* End of next hop determination */ #if UIP_CONF_IPV6_RPL if(rpl_update_header_final(nexthop)) { uip_clear_buf(); return; } #endif /* UIP_CONF_IPV6_RPL */ nbr = uip_ds6_nbr_lookup(nexthop); if(nbr == NULL) { #if UIP_ND6_SEND_NA if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE)) == NULL) { uip_clear_buf(); return; } else { #if UIP_CONF_IPV6_QUEUE_PKT /* Copy outgoing pkt in the queuing buffer for later transmit. */ if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) { memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len); uip_packetqueue_set_buflen(&nbr->packethandle, uip_len); } #endif /* RFC4861, 7.2.2: * "If the source address of the packet prompting the solicitation is the * same as one of the addresses assigned to the outgoing interface, that * address SHOULD be placed in the IP Source Address of the outgoing * solicitation. Otherwise, any one of the addresses assigned to the * interface should be used."*/ if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)){ uip_nd6_ns_output(&UIP_IP_BUF->srcipaddr, NULL, &nbr->ipaddr); } else { uip_nd6_ns_output(NULL, NULL, &nbr->ipaddr); } stimer_set(&nbr->sendns, uip_ds6_if.retrans_timer / 1000); nbr->nscount = 1; /* Send the first NS try from here (multicast destination IP address). */ } #else /* UIP_ND6_SEND_NA */ uip_len = 0; return; #endif /* UIP_ND6_SEND_NA */ } else { #if UIP_ND6_SEND_NA if(nbr->state == NBR_INCOMPLETE) { PRINTF("tcpip_ipv6_output: nbr cache entry incomplete\n"); #if UIP_CONF_IPV6_QUEUE_PKT /* Copy outgoing pkt in the queuing buffer for later transmit and set the destination nbr to nbr. */ if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) { memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len); uip_packetqueue_set_buflen(&nbr->packethandle, uip_len); } #endif /*UIP_CONF_IPV6_QUEUE_PKT*/ uip_clear_buf(); return; } /* Send in parallel if we are running NUD (nbc state is either STALE, DELAY, or PROBE). See RFC 4861, section 7.3.3 on node behavior. */ if(nbr->state == NBR_STALE) { nbr->state = NBR_DELAY; stimer_set(&nbr->reachable, UIP_ND6_DELAY_FIRST_PROBE_TIME); nbr->nscount = 0; PRINTF("tcpip_ipv6_output: nbr cache entry stale moving to delay\n"); } #endif /* UIP_ND6_SEND_NA */ tcpip_output(uip_ds6_nbr_get_ll(nbr)); #if UIP_CONF_IPV6_QUEUE_PKT /* * Send the queued packets from here, may not be 100% perfect though. * This happens in a few cases, for example when instead of receiving a * NA after sendiong a NS, you receive a NS with SLLAO: the entry moves * to STALE, and you must both send a NA and the queued packet. */ if(uip_packetqueue_buflen(&nbr->packethandle) != 0) { uip_len = uip_packetqueue_buflen(&nbr->packethandle); memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len); uip_packetqueue_free(&nbr->packethandle); tcpip_output(uip_ds6_nbr_get_ll(nbr)); } #endif /*UIP_CONF_IPV6_QUEUE_PKT*/ uip_clear_buf(); return; } } /* Multicast IP destination address. */ tcpip_output(NULL); uip_clear_buf(); }
void tcpip_ipv6_output(void) { struct uip_nd6_neighbor *nbc = NULL; struct uip_nd6_defrouter *dr = NULL; if(uip_len == 0) return; if(uip_len > UIP_LINK_MTU){ UIP_LOG("tcpip_ipv6_output: Packet to big"); uip_len = 0; return; } if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)){ UIP_LOG("tcpip_ipv6_output: Destination address unspecified"); uip_len = 0; return; } if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { /*If destination is on link */ nbc = NULL; if(uip_nd6_is_addr_onlink(&UIP_IP_BUF->destipaddr)){ nbc = uip_nd6_nbrcache_lookup(&UIP_IP_BUF->destipaddr); } else { #if UIP_CONF_ROUTER /*destination is not on link*/ uip_ipaddr_t ipaddr; uip_ipaddr_t *next_hop; /* Try to find the next hop address in the local routing table. */ next_hop = uip_router != NULL ? uip_router->lookup(&UIP_IP_BUF->destipaddr, &ipaddr) : NULL; if(next_hop != NULL) { /* Look for the next hop of the route in the neighbor cache. Add a cache entry if we can't find it. */ nbc = uip_nd6_nbrcache_lookup(next_hop); if(nbc == NULL) { nbc = uip_nd6_nbrcache_add(next_hop, NULL, 1, NO_STATE); } } else { #endif /* UIP_CONF_ROUTER */ /* No route found, check if a default router exists and use it then. */ dr = uip_nd6_choose_defrouter(); if(dr != NULL){ nbc = dr->nb; } else { /* shall we send a icmp error message destination unreachable ?*/ UIP_LOG("tcpip_ipv6_output: Destination off-link but no router"); uip_len = 0; return; } #if UIP_CONF_ROUTER } #endif /* UIP_CONF_ROUTER */ } /* there are two cases where the entry logically does not exist: * 1 it really does not exist. 2 it is in the NO_STATE state */ if (nbc == NULL || nbc->state == NO_STATE) { if (nbc == NULL) { /* create neighbor cache entry, original packet is replaced by NS*/ nbc = uip_nd6_nbrcache_add(&UIP_IP_BUF->destipaddr, NULL, 0, INCOMPLETE); } else { nbc->state = INCOMPLETE; } #if UIP_CONF_IPV6_QUEUE_PKT /* copy outgoing pkt in the queuing buffer for later transmmit */ memcpy(nbc->queue_buf, UIP_IP_BUF, uip_len); nbc->queue_buf_len = uip_len; #endif /* RFC4861, 7.2.2: * "If the source address of the packet prompting the solicitation is the * same as one of the addresses assigned to the outgoing interface, that * address SHOULD be placed in the IP Source Address of the outgoing * solicitation. Otherwise, any one of the addresses assigned to the * interface should be used."*/ if(uip_netif_is_addr_my_unicast(&UIP_IP_BUF->srcipaddr)){ uip_nd6_io_ns_output(&UIP_IP_BUF->srcipaddr, NULL, &nbc->ipaddr); } else { uip_nd6_io_ns_output(NULL, NULL, &nbc->ipaddr); } stimer_set(&(nbc->last_send), uip_netif_physical_if.retrans_timer / 1000); nbc->count_send = 1; } else { if (nbc->state == INCOMPLETE){ PRINTF("tcpip_ipv6_output: neighbor cache entry incomplete\n"); #if UIP_CONF_IPV6_QUEUE_PKT /* copy outgoing pkt in the queuing buffer for later transmmit and set the destination neighbor to nbc */ memcpy(nbc->queue_buf, UIP_IP_BUF, uip_len); nbc->queue_buf_len = uip_len; uip_len = 0; #endif /*UIP_CONF_IPV6_QUEUE_PKT*/ return; } /* if running NUD (nbc->state == STALE, DELAY, or PROBE ) keep sending in parallel see rfc 4861 Node behavior in section 7.7.3*/ if (nbc->state == STALE){ nbc->state = DELAY; stimer_set(&(nbc->reachable), UIP_ND6_DELAY_FIRST_PROBE_TIME); PRINTF("tcpip_ipv6_output: neighbor cache entry stale moving to delay\n"); } stimer_set(&(nbc->last_send), uip_netif_physical_if.retrans_timer / 1000); tcpip_output(&(nbc->lladdr)); #if UIP_CONF_IPV6_QUEUE_PKT /* Send the queued packets from here, may not be 100% perfect though. * This happens in a few cases, for example when instead of receiving a * NA after sendiong a NS, you receive a NS with SLLAO: the entry moves *to STALE, and you must both send a NA and the queued packet */ if(nbc->queue_buf_len != 0) { uip_len = nbc->queue_buf_len; memcpy(UIP_IP_BUF, nbc->queue_buf, uip_len); nbc->queue_buf_len = 0; tcpip_output(&(nbc->lladdr)); } #endif /*UIP_CONF_IPV6_QUEUE_PKT*/ uip_len = 0; return; } } /*multicast IP destination address */ tcpip_output(NULL); uip_len = 0; uip_ext_len = 0; }
void tcpip_ipv6_output(void) { uip_ds6_nbr_t *nbr = NULL; uip_ipaddr_t *nexthop; if(uip_len == 0) { return; } if(uip_len > UIP_LINK_MTU) { UIP_LOG("tcpip_ipv6_output: Packet to big"); uip_len = 0; return; } if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)) { UIP_LOG("tcpip_ipv6_output: Destination address unspecified"); uip_len = 0; return; } if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { /* Next hop determination */ nbr = NULL; if(uip_ds6_is_addr_onlink(&UIP_IP_BUF->destipaddr)) { nexthop = &UIP_IP_BUF->destipaddr; } else { uip_ds6_route_t* locrt; locrt = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr); if(locrt == NULL) { if((nexthop = uip_ds6_defrt_choose()) == NULL) { #ifdef UIP_FALLBACK_INTERFACE PRINTF("FALLBACK: removing ext hdrs & setting proto %d %d\n", uip_ext_len, *((uint8_t *)UIP_IP_BUF + 40)); if(uip_ext_len > 0) { extern void remove_ext_hdr(void); uint8_t proto = *((uint8_t *)UIP_IP_BUF + 40); remove_ext_hdr(); /* This should be copied from the ext header... */ UIP_IP_BUF->proto = proto; } UIP_FALLBACK_INTERFACE.output(); #else PRINTF("tcpip_ipv6_output: Destination off-link but no route\n"); #endif /* !UIP_FALLBACK_INTERFACE */ uip_len = 0; return; } } else { nexthop = &locrt->nexthop; } #if TCPIP_CONF_ANNOTATE_TRANSMISSIONS if(nexthop != NULL) { printf("#L %u 1; red\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]); } #endif /* TCPIP_CONF_ANNOTATE_TRANSMISSIONS */ } /* End of next hop determination */ #if UIP_CONF_IPV6_RPL if(rpl_update_header_final(nexthop)) { uip_len = 0; return; } #endif /* UIP_CONF_IPV6_RPL */ if((nbr = uip_ds6_nbr_lookup(nexthop)) == NULL) { #if UIP_ND6_SEND_NA if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE)) == NULL) { uip_len = 0; return; } else { #if UIP_CONF_IPV6_QUEUE_PKT /* Copy outgoing pkt in the queuing buffer for later transmit. */ if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) { memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len); uip_packetqueue_set_buflen(&nbr->packethandle, uip_len); } #endif /* RFC4861, 7.2.2: * "If the source address of the packet prompting the solicitation is the * same as one of the addresses assigned to the outgoing interface, that * address SHOULD be placed in the IP Source Address of the outgoing * solicitation. Otherwise, any one of the addresses assigned to the * interface should be used."*/ if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)) { uip_nd6_ns_output(&UIP_IP_BUF->srcipaddr, NULL, &nbr->ipaddr); } else { uip_nd6_ns_output(NULL, NULL, &nbr->ipaddr); } stimer_set(&nbr->sendns, uip_ds6_if.retrans_timer / 1000); nbr->nscount = 1; } #endif /* UIP_ND6_SEND_NA */ } else { #if UIP_ND6_SEND_NA if(nbr->state == NBR_INCOMPLETE) { PRINTF("tcpip_ipv6_output: nbr cache entry incomplete\n"); #if UIP_CONF_IPV6_QUEUE_PKT /* Copy outgoing pkt in the queuing buffer for later transmit and set the destination nbr to nbr. */ if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) { memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len); uip_packetqueue_set_buflen(&nbr->packethandle, uip_len); } #endif /*UIP_CONF_IPV6_QUEUE_PKT*/ uip_len = 0; return; } /* Send in parallel if we are running NUD (nbc state is either STALE, DELAY, or PROBE). See RFC 4861, section 7.7.3 on node behavior. */ if(nbr->state == NBR_STALE) { nbr->state = NBR_DELAY; stimer_set(&nbr->reachable, UIP_ND6_DELAY_FIRST_PROBE_TIME); nbr->nscount = 0; PRINTF("tcpip_ipv6_output: nbr cache entry stale moving to delay\n"); } #endif /* UIP_ND6_SEND_NA */ tcpip_output(&nbr->lladdr); #if UIP_CONF_IPV6_QUEUE_PKT /* * Send the queued packets from here, may not be 100% perfect though. * This happens in a few cases, for example when instead of receiving a * NA after sendiong a NS, you receive a NS with SLLAO: the entry moves * to STALE, and you must both send a NA and the queued packet. */ if(uip_packetqueue_buflen(&nbr->packethandle) != 0) { uip_len = uip_packetqueue_buflen(&nbr->packethandle); memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len); uip_packetqueue_free(&nbr->packethandle); tcpip_output(&nbr->lladdr); } #endif /*UIP_CONF_IPV6_QUEUE_PKT*/ uip_len = 0; return; } } /* Multicast IP destination address. */ tcpip_output(NULL); uip_len = 0; uip_ext_len = 0; }
/*---------------------------------------------------------------------------*/ static uint8_t send_packet(struct net_buf *buf, mac_callback_t sent, bool last_fragment, void *ptr) { struct rdc_buf_list *q; struct neighbor_queue *n; static uint8_t initialized = 0; static uint16_t seqno; const linkaddr_t *addr = packetbuf_addr(buf, PACKETBUF_ADDR_RECEIVER); if (!buf) { UIP_LOG("csma: send_packet(): net_buf is NULL, cannot send packet"); return 0; } if(!initialized) { initialized = 1; /* Initialize the sequence number to a random value as per 802.15.4. */ seqno = random_rand(); } if(seqno == 0) { /* PACKETBUF_ATTR_MAC_SEQNO cannot be zero, due to a pecuilarity in framer-802154.c. */ seqno++; } packetbuf_set_attr(buf, PACKETBUF_ATTR_MAC_SEQNO, seqno++); /* Look for the neighbor entry */ n = neighbor_queue_from_addr(buf, addr); if(n == NULL) { /* Allocate a new neighbor entry */ n = memb_alloc(&neighbor_memb); if(n != NULL) { /* Init neighbor entry */ linkaddr_copy(&n->addr, addr); n->transmissions = 0; n->collisions = 0; n->deferrals = 0; /* Init packet list for this neighbor */ LIST_STRUCT_INIT(n, queued_packet_list); /* Add neighbor to the list */ list_add(uip_neighbor_list(buf), n); } } if(n != NULL) { /* Add packet to the neighbor's queue */ if(list_length(n->queued_packet_list) < CSMA_MAX_PACKET_PER_NEIGHBOR) { q = memb_alloc(&packet_memb); if(q != NULL) { q->ptr = memb_alloc(&metadata_memb); if(q->ptr != NULL) { q->buf = queuebuf_new_from_packetbuf(buf); if(q->buf != NULL) { struct qbuf_metadata *metadata = (struct qbuf_metadata *)q->ptr; /* Neighbor and packet successfully allocated */ if(packetbuf_attr(buf, PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS) == 0) { /* Use default configuration for max transmissions */ metadata->max_transmissions = CSMA_MAX_MAC_TRANSMISSIONS; } else { metadata->max_transmissions = packetbuf_attr(buf, PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS); } metadata->sent = sent; metadata->cptr = ptr; if(packetbuf_attr(buf, PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_ACK) { list_push(n->queued_packet_list, q); } else { list_add(n->queued_packet_list, q); } PRINTF("csma: send_packet, queue length %d, free packets %d\n", list_length(n->queued_packet_list), memb_numfree(&packet_memb)); /* if received packet is last fragment/only one packet start sending * packets in list, do not start any timer.*/ if (last_fragment) { transmit_packet_list(buf, n); } return 1; } memb_free(&metadata_memb, q->ptr); PRINTF("csma: could not allocate queuebuf, dropping packet\n"); } memb_free(&packet_memb, q); PRINTF("csma: could not allocate queuebuf, dropping packet\n"); } /* The packet allocation failed. Remove and free neighbor entry if empty. */ if(list_length(n->queued_packet_list) == 0) { list_remove(uip_neighbor_list(buf), n); memb_free(&neighbor_memb, n); } } else { PRINTF("csma: Neighbor queue full\n"); } PRINTF("csma: could not allocate packet, dropping packet\n"); } else { PRINTF("csma: could not allocate neighbor, dropping packet\n"); } mac_call_sent_callback(buf, sent, ptr, MAC_TX_ERR, 1); return 0; }
/*------------------------------------------------------------------*/ void uip_nd6_io_ns_input(void) { PRINTF("Received NS from"); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF("to"); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF("with target address"); PRINT6ADDR((uip_ipaddr_t *)(&UIP_ND6_NS_BUF->tgtipaddr)); PRINTF("\n"); UIP_STAT(++uip_stat.nd6.recv); u8_t flags; #if UIP_CONF_IPV6_CHECKS if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) || (uip_is_addr_mcast(&UIP_ND6_NS_BUF->tgtipaddr)) || (UIP_ICMP_BUF->icode != 0)) { goto badpkt; } #endif /* UIP_CONF_IPV6_CHECKS */ /* Options reading: we handle only SLLAO for now */ nd6_opt_llao = NULL; nd6_opt_offset = UIP_ND6_NS_LEN; while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) { #if UIP_CONF_IPV6_CHECKS if(UIP_ND6_OPT_HDR_BUF->len == 0) { goto badpkt; } #endif /* UIP_CONF_IPV6_CHECKS */ switch(UIP_ND6_OPT_HDR_BUF->type) { case UIP_ND6_OPT_SLLAO: nd6_opt_llao = (struct uip_nd6_opt_llao *)UIP_ND6_OPT_HDR_BUF; break; default: UIP_LOG("ND option not supported in NS"); break; } nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3); } /* Options processing: only SLLAO */ if(nd6_opt_llao != NULL) { #if UIP_CONF_IPV6_CHECKS /* There must be NO option in a DAD NS */ if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) { goto badpkt; } else { #endif /*UIP_CONF_IPV6_CHECKS*/ neighbor = uip_nd6_nbrcache_lookup(&UIP_IP_BUF->srcipaddr); if(neighbor == NULL) { /* we need to add the neighbor*/ uip_nd6_nbrcache_add(&UIP_IP_BUF->srcipaddr, &nd6_opt_llao->addr, 0, STALE); } else { /* If LL address changed, set neighbor state to stale */ if(memcmp(&nd6_opt_llao->addr, &neighbor->lladdr, UIP_LLADDR_LEN) != 0) { memcpy(&neighbor->lladdr, &nd6_opt_llao->addr, UIP_LLADDR_LEN); neighbor->state = STALE; } else { /* If neighbor state is INCOMPLETE, set to STALE */ if(neighbor->state == INCOMPLETE) { neighbor->state = STALE; } } } #if UIP_CONF_IPV6_CHECKS } #endif /*UIP_CONF_IPV6_CHECKS*/ } /* * Rest of NS processing: Depends on the purpose of the NS: NUD or DAD or * Address Resolution */ /** \note we use ifaddr to remember the target address */ ifaddr = uip_netif_addr_lookup(&UIP_ND6_NS_BUF->tgtipaddr, 128, 0); if(ifaddr != NULL) { if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)){ /* DAD CASE */ #if UIP_CONF_IPV6_CHECKS /* Dst address must be solicited node mcast address */ if(!uip_netif_is_addr_my_solicited(&UIP_IP_BUF->destipaddr)){ goto badpkt; } #endif /* UIP_CONF_IPV6_CHECKS */ /* * If my address is not tentative, then send a NA to all nodes with * TLLAO flags are: override = yes. */ if(ifaddr->state!=TENTATIVE) { /* * we need to send a NA, we set the src, dest, flags. tgt remains the * same and the rest is done at "create_na" */ uip_create_linklocal_allnodes_mcast(&UIP_IP_BUF->destipaddr); uip_netif_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); flags = UIP_ND6_NA_FLAG_OVERRIDE; goto create_na; } else { /** \todo if I sent a NS before him, I win */ uip_netif_dad_failed(&UIP_ND6_NS_BUF->tgtipaddr); goto discard; } } #if UIP_CONF_IPV6_CHECKS /* Duplicate check */ if(uip_netif_is_addr_my_unicast(&UIP_IP_BUF->srcipaddr)) { /** * \NOTE do we do something here? we both are using the same address. * If we are doing dad, we could cancel it, though we should receive a * NA in response of DAD NS we sent, hence DAD will fail anyway. If we * were not doing DAD, it means there is a duplicate in the network! */ goto badpkt; } #endif /*UIP_CONF_IPV6_CHECKS*/ /* Address resolution case */ if(uip_netif_is_addr_my_solicited(&UIP_IP_BUF->destipaddr)){ /* * we need to send a NA, we set the src, dest, flags. The rest is * set at the "create_na" label. */ uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr); uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &UIP_ND6_NS_BUF->tgtipaddr); flags = UIP_ND6_NA_FLAG_SOLICITED | UIP_ND6_NA_FLAG_OVERRIDE; goto create_na; } /* * NUD CASE. at this point the packet must be for us! we check this, * and at the same time if target == dest */ if(uip_netif_addr_lookup(&UIP_IP_BUF->destipaddr, 128, 0) == ifaddr){ /* * we need to send a NA, we set the src, dest, flags. The rest is set * at the "create_na" label. */ uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr); uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &UIP_ND6_NS_BUF->tgtipaddr); flags = UIP_ND6_NA_FLAG_SOLICITED | UIP_ND6_NA_FLAG_OVERRIDE; goto create_na; } else { #if UIP_CONF_IPV6_CHECKS goto badpkt; #endif /* UIP_CONF_IPV6_CHECKS */ } } else { goto discard; } create_na: /* * Fill the part of the NA which is common to all NAs. If the NS contained * extension headers, we must set the target address properly */ uip_ext_len = 0; /* IP header */ UIP_IP_BUF->vtc = 0x60; UIP_IP_BUF->tcflow = 0; UIP_IP_BUF->flow = 0; UIP_IP_BUF->len[0] = 0; /* length will not be more than 255 */ UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN; UIP_IP_BUF->proto = UIP_PROTO_ICMP6; UIP_IP_BUF->ttl = UIP_ND6_HOP_LIMIT; /* ICMP header */ UIP_ICMP_BUF->type = ICMP6_NA; UIP_ICMP_BUF->icode = 0; /* NA static part */ UIP_ND6_NA_BUF->flagsreserved = flags; memcpy(&UIP_ND6_NA_BUF->tgtipaddr, &ifaddr->ipaddr, sizeof(uip_ipaddr_t)); /* NA option: TLLAO. note that length field is in unit of 8 bytes */ uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN; nd6_opt_llao = (struct uip_nd6_opt_llao *)&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_NA_LEN]; nd6_opt_llao->type = UIP_ND6_OPT_TLLAO; nd6_opt_llao->len = UIP_ND6_OPT_LLAO_LEN >> 3; memcpy(&(nd6_opt_llao->addr), &uip_lladdr, UIP_LLADDR_LEN); /* padding if needed */ memset((void *)(&nd6_opt_llao->addr) + UIP_LLADDR_LEN, 0, UIP_ND6_OPT_LLAO_LEN - 2 - UIP_LLADDR_LEN); /*ICMP checksum*/ UIP_ICMP_BUF->icmpchksum = 0; UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); UIP_STAT(++uip_stat.nd6.sent); PRINTF("Sending NA to"); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF("from"); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF("with target address"); PRINT6ADDR(&UIP_ND6_NA_BUF->tgtipaddr); PRINTF("\n"); return; #if UIP_CONF_IPV6_CHECKS badpkt: UIP_STAT(++uip_stat.nd6.drop); UIP_LOG("NS received is bad"); #endif /* UIP_CONF_IPV6_CHECKS */ discard: uip_len = 0; return; }
void tcpip_ipv6_output(void) { static uip_ds6_nbr_t *nbr = NULL; static uip_ipaddr_t* nexthop; if(uip_len == 0) { return; } if(uip_len > UIP_LINK_MTU) { UIP_LOG("tcpip_ipv6_output: Packet to big"); uip_len = 0; return; } if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)) { UIP_LOG("tcpip_ipv6_output: Destination address unspecified"); uip_len = 0; return; } if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { /* Next hop determination */ nbr = NULL; if(uip_ds6_is_addr_onlink(&UIP_IP_BUF->destipaddr)) { nexthop = &UIP_IP_BUF->destipaddr; } else { uip_ds6_route_t* locrt; locrt = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr); if(locrt == NULL) { if((nexthop = uip_ds6_defrt_choose()) == NULL) { #ifdef UIP_FALLBACK_INTERFACE UIP_FALLBACK_INTERFACE.output(); #else PRINTF("tcpip_ipv6_output: Destination off-link but no route\n"); #endif uip_len = 0; return; } } else { nexthop = &locrt->nexthop; } } /* end of next hop determination */ if((nbr = uip_ds6_nbr_lookup(nexthop)) == NULL) { // printf("add1 %d\n", nexthop->u8[15]); if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE)) == NULL) { // printf("add n\n"); uip_len = 0; return; } else { #if UIP_CONF_IPV6_QUEUE_PKT /* copy outgoing pkt in the queuing buffer for later transmmit */ if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) { memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len); uip_packetqueue_set_buflen(&nbr->packethandle, uip_len); } #endif /* RFC4861, 7.2.2: * "If the source address of the packet prompting the solicitation is the * same as one of the addresses assigned to the outgoing interface, that * address SHOULD be placed in the IP Source Address of the outgoing * solicitation. Otherwise, any one of the addresses assigned to the * interface should be used."*/ if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)) { uip_nd6_ns_output(&UIP_IP_BUF->srcipaddr, NULL, &nbr->ipaddr); } else { uip_nd6_ns_output(NULL, NULL, &nbr->ipaddr); } stimer_set(&(nbr->sendns), uip_ds6_if.retrans_timer / 1000); nbr->nscount = 1; } } else { if(nbr->state == NBR_INCOMPLETE) { PRINTF("tcpip_ipv6_output: nbr cache entry incomplete\n"); #if UIP_CONF_IPV6_QUEUE_PKT /* copy outgoing pkt in the queuing buffer for later transmmit and set the destination nbr to nbr */ if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) { memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len); uip_packetqueue_set_buflen(&nbr->packethandle, uip_len); } /* memcpy(nbr->queue_buf, UIP_IP_BUF, uip_len); nbr->queue_buf_len = uip_len;*/ uip_len = 0; #endif /*UIP_CONF_IPV6_QUEUE_PKT*/ return; } /* if running NUD (nbc->state == STALE, DELAY, or PROBE ) keep sending in parallel see rfc 4861 Node behavior in section 7.7.3*/ if(nbr->state == NBR_STALE) { nbr->state = NBR_DELAY; stimer_set(&(nbr->reachable), UIP_ND6_DELAY_FIRST_PROBE_TIME); nbr->nscount = 0; PRINTF("tcpip_ipv6_output: nbr cache entry stale moving to delay\n"); } stimer_set(&(nbr->sendns), uip_ds6_if.retrans_timer / 1000); tcpip_output(&(nbr->lladdr)); #if UIP_CONF_IPV6_QUEUE_PKT /* Send the queued packets from here, may not be 100% perfect though. * This happens in a few cases, for example when instead of receiving a * NA after sendiong a NS, you receive a NS with SLLAO: the entry moves *to STALE, and you must both send a NA and the queued packet */ /* if(nbr->queue_buf_len != 0) { uip_len = nbr->queue_buf_len; memcpy(UIP_IP_BUF, nbr->queue_buf, uip_len); nbr->queue_buf_len = 0; tcpip_output(&(nbr->lladdr)); }*/ if(uip_packetqueue_buflen(&nbr->packethandle) != 0) { uip_len = uip_packetqueue_buflen(&nbr->packethandle); memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len); uip_packetqueue_free(&nbr->packethandle); tcpip_output(&(nbr->lladdr)); } #endif /*UIP_CONF_IPV6_QUEUE_PKT*/ uip_len = 0; return; } } /*multicast IP destination address */ tcpip_output(NULL); uip_len = 0; uip_ext_len = 0; }
static s8_t tcpip_poll(void *arg,struct uip_tcp_pcb *pcb) { UIP_LOG("tcpip_poll()"); return UIP_ERR_OK; }
/* * IPCP RX protocol Handler */ void ipv6cp_rx(u8_t *buffer, u16_t count) { u8_t *bptr = buffer; // IPCPPKT *pkt=(IPCPPKT *)buffer; u16_t len; ANNOTATE("IPV6CP len %d\n",count); switch(*bptr++) { case CONF_REQ: /* parce request and see if we can ACK it */ ++bptr; len = (*bptr++ << 8); len |= *bptr++; /* len-=2; */ ANNOTATE("check lcplist\n"); if(scan_packet(IPV6CP, ipv6cplist, buffer, bptr, (u16_t)(len - 4))) { UIP_LOG("option was bad\n"); } else { ANNOTATE("IPV6CP options are good\n"); /* * Parse out the results */ /* lets try to implement what peer wants */ /* Reject any protocol not */ /* Error? if we we need to send a config Reject ++++ this is good for a subroutine*/ //GD-2011-09-15 None of the IPv6CP options are supported with current implementation. #if 0 #warning option implementation example based on IPCP IPv4 address configuration. /* All we should get is the peer IP address */ if(IPV6CP_IPADDRESS == *bptr++) { /* dump length */ ++bptr; #ifdef IPV6CP_GET_PEER_IP ((u8_t*)peer_ip_addr.u8)[0] = *bptr++; ((u8_t*)peer_ip_addr.u8)[1] = *bptr++; ((u8_t*)peer_ip_addr.u8)[2] = *bptr++; ((u8_t*)peer_ip_addr.u8)[3] = *bptr++; ANNOTATE("Peer IP "); /* printip(peer_ip_addr);*/ ANNOTATE("\n"); #else bptr += 18; #endif } else { UIP_LOG("HMMMM this shouldn't happen IPV6CP1\n"); } #endif #if 0 if(error) { /* write the config NAK packet we've built above, take on the header */ bptr = buffer; *bptr++ = CONF_NAK; /* Write Conf_rej */ *bptr++; /*tptr++;*/ /* skip over ID */ /* Write new length */ *bptr++ = 0; *bptr = tptr - buffer; /* write the reject frame */ UIP_LOG("Writing NAK frame \n"); ahdlc_tx(IPV6CP, buffer, (u16_t)(tptr - buffer)); ANNOTATE("- End NAK Write frame\n"); } else { } #endif /* * If we get here then we are OK, lets send an ACK and tell the rest * of our modules our negotiated config. */ ipv6cp_state |= IPV6CP_RX_UP; ipv6cp_state &= ~IPV6CP_TX_UP;//phlb force send request with ipv6cp task ANNOTATE("Send IPV6CP ACK!\n"); bptr = buffer; *bptr++ = CONF_ACK; /* Write Conf_ACK */ bptr++; /* Skip ID (send same one) */ /* * Set stuff */ ppp_flags |= tflag; ANNOTATE("SET- stuff -- are we up? c=%d dif=%d \n", count, (u16_t)(bptr-buffer)); /* write the ACK frame */ ANNOTATE("Writing ACK frame \n"); /* Send packet ahdlc_txz(procol,header,data,headerlen,datalen); */ ahdlc_tx(IPV6CP, 0, buffer, 0, count /*bptr-buffer*/); ANNOTATE("- End ACK Write frame\n"); /* expire the timer to make things happen after a state change */ TIMER_expire(); //timer_expire(); //modify phlb uncomment /* } */ } break; // case CONF_ACK: /* config Ack */ ANNOTATE("CONF ACK\n"); /* * Parse out the results * * Dump the ID and get the length. */ /* dump the ID */ bptr++; /* get the length */ len = (*bptr++ << 8); len |= *bptr++; #if 0 //modify phlb /* Parse ACK and set data */ while(bptr < buffer + len) { switch(*bptr++) { case IPV6CP_IPADDRESS: /* dump length */ bptr++; ((u8_t*)ipaddr)[0] = *bptr++; ((u8_t*)ipaddr)[1] = *bptr++; ((u8_t*)ipaddr)[2] = *bptr++; ((u8_t*)ipaddr)[3] = *bptr++; break; case IPV6CP_PRIMARY_DNS: bptr++; ((u8_t*)pri_dns_addr)[0] = *bptr++; ((u8_t*)pri_dns_addr)[1] = *bptr++; ((u8_t*)pri_dns_addr)[2] = *bptr++; ((u8_t*)pri_dns_addr)[3] = *bptr++; break; case IPV6CP_SECONDARY_DNS: bptr++; ((u8_t*)sec_dns_addr)[0] = *bptr++; ((u8_t*)sec_dns_addr)[1] = *bptr++; ((u8_t*)sec_dns_addr)[2] = *bptr++; ((u8_t*)sec_dns_addr)[3] = *bptr++; break; default: UIP_LOG("IPV6CP CONFIG_ACK problem1\n"); } } #endif ipv6cp_state |= IPV6CP_TX_UP; //ipv6cp_state &= ~IPV6CP_RX_UP; ANNOTATE("were up! \n"); printip(pppif.ipaddr); #ifdef IPV6CP_GET_PRI_DNS printip(pri_dns_addr); #endif #ifdef IPV6CP_GET_SEC_DNS printip(sec_dns_addr); #endif ANNOTATE("\n"); /* expire the timer to make things happen after a state change */ TIMER_expire(); break; // case CONF_NAK: /* Config Nack */ UIP_LOG("CONF NAK\n"); /* dump the ID */ bptr++; /* get the length */ len = (*bptr++ << 8); len |= *bptr++; /* Parse ACK and set data */ while(bptr < buffer + len) { switch(*bptr++) { #if 0 #warning option implementation example based on IPCP IPv4 address configuration. case IPV6CP_IPADDRESS: /* dump length */ bptr++; ((u8_t*)pppif.ipaddr.u8)[0] = *bptr++; ((u8_t*)pppif.ipaddr.u8)[1] = *bptr++; ((u8_t*)pppif.ipaddr.u8)[2] = *bptr++; ((u8_t*)pppif.ipaddr.u8)[3] = *bptr++; uip_fw_register( &pppif ); ANNOTATE("My PPP-ipno: (%d.%d.%d.%d)\n", ((u8_t*)pppif.ipaddr.u8)[0], ((u8_t*)pppif.ipaddr.u8)[1], ((u8_t*)pppif.ipaddr.u8)[2], ((u8_t*)pppif.ipaddr.u8)[3]); break; #endif #ifdef IPV6CP_GET_PRI_DNS case IPV6CP_PRIMARY_DNS: bptr++; ((u8_t*)pri_dns_addr)[0] = *bptr++; ((u8_t*)pri_dns_addr)[1] = *bptr++; ((u8_t*)pri_dns_addr)[2] = *bptr++; ((u8_t*)pri_dns_addr)[3] = *bptr++; break; #endif #ifdef IPV6CP_GET_SEC_DNS case IPV6CP_SECONDARY_DNS: bptr++; ((u8_t*)sec_dns_addr)[0] = *bptr++; ((u8_t*)sec_dns_addr)[1] = *bptr++; ((u8_t*)sec_dns_addr)[2] = *bptr++; ((u8_t*)sec_dns_addr)[3] = *bptr++; break; #endif // default: UIP_LOG("IPCP CONFIG_ACK problem 2\n"); } } ppp_id++; printip(pppif.ipaddr); #ifdef IPV6CP_GET_PRI_DNS printip(pri_dns_addr); #endif #ifdef IPV6CP_GET_PRI_DNS printip(sec_dns_addr); #endif ANNOTATE("\n"); /* expire the timer to make things happen after a state change */ TIMER_expire(); break; case CONF_REJ: /* Config Reject */ ANNOTATE("CONF REJ\n"); /* Remove the offending options*/ ppp_id++; /* dump the ID */ bptr++; /* get the length */ len = (*bptr++ << 8); len |= *bptr++; /* Parse ACK and set data */ while(bptr < buffer + len) { switch(*bptr++) { #if 0 #warning option implementation example based on IPCP IPv4 address configuration. case IPV6CP_IPADDRESS: ipv6cp_state |= IPV6CP_IP_BIT; bptr += 5; break; #endif #ifdef IPV6CP_GET_PRI_DNS case IPV6CP_PRIMARY_DNS: ipv6cp_state |= IPV6CP_PRI_DNS_BIT; bptr += 5; break; #endif #ifdef IPV6CP_GET_PRI_DNS case IPV6CP_SECONDARY_DNS: ipv6cp_state |= IPV6CP_SEC_DNS_BIT; bptr += 5; break; #endif default: UIP_LOG("IPV6CP this shoudln't happen 3\n"); } } /* expire the timer to make things happen after a state change */ /*timer_expire(); */ break; default: UIP_LOG("-Unknown 4\n"); } }
void tcpip_ipv6_output(void) { uip_ds6_nbr_t *nbr = NULL; uip_ipaddr_t *nexthop; uip_ds6_route_t *route = NULL; if(uip_len == 0) { return; } PRINTF("IPv6 packet send from "); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF(" to "); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF("\n"); if(uip_len > UIP_LINK_MTU) { UIP_LOG("tcpip_ipv6_output: Packet to big"); uip_clear_buf(); return; } if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)){ UIP_LOG("tcpip_ipv6_output: Destination address unspecified"); uip_clear_buf(); return; } if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { /* Next hop determination */ nbr = NULL; /* We first check if the destination address is on our immediate link. If so, we simply use the destination address as our nexthop address. */ if(uip_ds6_is_addr_onlink(&UIP_IP_BUF->destipaddr)){ nexthop = &UIP_IP_BUF->destipaddr; } else { /* Check if we have a route to the destination address. */ route = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr); /* No route was found - we send to the default route instead. */ if(route == NULL) { #if CETIC_6LBR_SMARTBRIDGE if (uip_ipaddr_prefixcmp(&wsn_net_prefix, &UIP_IP_BUF->destipaddr, 64)) { /* In smart-bridge mode, there is no route towards hosts on the Ethernet side Therefore we have to check the destination and assume the host is on-link */ nexthop = &UIP_IP_BUF->destipaddr; } else #endif #if CETIC_6LBR_ROUTER && UIP_CONF_IPV6_RPL if (is_dodag_root() && uip_ipaddr_prefixcmp(&wsn_net_prefix, &UIP_IP_BUF->destipaddr, 64)) { //In router mode, we drop packets towards unknown mote PRINTF("Dropping wsn packet with no route\n"); uip_len = 0; return; } else #endif #if CETIC_6LBR_IP64 if(ip64_addr_is_ip64(&UIP_IP_BUF->destipaddr)) { #if UIP_CONF_IPV6_RPL rpl_remove_header(); #endif IP64_CONF_UIP_FALLBACK_INTERFACE.output(); uip_len = 0; uip_ext_len = 0; return; } else #endif { PRINTF("tcpip_ipv6_output: no route found, using default route\n"); nexthop = uip_ds6_defrt_choose(); } if(nexthop == NULL) { #ifdef UIP_FALLBACK_INTERFACE PRINTF("FALLBACK: removing ext hdrs & setting proto %d %d\n", uip_ext_len, *((uint8_t *)UIP_IP_BUF + 40)); if(uip_ext_len > 0) { extern void remove_ext_hdr(void); uint8_t proto = *((uint8_t *)UIP_IP_BUF + 40); remove_ext_hdr(); /* This should be copied from the ext header... */ UIP_IP_BUF->proto = proto; } UIP_FALLBACK_INTERFACE.output(); #else PRINTF("tcpip_ipv6_output: Destination off-link but no route\n"); #endif /* !UIP_FALLBACK_INTERFACE */ uip_clear_buf(); return; } } else { /* A route was found, so we look up the nexthop neighbor for the route. */ nexthop = uip_ds6_route_nexthop(route); /* If the nexthop is dead, for example because the neighbor never responded to link-layer acks, we drop its route. */ if(nexthop == NULL) { #if UIP_CONF_IPV6_RPL /* If we are running RPL, and if we are the root of the network, we'll trigger a DIO before we remove the route. */ rpl_dag_t *dag; dag = (rpl_dag_t *)route->state.dag; if(dag != NULL) { rpl_reset_dio_timer(dag->instance); } #endif /* UIP_CONF_IPV6_RPL */ uip_ds6_route_rm(route); /* We don't have a nexthop to send the packet to, so we drop it. */ return; } } #if TCPIP_CONF_ANNOTATE_TRANSMISSIONS if(nexthop != NULL) { static uint8_t annotate_last; static uint8_t annotate_has_last = 0; if(annotate_has_last) { printf("#L %u 0; red\n", annotate_last); } printf("#L %u 1; red\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]); annotate_last = nexthop->u8[sizeof(uip_ipaddr_t) - 1]; annotate_has_last = 1; } #endif /* TCPIP_CONF_ANNOTATE_TRANSMISSIONS */ } /* End of next hop determination */ #if UIP_CONF_IPV6_RPL if(rpl_update_header_final(nexthop)) { uip_clear_buf(); return; } #endif /* UIP_CONF_IPV6_RPL */ nbr = uip_ds6_nbr_lookup(nexthop); if(nbr == NULL) { #if UIP_ND6_SEND_NA #if CETIC_6LBR && UIP_CONF_IPV6_RPL /* Don't perform NUD if it has been disabled for WSN */ if((nvm_data.global_flags & CETIC_GLOBAL_DISABLE_WSN_NUD) != 0 && uip_ipaddr_prefixcmp(&wsn_net_prefix, &UIP_IP_BUF->destipaddr, 64) && route != NULL) { uip_clear_buf(); return; } #endif if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE)) == NULL) { uip_clear_buf(); return; } else { #if UIP_CONF_IPV6_QUEUE_PKT /* Copy outgoing pkt in the queuing buffer for later transmit. */ if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) { memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len); uip_packetqueue_set_buflen(&nbr->packethandle, uip_len); } #endif /* RFC4861, 7.2.2: * "If the source address of the packet prompting the solicitation is the * same as one of the addresses assigned to the outgoing interface, that * address SHOULD be placed in the IP Source Address of the outgoing * solicitation. Otherwise, any one of the addresses assigned to the * interface should be used."*/ if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)){ uip_nd6_ns_output(&UIP_IP_BUF->srcipaddr, NULL, &nbr->ipaddr); } else { uip_nd6_ns_output(NULL, NULL, &nbr->ipaddr); } stimer_set(&nbr->sendns, uip_ds6_if.retrans_timer / 1000); nbr->nscount = 1; /* Send the first NS try from here (multicast destination IP address). */ } #else /* UIP_ND6_SEND_NA */ uip_len = 0; return; #endif /* UIP_ND6_SEND_NA */ } else { #if UIP_ND6_SEND_NA if(nbr->state == NBR_INCOMPLETE) { PRINTF("tcpip_ipv6_output: nbr cache entry incomplete\n"); #if UIP_CONF_IPV6_QUEUE_PKT /* Copy outgoing pkt in the queuing buffer for later transmit and set the destination nbr to nbr. */ if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) { memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len); uip_packetqueue_set_buflen(&nbr->packethandle, uip_len); } #endif /*UIP_CONF_IPV6_QUEUE_PKT*/ uip_clear_buf(); return; } /* Send in parallel if we are running NUD (nbc state is either STALE, DELAY, or PROBE). See RFC 4861, section 7.3.3 on node behavior. */ #if CETIC_6LBR && UIP_CONF_IPV6_RPL /* Don't update nbr state if we don't want to perform NUD for WSN */ if((nvm_data.global_flags & CETIC_GLOBAL_DISABLE_WSN_NUD) == 0 || !uip_ipaddr_prefixcmp(&wsn_net_prefix, &UIP_IP_BUF->destipaddr, 64) || route == NULL) #endif if(nbr->state == NBR_STALE) { nbr->state = NBR_DELAY; stimer_set(&nbr->reachable, UIP_ND6_DELAY_FIRST_PROBE_TIME); nbr->nscount = 0; PRINTF("tcpip_ipv6_output: nbr cache entry stale moving to delay\n"); } #endif /* UIP_ND6_SEND_NA */ tcpip_output(uip_ds6_nbr_get_ll(nbr)); #if UIP_CONF_IPV6_QUEUE_PKT /* * Send the queued packets from here, may not be 100% perfect though. * This happens in a few cases, for example when instead of receiving a * NA after sendiong a NS, you receive a NS with SLLAO: the entry moves * to STALE, and you must both send a NA and the queued packet. */ if(uip_packetqueue_buflen(&nbr->packethandle) != 0) { uip_len = uip_packetqueue_buflen(&nbr->packethandle); memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len); uip_packetqueue_free(&nbr->packethandle); tcpip_output(uip_ds6_nbr_get_ll(nbr)); } #endif /*UIP_CONF_IPV6_QUEUE_PKT*/ uip_clear_buf(); return; } } /* Multicast IP destination address. */ tcpip_output(NULL); uip_clear_buf(); }