Esempio n. 1
0
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;
}
Esempio n. 2
0
/*---------------------------------------------------------------------------*/
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();
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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;
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
/*-----------------------------------------------------------------------------------*/
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);
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
/*-----------------------------------------------------------------------------------*/
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;
}
Esempio n. 10
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;
}
Esempio n. 11
0
/*---------------------------------------------------------------------------*/
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;
}
Esempio n. 13
0
/*-----------------------------------------------------------------------------------*/
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);
}