Beispiel #1
0
/*---------------------------------------------------------------------------*/
void
ip64_dhcpc_init(const void *mac_addr, int mac_len)
{
  /* Although this is DHCPv4, we explicitly bind the socket to an IPv6
     address so that it can operate over the ip64 bridge. */
  uip_ip6addr_t v6addr;
  uip_ip4addr_t v4addr;
  struct uip_udp_conn *conn2;
  
  s.mac_addr = mac_addr;
  s.mac_len  = mac_len;

  s.state = STATE_INITIAL;
  uip_ipaddr(&v4addr, 255,255,255,255); 
  ip64_addr_4to6(&v4addr, &v6addr);
  s.conn = udp_new(&v6addr, UIP_HTONS(IP64_DHCPC_SERVER_PORT), NULL);
  conn2 = udp_new(NULL, UIP_HTONS(IP64_DHCPC_SERVER_PORT), NULL);
  if(s.conn != NULL) {
    udp_bind(s.conn, UIP_HTONS(IP64_DHCPC_CLIENT_PORT));
  }
  if(conn2 != NULL) {
    udp_bind(conn2, UIP_HTONS(IP64_DHCPC_CLIENT_PORT));
  }
  PT_INIT(&s.pt);
}
Beispiel #2
0
/**
 * Connect to MQTT broker.
 *
 * N.B. None-blocking call.
 */
mqtt_status_t
mqtt_connect(struct mqtt_connection* conn,
             const char* host,
             uint16_t port,
             uint16_t keep_alive)
{
  uip_ip6addr_t ip6addr;
  uip_ip4addr_t ip4addr;
  uip_ipaddr_t *ipaddr;
  ipaddr = &ip6addr;

  /* Sanity check */
  assert(conn != NULL &&
         host != NULL);

  /* Check if we are already trying to connect */
  if(conn->state > MQTT_CONN_STATE_NOT_CONNECTED) {
    return MQTT_STATUS_OK;
  }

  conn->server_host = host;
  conn->keep_alive = keep_alive;
  conn->server_port = port;
  conn->out_buffer_ptr = conn->out_buffer;
  conn->out_packet.qos_state = MQTT_QOS_STATE_NO_ACK;

  /* First check if the host is an IP address. If not, try to look it up. */
  if(uiplib_ip6addrconv(host, &ip6addr) == 0) {
    if(uiplib_ip4addrconv(host, &ip4addr) != 0) {
      ip64_addr_4to6(&ip4addr, &ip6addr);
    } else {
#if UIP_UDP
      ipaddr = mdns_lookup(host);

      if(ipaddr == NULL) {
        printf("MQTT - Resolving host...\r\n");
        mdns_query(host);
        conn->state = MQTT_CONN_STATE_DNS_LOOKUP;
        return MQTT_STATUS_OK;
      }
#else /* UIP_UDP */
      DBG("Error looking up hostname when mDNS is not used due to UIP_UDP = 0.");
      conn->state = MQTT_CONN_STATE_ERROR;
      return MQTT_STATUS_DNS_ERROR;
#endif /* UIP_UDP */
    }
  }
  uip_ipaddr_copy(&(conn->server_ip), ipaddr);

  /* Initiate the connection if the IP could be resolved. Otherwise the
   * connection will be initiated when the DNS lookup is finished, in the main
   * event loop.
   */
  process_post(&mqtt_process, mqtt_do_connect_tcp_event, conn);

  return MQTT_STATUS_OK;
}
Beispiel #3
0
/*---------------------------------------------------------------------------*/
void
ip64_dhcpc_configured(const struct ip64_dhcpc_state *s)
{
  uip_ip6addr_t ip6dnsaddr;
  printf("DHCP Configured with %d.%d.%d.%d\n",
	 s->ipaddr.u8[0], s->ipaddr.u8[1],
	 s->ipaddr.u8[2], s->ipaddr.u8[3]);

  ip64_set_hostaddr((uip_ip4addr_t *)&s->ipaddr);
  ip64_set_netmask((uip_ip4addr_t *)&s->netmask);
  ip64_set_draddr((uip_ip4addr_t *)&s->default_router);
  ip64_addr_4to6((uip_ip4addr_t *)&s->dnsaddr, &ip6dnsaddr);
  //  mdns_conf(&ip6dnsaddr);
}
Beispiel #4
0
/*---------------------------------------------------------------------------*/
static int
start_request(struct http_socket *s)
{
  uip_ip4addr_t ip4addr;
  uip_ip6addr_t ip6addr;
  uip_ip6addr_t *addr;
  char host[MAX_HOSTLEN];
  char path[MAX_PATHLEN];
  uint16_t port;
  int ret;

  if(parse_url(s->url, host, &port, path)) {

    printf("url %s host %s port %d path %s\n",
           s->url, host, port, path);

    /* Check if we are to route the request through a proxy. */
    if(s->proxy_port != 0) {
      /* The proxy address should be an IPv6 address. */
      uip_ip6addr_copy(&ip6addr, &s->proxy_addr);
      port = s->proxy_port;
    } else if(uiplib_ip6addrconv(host, &ip6addr) == 0) {
      /* First check if the host is an IP address. */
      if(uiplib_ip4addrconv(host, &ip4addr) != 0) {
        ip64_addr_4to6(&ip4addr, &ip6addr);
      } else {
        /* Try to lookup the hostname. If it fails, we initiate a hostname
           lookup. */
        ret = resolv_lookup(host, &addr);
        if(ret == RESOLV_STATUS_UNCACHED ||
           ret == RESOLV_STATUS_EXPIRED) {
          resolv_query(host);
          puts("Resolving host...");
          return HTTP_SOCKET_OK;
        }
        if(addr != NULL) {
          s->did_tcp_connect = 1;
          tcp_socket_connect(&s->s, addr, port);
          return HTTP_SOCKET_OK;
        } else {
          return HTTP_SOCKET_ERR;
        }
      }
    }
    tcp_socket_connect(&s->s, &ip6addr, port);
    return HTTP_SOCKET_OK;
  } else {
    return HTTP_SOCKET_ERR;
  }
}
/*-----------------------------------------------------------------------------------*/
unsigned char
websocket_http_client_get(struct websocket_http_client_state *s,
			  const char *host, uint16_t port, const char *file,
                          const char *subprotocol)
{
  struct uip_conn *conn;
  uip_ip6addr_t ip6addr;
  uip_ip4addr_t ip4addr;
  uip_ipaddr_t *ipaddr;

  ipaddr = &ip6addr;
  /* First check if the host is an IP address. */
  if(uiplib_ip6addrconv(host, &ip6addr) == 0) {
    if(uiplib_ip4addrconv(host, &ip4addr) != 0) {
      ip64_addr_4to6(&ip4addr, &ip6addr);
    } else {
#if UIP_UDP
      ipaddr = mdns_lookup(host);
      
      if(ipaddr == NULL) {
	return 0;
      }
#else /* UIP_UDP */
      return 0;
#endif /* UIP_UDP */
    }
  }
  
  conn = tcp_connect(ipaddr, uip_htons(port), NULL);
  
  if(conn == NULL) {
    return 0;
  }
  tcp_markconn(conn, s);
  s->conn = conn;
  s->port = port;
  strncpy(s->file, file, sizeof(s->file));
  strncpy(s->host, host, sizeof(s->host));
  strncpy(s->subprotocol, subprotocol, sizeof(s->subprotocol));
  init_connection(s);
  return 1;
}
Beispiel #6
0
/*---------------------------------------------------------------------------*/
static int
start_request(struct http_socket *s)
{
  uip_ip4addr_t ip4addr;
  uip_ip6addr_t ip6addr;
  uip_ip6addr_t *addr;
  char host[MAX_HOSTLEN];
  char path[MAX_PATHLEN];
  uint16_t port;

  if(parse_url(s->url, host, &port, path)) {

    printf("url %s host %s port %d path %s\n\r",
           s->url, host, port, path);

    /* First check if the host is an IP address. */
    if(uiplib_ip6addrconv(host, &ip6addr) == 0) {
      if(uiplib_ip4addrconv(host, &ip4addr) != 0) {
        ip64_addr_4to6(&ip4addr, &ip6addr);
      } else {
        /* Try to lookup the hostname. If it fails, we initiate a hostname
           lookup. */
        addr = mdns_lookup(host);
        if(addr == NULL) {
          mdns_query(host);
          puts("Resolving host...");
          return HTTP_SOCKET_OK;
        }
        tcp_socket_connect(&s->s, addr, port);
        return HTTP_SOCKET_OK;
      }
    }
    tcp_socket_connect(&s->s, &ip6addr, port);
    return HTTP_SOCKET_OK;
  } else {
    return HTTP_SOCKET_ERR;
  }
}
Beispiel #7
0
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(http_example_process, ev, data)
{
  static struct etimer et;
  uip_ip4addr_t ip4addr;
  uip_ip6addr_t ip6addr;

  PROCESS_BEGIN();

  uip_ipaddr(&ip4addr, 8, 8, 8, 8);
  ip64_addr_4to6(&ip4addr, &ip6addr);
  uip_nameserver_update(&ip6addr, UIP_NAMESERVER_INFINITE_LIFETIME);

  etimer_set(&et, CLOCK_SECOND * 20);
  PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));

  memset(url_buffer, 0, HTTP_CLIENT_BUFFER_LEN);
  snprintf(url_buffer, HTTP_CLIENT_BUFFER_LEN,
           "http://maker.ifttt.com/trigger/%s/with/key/%s",
           IFTTT_EVENT, IFTTT_KEY);

  http_socket_init(&s);

  restarts = 0;

  while(1) {
    PROCESS_YIELD();
    if((ev == sensors_event) && (data == &button_sensor)) {
      if(button_sensor.value(BUTTON_SENSOR_VALUE_TYPE_LEVEL) ==
        BUTTON_SENSOR_PRESSED_LEVEL) {
        leds_on(LEDS_GREEN);
        printf("Button pressed! sending a POST to IFTTT\n");
        http_socket_post(&s, url_buffer, NULL, 0, NULL, callback, NULL);
      }
    }
  }

  PROCESS_END();
}
Beispiel #8
0
/*---------------------------------------------------------------------------*/
static int
start_request(struct http_socket *s)
{
  uip_ip4addr_t ip4addr;
  uip_ip6addr_t ip6addr;
  uip_ipaddr_t *addr;
  char host[MAX_HOSTLEN];
  char path[MAX_PATHLEN];
  uint16_t port;

  if(parse_url(s->url, host, &port, path)) {

    PRINTF("%s url %s host %s port %d path %s\n",
           HTTP_METHOD_STR(s->method), s->url, host, port, path);

    /* First check if the host is an IP address. */
    if(uiplib_ip6addrconv(host, &ip6addr) == 0) {
      if(uiplib_ip4addrconv(host, &ip4addr) != 0) {
        ip64_addr_4to6(&ip4addr, &ip6addr);
      } else {
        /* Try to lookup the hostname. If it fails, we initiate a hostname
           lookup. */
        if(resolv_lookup(host, &addr) != RESOLV_STATUS_CACHED) {
          resolv_query(host);
          PRINTF("Resolving host...\n");
          return HTTP_SOCKET_OK;
        }
        tcp_socket_connect(&s->s, addr, port);
        return HTTP_SOCKET_OK;
      }
    }
    tcp_socket_connect(&s->s, (uip_ipaddr_t *)&ip6addr, port);
    return HTTP_SOCKET_OK;
  } else {
    return HTTP_SOCKET_ERR;
  }
}
Beispiel #9
0
/*---------------------------------------------------------------------------*/
void
ip64_dhcpc_configured(const struct ip64_dhcpc_state *s)
{
  uip_ip6addr_t ip6dnsaddr;
  PRINTF("DHCP Configured with %d.%d.%d.%d\n",
	 s->ipaddr.u8[0], s->ipaddr.u8[1],
	 s->ipaddr.u8[2], s->ipaddr.u8[3]);

  ip64_set_hostaddr((uip_ip4addr_t *)&s->ipaddr);
  ip64_set_netmask((uip_ip4addr_t *)&s->netmask);
  ip64_set_draddr((uip_ip4addr_t *)&s->default_router);
  if(!uip_ip4addr_cmp((uip_ip4addr_t *)&s->dnsaddr, &uip_all_zeroes_addr)) {
    //Note: Currently we assume only one DNS server
    uip_ipaddr_t * dns = uip_nameserver_get(0);
    //Only update DNS entry if it is empty or already IPv4
    if(uip_is_addr_unspecified(dns) || ip64_addr_is_ip64(dns)) {
      ip64_addr_4to6((uip_ip4addr_t *)&s->dnsaddr, &ip6dnsaddr);
      uip_nameserver_update(&ip6dnsaddr, uip_ntohs(s->lease_time[0])*65536ul + uip_ntohs(s->lease_time[1]));
    }
  }
#if CETIC_6LBR
  cetic_6lbr_ip64_dhcpc_configured(s);
#endif
}
/*---------------------------------------------------------------------------*/
void
contiki_init(void)
{
  int i;
  uint8_t addr[sizeof(uip_lladdr.addr)];
  uip_ipaddr_t ipaddr;
  uip_ds6_addr_t *lladdr;
  uip_ip4addr_t ipv4addr, netmask;

  /* Start process handler */
  process_init();

  /* Start Contiki processes */
  process_start(&etimer_process, NULL);
  process_start(&sensors_process, NULL);
  ctimer_init();

  /* Print startup information */
  printf(CONTIKI_VERSION_STRING " started. ");
  if(node_id > 0) {
    printf("Node id is set to %u.\n", node_id);
  } else {
    printf("Node id is not set.\n");
  }

  set_mac_addr();

  queuebuf_init();

  /* Initialize communication stack */
  netstack_init();
  printf("%s/%s/%s, channel check rate %lu Hz\n",
         NETSTACK_NETWORK.name, NETSTACK_MAC.name, NETSTACK_RDC.name,
         CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval() == 0 ? 1:
                         NETSTACK_RDC.channel_check_interval()));

  /* IPv6 CONFIGURATION */


  for(i = 0; i < sizeof(uip_lladdr.addr); i += 2) {
    addr[i + 1] = node_id & 0xff;
    addr[i + 0] = node_id >> 8;
  }
  linkaddr_copy(addr, &linkaddr_node_addr);
  memcpy(&uip_lladdr.addr, addr, sizeof(uip_lladdr.addr));

  process_start(&tcpip_process, NULL);

  printf("Tentative link-local IPv6 address ");

  lladdr = uip_ds6_get_link_local(-1);
  for(i = 0; i < 7; ++i) {
    printf("%02x%02x:", lladdr->ipaddr.u8[i * 2],
           lladdr->ipaddr.u8[i * 2 + 1]);
  }
  printf("%02x%02x\n", lladdr->ipaddr.u8[14],
         lladdr->ipaddr.u8[15]);

  uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0);
  uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr);
  uip_ds6_addr_add(&ipaddr, 0, ADDR_TENTATIVE);
  printf("Tentative global IPv6 address ");
  for(i = 0; i < 7; ++i) {
    printf("%02x%02x:",
           ipaddr.u8[i * 2], ipaddr.u8[i * 2 + 1]);
  }
  printf("%02x%02x\n",
         ipaddr.u8[7 * 2], ipaddr.u8[7 * 2 + 1]);

  /* Start serial process */
  serial_line_init();

  /* Start autostart processes (defined in Contiki application) */
  print_processes(autostart_processes);
  autostart_start(autostart_processes);

  /* Start the SLIP */
  printf("Initiating SLIP with IP address is 172.16.0.2.\n");

  uip_ipaddr(&ipv4addr, 172, 16, 0, 2);
  uip_ipaddr(&netmask, 255, 255, 255, 0);
  ip64_set_ipv4_address(&ipv4addr, &netmask);

  rs232_set_input(slip_input_byte);
  log_set_putchar_with_slip(1);

  uip_ip4addr_t ip4addr;
  uip_ip6addr_t ip6addr;

  uip_ipaddr(&ip4addr, 8,8,8,8);
  ip64_addr_4to6(&ip4addr, &ip6addr);

  uip_nameserver_update((uip_ipaddr_t *)&ip6addr, UIP_NAMESERVER_INFINITE_LIFETIME);
}
/*---------------------------------------------------------------------------*/
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;
}