uint8_t router_find_stack(uip_ipaddr_t *forwardip) { uint8_t i; routing_input: for (i = 0; i < STACK_LEN; i++) { uip_stack_set_active(i); if((! forwardip) && uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr)) return i; #ifdef IPV6_SUPPORT if(forwardip && uip_ipaddr_prefixlencmp(*forwardip, uip_hostaddr, uip_prefix_len)) return i; #else /* !UIP_CONF_IPV6 */ if(forwardip && uip_ipaddr_maskcmp(*forwardip, uip_hostaddr, uip_netmask)) return i; #endif } /* we didn't find an interface for the forwadip, so try it again with the * default router */ if (forwardip && forwardip != &uip_draddr){ forwardip = &uip_draddr; goto routing_input; } /* Drop the packet */ return 255; }
/*---------------------------------------------------------------------------*/ static void recv_data(struct unicast_conn *c, const linkaddr_t *from) { struct route_entry *e; linkaddr_t source; uip_len = packetbuf_copyto(&uip_buf[UIP_LLH_LEN]); source.u8[0] = BUF->srcipaddr.u8[2]; source.u8[1] = BUF->srcipaddr.u8[3]; e = route_lookup(&source); if(e == NULL) { route_add(&source, from, 10, 0); } else { route_refresh(e); } /* If we received data via a gateway, we refresh the gateway route. * Note: we refresh OUR gateway route, although we are not sure it forwarded the data. */ if(!uip_ipaddr_maskcmp(&BUF->srcipaddr, &netaddr, &netmask)) { e = route_lookup(&gateway); if(e != NULL) { route_refresh(e); } } PRINTF("uip-over-mesh: %d.%d: recv_data with len %d\n", linkaddr_node_addr.u8[0], linkaddr_node_addr.u8[1], uip_len); tcpip_input(); }
void uip_arp_ipin(void) { /* Only insert/update an entry if the source IP address of the incoming IP packet comes from a host on the local network. */ uip_stack_set_active(STACK_ENC); if (uip_ipaddr_maskcmp(IPBUF->srcipaddr, uip_hostaddr, uip_netmask)) uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src)); return; }
boolean Server::clientIsLocal() { // Check if there is a current connection if (uip_conn != NULL) { // Check if the remote host is local to the server uip_ipaddr_t hostaddr, mask; // Get the server's address uip_gethostaddr(&hostaddr); // Get the subnet mask uip_getnetmask(&mask); // Compare with the client's address return uip_ipaddr_maskcmp(&hostaddr, uip_conn->ripaddr, &mask); } return false; }
static FAR struct uip_driver_s *netdev_finddevice(const uip_ipaddr_t addr) { struct uip_driver_s *dev; netdev_semtake(); for (dev = g_netdevices; dev; dev = dev->flink) { if (uip_ipaddr_maskcmp(dev->d_ipaddr, addr, dev->d_netmask)) { netdev_semgive(); return dev; } } netdev_semgive(); return NULL; }
uint8_t syslog_check_cache(void) { uip_ipaddr_t ipaddr; #ifdef IPV6_SUPPORT if(memcmp(syslog_conn->ripaddr, uip_hostaddr, 8)) /* Remote address is not on the local network, use router */ uip_ipaddr_copy(&ipaddr, uip_draddr); else /* Remote address is on the local network, send directly. */ uip_ipaddr_copy(&ipaddr, syslog_conn->ripaddr); if (uip_ipaddr_cmp(&ipaddr, &all_zeroes_addr)) return 1; /* Cowardly refusing to send IPv6 packet to :: */ if(uip_neighbor_lookup (ipaddr)) return 0; #else /* IPV4_SUPPORT */ if(!uip_ipaddr_maskcmp(syslog_conn->ripaddr, uip_hostaddr, uip_netmask)) /* Remote address is not on the local network, use router */ uip_ipaddr_copy(&ipaddr, uip_draddr); else /* Remote address is on the local network, send directly. */ uip_ipaddr_copy(&ipaddr, syslog_conn->ripaddr); #ifdef ETHERNET_SUPPORT /* uip_arp_lookup returns a pointer if the mac is in the arp cache */ if(uip_arp_lookup (ipaddr)) #endif return 0; #endif return 1; }
/*-----------------------------------------------------------------------------------*/ void uip_arp_out(void) { struct arp_entry* tabptr; /* Find the destination IP address in the ARP table and construct the Ethernet header. If the destination IP addres isn't on the local network, we use the default router's IP address instead. If not ARP table entry is found, we overwrite the original IP packet with an ARP request for the IP address. */ /* First check if destination is a local broadcast. */ if (uip_ipaddr_cmp(IPBUF->destipaddr, broadcast_ipaddr)) { memcpy(IPBUF->ethhdr.dest.addr, broadcast_ethaddr.addr, 6); } else { /* Check if the destination address is on the local network. */ if (!uip_ipaddr_maskcmp(IPBUF->destipaddr, uip_hostaddr, uip_netmask)) { /* Destination address was not on the local network, so we need to use the default router's IP address instead of the destination address when determining the MAC address. */ uip_ipaddr_copy(ipaddr, uip_draddr); } else { /* Else, we use the destination IP address. */ uip_ipaddr_copy(ipaddr, IPBUF->destipaddr); } for (i = 0; i < UIP_ARPTAB_SIZE; ++i) { tabptr = &arp_table[i]; if (uip_ipaddr_cmp(ipaddr, tabptr->ipaddr)) { break; } } if (i == UIP_ARPTAB_SIZE) { /* The destination address was not in our ARP table, so we overwrite the IP packet with an ARP request. */ memset(BUF->ethhdr.dest.addr, 0xff, 6); memset(BUF->dhwaddr.addr, 0x00, 6); memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6); memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6); uip_ipaddr_copy(BUF->dipaddr, ipaddr); uip_ipaddr_copy(BUF->sipaddr, uip_hostaddr); BUF->opcode = HTONS(ARP_REQUEST); /* ARP request. */ BUF->hwtype = HTONS(ARP_HWTYPE_ETH); BUF->protocol = HTONS(UIP_ETHTYPE_IP); BUF->hwlen = 6; BUF->protolen = 4; BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); uip_appdata = &uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN]; uip_len = sizeof(struct arp_hdr); return; } /* Build an ethernet header. */ memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6); } memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6); IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP); uip_len += sizeof(struct uip_eth_hdr); }
static uint16_t ping_interrupt(struct uip_driver_s *dev, void *conn, void *pvpriv, uint16_t flags) { struct icmp_ping_s *pstate = (struct icmp_ping_s *)pvpriv; uint8_t *ptr; int failcode = -ETIMEDOUT; int i; nllvdbg("flags: %04x\n", flags); if (pstate) { /* Check if this device is on the same network as the destination device. */ if (!uip_ipaddr_maskcmp(pstate->png_addr, dev->d_ipaddr, dev->d_netmask)) { /* Destination address was not on the local network served by this * device. If a timeout occurs, then the most likely reason is * that the destination address is not reachable. */ nllvdbg("Not reachable\n"); failcode = -ENETUNREACH; } else { /* Check if this is a ICMP ECHO reply. If so, return the sequence * number to the caller. NOTE: We may not even have sent the * requested ECHO request; this could have been the delayed ECHO * response from a previous ping. */ if ((flags & UIP_ECHOREPLY) != 0 && conn != NULL) { struct uip_icmpip_hdr *icmp = (struct uip_icmpip_hdr *)conn; nlldbg("ECHO reply: id=%d seqno=%d\n", ntohs(icmp->id), ntohs(icmp->seqno)); if (ntohs(icmp->id) == pstate->png_id) { /* Consume the ECHOREPLY */ flags &= ~UIP_ECHOREPLY; dev->d_len = 0; /* Return the result to the caller */ pstate->png_result = OK; pstate->png_seqno = ntohs(icmp->seqno); goto end_wait; } } /* Check: * If the outgoing packet is available (it may have been claimed * by a sendto interrupt serving a different thread * -OR- * If the output buffer currently contains unprocessed incoming * data. * -OR- * If we have alread sent the ECHO request * * In the first two cases, we will just have to wait for the next * polling cycle. */ if (dev->d_sndlen <= 0 && /* Packet available */ (flags & UIP_NEWDATA) == 0 && /* No incoming data */ !pstate->png_sent) /* Request not sent */ { struct uip_icmpip_hdr *picmp = ICMPBUF; /* We can send the ECHO request now. * * Format the ICMP ECHO request packet */ picmp->type = ICMP_ECHO_REQUEST; picmp->icode = 0; #ifndef CONFIG_NET_IPv6 picmp->id = htons(pstate->png_id); picmp->seqno = htons(pstate->png_seqno); #else # error "IPv6 ECHO Request not implemented" #endif /* Add some easily verifiable data */ for (i = 0, ptr = ICMPDAT; i < pstate->png_datlen; i++) { *ptr++ = i; } /* Send the ICMP echo request. Note that d_sndlen is set to * the size of the ICMP payload and does not include the size * of the ICMP header. */ nlldbg("Send ECHO request: seqno=%d\n", pstate->png_seqno); dev->d_sndlen= pstate->png_datlen + 4; uip_icmpsend(dev, &pstate->png_addr); pstate->png_sent = true; return flags; } } /* Check if the selected timeout has elapsed */ if (ping_timeout(pstate)) { /* Yes.. report the timeout */ nlldbg("Ping timeout\n"); pstate->png_result = failcode; goto end_wait; } /* Continue waiting */ } return flags; end_wait: nllvdbg("Resuming\n"); /* Do not allow any further callbacks */ pstate->png_cb->flags = 0; pstate->png_cb->priv = NULL; pstate->png_cb->event = NULL; /* Wake up the waiting thread */ sem_post(&pstate->png_sem); return flags; }
/*-----------------------------------------------------------------------------------*/ uint8_t uip_arp_out(void) { #ifdef MDNS_SD_SUPPORT uip_ipaddr_t mdns_address = {0x00e0, 0xfb00}; #endif /* Find the destination IP address in the ARP table and construct the Ethernet header. If the destination IP addres isn't on the local network, we use the default router's IP address instead. If not ARP table entry is found, we overwrite the original IP packet with an ARP request for the IP address. */ /* First check if destination is a local broadcast. */ if(((const uint8_t *)IPBUF->destipaddr)[0] >= 224 && ((const uint8_t *)IPBUF->destipaddr)[0] <= 239) { /* packet is addressed to multicast ip range, generate the associated mac address for it. */ IPBUF->ethhdr.dest.addr[0] = 0x01; IPBUF->ethhdr.dest.addr[1] = 0x00; IPBUF->ethhdr.dest.addr[2] = 0x5e; IPBUF->ethhdr.dest.addr[3] = ((const uint8_t *)IPBUF->destipaddr)[1] & 0x7f; IPBUF->ethhdr.dest.addr[4] = ((const uint8_t *)IPBUF->destipaddr)[2]; IPBUF->ethhdr.dest.addr[5] = ((const uint8_t *)IPBUF->destipaddr)[3]; } else if((IPBUF->destipaddr[0] == (uip_hostaddr[0] | ~uip_netmask[0]) && IPBUF->destipaddr[1] == (uip_hostaddr[1] | ~uip_netmask[1])) || (uip_ipaddr_cmp(IPBUF->destipaddr, broadcast_ipaddr))) { memcpy(IPBUF->ethhdr.dest.addr, broadcast_ethaddr.addr, 6); #ifdef MDNS_SD_SUPPORT /* If the ip is the mdns mulicast ip, we answer to the mac who asked */ } else if (uip_ipaddr_cmp(IPBUF->destipaddr, mdns_address)) { memcpy(IPBUF->ethhdr.dest.addr, &((struct uip_eth_hdr *) uip_buf)->dest, 6); #endif } else { /* Check if the destination address is on the local network. */ if(!uip_ipaddr_maskcmp(IPBUF->destipaddr, uip_hostaddr, uip_netmask)) { /* Destination address was not on the local network, so we need to use the default router's IP address instead of the destination address when determining the MAC address. */ uip_ipaddr_copy(ipaddr, uip_draddr); } else { /* Else, we use the destination IP address. */ uip_ipaddr_copy(ipaddr, IPBUF->destipaddr); } struct arp_entry *tabptr = uip_arp_lookup (ipaddr); if(!tabptr) { /* The destination address was not in our ARP table, so we overwrite the IP packet with an ARP request. */ memset(BUF->ethhdr.dest.addr, 0xff, 6); memset(BUF->dhwaddr.addr, 0x00, 6); memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6); memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6); uip_ipaddr_copy(BUF->dipaddr, ipaddr); uip_ipaddr_copy(BUF->sipaddr, uip_hostaddr); BUF->opcode = HTONS(ARP_REQUEST); /* ARP request. */ BUF->hwtype = HTONS(ARP_HWTYPE_ETH); BUF->protocol = HTONS(UIP_ETHTYPE_IP); BUF->hwlen = 6; BUF->protolen = 4; BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); /* FIXME uip_appdata = &uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN]; */ uip_len = sizeof(struct arp_hdr); return 1; } /* Build an ethernet header. */ memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6); } memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6); IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP); uip_len += sizeof(struct uip_eth_hdr); return 0; }
/*-----------------------------------------------------------------------------------*/ void uip_arp_arpin(void) { if(uip_len < sizeof(struct arp_hdr)) { uip_len = 0; return; } uip_len = 0; switch(BUF->opcode) { case HTONS(ARP_REQUEST): /* ARP request. If it asked for our address, we send out a reply. */ if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr) #ifdef RFM12_ARP_PROXY /* If RFM12 ARP-proxy is enabled, check that one's IP address as well and possibly answer it. */ || uip_ipaddr_maskcmp(BUF->dipaddr, rfm12_stack_hostaddr, rfm12_stack_netmask) #endif #ifdef ZBUS_ARP_PROXY /* If ZBUS ARP-proxy is enabled, check that one's IP address as well and possibly answer it. */ || uip_ipaddr_maskcmp(BUF->dipaddr, zbus_stack_hostaddr, zbus_stack_netmask) #endif #ifdef USB_ARP_PROXY /* If USB ARP-proxy is enabled, check that one's IP address as well and possibly answer it. */ || uip_ipaddr_maskcmp(BUF->dipaddr, usb_stack_hostaddr, usb_stack_netmask) #endif ) { /* First, we register the one who made the request in our ARP table, since it is likely that we will do more communication with this host in the future. */ uip_arp_update(BUF->sipaddr, &BUF->shwaddr); /* The reply opcode is 2. */ BUF->opcode = HTONS(2); memcpy(BUF->dhwaddr.addr, BUF->shwaddr.addr, 6); memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6); memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6); memcpy(BUF->ethhdr.dest.addr, BUF->dhwaddr.addr, 6); for (uint8_t i = 0; i < 4; i ++) flip (uint8_t, ((uint8_t *) BUF->dipaddr)[i], ((uint8_t *) BUF->sipaddr)[i]); /* BUF->dipaddr[0] = BUF->sipaddr[0]; BUF->dipaddr[1] = BUF->sipaddr[1]; BUF->sipaddr[0] = uip_hostaddr[0]; BUF->sipaddr[1] = uip_hostaddr[1]; */ BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); uip_len = sizeof(struct arp_hdr); } break; case HTONS(ARP_REPLY): /* ARP reply. We insert or update the ARP table if it was meant for us. */ if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr)) { uip_arp_update(BUF->sipaddr, &BUF->shwaddr); } break; } return; }
/*---------------------------------------------------------------------------*/ uint8_t uip_over_mesh_send(void) { linkaddr_t receiver; struct route_entry *rt; /* This function is called by the uip-fw module to send out an IP packet. We try to send the IP packet to the next hop route, or we queue the packet and send out a route request for the final receiver of the packet. */ /* Packets destined to this network is sent using mesh, whereas packets destined to a network outside this network is sent towards the gateway node. */ if(uip_ipaddr_maskcmp(&BUF->destipaddr, &netaddr, &netmask)) { receiver.u8[0] = BUF->destipaddr.u8[2]; receiver.u8[1] = BUF->destipaddr.u8[3]; } else { if(linkaddr_cmp(&gateway, &linkaddr_node_addr)) { PRINTF("uip_over_mesh_send: I am gateway, packet to %d.%d.%d.%d to local interface\n", uip_ipaddr_to_quad(&BUF->destipaddr)); if(gw_netif != NULL) { return gw_netif->output(); } return UIP_FW_DROPPED; } else if(linkaddr_cmp(&gateway, &linkaddr_null)) { PRINTF("uip_over_mesh_send: No gateway setup, dropping packet\n"); return UIP_FW_OK; } else { PRINTF("uip_over_mesh_send: forwarding packet to %d.%d.%d.%d towards gateway %d.%d\n", uip_ipaddr_to_quad(&BUF->destipaddr), gateway.u8[0], gateway.u8[1]); linkaddr_copy(&receiver, &gateway); } } PRINTF("uIP over mesh send to %d.%d with len %d\n", receiver.u8[0], receiver.u8[1], uip_len); packetbuf_copyfrom(&uip_buf[UIP_LLH_LEN], uip_len); /* Send TCP data with the PACKETBUF_ATTR_ERELIABLE set so that an underlying power-saving MAC layer knows that it should be waiting for an ACK. */ if(BUF->proto == UIP_PROTO_TCP) { packetbuf_set_attr(PACKETBUF_ATTR_ERELIABLE, 1); packetbuf_set_attr(PACKETBUF_ATTR_RELIABLE, 1); /* packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE, PACKETBUF_ATTR_PACKET_TYPE_STREAM);*/ } rt = route_lookup(&receiver); if(rt == NULL) { PRINTF("uIP over mesh no route to %d.%d\n", receiver.u8[0], receiver.u8[1]); if(queued_packet == NULL) { queued_packet = queuebuf_new_from_packetbuf(); linkaddr_copy(&queued_receiver, &receiver); route_discovery_discover(&route_discovery, &receiver, ROUTE_TIMEOUT); } else if(!linkaddr_cmp(&queued_receiver, &receiver)) { route_discovery_discover(&route_discovery, &receiver, ROUTE_TIMEOUT); } } else { route_decay(rt); send_data(&rt->nexthop); } return UIP_FW_OK; }
/*---------------------------------------------------------------------------*/ 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; }
/*-----------------------------------------------------------------------------------*/ void uip_arp_out(struct net_buf *buf) { struct arp_entry *tabptr = arp_table; /* Find the destination IP address in the ARP table and construct the Ethernet header. If the destination IP addres isn't on the local network, we use the default router's IP address instead. If not ARP table entry is found, we overwrite the original IP packet with an ARP request for the IP address. */ /* First check if destination is a local broadcast. */ if(uip_ipaddr_cmp(&IPBUF(buf)->destipaddr, &uip_broadcast_addr)) { memcpy(IPBUF(buf)->ethhdr.dest.addr, broadcast_ethaddr.addr, 6); } else if(IPBUF(buf)->destipaddr.u8[0] == 224) { /* Multicast. */ IPBUF(buf)->ethhdr.dest.addr[0] = 0x01; IPBUF(buf)->ethhdr.dest.addr[1] = 0x00; IPBUF(buf)->ethhdr.dest.addr[2] = 0x5e; IPBUF(buf)->ethhdr.dest.addr[3] = IPBUF(buf)->destipaddr.u8[1]; IPBUF(buf)->ethhdr.dest.addr[4] = IPBUF(buf)->destipaddr.u8[2]; IPBUF(buf)->ethhdr.dest.addr[5] = IPBUF(buf)->destipaddr.u8[3]; } else { /* Check if the destination address is on the local network. */ if(!uip_ipaddr_maskcmp(&IPBUF(buf)->destipaddr, &uip_hostaddr, &uip_netmask)) { /* Destination address was not on the local network, so we need to use the default router's IP address instead of the destination address when determining the MAC address. */ uip_ipaddr_copy(&ipaddr, &uip_draddr); } else { /* Else, we use the destination IP address. */ uip_ipaddr_copy(&ipaddr, &IPBUF(buf)->destipaddr); } for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { if(uip_ipaddr_cmp(&ipaddr, &tabptr->ipaddr)) { break; } tabptr++; } if(i == UIP_ARPTAB_SIZE) { /* The destination address was not in our ARP table, so we overwrite the IP packet with an ARP request. */ memset(BUF(buf)->ethhdr.dest.addr, 0xff, 6); memset(BUF(buf)->dhwaddr.addr, 0x00, 6); memcpy(BUF(buf)->ethhdr.src.addr, uip_lladdr.addr, 6); memcpy(BUF(buf)->shwaddr.addr, uip_lladdr.addr, 6); uip_ipaddr_copy(&BUF(buf)->dipaddr, &ipaddr); uip_ipaddr_copy(&BUF(buf)->sipaddr, &uip_hostaddr); BUF(buf)->opcode = UIP_HTONS(ARP_REQUEST); /* ARP request. */ BUF(buf)->hwtype = UIP_HTONS(ARP_HWTYPE_ETH); BUF(buf)->protocol = UIP_HTONS(UIP_ETHTYPE_IP); BUF(buf)->hwlen = 6; BUF(buf)->protolen = 4; BUF(buf)->ethhdr.type = UIP_HTONS(UIP_ETHTYPE_ARP); uip_appdata(buf) = &uip_buf(buf)[UIP_TCPIP_HLEN + UIP_LLH_LEN]; uip_len(buf) = sizeof(struct arp_hdr); return; } /* Build an ethernet header. */ memcpy(IPBUF(buf)->ethhdr.dest.addr, tabptr->ethaddr.addr, 6); } memcpy(IPBUF(buf)->ethhdr.src.addr, uip_lladdr.addr, 6); IPBUF(buf)->ethhdr.type = UIP_HTONS(UIP_ETHTYPE_IP); uip_len(buf) += sizeof(struct uip_eth_hdr); }