Skip to content

Commit

Permalink
Work in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
Caleb James DeLisle committed Jul 31, 2013
1 parent dd94a9d commit 34b62a0
Show file tree
Hide file tree
Showing 9 changed files with 230 additions and 8 deletions.
1 change: 1 addition & 0 deletions interface/tuntap/windows/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
add_library(cjdns-interface-tuntap-win32
TAPDevice.c
TAPInterface.c
NDPServer.c
# TUNInterface_WIN32.c
)
target_link_libraries(cjdns-interface-tuntap-win32
Expand Down
130 changes: 130 additions & 0 deletions interface/tuntap/windows/NDPServer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/* vim: set expandtab ts=4 sw=4: */
/*
* You may redistribute this program and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "interface/tuntap/windows/NDPServer.h"
#include "interface/InterfaceWrapper.h"
#include "util/Bits.h"
#include "util/Identity.h"
#include "wire/Message.h"
#include "wire/Ethernet.h"
#include "wire/Headers.h"

struct NDPServer_pvt
{
struct Interface pub;
struct Interface* wrapped;
Identity
};

#define MULTICAST_ADDR "\xff\x02\0\0\0\0\0\0\0\0\0\1\xff\0\0\x08"
#define UNICAST_ADDR "\xfe\x80\0\0\0\0\0\0\0\0\0\0\0\0\0\x08"

/**
* 0 - not a solicitation
* 1 - multicast solicitation
* 2 - unicast solicitation
*/
static int getMessageType(struct Message* msg)
{
if (msg->length < Ethernet_SIZE + Headers_IP6Header_SIZE + Headers_ICMP6Header_SIZE) {
return 0;
}
struct Ethernet* eth = msg->bytes;
struct Headers_IP6Header* ip6 = &eth[1];
struct Headers_ICMP6Header* icmp = &ip6[1];

int type;
if (!Bits_memcmp(ip6->destinationAddr, UNICAST_ADDR, 16)) {
type = 2;
} else if (!Bits_memcmp(ip6->destinationAddr, MULTICAST_ADDR, 16)) {
type = 1;
} else {
return 0;
}

if (ip6->nextHeader != 58 /* IPPROTO_ICMPV6 */) {
return 0;

} else if (Bits_memcmp(ip6->sourceAddr, UNICAST_ADDR, 16)) {
return 0;

} else if (icmp->type != 135 /* ICMPV6_TYPE_NS */ || icmp->code != 0) {
return 0;
}
return type;
}

static uint8_t receiveMessage(struct Message* msg, struct Interface* iface)
{
struct NDPServer_pvt* ns = Identity_cast((struct NDPServer_pvt*)iface->receiverContext);

int msgType = getMessageType(msg);
if (!msgType) {
return Interface_receiveMessage(&ns->pub, msg);
}

// store the eth header so it doesn't get clobbered
struct Ethernet eth;
Message_pop(msg, &eth, sizeof(eth));

Message_shift(msg, -msg->length);

// NDP mac address option
struct NDPHeader_NeighborAdvert_MacOpt macOpt = { .two = 2, .one = 1 };
Bits_memcpyConst(&macOpt, eth->destAddr, 6);
Message_push(msg, &macOpt, sizeof(macOpt));

// NDP message
struct NDPHeader_NeighborAdvert adv = {
.oneThirtyFive = 135,
.bits = NDPHeader_NeighborAdvert_bits_SOLICITED | NDPHeader_NeighborAdvert_bits_OVERRIDE
};
Bits_memcpyConst(adv->targetAddr, UNICAST_ADDR, 16); // TODO: Why does this work?
Message_push(msg, &adv, sizeof(adv));

// IPv6
struct Headers_IP6Header* ip6 = {
.payloadLength_be = Endian_hostToBigEndian16(contentLen),
.nextHeader = 58, /* IPPROTO_ICMPV6 */
.hopLimit = 255
};
Headers_setIpVersion(ip6);
Bits_memcpyConst(ip6->sourceAddr, UNICAST_ADDR, 16);
Bits_memcpyConst(ip6->destinationAddr, ((msgType == 2) ? MULTICAST_ADDR : UNICAST_ADDR), 16);
Message_push(msg, &ip6, sizeof(ip6));

// Eth
Message_push(msg, &eth, sizeof(eth));
struct Ethernet* ethP = (struct Ethernet*) message->bytes;
Bits_memcpy(ethP->destAddr, eth.srcAddr, 6);
Bits_memcpy(ethP->srcAddr, eth.destAddr, 6);

return Interface_receiveMessage(ns->wrapped, msg);
}

static uint8_t sendMessage(struct Message* msg, struct Interface* iface)
{
struct NDPServer_pvt* ns = Identity_cast((struct NDPServer_pvt*)iface);
return Interface_sendMessage(ns->wrapped, msg);
}

struct Interface* NDPServer_new(struct Interface* external, struct Allocator* alloc)
{
struct NDPServer_pvt* out = Allocator_clone(alloc, (&(struct NDPServer_pvt*) {
.wrapped = wrapped
}));
Identity_set(out);
return InterfaceWrapper_wrap(external, sendMessage, receiveMessage, &out->pub);
}
23 changes: 23 additions & 0 deletions interface/tuntap/windows/NDPServer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/* vim: set expandtab ts=4 sw=4: */
/*
* You may redistribute this program and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NDPServer_H
#define NDPServer_H

#include "interface/Interface.h"
#include "memory/Allocator.h"

struct Interface* NDPServer_new(struct Interface* external, struct Allocator* alloc);

#endif
3 changes: 2 additions & 1 deletion interface/tuntap/windows/TAPInterface.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "interface/FramingInterface.h"
#include "util/events/EventBase.h"
#include "util/events/Pipe.h"
#include "util/platform/netdev/NetDev.h"

/*
* Portions of this code are copied from QEMU project which is licensed
Expand Down Expand Up @@ -170,7 +171,7 @@ struct Interface* TAPInterface_new(const char* preferredName,
struct TAPDevice* dev = TAPDevice_find(preferredName, eh, alloc);
*assignedName = dev->name;

flushAddresses(dev->name, eh);
NetDev_flushAddresses(dev->name, eh);

Log_debug(logger, "Opening TAP-Windows device [%s] at location [%s]", dev->name, dev->path);

Expand Down
7 changes: 7 additions & 0 deletions util/platform/netdev/NetDev.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,10 @@ void NetDev_setMTU(const char* interfaceName,
{
NetPlatform_setMTU(interfaceName, mtu, logger, eh);
}

void NetDev_flushAddresses(const char* deviceName, struct Except* eh)
{
#ifdef Windows
NetPlatform_flushAddresses(deviceName, eh);
#endif
}
4 changes: 4 additions & 0 deletions util/platform/netdev/NetDev.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#ifndef NetDev_H
#define NetDev_H

#include "util/platform/Sockaddr.h"

/**
* Set an address on an interface, if the interface is down (linux) bring it up,
* and if the interface requires an explicit route (Illumos), configure it.
Expand Down Expand Up @@ -44,4 +46,6 @@ void NetDev_setMTU(const char* interfaceName,
struct Log* logger,
struct Except* eh);

void NetDev_flushAddresses(const char* deviceName, struct Except* eh);

#endif
18 changes: 11 additions & 7 deletions util/platform/netdev/NetPlatform_Windows.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ static NET_LUID getLuid(const char* name, struct Except* eh)
return out;
}

static LONG flushAddresses(NET_LUID luid, PMIB_UNICASTIPADDRESS_TABLE* table)
static LONG flushAddresses(NET_LUID luid, MIB_UNICASTIPADDRESS_TABLE* table)
{
LONG out = NO_ERROR;
for (int i = 0; i < table->NumEntries; i++) {
for (int i = 0; i < (int)table->NumEntries; i++) {
if (table->Table[i].InterfaceLuid.Value == luid.Value) {
if ((out = DeleteUnicastIpAddressEntry(&table->Table[i]))) {
return out;
Expand All @@ -79,17 +79,21 @@ static LONG flushAddresses(NET_LUID luid, PMIB_UNICASTIPADDRESS_TABLE* table)
void NetPlatform_flushAddresses(const char* deviceName, struct Except* eh)
{
NET_LUID luid = getLuid(deviceName, eh);
PMIB_UNICASTIPADDRESS_TABLE* table;
MIB_UNICASTIPADDRESS_TABLE* table;

WinFail_check(eh, GetUnicastIpAddressTable(AF_INET, fourTable));
WinFail_check(eh, GetUnicastIpAddressTable(AF_INET, &table));
LONG ret = flushAddresses(luid, table);
FreeMibTable(table);
WinFail_fail(eh, "DeleteUnicastIpAddressEntry(&table->Table[i])", ret);
if (ret) {
WinFail_fail(eh, "DeleteUnicastIpAddressEntry(&table->Table[i])", ret);
}

WinFail_check(eh, GetUnicastIpAddressTable(AF_INET6, table);
WinFail_check(eh, GetUnicastIpAddressTable(AF_INET6, &table));
ret = flushAddresses(luid, table);
FreeMibTable(table);
WinFail_fail(eh, "DeleteUnicastIpAddressEntry(&table->Table[i])", ret);
if (ret) {
WinFail_fail(eh, "DeleteUnicastIpAddressEntry(&table->Table[i])", ret);
}
}

void NetPlatform_addAddress(const char* name,
Expand Down
10 changes: 10 additions & 0 deletions wire/Ethernet.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@

#include "util/Endian.h"

struct Ethernet
{
uint16_t pad;
uint8_t destAddr[6];
uint8_t srcAddr[6];
uint16_t ethertype;
};
#define Ethernet_SIZE 16
Assert_compileTime(sizeof(struct Ethernet) == Ethernet_SIZE);

#define Ethernet_TYPE_IP4 Endian_hostToBigEndian16( 0x0800 )
#define Ethernet_TYPE_IP6 Endian_hostToBigEndian16( 0x86DD )
#define Ethernet_TYPE_CJDNS Endian_hostToBigEndian16( 0xFC00 )
Expand Down
42 changes: 42 additions & 0 deletions wire/NDPHeader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/* vim: set expandtab ts=4 sw=4: */
/*
* You may redistribute this program and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NDPHeader_H
#define NDPHeader_H

#include "util/Assert.h"
#include "util/Endian.h"

#include <stdint.h>

struct NDPHeader_NeighborAdvert {
uint8_t oneThirtyFive;
uint8_t zero;
uint16_t checksum;
uint8_t bits;
uint8_t reserved[3];
uint8_t targetAddr[16];
};

#define NDPHeader_NeighborAdvert_bits_ROUTER (1<<7)
#define NDPHeader_NeighborAdvert_bits_SOLICITED (1<<6)
#define NDPHeader_NeighborAdvert_bits_OVERRIDE (1<<5)

struct NDPHeader_NeighborAdvert_MacOpt {
uint8_t two; // type
uint8_t one; // length in 8 byte increments
uint8_t mac[6];
};

#endif

0 comments on commit 34b62a0

Please sign in to comment.