/*---------------------------------------------------------------------------*/ static void check_entries(void) { register struct dns_hdr *hdr; char *query, *nptr, *nameptr; static u8_t i; static u8_t n; register struct namemap *namemapptr; for(i = 0; i < RESOLV_ENTRIES; ++i) { namemapptr = &names[i]; if(namemapptr->state == STATE_NEW || namemapptr->state == STATE_ASKING) { if(namemapptr->state == STATE_ASKING) { if(--namemapptr->tmr == 0) { if(++namemapptr->retries == MAX_RETRIES) { namemapptr->state = STATE_ERROR; resolv_found(namemapptr->name, NULL); continue; } namemapptr->tmr = namemapptr->retries; } else { /* printf("Timer %d\n", namemapptr->tmr);*/ /* Its timer has not run out, so we move on to next entry. */ continue; } } else { namemapptr->state = STATE_ASKING; namemapptr->tmr = 1; namemapptr->retries = 0; } hdr = (struct dns_hdr *)uip_appdata; memset(hdr, 0, sizeof(struct dns_hdr)); hdr->id = uip_htons(i); hdr->flags1 = DNS_FLAG1_RD; hdr->numquestions = UIP_HTONS(1); query = (char *)uip_appdata + 12; nameptr = namemapptr->name; --nameptr; /* Convert hostname into suitable query format. */ do { ++nameptr; nptr = query; ++query; for(n = 0; *nameptr != '.' && *nameptr != 0; ++nameptr) { *query = *nameptr; ++query; ++n; } *nptr = n; } while(*nameptr != 0); { static unsigned char endquery[] = {0,0,1,0,1}; memcpy(query, endquery, 5); } uip_udp_send((unsigned char)(query + 5 - (char *)uip_appdata)); break; } } }
/*-----------------------------------------------------------------------------------*/ void vnc_server_send_data(struct vnc_server_state *vs) { register struct rfb_server_init *initmsg; switch(vs->state) { case VNC_VERSION: uip_send(RFB_SERVER_VERSION_STRING, sizeof(RFB_SERVER_VERSION_STRING)); break; case VNC_AUTH: ((char *)uip_appdata)[0] = 0; ((char *)uip_appdata)[1] = 0; ((char *)uip_appdata)[2] = 0; ((char *)uip_appdata)[3] = RFB_AUTH_NONE; uip_send(uip_appdata, 4); break; case VNC_INIT: initmsg = (struct rfb_server_init *)uip_appdata; initmsg->width = uip_htons(vs->width); initmsg->height = uip_htons(vs->height); /* BGR233 pixel format. */ initmsg->format.bps = 8; initmsg->format.depth = 8; initmsg->format.endian = 1; initmsg->format.truecolor = 1; initmsg->format.red_max = uip_htons(7); initmsg->format.green_max = uip_htons(7); initmsg->format.blue_max = uip_htons(3); initmsg->format.red_shift = 0; initmsg->format.green_shift = 3; initmsg->format.blue_shift = 6; initmsg->namelength[0] = 0; initmsg->namelength[1] = 0; initmsg->namelength[2] = 0; initmsg->namelength[3] = 4; memcpy(&((char *)uip_appdata)[sizeof(struct rfb_server_init)], uvnc_name, 4); /* ((char *)uip_appdata)[sizeof(struct rfb_server_init)+0] = 'u'; ((char *)uip_appdata)[sizeof(struct rfb_server_init)+1] = 'V'; ((char *)uip_appdata)[sizeof(struct rfb_server_init)+2] = 'N'; ((char *)uip_appdata)[sizeof(struct rfb_server_init)+3] = 'C';*/ uip_send(uip_appdata, sizeof(struct rfb_server_init) + 4); break; case VNC_RUNNING: switch(vs->sendmsg) { case SEND_NONE: PRINTF(("Sending none\n")); break; case SEND_BLANK: case SENT_BLANK: PRINTF(("Sending blank\n")); vnc_send_blank(vs); break; case SEND_SCREEN: PRINTF(("Sending screen\n")); vnc_send_screen(vs); break; case SEND_UPDATE: PRINTF(("Sending update\n")); vnc_send_update(vs); break; } break; default: break; } }
/*---------------------------------------------------------------------------*/ static void pollhandler(void) { #if !FALLBACK_HAS_ETHERNET_HEADERS //native br is fallback only process_poll(&wpcap_process); uip_len = wpcap_poll(); if(uip_len > 0) { #if UIP_CONF_IPV6 if(BUF->type == uip_htons(UIP_ETHTYPE_IPV6)) { printf("wpcap poll calls tcpip"); tcpip_input(); } else #endif /* UIP_CONF_IPV6 */ if(BUF->type == uip_htons(UIP_ETHTYPE_IP)) { uip_len -= sizeof(struct uip_eth_hdr); tcpip_input(); #if !UIP_CONF_IPV6 } else if(BUF->type == uip_htons(UIP_ETHTYPE_ARP)) { uip_arp_arpin(); //math /* If the above function invocation resulted in data that should be sent out on the network, the global variable uip_len is set to a value > 0. */ if(uip_len > 0) { wpcap_send(); } #endif /* !UIP_CONF_IPV6 */ } else { uip_len = 0; } } #endif #ifdef UIP_FALLBACK_INTERFACE process_poll(&wpcap_process); uip_len = wfall_poll(); if(uip_len > 0) { #if FALLBACK_HAS_ETHERNET_HEADERS if(BUF->type == uip_htons(UIP_ETHTYPE_IPV6)) { //remove ethernet header and pass ipv6 packet to stack uip_len-=14; //{int i;printf("\n0000 ");for (i=0;i<uip_len;i++) printf("%02x ",*(unsigned char*)(uip_buf+i));printf("\n");} // memcpy(uip_buf, uip_buf+14, uip_len); memcpy(&uip_buf[UIP_LLH_LEN], uip_buf+14, uip_len); //LLH_LEN is zero for native border router to slip radio // CopyMemory(uip_buf, uip_buf+14, uip_len); //{int i;printf("\n0000 ");for (i=0;i<uip_len;i++) printf("%02x ",*(char*)(uip_buf+i));printf("\n");} tcpip_input(); } else goto bail; #elif UIP_CONF_IPV6 if(BUF->type == uip_htons(UIP_ETHTYPE_IPV6)) { tcpip_input(); } else goto bail; #endif /* UIP_CONF_IPV6 */ if(BUF->type == uip_htons(UIP_ETHTYPE_IP)) { uip_len -= sizeof(struct uip_eth_hdr); tcpip_input(); #if !UIP_CONF_IPV6 } else if(BUF->type == uip_htons(UIP_ETHTYPE_ARP)) { uip_arp_arpin(); //math /* If the above function invocation resulted in data that should be sent out on the network, the global variable uip_len is set to a value > 0. */ if(uip_len > 0) { wfall_send(); } #endif /* !UIP_CONF_IPV6 */ } else { bail: uip_len = 0; } } #endif }
static size_t dsrv_print_addr(const session_t *addr, char *buf, size_t len) { #ifdef HAVE_ARPA_INET_H const void *addrptr = NULL; in_port_t port; char *p = buf; switch (addr->addr.sa.sa_family) { case AF_INET: if (len < INET_ADDRSTRLEN) return 0; addrptr = &addr->addr.sin.sin_addr; port = ntohs(addr->addr.sin.sin_port); break; case AF_INET6: if (len < INET6_ADDRSTRLEN + 2) return 0; *p++ = '['; addrptr = &addr->addr.sin6.sin6_addr; port = ntohs(addr->addr.sin6.sin6_port); break; default: memcpy(buf, "(unknown address type)", min(22, len)); return min(22, len); } if (inet_ntop(addr->addr.sa.sa_family, addrptr, p, len) == 0) { perror("dsrv_print_addr"); return 0; } p += dtls_strnlen(p, len); if (addr->addr.sa.sa_family == AF_INET6) { if (p < buf + len) { *p++ = ']'; } else return 0; } p += snprintf(p, buf + len - p + 1, ":%d", port); return p - buf; #else /* HAVE_ARPA_INET_H */ # if WITH_CONTIKI char *p = buf; # if NETSTACK_CONF_WITH_IPV6 uint8_t i; const char hex[] = "0123456789ABCDEF"; if (len < 41) return 0; *p++ = '['; for (i=0; i < 16; i += 2) { if (i) { *p++ = ':'; } *p++ = hex[(addr->addr.u8[i] & 0xf0) >> 4]; *p++ = hex[(addr->addr.u8[i] & 0x0f)]; *p++ = hex[(addr->addr.u8[i+1] & 0xf0) >> 4]; *p++ = hex[(addr->addr.u8[i+1] & 0x0f)]; } *p++ = ']'; # else /* NETSTACK_CONF_IPV6 */ if (len < 21) return 0; p += sprintf(p, "%u.%u.%u.%u", addr->addr.u8[0], addr->addr.u8[1], addr->addr.u8[2], addr->addr.u8[3]); # endif /* NETSTACK_CONF_IPV6 */ if (buf + len - p < 6) return 0; p += sprintf(p, ":%d", uip_htons(addr->port)); return p - buf; # else /* WITH_CONTIKI */ /* TODO: output addresses manually */ # warning "inet_ntop() not available, network addresses will not be included in debug output" # endif /* WITH_CONTIKI */ return 0; #endif }
/*---------------------------------------------------------------------------*/ void uip_nd6_ra_output(uip_ipaddr_t * dest) { UIP_IP_BUF->vtc = 0x60; UIP_IP_BUF->tcflow = 0; UIP_IP_BUF->flow = 0; UIP_IP_BUF->proto = UIP_PROTO_ICMP6; UIP_IP_BUF->ttl = UIP_ND6_HOP_LIMIT; if(dest == NULL) { uip_create_linklocal_allnodes_mcast(&UIP_IP_BUF->destipaddr); } else { /* For sollicited RA */ uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, dest); } uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); UIP_ICMP_BUF->type = ICMP6_RA; UIP_ICMP_BUF->icode = 0; UIP_ND6_RA_BUF->cur_ttl = uip_ds6_if.cur_hop_limit; UIP_ND6_RA_BUF->flags_reserved = (UIP_ND6_M_FLAG << 7) | (UIP_ND6_O_FLAG << 6); UIP_ND6_RA_BUF->router_lifetime = uip_htons(UIP_ND6_ROUTER_LIFETIME); //UIP_ND6_RA_BUF->reachable_time = uip_htonl(uip_ds6_if.reachable_time); //UIP_ND6_RA_BUF->retrans_timer = uip_htonl(uip_ds6_if.retrans_timer); UIP_ND6_RA_BUF->reachable_time = 0; UIP_ND6_RA_BUF->retrans_timer = 0; uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_RA_LEN; nd6_opt_offset = UIP_ND6_RA_LEN; #if !UIP_CONF_ROUTER /* Prefix list */ for(prefix = uip_ds6_prefix_list; prefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; prefix++) { if((prefix->isused) && (prefix->advertise)) { UIP_ND6_OPT_PREFIX_BUF->type = UIP_ND6_OPT_PREFIX_INFO; UIP_ND6_OPT_PREFIX_BUF->len = UIP_ND6_OPT_PREFIX_INFO_LEN / 8; UIP_ND6_OPT_PREFIX_BUF->preflen = prefix->length; UIP_ND6_OPT_PREFIX_BUF->flagsreserved1 = prefix->l_a_reserved; UIP_ND6_OPT_PREFIX_BUF->validlt = uip_htonl(prefix->vlifetime); UIP_ND6_OPT_PREFIX_BUF->preferredlt = uip_htonl(prefix->plifetime); UIP_ND6_OPT_PREFIX_BUF->reserved2 = 0; uip_ipaddr_copy(&(UIP_ND6_OPT_PREFIX_BUF->prefix), &(prefix->ipaddr)); nd6_opt_offset += UIP_ND6_OPT_PREFIX_INFO_LEN; uip_len += UIP_ND6_OPT_PREFIX_INFO_LEN; } } #endif /* !UIP_CONF_ROUTER */ /* Source link-layer option */ create_llao((uint8_t *)UIP_ND6_OPT_HDR_BUF, UIP_ND6_OPT_SLLAO); uip_len += UIP_ND6_OPT_LLAO_LEN; nd6_opt_offset += UIP_ND6_OPT_LLAO_LEN; /* MTU */ UIP_ND6_OPT_MTU_BUF->type = UIP_ND6_OPT_MTU; UIP_ND6_OPT_MTU_BUF->len = UIP_ND6_OPT_MTU_LEN >> 3; UIP_ND6_OPT_MTU_BUF->reserved = 0; //UIP_ND6_OPT_MTU_BUF->mtu = uip_htonl(uip_ds6_if.link_mtu); UIP_ND6_OPT_MTU_BUF->mtu = uip_htonl(1500); uip_len += UIP_ND6_OPT_MTU_LEN; nd6_opt_offset += UIP_ND6_OPT_MTU_LEN; UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); /*ICMP checksum */ UIP_ICMP_BUF->icmpchksum = 0; UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); UIP_STAT(++uip_stat.nd6.sent); PRINTF("Sending RA to"); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF("from"); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF("\n"); return; }
/*---------------------------------------------------------------------*/ static PT_THREAD(recv_tcpthread(struct pt *pt)) { uint8_t *dataptr; struct codeprop_tcphdr *th; int datalen = uip_datalen(); PT_BEGIN(pt); while(1) { PT_WAIT_UNTIL(pt, uip_connected()); s.state = STATE_RECEIVING_TCPDATA; s.addr = 0; s.count = 0; process_post(PROCESS_BROADCAST, codeprop_event_quit, (process_data_t)NULL); /* Read the header. */ PT_WAIT_UNTIL(pt, uip_newdata() && uip_datalen() > 0); dataptr = uip_appdata; if(uip_datalen() < sizeof(struct codeprop_tcphdr)) { PRINTF(("codeprop: header not found in first tcp segment\n")); uip_abort(); } th = (struct codeprop_tcphdr *)uip_appdata; s.len = uip_htons(th->len); s.addr = 0; uip_appdata += sizeof(struct codeprop_tcphdr); datalen = uip_datalen() - sizeof(struct codeprop_tcphdr); /* Read the rest of the data. */ do { if(datalen > 0) { /* printf("Got %d bytes\n", uip_len);*/ eeprom_write(EEPROMFS_ADDR_CODEPROP + s.addr, uip_appdata, datalen); s.addr += datalen; } if(s.addr < s.len) { PT_YIELD_UNTIL(pt, uip_newdata()); } } while(s.addr < s.len); /* Print out the "ok" message. */ do { uip_send("ok\r\n", 4); PT_WAIT_UNTIL(pt, uip_acked() || uip_rexmit() || uip_closed()); } while(uip_rexmit()); /* Close the connection. */ uip_close(); ++s.id; s.state = STATE_SENDING_UDPDATA; tcpip_poll_udp(udp_conn); codeprop_start_program(); PT_WAIT_UNTIL(pt, s.state != STATE_SENDING_UDPDATA); /* printf("recv_tcpthread: unblocked\n");*/ } PT_END(pt); }
static int eth_output(const uip_lladdr_t * src, const uip_lladdr_t * dest) { if(IS_BROADCAST_ADDR(dest)) { LOG6LBR_PRINTF(PACKET, PF_OUT, "eth_output: broadcast\n"); } else { LOG6LBR_LLADDR_PRINTF(PACKET, PF_OUT, dest, "eth_output: "); } //Packet filtering //---------------- if(uip_len == 0) { LOG6LBR_ERROR("eth_output: uip_len = 0\n"); return 0; } if(dest && linkaddr_cmp((linkaddr_t *) & dest, (linkaddr_t *) & eth_mac64_addr)) { LOG6LBR_ERROR("ethernet_output: sending to self\n"); return 0; } #if CETIC_6LBR_ETH_FILTER_RPL //Filter out RPL (broadcast) traffic if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type == ICMP6_RPL) { //LOG6LBR_PRINTF(PACKET, PF_OUT, "eth_output: Filtering out RPL traffic\n"); return 0; } #endif //IP packet alteration //-------------------- #if CETIC_6LBR_ROUTER //Modify source address if((nvm_data.mode & CETIC_MODE_REWRITE_ADDR_MASK) != 0 && uip_is_addr_link_local(&UIP_IP_BUF->srcipaddr) && uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)) { LOG6LBR_PRINTF(PACKET, PF_OUT, "eth_output: Update src address\n"); uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, ð_ip_local_addr); } #endif #if CETIC_6LBR_SMARTBRIDGE //Reset Hop Limit when in smart-bridge for NDP packets //TODO: Is this still needed after #4467 ? if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && (UIP_ICMP_BUF->type == ICMP6_NS || UIP_ICMP_BUF->type == ICMP6_NA || UIP_ICMP_BUF->type == ICMP6_RS || UIP_ICMP_BUF->type == ICMP6_RA)) { UIP_IP_BUF->ttl = 255; } #endif #if CETIC_6LBR_SMARTBRIDGE || CETIC_6LBR_TRANSPARENTBRIDGE //Remove ROUTER flag when in bridge mode if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type == ICMP6_NA) { //LOG6LBR_PRINTF(PACKET, PF_OUT, "eth_output: Updating NA\n"); UIP_ND6_NA_BUF->flagsreserved &= ~UIP_ND6_NA_FLAG_ROUTER; } #endif //Some IP packets have link layer in them, need to change them around! mac_translateIPLinkLayer(ll_8023_type); //IP header alteration //-------------------- #if UIP_CONF_IPV6_RPL rpl_remove_header(); #endif //Create packet header //-------------------- //Packet type BUF->type = uip_htons(UIP_ETHTYPE_IPV6); //Destination address if(IS_BROADCAST_ADDR(dest)) { BUF->dest.addr[0] = 0x33; BUF->dest.addr[1] = 0x33; BUF->dest.addr[2] = UIP_IP_BUF->destipaddr.u8[12]; BUF->dest.addr[3] = UIP_IP_BUF->destipaddr.u8[13]; BUF->dest.addr[4] = UIP_IP_BUF->destipaddr.u8[14]; BUF->dest.addr[5] = UIP_IP_BUF->destipaddr.u8[15]; } else { mac_createEthernetAddr(BUF->dest.addr, dest); } //Source address if ( src != NULL ) { mac_createEthernetAddr(BUF->src.addr, src); } else { memcpy(BUF->src.addr, eth_mac_addr, 6); } //Sending packet //-------------- LOG6LBR_PRINTF(PACKET, PF_OUT, "eth_output: Sending packet to Ethernet\n"); eth_drv_send(); return 1; }
/*---------------------------------------------------------------------------*/ int ip64_4to6(const uint8_t *ipv4packet, const uint16_t ipv4packet_len, uint8_t *resultpacket) { struct ipv4_hdr *v4hdr; struct ipv6_hdr *v6hdr; struct udp_hdr *udphdr; struct tcp_hdr *tcphdr; struct icmpv4_hdr *icmpv4hdr; struct icmpv6_hdr *icmpv6hdr; uint16_t ipv4len, ipv6len, ipv6_packet_len; struct ip64_addrmap_entry *m; v6hdr = (struct ipv6_hdr *)resultpacket; v4hdr = (struct ipv4_hdr *)ipv4packet; if((v4hdr->len[0] << 8) + v4hdr->len[1] <= ipv4packet_len) { ipv4len = (v4hdr->len[0] << 8) + v4hdr->len[1]; } else { PRINTF("ip64_4to6: packet smaller than reported in IPv4 header, dropping\n"); return 0; } if(ipv4len <= IPV4_HDRLEN) { return 0; } /* Make sure that the resulting packet fits in the ip64 packet buffer. If not, we drop it. */ if(ipv4len - IPV4_HDRLEN + IPV6_HDRLEN > BUFSIZE) { PRINTF("ip64_4to6: packet too big to fit in buffer, dropping\n"); return 0; } /* We copy the data from the IPv4 packet into the IPv6 packet. */ memcpy(&resultpacket[IPV6_HDRLEN], &ipv4packet[IPV4_HDRLEN], ipv4len - IPV4_HDRLEN); udphdr = (struct udp_hdr *)&resultpacket[IPV6_HDRLEN]; tcphdr = (struct tcp_hdr *)&resultpacket[IPV6_HDRLEN]; icmpv4hdr = (struct icmpv4_hdr *)&ipv4packet[IPV4_HDRLEN]; icmpv6hdr = (struct icmpv6_hdr *)&resultpacket[IPV6_HDRLEN]; ipv6len = ipv4len - IPV4_HDRLEN + IPV6_HDRLEN; ipv6_packet_len = ipv6len - IPV6_HDRLEN; /* Translate the IPv4 header into an IPv6 header. */ /* We first fill in the simple fields: IP header version, traffic class and flow label, and length fields. */ v6hdr->vtc = 0x60; v6hdr->tcflow = 0; v6hdr->flow = 0; v6hdr->len[0] = ipv6_packet_len >> 8; v6hdr->len[1] = ipv6_packet_len & 0xff; /* We use the IPv4 TTL field as the IPv6 hop limit field. */ v6hdr->hoplim = v4hdr->ttl; /* We now translate the IPv4 source and destination addresses to IPv6 source and destination addresses. We translate the IPv4 source address into an IPv6-encoded IPv4 address. The IPv4 destination address will be the address with which we have previously been configured, through the ip64_set_ipv4_address() function. We use the mapping table to look up the new IPv6 destination address. As we assume that the IPv4 packet is a response to a previously sent IPv6 packet, we should have a mapping between the (protocol, destport, srcport, srcaddress) tuple. If not, we'll return 0 to indicate that we failed to translate the packet. */ if(ip64_addr_4to6(&v4hdr->srcipaddr, &v6hdr->srcipaddr) == 0) { PRINTF("ip64_packet_4to6: failed to convert source IP address\n"); return 0; } /* For the next header field, we simply use the IPv4 protocol field. We only support UDP and TCP packets. */ switch(v4hdr->proto) { case IP_PROTO_UDP: v6hdr->nxthdr = IP_PROTO_UDP; break; case IP_PROTO_TCP: v6hdr->nxthdr = IP_PROTO_TCP; break; case IP_PROTO_ICMPV4: /* Allow only ICMPv4 ECHO_REQUESTS (ping packets) through to the local IPv6 host. */ if(icmpv4hdr->type == ICMP_ECHO) { PRINTF("ip64_4to6: translating ICMPv4 ECHO packet\n"); v6hdr->nxthdr = IP_PROTO_ICMPV6; icmpv6hdr->type = ICMP6_ECHO; ip64_addr_copy6(&v6hdr->destipaddr, &ipv6_local_address); } else { PRINTF("ip64_packet_4to6: ICMPv4 packet type %d not supported\n", icmpv4hdr->type); return 0; } break; default: /* For protocol types that we do not support, we return 0 to indicate that we failed to translate the packet to an IPv6 packet. */ PRINTF("ip64_packet_4to6: protocol type %d not supported\n", v4hdr->proto); return 0; } /* Translate IPv4 broadcasts to IPv6 all-nodes multicasts. */ if(uip_ip4addr_cmp(&v4hdr->destipaddr, &ipv4_broadcast_addr) || (uip_ipaddr_maskcmp(&v4hdr->destipaddr, &ip64_hostaddr, &ip64_netmask) && ((v4hdr->destipaddr.u16[0] & (~ip64_netmask.u16[0])) == (ipv4_broadcast_addr.u16[0] & (~ip64_netmask.u16[0]))) && ((v4hdr->destipaddr.u16[1] & (~ip64_netmask.u16[1])) == (ipv4_broadcast_addr.u16[1] & (~ip64_netmask.u16[1]))))) { uip_create_linklocal_allnodes_mcast(&v6hdr->destipaddr); } else { if(!ip64_hostaddr_configured) { PRINTF("ip64_packet_4to6: no local IPv4 address configured, dropping incoming packet.\n"); return 0; } if(!uip_ip4addr_cmp(&v4hdr->destipaddr, &ip64_hostaddr)) { PRINTF("ip64_packet_4to6: the IPv4 destination address %d.%d.%d.%d did not match our IPv4 address %d.%d.%d.%d\n", uip_ipaddr_to_quad(&v4hdr->destipaddr), uip_ipaddr_to_quad(&ip64_hostaddr)); return 0; } /* Now we translate the transport layer port numbers. We assume that the IPv4 packet is a response to a packet that has previously been translated from IPv6 to IPv4. If this is the case, the tuple (protocol, destport, srcport, srcaddress) corresponds to an address/port pair in our mapping table. If we do not find a mapping, we return 0 to indicate that we could not translate the IPv4 packet to an IPv6 packet. */ /* XXX treat a few ports differently: those ports should be let through to the local host. For those ports, we set up an address mapping that ensures that the local port number is retained. */ if((v4hdr->proto == IP_PROTO_TCP || v4hdr->proto == IP_PROTO_UDP)) { if(uip_htons(tcphdr->destport) < EPHEMERAL_PORTRANGE) { /* This packet should go to the local host. */ PRINTF("Port is in the non-ephemeral port range %d (%d)\n", tcphdr->destport, uip_htons(tcphdr->destport)); ip64_addr_copy6(&v6hdr->destipaddr, &ipv6_local_address); } else if(ip64_special_ports_incoming_is_special(uip_htons(tcphdr->destport))) { uip_ip6addr_t newip6addr; uint16_t newport; PRINTF("ip64 port %d (%d) is special, treating it differently\n", tcphdr->destport, uip_htons(tcphdr->destport)); if(ip64_special_ports_translate_incoming(uip_htons(tcphdr->destport), &newip6addr, &newport)) { ip64_addr_copy6(&v6hdr->destipaddr, &newip6addr); tcphdr->destport = uip_htons(newport); PRINTF("New port %d (%d)\n", tcphdr->destport, uip_htons(tcphdr->destport)); } else { ip64_addr_copy6(&v6hdr->destipaddr, &ipv6_local_address); PRINTF("No new port\n"); } } else { /* The TCP or UDP port numbers were not non-ephemeral and not special, so we map the port number according to the address mapping table. */ m = ip64_addrmap_lookup_port(uip_ntohs(udphdr->destport), v4hdr->proto); if(m == NULL) { PRINTF("Inbound lookup failed\n"); return 0; } else { PRINTF("Inbound lookup did not fail\n"); } ip64_addr_copy6(&v6hdr->destipaddr, &m->ip6addr); udphdr->destport = uip_htons(m->ip6port); } } } /* The checksum is in different places in the different protocol headers, so we need to be sure that we update the correct field. */ switch(v6hdr->nxthdr) { case IP_PROTO_TCP: tcphdr->tcpchksum = 0; tcphdr->tcpchksum = ~(ipv6_transport_checksum(resultpacket, ipv6len, IP_PROTO_TCP)); break; case IP_PROTO_UDP: udphdr->udpchksum = 0; udphdr->udpchksum = ~(ipv6_transport_checksum(resultpacket, ipv6len, IP_PROTO_UDP)); if(udphdr->udpchksum == 0) { udphdr->udpchksum = 0xffff; } break; case IP_PROTO_ICMPV6: icmpv6hdr->icmpchksum = 0; icmpv6hdr->icmpchksum = ~(ipv6_transport_checksum(resultpacket, ipv6len, IP_PROTO_ICMPV6)); break; default: PRINTF("ip64_4to6: transport protocol %d not implemented\n", v4hdr->proto); return 0; } /* Finally, we return the length of the resulting IPv6 packet. */ PRINTF("ip64_4to6: ipv6len %d\n", ipv6len); return ipv6len; }
static PT_THREAD(recv_tcpthread(struct pt *pt)) { struct codeprop_tcphdr *th; int datalen = uip_datalen(); PT_BEGIN(pt); while(1) { PT_WAIT_UNTIL(pt, uip_connected()); codeprop_exit_program(); s.state = STATE_RECEIVING_TCPDATA; s.addr = 0; s.count = 0; /* Read the header. */ PT_WAIT_UNTIL(pt, uip_newdata() && uip_datalen() > 0); if(uip_datalen() < CODEPROP_TCPHDR_SIZE) { PRINTF(("codeprop: header not found in first tcp segment\n")); uip_abort(); } th = (struct codeprop_tcphdr *)uip_appdata; s.len = uip_htons(th->len); s.addr = 0; uip_appdata += CODEPROP_TCPHDR_SIZE; datalen -= CODEPROP_TCPHDR_SIZE; /* Read the rest of the data. */ do { if(datalen > 0) { /* printf("Got %d bytes\n", datalen); */ if (cfs_seek(fd, s.addr, CFS_SEEK_SET) != s.addr) { PRINTF(("codeprop: seek in buffer file failed\n")); uip_abort(); } if (cfs_write(fd, uip_appdata, datalen) != datalen) { PRINTF(("codeprop: write to buffer file failed\n")); uip_abort(); } s.addr += datalen; } if(s.addr < s.len) { PT_YIELD_UNTIL(pt, uip_newdata()); } } while(s.addr < s.len); #if 1 { static int err; err = codeprop_start_program(); /* Print out the "OK"/error message. */ do { if (err >= 0 && err < sizeof(err_msgs)/sizeof(char*)) { uip_send(err_msgs[err], strlen(err_msgs[err])); } else { uip_send("Unknown error\r\n", 15); } PT_WAIT_UNTIL(pt, uip_acked() || uip_rexmit() || uip_closed()); } while(uip_rexmit()); /* Close the connection. */ uip_close(); } #endif ++s.id; s.state = STATE_SENDING_UDPDATA; tcpip_poll_udp(udp_conn); PT_WAIT_UNTIL(pt, s.state != STATE_SENDING_UDPDATA); /* printf("recv_tcpthread: unblocked\n");*/ } PT_END(pt); }
/*---------------------------------------------------------------------------*/ int tcpdump_format(u8_t *packet, u16_t packetlen, char *buf, u16_t buflen) { char flags[8]; if(IPBUF->proto == UIP_PROTO_ICMP) { if(ICMPBUF->type == ICMP_ECHO) { return s(" ping", n(IPBUF->destipaddr[3], d( n(IPBUF->destipaddr[2], d( n(IPBUF->destipaddr[1], d( n(IPBUF->destipaddr[0], s(" ", n(IPBUF->srcipaddr[3], d( n(IPBUF->srcipaddr[2], d( n(IPBUF->srcipaddr[1], d( n(IPBUF->srcipaddr[0], buf)))))))))))))))) - buf; /* return sprintf(buf, "%d.%d.%d.%d %d.%d.%d.%d ping", IPBUF->srcipaddr[0], IPBUF->srcipaddr[1], IPBUF->srcipaddr[2], IPBUF->srcipaddr[3], IPBUF->destipaddr[0], IPBUF->destipaddr[1], IPBUF->destipaddr[2], IPBUF->destipaddr[3]);*/ } else if(ICMPBUF->type == ICMP_ECHO_REPLY) { return s(" pong", n(IPBUF->destipaddr[3], d( n(IPBUF->destipaddr[2], d( n(IPBUF->destipaddr[1], d( n(IPBUF->destipaddr[0], s(" ", n(IPBUF->srcipaddr[3], d( n(IPBUF->srcipaddr[2], d( n(IPBUF->srcipaddr[1], d( n(IPBUF->srcipaddr[0], buf)))))))))))))))) - buf; /* return sprintf(buf, "%d.%d.%d.%d %d.%d.%d.%d pong", IPBUF->srcipaddr[0], IPBUF->srcipaddr[1], IPBUF->srcipaddr[2], IPBUF->srcipaddr[3], IPBUF->destipaddr[0], IPBUF->destipaddr[1], IPBUF->destipaddr[2], IPBUF->destipaddr[3]);*/ } } else if(IPBUF->proto == UIP_PROTO_UDP) { return s(" UDP", n(uip_htons(UDPBUF->destport), d( n(IPBUF->destipaddr[3], d( n(IPBUF->destipaddr[2], d( n(IPBUF->destipaddr[1], d( n(IPBUF->destipaddr[0], s(" ", n(uip_htons(UDPBUF->srcport), d( n(IPBUF->srcipaddr[3], d( n(IPBUF->srcipaddr[2], d( n(IPBUF->srcipaddr[1], d( n(IPBUF->srcipaddr[0], buf)))))))))))))))))))) - buf; /* return sprintf(buf, "%d.%d.%d.%d.%d %d.%d.%d.%d.%d UDP", IPBUF->srcipaddr[0], IPBUF->srcipaddr[1], IPBUF->srcipaddr[2], IPBUF->srcipaddr[3], uip_htons(UDPBUF->srcport), IPBUF->destipaddr[0], IPBUF->destipaddr[1], IPBUF->destipaddr[2], IPBUF->destipaddr[3], uip_htons(UDPBUF->destport));*/ } else if(IPBUF->proto == UIP_PROTO_TCP) { tcpflags(TCPBUF->flags, flags); return s(flags, s(" ", n(uip_htons(TCPBUF->destport), d( n(IPBUF->destipaddr[3], d( n(IPBUF->destipaddr[2], d( n(IPBUF->destipaddr[1], d( n(IPBUF->destipaddr[0], s(" ", n(uip_htons(TCPBUF->srcport), d( n(IPBUF->srcipaddr[3], d( n(IPBUF->srcipaddr[2], d( n(IPBUF->srcipaddr[1], d( n(IPBUF->srcipaddr[0], buf))))))))))))))))))))) - buf; /* return sprintf(buf, "%d.%d.%d.%d.%d %d.%d.%d.%d.%d %s", IPBUF->srcipaddr[0], IPBUF->srcipaddr[1], IPBUF->srcipaddr[2], IPBUF->srcipaddr[3], uip_htons(TCPBUF->srcport), IPBUF->destipaddr[0], IPBUF->destipaddr[1], IPBUF->destipaddr[2], IPBUF->destipaddr[3], uip_htons(TCPBUF->destport), flags); */ } else { strcpy(buf, "Unrecognized protocol"); } return 0; }
/*---------------------------------------------------------------------------*/ int ip64_6to4(const uint8_t *ipv6packet, const uint16_t ipv6packet_len, uint8_t *resultpacket) { struct ipv4_hdr *v4hdr; struct ipv6_hdr *v6hdr; struct udp_hdr *udphdr; struct tcp_hdr *tcphdr; struct icmpv4_hdr *icmpv4hdr; struct icmpv6_hdr *icmpv6hdr; uint16_t ipv6len, ipv4len; struct ip64_addrmap_entry *m; v6hdr = (struct ipv6_hdr *)ipv6packet; v4hdr = (struct ipv4_hdr *)resultpacket; if((v6hdr->len[0] << 8) + v6hdr->len[1] <= ipv6packet_len) { ipv6len = (v6hdr->len[0] << 8) + v6hdr->len[1] + IPV6_HDRLEN; } else { PRINTF("ip64_6to4: packet smaller than reported in IPv6 header, dropping\n"); return 0; } /* We copy the data from the IPv6 packet into the IPv4 packet. We do not modify the data in any way. */ memcpy(&resultpacket[IPV4_HDRLEN], &ipv6packet[IPV6_HDRLEN], ipv6len - IPV6_HDRLEN); udphdr = (struct udp_hdr *)&resultpacket[IPV4_HDRLEN]; tcphdr = (struct tcp_hdr *)&resultpacket[IPV4_HDRLEN]; icmpv4hdr = (struct icmpv4_hdr *)&resultpacket[IPV4_HDRLEN]; icmpv6hdr = (struct icmpv6_hdr *)&ipv6packet[IPV6_HDRLEN]; /* Translate the IPv6 header into an IPv4 header. */ /* First the basics: the IPv4 version, header length, type of service, and offset fields. Those are the same for all IPv4 packets we send, regardless of the values found in the IPv6 packet. */ v4hdr->vhl = 0x45; v4hdr->tos = 0; v4hdr->ipoffset[0] = v4hdr->ipoffset[1] = 0; /* We assume that the IPv6 packet has a fixed size header with no extension headers, and compute the length of the IPv4 packet and place the resulting value in the IPv4 packet header. */ ipv4len = ipv6len - IPV6_HDRLEN + IPV4_HDRLEN; v4hdr->len[0] = ipv4len >> 8; v4hdr->len[1] = ipv4len & 0xff; /* For simplicity, we set a unique IP id for each outgoing IPv4 packet. */ ipid++; v4hdr->ipid[0] = ipid >> 8; v4hdr->ipid[1] = ipid & 0xff; /* Set the IPv4 protocol. We only support TCP, UDP, and ICMP at this point. While the IPv4 header protocol numbers are the same as the IPv6 next header numbers, the ICMPv4 and ICMPv6 numbers are different so we cannot simply copy the contents of the IPv6 next header field. */ switch(v6hdr->nxthdr) { case IP_PROTO_TCP: PRINTF("ip64_6to4: TCP header\n"); v4hdr->proto = IP_PROTO_TCP; break; case IP_PROTO_UDP: PRINTF("ip64_6to4: UDP header\n"); v4hdr->proto = IP_PROTO_UDP; break; case IP_PROTO_ICMPV6: PRINTF("ip64_6to4: ICMPv6 header\n"); v4hdr->proto = IP_PROTO_ICMPV4; /* Translate only ECHO_REPLY messages. */ if(icmpv6hdr->type == ICMP6_ECHO_REPLY) { icmpv4hdr->type = ICMP_ECHO_REPLY; } else { PRINTF("ip64_6to4: ICMPv6 mapping for type %d not implemented.\n", icmpv6hdr->type); return 0; } break; default: /* We did not recognize the next header, and we do not attempt to translate something we do not understand, so we return 0 to indicate that no successful translation could be made. */ PRINTF("ip64_6to4: Could not convert IPv6 next hop %d to an IPv4 protocol number.\n", v6hdr->nxthdr); return 0; } /* We set the IPv4 ttl value to the hoplim number from the IPv6 header. This means that information about the IPv6 topology is transported into to the IPv4 network. */ v4hdr->ttl = v6hdr->hoplim; /* We next convert the destination address. We make this conversion with the ip64_addr_6to4() function. If the conversion fails, ip64_addr_6to4() returns 0. If so, we also return 0 to indicate failure. */ if(ip64_addr_6to4(&v6hdr->destipaddr, &v4hdr->destipaddr) == 0) { PRINTF("ip64_6to4: Could not convert IPv6 destination address.\n"); uip_debug_ipaddr_print(&v6hdr->destipaddr); PRINTF("\n"); return 0; } /* We set the source address in the IPv4 packet to be the IPv4 address that we have been configured with through the ip64_set_ipv4_address() function. Only let broadcasts through. */ if(!ip64_hostaddr_configured && !uip_ip4addr_cmp(&v4hdr->destipaddr, &ipv4_broadcast_addr)) { PRINTF("ip64_6to4: no IPv4 address configured.\n"); return 0; } ip64_addr_copy4(&v4hdr->srcipaddr, &ip64_hostaddr); /* Next we update the transport layer header. This must be updated in two ways: the source port number is changed and the transport layer checksum must be recomputed. The reason why we change the source port number is so that we can remember what IPv6 address this packet came from, in case the packet will result in a reply from the host on the IPv4 network. If a reply would be sent, it would be sent to the port number that we chose, and we will be able to map this back to the IPv6 address of the original sender of the packet. */ /* We check to see if we already have an existing IP address mapping for this connection. If not, we create a new one. */ if((v4hdr->proto == IP_PROTO_UDP || v4hdr->proto == IP_PROTO_TCP)) { if(ip64_special_ports_outgoing_is_special(uip_ntohs(udphdr->srcport))) { uint16_t newport; if(ip64_special_ports_translate_outgoing(uip_ntohs(udphdr->srcport), &v6hdr->srcipaddr, &newport)) { udphdr->srcport = uip_htons(newport); } } else if(uip_ntohs(udphdr->srcport) >= EPHEMERAL_PORTRANGE) { m = ip64_addrmap_lookup(&v6hdr->srcipaddr, uip_ntohs(udphdr->srcport), &v4hdr->destipaddr, uip_ntohs(udphdr->destport), v4hdr->proto); if(m == NULL) { PRINTF("Lookup failed\n"); m = ip64_addrmap_create(&v6hdr->srcipaddr, uip_ntohs(udphdr->srcport), &v4hdr->destipaddr, uip_ntohs(udphdr->destport), v4hdr->proto); if(m == NULL) { PRINTF("Could not create new map\n"); return 0; } else { PRINTF("Could create new local port %d\n", m->mapped_port); } } else { PRINTF("Lookup: found local port %d (%d)\n", m->mapped_port, uip_htons(m->mapped_port)); } udphdr->srcport = uip_htons(m->mapped_port); } } /* The IPv4 header is now complete, so we can compute the IPv4 header checksum. */ v4hdr->ipchksum = 0; v4hdr->ipchksum = ~(ipv4_checksum(v4hdr)); /* The checksum is in different places in the different protocol headers, so we need to be sure that we update the correct field. */ switch(v4hdr->proto) { case IP_PROTO_TCP: tcphdr->tcpchksum = 0; tcphdr->tcpchksum = ~(ipv4_transport_checksum(resultpacket, ipv4len, IP_PROTO_TCP)); break; case IP_PROTO_UDP: udphdr->udpchksum = 0; udphdr->udpchksum = ~(ipv4_transport_checksum(resultpacket, ipv4len, IP_PROTO_UDP)); if(udphdr->udpchksum == 0) { udphdr->udpchksum = 0xffff; } break; case IP_PROTO_ICMPV4: icmpv4hdr->icmpchksum = 0; icmpv4hdr->icmpchksum = ~(ipv4_transport_checksum(resultpacket, ipv4len, IP_PROTO_ICMPV4)); break; default: PRINTF("ip64_6to4: transport protocol %d not implemented\n", v4hdr->proto); return 0; } /* Finally, we return the length of the resulting IPv4 packet. */ PRINTF("ip64_6to4: ipv4len %d\n", ipv4len); return ipv4len; }
bool sendUDP(NetworkSocket * networkSocket, NetworkAddress * destAddress, const uint8_t * buffer, int bufferLength) { uip_udp_packet_sendto(networkSocket->Socket, buffer, bufferLength, &destAddress->Address, uip_htons(destAddress->Port)); return true; }
PROCESS_THREAD(usb_eth_process, ev , data) { PROCESS_BEGIN(); usb_register_request_handler(&cdc_eth_request_hook); usb_setup(); usb_set_ep_event_process(DATA_OUT, process_current); usb_set_global_event_process(process_current); uip_fw_default(&usbethif); uip_setethaddr(default_uip_ethaddr); uip_arp_init(); while(1) { PROCESS_WAIT_EVENT(); if (ev == PROCESS_EVENT_EXIT) break; if (ev == PROCESS_EVENT_POLL) { unsigned int events = usb_get_global_events(); if (events) { if (events & USB_EVENT_CONFIG) { if (usb_get_current_configuration() != 0) { printf("Configured\n"); usb_setup_bulk_endpoint(DATA_IN); usb_setup_bulk_endpoint(DATA_OUT); usb_setup_interrupt_endpoint(INTERRUPT_IN); init_recv_buffer(); usb_submit_recv_buffer(DATA_OUT, &recv_buffer); #if 0 { static const uint8_t foo[4] = {0x12,0x34,0x56,0x78}; xmit_buffer[0].next = NULL; xmit_buffer[0].left = sizeof(foo); xmit_buffer[0].flags = USB_BUFFER_SHORT_END; xmit_buffer[0].data = &foo; usb_submit_xmit_buffer(DATA_IN, &xmit_buffer[0]); } #endif } else { usb_disable_endpoint(DATA_IN); usb_disable_endpoint(DATA_OUT); usb_disable_endpoint(INTERRUPT_IN); } } } events = usb_get_ep_events(DATA_OUT); if (events & USB_EP_EVENT_NOTIFICATION) { uip_len = sizeof(recv_data) - recv_buffer.left; /* printf("Received: %d bytes\n", uip_len); */ memcpy(uip_buf, recv_data, uip_len); #if UIP_CONF_IPV6 if(BUF->type == uip_htons(UIP_ETHTYPE_IPV6)) { uip_neighbor_add(&IPBUF->srcipaddr, &BUF->src); tcpip_input(); } else #endif /* UIP_CONF_IPV6 */ if(BUF->type == uip_htons(UIP_ETHTYPE_IP)) { uip_len -= sizeof(struct uip_eth_hdr); tcpip_input(); } else if(BUF->type == uip_htons(UIP_ETHTYPE_ARP)) { uip_arp_arpin(); /* If the above function invocation resulted in data that should be sent out on the network, the global variable uip_len is set to a value > 0. */ if (uip_len > 0) { memcpy(xmit_data, uip_buf, uip_len); xmit_buffer[0].next = NULL; xmit_buffer[0].data = xmit_data; xmit_buffer[0].left = uip_len; xmit_buffer[0].flags = USB_BUFFER_SHORT_END; usb_submit_xmit_buffer(DATA_IN, &xmit_buffer[0]); /* printf("Sent: %d bytes\n", uip_len); */ } } init_recv_buffer(); usb_submit_recv_buffer(DATA_OUT, &recv_buffer); } } } PROCESS_END(); }
/*---------------------------------------------------------------------------*/ static void newdata(void) { unsigned char *nameptr; struct dns_answer *ans; struct dns_hdr *hdr; static u8_t nanswers; static u8_t i; register struct namemap *namemapptr; hdr = (struct dns_hdr *)uip_appdata; /* printf("ID %d\n", uip_htons(hdr->id)); printf("Query %d\n", hdr->flags1 & DNS_FLAG1_RESPONSE); printf("Error %d\n", hdr->flags2 & DNS_FLAG2_ERR_MASK); printf("Num questions %d, answers %d, authrr %d, extrarr %d\n", uip_htons(hdr->numquestions), uip_htons(hdr->numanswers), uip_htons(hdr->numauthrr), uip_htons(hdr->numextrarr)); */ /* The ID in the DNS header should be our entry into the name table. */ i = uip_htons(hdr->id); namemapptr = &names[i]; if(i < RESOLV_ENTRIES && namemapptr->state == STATE_ASKING) { /* This entry is now finished. */ namemapptr->state = STATE_DONE; namemapptr->err = hdr->flags2 & DNS_FLAG2_ERR_MASK; /* Check for error. If so, call callback to inform. */ if(namemapptr->err != 0) { namemapptr->state = STATE_ERROR; resolv_found(namemapptr->name, NULL); return; } /* We only care about the question(s) and the answers. The authrr and the extrarr are simply discarded. */ nanswers = uip_htons(hdr->numanswers); /* Skip the name in the question. XXX: This should really be checked agains the name in the question, to be sure that they match. */ nameptr = parse_name((unsigned char *)uip_appdata + 12) + 4; while(nanswers > 0) { /* The first byte in the answer resource record determines if it is a compressed record or a normal one. */ if(*nameptr & 0xc0) { /* Compressed name. */ nameptr +=2; /* printf("Compressed anwser\n");*/ } else { /* Not compressed name. */ nameptr = parse_name((unsigned char *)nameptr); } ans = (struct dns_answer *)nameptr; /* printf("Answer: type %x, class %x, ttl %x, length %x\n", uip_htons(ans->type), uip_htons(ans->dclass), (uip_htons(ans->ttl[0]) << 16) | uip_htons(ans->ttl[1]), uip_htons(ans->len));*/ /* Check for IP address type and Internet class. Others are discarded. */ if(ans->type == UIP_HTONS(1) && ans->dclass == UIP_HTONS(1) && ans->len == UIP_HTONS(4)) { /* printf("IP address %d.%d.%d.%d\n", uip_htons(ans->ipaddr[0]) >> 8, uip_htons(ans->ipaddr[0]) & 0xff, uip_htons(ans->ipaddr[1]) >> 8, uip_htons(ans->ipaddr[1]) & 0xff);*/ /* XXX: we should really check that this IP address is the one we want. */ namemapptr->ipaddr[0] = ans->ipaddr[0]; namemapptr->ipaddr[1] = ans->ipaddr[1]; resolv_found(namemapptr->name, namemapptr->ipaddr); return; } else { nameptr = nameptr + 10 + uip_htons(ans->len); } --nanswers; } } }
PROCESS_THREAD(tftpd_process, ev, data) { static struct etimer t; static tftp_header *h; static int len, block, ack; static int tries; static int fd = -1; #if WITH_EXEC static char *elf_err; #endif PROCESS_BEGIN(); etimer_set(&t, CLOCK_CONF_SECOND*3); PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_TIMER); setup_server(); #if WITH_EXEC elfloader_init(); #endif print_local_addresses(); while(1) { /* connection from client */ RECV_PACKET(h); len = 0; init_config(); if(h->op == uip_htons(TFTP_RRQ)) { connect_back(); PRINTF("< rrq for %s\n", h->filename); len += strlen(h->filename)+1; if(strcmp("octet", h->filename+len)) { send_error(EUNDEF, "only octet mode supported"); goto close_connection; } len += strlen(h->filename+len)+1; /* skip mode */ parse_opts(h->options+len, uip_datalen()-len-2); if(config.to_ack & OACK_ERROR) { send_error(EOPTNEG, ""); goto close_connection; } fd = cfs_open(h->filename, CFS_READ); if(fd<0) { send_error(ENOTFOUND, ""); goto close_connection; } block = 0; ack = 0; tries = TFTP_MAXTRIES; PRINTF("starting transfer...\n"); for(;;) { if(send_oack()) len = config.blksize; /* XXX hack to prevent loop exit*/ else len = send_data(fd, block+1); if(len<0) { send_error(EUNDEF, "read failed"); goto close_file; } RECV_PACKET_TIMEOUT(h,t); if(ev == PROCESS_EVENT_TIMER) { PRINTF("ack timed out, tries left: %d\n", tries); if(--tries<=0) goto close_file; continue; } if(h->op != uip_htons(TFTP_ACK)) { send_error(EBADOP, ""); goto close_file; } config.to_ack = 0; tries = TFTP_MAXTRIES; ack = uip_htons(h->block_nr); if(ack == block+1) block++; if(len < config.blksize && ack == block) goto done; } } else if(h->op == uip_htons(TFTP_WRQ)) { connect_back(); PRINTF("< wrq for %s\n", h->filename); len += strlen(h->filename)+1; strncpy(config.filename, h->filename, sizeof(config.filename)-1); if(strcmp("octet", h->filename+strlen(h->filename)+1)) { send_error(EUNDEF, "only octet mode supported"); goto close_connection; } len += strlen(h->filename+len)+1; /* skip mode */ parse_opts(h->options+len, uip_datalen()-len-2); if(config.to_ack & OACK_ERROR) { send_error(EOPTNEG, ""); goto close_connection; } cfs_remove(h->filename); fd = cfs_open(h->filename, CFS_WRITE); if(fd<0) { send_error(EACCESS, ""); goto close_connection; } block = 0; ack = 0; tries = TFTP_MAXTRIES; PRINTF("starting transfer...\n"); if(!send_oack()) send_ack(block); for(;;) { RECV_PACKET_TIMEOUT(h,t); if(ev == PROCESS_EVENT_TIMER) { PRINTF("data timed out, tries left: %d\n", tries); if(--tries<=0) goto close_file; len = config.blksize; /* XXX hack to prevent loop exit*/ goto resend_ack; } if(h->op != uip_htons(TFTP_DATA)) { send_error(EBADOP, ""); goto close_file; } config.to_ack = 0; tries = TFTP_MAXTRIES; ack = uip_htons(h->block_nr); if(ack != block+1) continue; /* else */ block++; len = recv_data(fd, block); if(len<0) { send_error(EUNDEF, "write failed"); goto close_file; } #if WITH_EXEC if(len < config.blksize) { if(config.exec) { if(exec_file(config.filename, &elf_err) != 0) { send_error(EUNDEF, elf_err); goto close_file; } } } #endif resend_ack: if(!send_oack()) send_ack(block); if(len < config.blksize) goto done; } } done: PRINTF("done.\n"); close_file: if(fd>=0) cfs_close(fd); fd = -1; close_connection: if(client_conn) uip_udp_remove(client_conn); client_conn = 0; PRINTF("connection closed.\n"); } PROCESS_END(); }
int netSockConnect(UosFile* file, uip_ipaddr_t* ip, int port) { struct uip_conn* tcp; struct uip_udp_conn* udp; P_ASSERT("netSockConnect", file->fs->cf == &netFSConf); NetSock* sock = (NetSock*)file->fsPriv; #if UIP_ACTIVE_OPEN == 1 P_ASSERT("sockConnect", (sock->state == NET_SOCK_UNDEF_TCP || sock->state == NET_SOCK_UNDEF_UDP || sock->state == NET_SOCK_BOUND || sock->state == NET_SOCK_BOUND_UDP)); #else P_ASSERT("sockConnect", (sock->state == NET_SOCK_UNDEF_UDP || NET_SOCK_BOUND_UDP)); #endif if (sock->state == NET_SOCK_UNDEF_TCP) { #if UIP_ACTIVE_OPEN == 1 posMutexLock(uipMutex); tcp = uip_connect(ip, uip_htons(port)); if (tcp == NULL) { posMutexUnlock(uipMutex); return -1; } tcp->appstate.file = file; posMutexLock(sock->mutex); sock->state = NET_SOCK_CONNECT; posMutexUnlock(uipMutex); while (sock->state == NET_SOCK_CONNECT) { posMutexUnlock(sock->mutex); posFlagGet(sock->uipChange, POSFLAG_MODE_GETMASK); posMutexLock(sock->mutex); } if (sock->state == NET_SOCK_PEER_CLOSED || sock->state == NET_SOCK_PEER_ABORTED) { posMutexUnlock(sock->mutex); uosFileClose(file); return -1; } P_ASSERT("sockConnect", sock->state == NET_SOCK_CONNECT_OK); sock->state = NET_SOCK_BUSY; #endif } else { #if UIP_CONF_UDP == 1 posMutexLock(uipMutex); udp = uip_udp_new(ip, uip_htons(port)); if (udp == NULL) { posMutexUnlock(uipMutex); return -1; } udp->appstate.file = file; if (sock->state == NET_SOCK_BOUND_UDP) uip_udp_bind(udp, sock->port); sock->state = NET_SOCK_BUSY; posMutexUnlock(uipMutex); #endif } return 0; }
/*---------------------------------------------------------------------*/ static PT_THREAD(recv_udpthread(struct pt *pt)) { int len; struct codeprop_udphdr *uh = (struct codeprop_udphdr *)uip_appdata; /* if(uip_newdata()) { PRINTF(("recv_udpthread: id %d uh->id %d\n", s.id, uip_htons(uh->id))); }*/ PT_BEGIN(pt); while(1) { do { PT_WAIT_UNTIL(pt, uip_newdata() && uh->type == UIP_HTONS(TYPE_DATA) && uip_htons(uh->id) > s.id); if(uip_htons(uh->addr) != 0) { s.addr = 0; send_nack(uh, 0); } } while(uip_htons(uh->addr) != 0); leds_on(LEDS_YELLOW); s.addr = 0; s.id = uip_htons(uh->id); s.len = uip_htons(uh->len); timer_set(&s.timer, CONNECTION_TIMEOUT); process_post(PROCESS_BROADCAST, codeprop_event_quit, (process_data_t)NULL); while(s.addr < s.len) { if(uip_htons(uh->addr) == s.addr) { leds_blink(); len = uip_datalen() - UDPHEADERSIZE; if(len > 0) { eeprom_write(EEPROMFS_ADDR_CODEPROP + s.addr, &uh->data[0], len); PRINTF(("Saved %d bytes at address %d, %d bytes left\n", uip_datalen() - UDPHEADERSIZE, s.addr, s.len - s.addr)); s.addr += len; } } else if(uip_htons(uh->addr) > s.addr) { PRINTF(("sending nack since 0x%x != 0x%x\n", uip_htons(uh->addr), s.addr)); send_nack(uh, s.addr); } if(s.addr < s.len) { /* timer_set(&s.nacktimer, NACK_TIMEOUT);*/ do { timer_set(&s.nacktimer, HIT_NACK_TIMEOUT); PT_YIELD_UNTIL(pt, timer_expired(&s.nacktimer) || (uip_newdata() && uh->type == UIP_HTONS(TYPE_DATA) && uip_htons(uh->id) == s.id)); if(timer_expired(&s.nacktimer)) { send_nack(uh, s.addr); } } while(timer_expired(&s.nacktimer)); } } leds_off(LEDS_YELLOW); /* printf("Received entire bunary over udr\n");*/ process_post(PROCESS_BROADCAST, codeprop_event_quit, (process_data_t)NULL); process_post(&codeprop_process, EVENT_START_PROGRAM, NULL); PT_EXIT(pt); } PT_END(pt); }
/*---------------------------------------------------------------------------*/ u16_t uip_chksum(u16_t *data, u16_t len) { return uip_htons(chksum(0, (u8_t *)data, len)); }
/*---------------------------------------------------------------------------*/ void ipv6cp_task(u8_t *buffer) { u8_t *bptr; u16_t t; IPCPPKT *pkt; /* IPCP tx not up and hasn't timed out then lets see if we need to send a request */ if(!(ipv6cp_state & IPV6CP_TX_UP) && !(ipv6cp_state & IPV6CP_TX_TIMEOUT)) { /* Check if we have a request pending */ /*t=get_seconds()-ipv6cp_tx_time;*/ #if 1//0//phlb modify if(TIMER_timeout(IPV6CP_TIMEOUT)) { #else if((clock_seconds() - prev_ipv6cp_seconds) > IPV6CP_TIMEOUT) { prev_ipv6cp_seconds = clock_seconds(); #endif /* * No pending request, lets build one */ pkt=(IPCPPKT *)buffer; /* Configure-Request only here, write id */ pkt->code = CONF_REQ; pkt->id = ppp_id; bptr = (u8_t*)&pkt->data; /* * Write options, we want IP address, and DNS addresses if set. */ /* Write zeros for IP address the first time */ *bptr++ = 0x01;//IPV6CP_IPADDRESS; *bptr++ = 0x0a;//10 *bptr++ = ((u8_t*)uip_hostaddr.u8)[8]; *bptr++ = ((u8_t*)uip_hostaddr.u8)[9]; *bptr++ = ((u8_t*)uip_hostaddr.u8)[10]; *bptr++ = ((u8_t*)uip_hostaddr.u8)[11]; *bptr++ = ((u8_t*)uip_hostaddr.u8)[12]; *bptr++ = ((u8_t*)uip_hostaddr.u8)[13]; *bptr++ = ((u8_t*)uip_hostaddr.u8)[14]; *bptr++ = ((u8_t*)uip_hostaddr.u8)[15]; #ifdef IPV6CP_GET_PRI_DNS if(!(ipv6cp_state & IPCP_PRI_DNS_BIT)) { /* Write zeros for IP address the first time */ *bptr++ = IPV6CP_PRIMARY_DNS; *bptr++ = 0x6; *bptr++ = ((u8_t*)pri_dns_addr.u8)[0]; *bptr++ = ((u8_t*)pri_dns_addr.u8)[1]; *bptr++ = ((u8_t*)pri_dns_addr.u8)[2]; *bptr++ = ((u8_t*)pri_dns_addr.u8)[3]; } #endif #ifdef IPV6CP_GET_SEC_DNS if(!(ipv6cp_state & IPV6CP_SEC_DNS_BIT)) { /* Write zeros for IP address the first time */ *bptr++ = IPV6CP_SECONDARY_DNS; *bptr++ = 0x6; *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]; } #endif /* Write length */ t = bptr - buffer; /* length here - code and ID + */ pkt->len = uip_htons(t); ANNOTATE("\n**Sending IPV6CP Request packet\n"); /* Send packet ahdlc_txz(procol,header,data,headerlen,datalen); */ ahdlc_tx(IPV6CP, 0, buffer, 0, t); /* Set timer */ /*ipv6cp_tx_time=get_seconds();*/ TIMER_set(); /* Inc retry */ /*ipv6cp_retry++;*/ // ppp_retry++; /* * Have we timed out? (combide the timers?) */ if(ppp_retry > IPV6CP_RETRY_COUNT) ipv6cp_state |= IPV6CP_TX_TIMEOUT; } } }
/* handle_data(): * * Handles the data. */ static unsigned short handle_data(CC_REGISTER_ARG uint8_t *data, uint16_t datalen) { switch(vs->waitmsg) { case VNC_WAIT_VERSION: /* Make sure we get the right version string from the server. */ /* XXX: not implemented. */ PRINTF(("Got version, waiting for auth, sending version\n")); vs->waitmsg = VNC_WAIT_AUTH; vs->sendmsg = VNC_SEND_VERSION; break; case VNC_WAIT_AUTH: switch(data[3]) { case RFB_AUTH_FAILED: PRINTF(("Connection failed.\n")); uip_abort(); return 0; case RFB_AUTH_NONE: vs->sendmsg = VNC_SEND_CINIT; vs->waitmsg = VNC_WAIT_SINIT; PRINTF(("No authentication needed.\n")); break; case RFB_AUTH_VNC: vs->sendmsg = VNC_SEND_AUTH; vs->waitmsg = VNC_WAIT_AUTH_RESPONSE; PRINTF(("VNC authentication needed.\n")); break; } break; case VNC_WAIT_SINIT: /* PRINTF(("Server init: w %d h %d, bps %d, d %d, name '%s'\n", uip_htons(((struct rfb_server_init *)data)->width), uip_htons(((struct rfb_server_init *)data)->height), ((struct rfb_server_init *)data)->format.bps, ((struct rfb_server_init *)data)->format.depth, ((uint8_t *)data + sizeof(struct rfb_server_init))));*/ vs->w = uip_htons(((struct rfb_server_init *)data)->width); vs->h = uip_htons(((struct rfb_server_init *)data)->height); vs->sendmsg = VNC_SEND_PFMT; vs->waitmsg = VNC_WAIT_NONE; break; case VNC_WAIT_UPDATE: case VNC_WAIT_NONE: switch(*data) { case RFB_FB_UPDATE: vs->waitmsg = VNC_WAIT_UPDATE_RECT; vs->rectsleft = uip_htons(((struct rfb_fb_update *)data)->rects); PRINTF(("Handling RFB FB UPDATE for %d rects\n", vs->rectsleft)); break; case RFB_BELL: PRINTF(("BELL\n")); break; case RFB_SERVER_CUT_TEXT: PRINTF(("Cut text received, unhandled\n")); break; case RFB_SET_COLORMAP_ENTRIES: PRINTF(("Set colormap entries received, unhandled\n")); break; default: PRINTF(("Weird message type received (%d)\n", *(uint8_t *)data)); break; } break; case VNC_WAIT_UPDATE_RECT: PRINTF(("Handling data in WAIT_UPDATE_RECT, %d rects left (%d bytes)\n", vs->rectsleft, datalen)); --vs->rectsleft; if(vs->rectsleft > 0) { vs->waitmsg = VNC_WAIT_UPDATE_RECT; } else { vs->waitmsg = VNC_WAIT_NONE; vs->sendmsg = VNC_SEND_NONE; vs->rectstate = VNC_RECTSTATE_NONE; } return recv_update_rect((struct rfb_fb_update_rect_hdr *)data, datalen); break; } return 0; }
/** * \brief Take a packet received over the 802.15.4 link, and send it * out over ethernet, performing any translations needed. */ void mac_LowpanToEthernet(void) { #if !RF230BB parsed_frame = sicslowmac_get_frame(); #endif //Setup generic ethernet stuff ETHBUF(uip_buf)->type = uip_htons(UIP_ETHTYPE_IPV6); //Check for broadcast message #if RF230BB if(linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &linkaddr_null)) { // if(linkaddr_cmp((const linkaddr_t *)destAddr, &linkaddr_null)) { #else if( ( parsed_frame->fcf->destAddrMode == SHORTADDRMODE) && ( parsed_frame->dest_addr->addr16 == 0xffff) ) { #endif ETHBUF(uip_buf)->dest.addr[0] = 0x33; ETHBUF(uip_buf)->dest.addr[1] = 0x33; #if UIP_CONF_IPV6 ETHBUF(uip_buf)->dest.addr[2] = UIP_IP_BUF->destipaddr.u8[12]; ETHBUF(uip_buf)->dest.addr[3] = UIP_IP_BUF->destipaddr.u8[13]; ETHBUF(uip_buf)->dest.addr[4] = UIP_IP_BUF->destipaddr.u8[14]; ETHBUF(uip_buf)->dest.addr[5] = UIP_IP_BUF->destipaddr.u8[15]; #else //Not intended to be functional, but allows ip4 build without errors. ETHBUF(uip_buf)->dest.addr[2] = UIP_IP_BUF->destipaddr.u8[0]; ETHBUF(uip_buf)->dest.addr[3] = UIP_IP_BUF->destipaddr.u8[1]; ETHBUF(uip_buf)->dest.addr[4] = UIP_IP_BUF->destipaddr.u8[2]; ETHBUF(uip_buf)->dest.addr[5] = UIP_IP_BUF->destipaddr.u8[3]; #endif } else { //Otherwise we have a real address mac_createEthernetAddr((uint8_t *) &(ETHBUF(uip_buf)->dest.addr[0]), (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); } #if !UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS //Source ethernet depends on node if(!mac_createEthernetAddr( (uint8_t *) &(ETHBUF(uip_buf)->src.addr[0]), (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER) )) #endif { mac_createDefaultEthernetAddr((uint8_t *) &(ETHBUF(uip_buf)->src.addr[0])); } //We only do address translation in network mode! if (usbstick_mode.translate) { //Some IP packets have link layer in them, need to change them around! mac_translateIPLinkLayer(ll_8023_type); } #if UIP_CONF_IPV6_RPL /* We won't play ping-pong with the host! */ if(uip_ipaddr_cmp(&last_sender, &UIP_IP_BUF->srcipaddr)) { PRINTF("siclow_ethernet: Destination off-link but no route\n"); uip_len=0; return; } #endif PRINTF("Low2Eth: Sending packet to ethernet\n\r"); uip_len += UIP_LLH_LEN; usb_eth_send(uip_buf, uip_len, 1); #if !RF230BB usb_eth_stat.rxok++; #endif uip_len = 0; } /** * \brief Translate IP packet's possible link-layer addresses, passing * the message to the appropriate higher level function for this * packet (aka: ICMP) * \param target The target we want to end up with - either ll_8023_type * for ethernet, or ll_802154_type for 802.15.4 * \return Returns how successful the translation was * \retval 0 Addresses, if present, were translated. * \retval <0 Negative return values indicate various errors, as defined * by the higher level function. */ int8_t mac_translateIPLinkLayer(lltype_t target) { #if UIP_LLADDR_LEN == 8 if (UIP_IP_BUF->proto == UIP_PROTO_ICMP6) { PRINTF("eth2low: ICMP Message detected\n\r"); return mac_translateIcmpLinkLayer(target); } return 0; #else return 1; #endif } #include "net/ipv6/uip-icmp6.h" #include "net/ipv6/uip-nd6.h" typedef struct { uint8_t type; uint8_t length; uint8_t data[16]; } icmp_opts_t; #define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN]) #define UIP_ICMP_OPTS(x) ((icmp_opts_t *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN + x]) void slide(uint8_t * data, uint8_t length, int16_t slide); /** * \brief Translate the link-layer (L2) addresses in an ICMP packet. * This will just be NA/NS/RA/RS packets currently. * \param target The target we want to end up with - either ll_8023_type * for ethernet, or ll_802154_type for 802.15.4 * \return Returns how successful the translation was * \retval 0 Addresses, if present, were translated. * \retval -1 ICMP message was unknown type, nothing done. * \retval -2 ICMP Length does not make sense? * \retval -3 Unknown 'target' type */ int8_t mac_translateIcmpLinkLayer(lltype_t target) { uint16_t icmp_opt_offset = 0; int16_t len = UIP_IP_BUF->len[1] | (UIP_IP_BUF->len[0] << 8); uint16_t iplen; uint8_t i; int16_t sizechange; uint8_t llbuf[16]; //Figure out offset to start of options switch(UIP_ICMP_BUF->type) { case ICMP6_NS: case ICMP6_NA: icmp_opt_offset = 24; break; case ICMP6_RS: icmp_opt_offset = 8; break; case ICMP6_RA: icmp_opt_offset = 16; break; case ICMP6_REDIRECT: icmp_opt_offset = 40; break; /** Things without link-layer */ case ICMP6_DST_UNREACH: case ICMP6_PACKET_TOO_BIG: case ICMP6_TIME_EXCEEDED: case ICMP6_PARAM_PROB: case ICMP6_ECHO_REQUEST: case ICMP6_ECHO_REPLY: return 0; break; default: return -1; } //Figure out length of options len -= icmp_opt_offset; //Sanity check if (len < 8) return -2; //While we have options to do... while (len >= 8){ //If we have one of these, we have something useful! if (((UIP_ICMP_OPTS(icmp_opt_offset)->type) == UIP_ND6_OPT_SLLAO) || ((UIP_ICMP_OPTS(icmp_opt_offset)->type) == UIP_ND6_OPT_TLLAO) ) { /* Shrinking the buffer may thrash things, so we store the old link-layer address */ for(i = 0; i < (UIP_ICMP_OPTS(icmp_opt_offset)->length*8 - 2); i++) { llbuf[i] = UIP_ICMP_OPTS(icmp_opt_offset)->data[i]; } //Shrink/grow buffer as needed if (target == ll_802154_type) { //Current is 802.3, Hence current link-layer option is 6 extra bytes sizechange = 8; slide(UIP_ICMP_OPTS(icmp_opt_offset)->data + 6, len - 6, sizechange); } else if (target == ll_8023_type) { /* Current is 802.15.4, Hence current link-layer option is 14 extra * bytes. * (Actual LL is 8 bytes, but total option length is in multiples of * 8 Bytes, hence 8 + 2 = 10. Closest is 16 bytes, then 16 bytes for * total optional length - 2 bytes for type + length leaves 14 ) */ sizechange = -8; slide(UIP_ICMP_OPTS(icmp_opt_offset)->data + 14, len - 14, sizechange); } else { return -3; //Uh-oh! } //Translate addresses if (target == ll_802154_type) { mac_createSicslowpanLongAddr(llbuf, (uip_lladdr_t *)UIP_ICMP_OPTS(icmp_opt_offset)->data); } else { #if !UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS if(!mac_createEthernetAddr(UIP_ICMP_OPTS(icmp_opt_offset)->data, (uip_lladdr_t *)llbuf)) #endif mac_createDefaultEthernetAddr(UIP_ICMP_OPTS(icmp_opt_offset)->data); } //Adjust the length if (target == ll_802154_type) { UIP_ICMP_OPTS(icmp_opt_offset)->length = 2; } else { UIP_ICMP_OPTS(icmp_opt_offset)->length = 1; } //Adjust the IP header length, as well as uIP length iplen = UIP_IP_BUF->len[1] | (UIP_IP_BUF->len[0]<<8); iplen += sizechange; len += sizechange; UIP_IP_BUF->len[1] = (uint8_t)iplen; UIP_IP_BUF->len[0] = (uint8_t)(iplen >> 8); uip_len += sizechange; //We broke ICMP checksum, be sure to fix that UIP_ICMP_BUF->icmpchksum = 0; #if UIP_CONF_IPV6 //allow non ipv6 builds UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); #endif //Finally set up next run in while loop len -= 8 * UIP_ICMP_OPTS(icmp_opt_offset)->length; icmp_opt_offset += 8 * UIP_ICMP_OPTS(icmp_opt_offset)->length; } else { //Not an option we care about, ignore it len -= 8 * UIP_ICMP_OPTS(icmp_opt_offset)->length; //This shouldn't happen! if (UIP_ICMP_OPTS(icmp_opt_offset)->length == 0) { PRINTF("Option in ND packet has length zero, error?\n\r"); len = 0; } icmp_opt_offset += 8 * UIP_ICMP_OPTS(icmp_opt_offset)->length; } //If ICMP_OPT is one we care about } //while(len >= 8)
/*-----------------------------------------------------------------------------------*/ static void senddata(void) { register uint8_t *dataptr; uint16_t dataleft; dataptr = (uint8_t *)uip_appdata; switch(vs->sendmsg) { case VNC_SEND_VERSION: PRINTF(("Sending VERSION_STRING\n")); uip_send(RFB_SERVER_VERSION_STRING, sizeof(RFB_SERVER_VERSION_STRING)); break; case VNC_SEND_AUTH: /* Send 16 bytes of encrypted challange response. */ /* XXX: not implemented. */ PRINTF(("Sending AUTH\n")); uip_send(uip_appdata, 16); break; case VNC_SEND_CINIT: PRINTF(("Sending CINIT\n")); /* Send one byte of client init. */ *(uint8_t *)dataptr = 1; uip_send(uip_appdata, 1); break; case VNC_SEND_PFMT: PRINTF(("Sending PFMT\n")); ((struct rfb_set_pixel_format *)dataptr)->type = RFB_SET_PIXEL_FORMAT; /* Set to BGR233 pixel format. */ ((struct rfb_set_pixel_format *)dataptr)->format.bps = 8; ((struct rfb_set_pixel_format *)dataptr)->format.depth = 8; ((struct rfb_set_pixel_format *)dataptr)->format.endian = 1; ((struct rfb_set_pixel_format *)dataptr)->format.truecolor = 1; ((struct rfb_set_pixel_format *)dataptr)->format.red_max = uip_htons(7); ((struct rfb_set_pixel_format *)dataptr)->format.green_max = uip_htons(7); ((struct rfb_set_pixel_format *)dataptr)->format.blue_max = uip_htons(3); ((struct rfb_set_pixel_format *)dataptr)->format.red_shift = 0; ((struct rfb_set_pixel_format *)dataptr)->format.green_shift = 3; ((struct rfb_set_pixel_format *)dataptr)->format.blue_shift = 6; uip_send(uip_appdata, sizeof(struct rfb_set_pixel_format)); break; case VNC_SEND_ENCODINGS: PRINTF(("Sending ENCODINGS\n")); ((struct rfb_set_encodings *)dataptr)->type = RFB_SET_ENCODINGS; ((struct rfb_set_encodings *)dataptr)->encodings = uip_htons(1); dataptr += sizeof(struct rfb_set_encodings); dataptr[0] = dataptr[1] = dataptr[2] = 0; dataptr[3] = RFB_ENC_RAW; /* ((uint8_t *)dataptr + sizeof(struct rfb_set_encodings))[4] = ((uint8_t *)dataptr + sizeof(struct rfb_set_encodings))[5] = ((uint8_t *)dataptr + sizeof(struct rfb_set_encodings))[6] = 0; ((uint8_t *)dataptr + sizeof(struct rfb_set_encodings))[7] = RFB_ENC_RRE;*/ uip_send(uip_appdata, sizeof(struct rfb_set_encodings) + 4); break; case VNC_SEND_UPDATERQ: ((struct rfb_fb_update_request *)dataptr)->type = RFB_FB_UPDATE_REQ; ((struct rfb_fb_update_request *)dataptr)->incremental = 0; ((struct rfb_fb_update_request *)dataptr)->x = uip_htons(vnc_draw_viewport_x()); ((struct rfb_fb_update_request *)dataptr)->y = uip_htons(vnc_draw_viewport_y()); ((struct rfb_fb_update_request *)dataptr)->w = uip_htons(vnc_draw_viewport_w()); ((struct rfb_fb_update_request *)dataptr)->h = uip_htons(vnc_draw_viewport_h()); uip_send(uip_appdata, sizeof(struct rfb_fb_update_request)); break; case VNC_SEND_UPDATERQ_INC: ((struct rfb_fb_update_request *)dataptr)->type = RFB_FB_UPDATE_REQ; ((struct rfb_fb_update_request *)dataptr)->incremental = 1; ((struct rfb_fb_update_request *)dataptr)->x = uip_htons(vnc_draw_viewport_x()); ((struct rfb_fb_update_request *)dataptr)->y = uip_htons(vnc_draw_viewport_y()); ((struct rfb_fb_update_request *)dataptr)->w = uip_htons(vnc_draw_viewport_w()); ((struct rfb_fb_update_request *)dataptr)->h = uip_htons(vnc_draw_viewport_h()); uip_send(uip_appdata, sizeof(struct rfb_fb_update_request)); break; case VNC_SEND_EVENTS: dataleft = uip_mss(); vs->eventptr_unacked = vs->eventptr_acked; while(vs->eventptr_unacked != vs->eventptr_next && dataleft > sizeof(struct rfb_key_event)) { switch(vs->event_queue[vs->eventptr_unacked].type) { case VNC_POINTER_EVENT: ((struct rfb_pointer_event *)dataptr)->type = RFB_POINTER_EVENT; ((struct rfb_pointer_event *)dataptr)->buttonmask = vs->event_queue[vs->eventptr_unacked].ev.ptr.buttonmask; ((struct rfb_pointer_event *)dataptr)->x = uip_htons(vs->event_queue[vs->eventptr_unacked].ev.ptr.x); ((struct rfb_pointer_event *)dataptr)->y = uip_htons(vs->event_queue[vs->eventptr_unacked].ev.ptr.y); /* uip_send(uip_appdata, sizeof(struct rfb_pointer_event));*/ dataptr += sizeof(struct rfb_pointer_event); dataleft -= sizeof(struct rfb_pointer_event); break; case VNC_KEY_EVENT: PRINTF(("Send key event.\n")); ((struct rfb_key_event *)dataptr)->type = RFB_KEY_EVENT; ((struct rfb_key_event *)dataptr)->down = vs->event_queue[vs->eventptr_unacked].ev.key.down; ((struct rfb_key_event *)dataptr)->key[0] = ((struct rfb_key_event *)dataptr)->key[1]; ((struct rfb_key_event *)dataptr)->key[2] = vs->event_queue[vs->eventptr_unacked].ev.key.key >> 8; ((struct rfb_key_event *)dataptr)->key[3] = vs->event_queue[vs->eventptr_unacked].ev.key.key & 0xff; /* uip_send(uip_appdata, sizeof(struct rfb_key_event));*/ dataptr += sizeof(struct rfb_key_event); dataleft -= sizeof(struct rfb_key_event); break; case VNC_UPDATERQ_EVENT: ((struct rfb_fb_update_request *)dataptr)->type = RFB_FB_UPDATE_REQ; ((struct rfb_fb_update_request *)dataptr)->incremental = 0; ((struct rfb_fb_update_request *)dataptr)->x = uip_htons(vs->event_queue[vs->eventptr_unacked].ev.urq.x); ((struct rfb_fb_update_request *)dataptr)->y = uip_htons(vs->event_queue[vs->eventptr_unacked].ev.urq.y); ((struct rfb_fb_update_request *)dataptr)->w = uip_htons(vs->event_queue[vs->eventptr_unacked].ev.urq.w); ((struct rfb_fb_update_request *)dataptr)->h = uip_htons(vs->event_queue[vs->eventptr_unacked].ev.urq.h); /* uip_send(uip_appdata, sizeof(struct rfb_fb_update_request)); */ dataptr += sizeof(struct rfb_fb_update_request); dataleft -= sizeof(struct rfb_fb_update_request); break; } vs->eventptr_unacked = (vs->eventptr_unacked + 1) % VNC_EVENTQUEUE_SIZE; } uip_send(uip_appdata, uip_mss() - dataleft); break; } }
/*---------------------------------------------------------------------------*/ void uip_nd6_ra_output(uip_ipaddr_t * dest) { UIP_IP_BUF->vtc = 0x60; UIP_IP_BUF->tcflow = 0; UIP_IP_BUF->flow = 0; UIP_IP_BUF->proto = UIP_PROTO_ICMP6; UIP_IP_BUF->ttl = UIP_ND6_HOP_LIMIT; if(dest == NULL) { uip_create_linklocal_allnodes_mcast(&UIP_IP_BUF->destipaddr); } else { /* For sollicited RA */ uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, dest); } uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); UIP_ICMP_BUF->type = ICMP6_RA; UIP_ICMP_BUF->icode = 0; UIP_ND6_RA_BUF->cur_ttl = uip_ds6_if.cur_hop_limit; UIP_ND6_RA_BUF->flags_reserved = (UIP_ND6_M_FLAG << 7) | (UIP_ND6_O_FLAG << 6); UIP_ND6_RA_BUF->router_lifetime = uip_htons(UIP_ND6_ROUTER_LIFETIME); //UIP_ND6_RA_BUF->reachable_time = uip_htonl(uip_ds6_if.reachable_time); //UIP_ND6_RA_BUF->retrans_timer = uip_htonl(uip_ds6_if.retrans_timer); UIP_ND6_RA_BUF->reachable_time = 0; UIP_ND6_RA_BUF->retrans_timer = 0; uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_RA_LEN; nd6_opt_offset = UIP_ND6_RA_LEN; /* Prefix list */ for(prefix = uip_ds6_prefix_list; prefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; prefix++) { if((prefix->isused) && (prefix->advertise)) { UIP_ND6_OPT_PREFIX_BUF->type = UIP_ND6_OPT_PREFIX_INFO; UIP_ND6_OPT_PREFIX_BUF->len = UIP_ND6_OPT_PREFIX_INFO_LEN / 8; UIP_ND6_OPT_PREFIX_BUF->preflen = prefix->length; UIP_ND6_OPT_PREFIX_BUF->flagsreserved1 = prefix->l_a_reserved; UIP_ND6_OPT_PREFIX_BUF->validlt = uip_htonl(prefix->vlifetime); UIP_ND6_OPT_PREFIX_BUF->preferredlt = uip_htonl(prefix->plifetime); UIP_ND6_OPT_PREFIX_BUF->reserved2 = 0; uip_ipaddr_copy(&(UIP_ND6_OPT_PREFIX_BUF->prefix), &(prefix->ipaddr)); nd6_opt_offset += UIP_ND6_OPT_PREFIX_INFO_LEN; uip_len += UIP_ND6_OPT_PREFIX_INFO_LEN; } } /* Source link-layer option */ create_llao((uint8_t *)UIP_ND6_OPT_HDR_BUF, UIP_ND6_OPT_SLLAO); uip_len += UIP_ND6_OPT_LLAO_LEN; nd6_opt_offset += UIP_ND6_OPT_LLAO_LEN; /* MTU */ UIP_ND6_OPT_MTU_BUF->type = UIP_ND6_OPT_MTU; UIP_ND6_OPT_MTU_BUF->len = UIP_ND6_OPT_MTU_LEN >> 3; UIP_ND6_OPT_MTU_BUF->reserved = 0; //UIP_ND6_OPT_MTU_BUF->mtu = uip_htonl(uip_ds6_if.link_mtu); UIP_ND6_OPT_MTU_BUF->mtu = uip_htonl(1500); uip_len += UIP_ND6_OPT_MTU_LEN; nd6_opt_offset += UIP_ND6_OPT_MTU_LEN; #if UIP_CONF_DS6_ROUTE_INFORMATION for(rtinfo = uip_ds6_route_info_list; rtinfo < uip_ds6_route_info_list + UIP_DS6_ROUTE_INFO_NB; rtinfo++) { if((rtinfo->isused)) { UIP_ND6_OPT_ROUTE_BUF->type = UIP_ND6_OPT_ROUTE_INFO; UIP_ND6_OPT_ROUTE_BUF->len =(rtinfo->length >> 6) + 1 ; UIP_ND6_OPT_ROUTE_BUF->preflen = rtinfo->length; UIP_ND6_OPT_ROUTE_BUF->flagsreserved = rtinfo->flags; UIP_ND6_OPT_ROUTE_BUF->rlifetime = uip_htonl(rtinfo->lifetime); uip_ipaddr_copy(&(UIP_ND6_OPT_ROUTE_BUF->prefix), &(rtinfo->ipaddr)); nd6_opt_offset += ((rtinfo->length >> 6) + 1)<<3; uip_len += ((rtinfo->length >> 6) + 1)<<3; } }
/*-------------------------------------------------------------------------------------------*/ PROCESS_THREAD(test_process, ev, data) { user.userID=1; uip_ipaddr_t ipaddr; ds2401_init(); int ii; for (ii = 0; ii < 7; ii++) { printf("%02x:", ds2401_id[ii]); } printf("%02x\n", ds2401_id[7]); static struct etimer timer; struct udp_tx *udp_tx_info = (udp_tx*) malloc(sizeof(udp_tx)); PROCESS_BEGIN(); uip_ip6addr(&ipaddr, ipv6_addr[0], ipv6_addr[1],ipv6_addr[2],ipv6_addr[3], ipv6_addr[4],ipv6_addr[5],ipv6_addr[6],ipv6_addr[7]); server_conn = udp_new(NULL,UIP_HTONS(0), NULL); server_conn2 = udp_new(&ipaddr,UIP_HTONS(3007), NULL); udp_bind(server_conn, uip_htons(3001)); udp_bind(server_conn2, uip_htons(3005)); memset(udp_tx_info, 0, sizeof(udp_tx)); while(1) { /*--------------------------------------------------------------------------------------------*/ if(Sendonce_flag == 0){ etimer_set(&timer, CLOCK_SECOND*5); PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&timer)); udp_send_register(udp_tx_info); // udp_send_data(udp_tx_info); PRINTF("udp_tx_info->len = %d\r\n",udp_tx_info->len); server_conn2->rport=uip_htons(3007); uip_udp_packet_send(server_conn2, &udp_tx_info->buf[0], udp_tx_info->len); server_conn2->rport=0; Sendonce_flag = 1; printf("Send once!\n"); leds_toggle(LEDS_GREEN); } /*--------------------------------------------------------------------------------------------*/ if(Sample_begin_flag==1) { etimer_set(&timer, CLOCK_SECOND*Sample_Interval); printf("Sample_Interval:%d\n",Sample_Interval); do{ PROCESS_WAIT_EVENT(); if (ev == PROCESS_EVENT_TIMER) { printf("data send lym 001\n"); udp_send_data(udp_tx_info); PRINTF("udp_tx_info->len = %d\r\n",udp_tx_info->len); uip_udp_packet_send(server_conn2, &udp_tx_info->buf[0], udp_tx_info->len); printf("wait\n"); etimer_reset(&timer); leds_toggle(LEDS_GREEN); } else if(ev == tcpip_event) { tcpip_handler(udp_tx_info); } } while(Sample_begin_flag==1); } /*--------------------------------------------------------------------------------------------*/ PROCESS_WAIT_EVENT_UNTIL(ev == tcpip_event); tcpip_handler(udp_tx_info); } PROCESS_END(); }
uip_ipaddr_t * coap_getIpFromURI(const char * uri) { char * ipStart = NULL; char * ipEnd = NULL; static uip_ipaddr_t ipaddr; memset(&ipaddr, 0, sizeof(uip_ipaddr_t)); ipStart = strchr(uri, '[') + 1; if(ipStart != NULL) { ipEnd = strchr(ipStart, ']'); if(ipEnd != NULL) { int ipLen = ipEnd - ipStart; char * str = ipStart; int colonCount; //Count colons for (colonCount = 0; ipEnd != &str[colonCount]; str[colonCount] == ':' ? colonCount++ : *str++); if(colonCount < 8) { int currentWord = 0; int currentNibble = strchr(ipStart, ':') - (ipStart+1); bool jump = false; int i; if((currentNibble > 3) || (currentNibble < 0)) { i = ipLen; } else { i = 0; } for(; i < ipLen; i++) { if(ipStart[i] == ':') { if(ipStart[i+1] == ':') { if(!jump) { currentWord += (8 - colonCount); i++; jump = true; } else { break; } } currentWord++; if(currentWord < 7) { currentNibble = strchr(&ipStart[i]+1, ':') - (&ipStart[i]+2); } else { currentNibble = ipEnd - (&ipStart[i]+2); } if((currentNibble > 3) || (currentNibble < 0)) { break; } } else { if(currentNibble >= 0) { uint8_t nibble; if(convert_nibble((uint8_t)ipStart[i], &nibble) != -1) { ipaddr.u16[currentWord] += nibble << (currentNibble*4); if(currentNibble == 0) { ipaddr.u16[currentWord] = uip_htons(ipaddr.u16[currentWord]); } } else { break; } } else { break; } currentNibble--; } } } } } return &ipaddr; }
/*---------------------------------------------------------------------------*/ static void appcall(void *state) { struct tcp_socket *s = state; if(s != NULL && s->c != NULL && s->c != uip_conn) { /* Safe-guard: this should not happen, as the incoming event relates to * a previous connection */ return; } if(uip_connected()) { /* Check if this connection originated in a local listen socket. We do this by checking the state pointer - if NULL, this is an incoming listen connection. If so, we need to connect the socket to the uip_conn and call the event function. */ if(s == NULL) { for(s = list_head(socketlist); s != NULL; s = list_item_next(s)) { if((s->flags & TCP_SOCKET_FLAGS_LISTENING) != 0 && s->listen_port != 0 && s->listen_port == uip_htons(uip_conn->lport)) { s->flags &= ~TCP_SOCKET_FLAGS_LISTENING; s->output_data_max_seg = uip_mss(); tcp_markconn(uip_conn, s); call_event(s, TCP_SOCKET_CONNECTED); break; } } } else { s->output_data_max_seg = uip_mss(); call_event(s, TCP_SOCKET_CONNECTED); } if(s == NULL) { uip_abort(); } else { if(uip_newdata()) { newdata(s); } senddata(s); } return; } if(uip_timedout()) { call_event(s, TCP_SOCKET_TIMEDOUT); relisten(s); } if(uip_aborted()) { tcp_markconn(uip_conn, NULL); call_event(s, TCP_SOCKET_ABORTED); relisten(s); } if(s == NULL) { uip_abort(); return; } if(uip_acked()) { acked(s); } if(uip_newdata()) { newdata(s); } if(uip_rexmit() || uip_newdata() || uip_acked()) { senddata(s); } else if(uip_poll()) { senddata(s); } if(s->output_data_len == 0 && s->flags & TCP_SOCKET_FLAGS_CLOSING) { s->flags &= ~TCP_SOCKET_FLAGS_CLOSING; uip_close(); s->c = NULL; tcp_markconn(uip_conn, NULL); s->c = NULL; /*call_event(s, TCP_SOCKET_CLOSED);*/ relisten(s); } if(uip_closed()) { tcp_markconn(uip_conn, NULL); s->c = NULL; call_event(s, TCP_SOCKET_CLOSED); relisten(s); } }
/*-----------------------------------------------------------------------------------*/ static uint8_t vnc_read_data(CC_REGISTER_ARG struct vnc_server_state *vs) { uint8_t *appdata; uint16_t len; struct rfb_fb_update_request *req; /* uint8_t niter;*/ len = uip_datalen(); appdata = (uint8_t *)uip_appdata; /* First, check if there is data left to discard since last read. */ if(vs->readlen > 0) { appdata += vs->readlen; if(len > vs->readlen) { len -= vs->readlen; vs->readlen = 0; } else { vs->readlen -= len; len = 0; } } if(vs->readlen != 0) { return 1; } /* All data read and ignored, parse next message. */ /* for(niter = 32; niter > 0 && len > 0; --niter) {*/ while(len > 0) { switch(vs->state) { case VNC_VERSION: case VNC_VERSION2: PRINTF(("Read in version\n")); /* Receive and ignore client version string (12 bytes). */ vs->state = VNC_AUTH; vs->readlen = 12; break; case VNC_AUTH: case VNC_AUTH2: PRINTF(("Read in auth \n")); /* Read and discard initialization from client (1 byte). */ vs->readlen = 1; vs->state = VNC_INIT; break; case VNC_INIT: case VNC_INIT2: PRINTF(("Read in init \n")); vs->readlen = 0; vs->state = VNC_RUNNING; case VNC_RUNNING: /* Handle all client events. */ switch(*appdata) { case RFB_SET_PIXEL_FORMAT: PRINTF(("Set pixel format\n")); vs->readlen = sizeof(struct rfb_set_pixel_format); /* Check if client runs with BGR233 format. If not, abort the connection. */ /* XXX: not implemented yet. */ break; case RFB_FIX_COLORMAP_ENTRIES: PRINTF(("Fix colormap entries\n")); return 0; case RFB_SET_ENCODINGS: PRINTF(("Set encodings\n")); vs->readlen = sizeof(struct rfb_set_encoding); vs->readlen += uip_htons(((struct rfb_set_encoding *)appdata)->encodings) * 4; /* Make sure that client supports the encodings we use. */ /* XXX: not implemented yet. */ break; case RFB_FB_UPDATE_REQ: PRINTF(("Update request\n")); vs->update_requested = 1; vs->readlen = sizeof(struct rfb_fb_update_request); /* blank the screen initially */ req = (struct rfb_fb_update_request *)appdata; if(req->incremental == 0) { /* vs->sendmsg = SEND_BLANK;*/ vnc_out_update_area(vs, 0, 0, vs->w, vs->h); } break; case RFB_KEY_EVENT: vs->readlen = sizeof(struct rfb_key_event); vnc_key_event(vs); break; case RFB_POINTER_EVENT: vs->readlen = sizeof(struct rfb_pointer_event); vnc_pointer_event(vs); break; case RFB_CLIENT_CUT_TEXT: PRINTF(("Client cut text\n")); if(((struct rfb_client_cut_text *)appdata)->len[0] != 0 || ((struct rfb_client_cut_text *)appdata)->len[1] != 0) { return 0; } vs->readlen = sizeof(struct rfb_client_cut_text) + (((struct rfb_client_cut_text *)appdata)->len[2] << 8) + ((struct rfb_client_cut_text *)appdata)->len[3]; /* return 0;*/ break; default: PRINTF(("Unknown message %d\n", *appdata)); return 0; } break; default: return 0; } if(vs->readlen > 0) { if(len > vs->readlen) { len -= vs->readlen; appdata += vs->readlen; vs->readlen = 0; } else { vs->readlen -= len; len = 0; } } else { /* Lost data. */ break; } } /* if(vs->readlen > 0) { printf("More data %d\n", vs->readlen); }*/ /* uip_appdata = appdata;*/ return 1; }
static void send_ack(int block) { tftp_header *h = (tftp_header *)uip_appdata; h->op = uip_htons(TFTP_ACK); h->block_nr = uip_htons(block); send_packet(h, 4); }
/*---------------------------------------------------------------------------*/ void ipcp_tx_confreq(u8_t *buffer){ u8_t *bptr; u16_t t; IPCPPKT *pkt; /* * No pending request, lets build one */ pkt=(IPCPPKT *)buffer; /* Configure-Request only here, write id */ pkt->code = CONF_REQ; pkt->id = ppp_id; bptr = (u8_t*)&pkt->data; /* * Write options, we want IP address, and DNS addresses if set. */ /* Write zeros for IP address the first time */ *bptr++ = IPCP_IPADDRESS; *bptr++ = 0x6; *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]; #ifdef IPCP_GET_PRI_DNS if(!(ipcp_state & IPCP_PRI_DNS_BIT)) { /* Write zeros for IP address the first time */ *bptr++ = IPCP_PRIMARY_DNS; *bptr++ = 0x6; *bptr++ = ((u8_t*)pri_dns_addr.u8)[0]; *bptr++ = ((u8_t*)pri_dns_addr.u8)[1]; *bptr++ = ((u8_t*)pri_dns_addr.u8)[2]; *bptr++ = ((u8_t*)pri_dns_addr.u8)[3]; } #endif #ifdef IPCP_GET_SEC_DNS if(!(ipcp_state & IPCP_SEC_DNS_BIT)) { /* Write zeros for IP address the first time */ *bptr++ = IPCP_SECONDARY_DNS; *bptr++ = 0x6; *bptr++ = sec_dns_addr.u8[0]; *bptr++ = sec_dns_addr.u8[1]; *bptr++ = sec_dns_addr.u8[2]; *bptr++ = sec_dns_addr.u8[3]; } #endif /* Write length */ t = bptr - buffer; /* length here - code and ID + */ pkt->len = uip_htons(t); ANNOTATE("\n**Sending IPCP Request packet\n"); /* Send packet ahdlc_txz(procol,header,data,headerlen,datalen); */ ahdlc_tx(IPCP, 0, buffer, 0, t); }
/*---------------------------------------------------------------------*/ static PT_THREAD(recv_tcpthread(struct pt *pt)) { register int ret; PT_BEGIN(pt); /* Read the header. */ PT_WAIT_UNTIL(pt, uip_newdata() && uip_datalen() > 0); if(uip_datalen() < sizeof(struct codeprop_tcphdr)) { PRINTF(("codeprop: header not found in first tcp segment\n")); uip_abort(); goto thread_done; } s.len = uip_htons(((struct codeprop_tcphdr *)uip_appdata)->len); s.addr = 0; uip_appdata += sizeof(struct codeprop_tcphdr); uip_len -= sizeof(struct codeprop_tcphdr); ret = xmem_erase(XMEM_ERASE_UNIT_SIZE, EEPROMFS_ADDR_CODEPROP); assert(ret == 0); /* Read the rest of the data. */ do { if(uip_len > 0) { ret = xmem_pwrite(uip_appdata, uip_len, EEPROMFS_ADDR_CODEPROP + s.addr); assert(ret = uip_len); s.addr += uip_len; } if(s.addr < s.len) { PT_YIELD_UNTIL(pt, uip_newdata()); } } while(s.addr < s.len); /* Kill old program. */ cmod_unload(0); /* Link, load, and start new program. */ int s; static char msg[30 + 10]; cle_scratch elfloader_unknown; s = cmod_load(0, elfloader_unknown, xmem_pread, EEPROMFS_ADDR_CODEPROP); if (s == CMOD_OK) sprintf(msg, "ok\n"); else sprintf(msg, "err %d %s\n", s, elfloader_unknown); /* Return "ok" message. */ do { s = strlen(msg); uip_send(msg, s); PT_WAIT_UNTIL(pt, uip_acked() || uip_rexmit() || uip_closed()); } while(uip_rexmit()); /* Close the connection. */ uip_close(); thread_done:; PT_END(pt); }