struct {
+#ifdef PEER_USE_TAP
struct ethhdr eth;
+#else
+ struct tun_pi tun;
+#endif
union {
struct {
struct ip6_hdr v6hdr;
} udata;
} __attribute__((packed)) v4data6;
+#ifdef PEER_USE_TAP
#define v4ether (v4data6.eth)
+#else
+#define v4tunpi6 (v4data6.tun)
+#endif
#define v4data ((uint8_t *) &v4data6.udata)
#define v4hdr6 (&v4data6.udata.idata.v6hdr)
#define v4src6 (&v4data6.udata.idata.v6hdr.ip6_src)
struct {
+#ifdef PEER_USE_TAP
struct ethhdr eth;
+#else
+ struct tun_pi tun;
+#endif
union {
uint8_t data [MTU];
struct {
} udata;
} __attribute__((packed)) v6data6;
+#ifdef PEER_USE_TAP
#define v6ether (v6data6.eth)
+#else
+#define v6tuncmd (v6data6.tun)
+#endif
#define v6data (v6data6.udata.data)
#define v6hdr6 (&v6data6.udata.ndata.v6hdr)
#define v6hops (v6data6.udata.ndata.v6hdr.ip6_hops)
#define v6icmp6csum (v6data6.udata.ndata.v6icmp.icmp6_cksum)
#define v6ndtarget (&v6data6.udata.ndata.v6icmp.icmp6_data16[2])
+#ifdef PEER_USE_TAP
+#define HDR_SIZE (sizeof(struct ethhdr))
+#else
+#define HDR_SIZE (sizeof(struct tun_pi))
+#endif
/* Structure for tasks in neighbor discovery queues
*/
if (!have_tunnel) {
memset (&ifreq, 0, sizeof (ifreq));
strncpy (ifreq.ifr_name, INTERFACE_NAME_6BED4, IFNAMSIZ);
+#ifdef PEER_USE_TAP
ifreq.ifr_flags = IFF_TAP | IFF_NO_PI;
+#else
+ ifreq.ifr_flags = IFF_TUN;
+#endif
if (ok && (ioctl (v6sox, TUNSETIFF, (void *) &ifreq) == -1)) {
syslog (LOG_CRIT, "Failed to set interface name: %s\n", strerror (errno));
ok = false;
memcpy (v6src6, &v6listen, 16);
memcpy (v6dst6, v4src6, 16);
v6icmp6csum = icmp6_checksum ((uint8_t *) v4hdr6, 8 + 16 + 16);
- handle_6to4_plain_unicast (sizeof (struct ethhdr) + 40 + 8 + 16 + 16, ngbc_llremote);
+ handle_6to4_plain_unicast (HDR_SIZE + 40 + 8 + 16 + 16, ngbc_llremote);
}
* a target IPv6 address to service.
*/
void advertise_6bed4_public_service (struct ndqueue *info) {
+#ifdef PEER_USE_TAP
+
if (info) {
memcpy (v6ether.h_dest, info->source_lladdr, 6);
} else {
memcpy (v6ether.h_dest, v6ether.h_source, 6);
}
memcpy (v6ether.h_source, SERVER_6BED4_PORT_IPV4_MACSTR, 6);
+#endif
memcpy (v6data, ipv6_defaultrouter_neighbor_advertisement, 8);
if (info) {
memcpy (v6dst6, &info->source, 16);
memcpy (&v6icmp6data [4], &info->target, 16);
}
v6icmp6csum = icmp6_checksum ((uint8_t *) v6hdr6, 32);
- int sent = write (v6sox, &v6data6, sizeof (struct ethhdr) + sizeof (ipv6_defaultrouter_neighbor_advertisement));
+ int sent = write (v6sox, &v6data6, HDR_SIZE + sizeof (ipv6_defaultrouter_neighbor_advertisement));
if (info) {
syslog (LOG_DEBUG, "TODO: Neighbor Discovery failed to contact directly -- standard response provided\n");
} else {
void handle_4to6_plain (ssize_t v4datalen, struct sockaddr_in *sin) {
//
// Send the unwrapped IPv6 message out over v6sox
+#ifdef PEER_USE_TAP
v4ether.h_proto = htons (ETH_P_IPV6);
memcpy (v4ether.h_dest, v6lladdr, 6);
v4ether.h_source [0] = ntohs (sin->sin_port) & 0xff;
v4ether.h_source [1] = ntohs (sin->sin_port) >> 8;
memcpy (v4ether.h_source + 2, &sin->sin_addr, 4);
+#endif
syslog (LOG_INFO, "Writing IPv6, result = %zd\n",
- write (v6sox, &v4data6, sizeof (struct ethhdr) + v4datalen)
+ write (v6sox, &v4data6, HDR_SIZE + v4datalen)
)
;
}
ntohs (v4dest.sin_port),
sendto (v4sox,
v6data,
- pktlen - sizeof (struct ethhdr),
+ pktlen - HDR_SIZE,
MSG_DONTWAIT,
(struct sockaddr *) &v4dest,
sizeof (struct sockaddr_in))
memcpy (v6dst6, v6src6, 16);
memcpy (v6src6, v6listen_linklocal_complete, 16);
v6icmp6csum = icmp6_checksum ((uint8_t *) v6hdr6, 4 + writepos);
+#ifdef PEER_USE_TAP
v6ether.h_proto = htons (ETH_P_IPV6);
memcpy (v6ether.h_dest, v6ether.h_source, 6);
memcpy (v6ether.h_source, v6lladdr, 6);
+#endif
syslog (LOG_INFO, "Replying Router Advertisement to the IPv6 Link, result = %zd\n",
- write (v6sox, &v6data6, sizeof (struct ethhdr) + sizeof (struct ip6_hdr) + 4 + writepos)
+ write (v6sox, &v6data6, HDR_SIZE + sizeof (struct ip6_hdr) + 4 + writepos)
)
;
break;
v6plen = htons (4 + 28);
memcpy (v6dst6, v6src6, 16);
memcpy (v6src6, &v6listen, 16);
+#ifdef PEER_USE_TAP
memcpy (v6ether.h_dest, v6ether.h_source, 6);
memcpy (v6ether.h_source, v6lladdr, 6);
+#endif
v6icmp6csum = icmp6_checksum ((uint8_t *) v6hdr6, 4 + 28);
syslog (LOG_DEBUG, "Sending trivial reply to fe80::/64 type query\n");
- write (v6sox, &v6data6, sizeof (struct ethhdr) + sizeof (struct ip6_hdr) + 4 + 28);
+ write (v6sox, &v6data6, HDR_SIZE + sizeof (struct ip6_hdr) + 4 + 28);
return;
} else {
+// TODO
+#ifdef PEER_USE_TAP
enqueue ((struct in6_addr *) v6ndtarget, (struct in6_addr *) v6src6, v6ether.h_source);
+#endif
}
break;
case ND_NEIGHBOR_ADVERT:
}
}
-
/*
* Receive an IPv6 package, check its address and pickup IPv4 address and
* port, then package it as a tunnel message and forward it to IPv4:port.
* locally generated.
*/
void handle_6to4 (void) {
+#ifndef PEER_USE_TAP
+ static uint8_t lladdr [] =
+ {
+ // UDP port
+ UDP_PORT_6BED4 & 0xff,
+ UDP_PORT_6BED4 >> 8,
+ // IPv4 address
+ SERVER_6BED4_IPV4_INT0,
+ SERVER_6BED4_IPV4_INT1,
+ SERVER_6BED4_IPV4_INT2,
+ SERVER_6BED4_IPV4_INT3
+ };
+#endif
//
// Receive the IPv6 package and ensure a consistent size
size_t rawlen = read (v6sox, &v6data6, sizeof (v6data6));
if (rawlen == -1) {
return; /* failure to read, drop */
}
- if (rawlen < sizeof (struct ethhdr) + sizeof (struct ip6_hdr) + 1) {
+ if (rawlen < HDR_SIZE + sizeof (struct ip6_hdr) + 1) {
return; /* packet too small, drop */
}
+#ifdef PEER_USE_TAP
if (v6ether.h_proto != htons (ETH_P_IPV6)) {
return; /* not IPv6, drop */
}
syslog (LOG_DEBUG, "TODO: Self-to-self messaging in IPv6 stack ignored\n");
return;
}
+#endif
/*
* Distinguish types of traffic:
* Non-plain, Plain Unicast, Plain Multicast
return;
}
syslog (LOG_DEBUG, "Forwarding plain unicast from IPv6 to 6bed4\n");
+#ifdef PEER_USE_TAP
handle_6to4_plain_unicast (rawlen, v6ether.h_dest);
+#else
+ handle_6to4_plain_unicast (rawlen, lladdr);
+#endif
+
} else {
//
// Plain Multicast
memcpy (&v4listen, &v4peer.sin_addr, 4);
memset (&v4bind, 0, sizeof (v4bind));
v4bind.sin_family = AF_INET;
+#ifndef PEER_USE_TAP
+ v4tunpi6.flags = 0;
+ v4tunpi6.proto = htons (ETH_P_IPV6);
+#endif
//
// Parse commandline arguments
if (!process_args (argc, argv)) {