Skip to content

Commit

Permalink
Added spoofing of ipv6 NDP Solicitations
Browse files Browse the repository at this point in the history
Ticket #42
  • Loading branch information
PherricOxide committed Nov 13, 2012
1 parent 3968455 commit 6ad12c2
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 14 deletions.
19 changes: 12 additions & 7 deletions honeyd.c
Original file line number Diff line number Diff line change
Expand Up @@ -2886,22 +2886,21 @@ honeyd_dispatch(struct template *tmpl, struct ip_hdr *ip, u_short iplen)
}

void
honeyd_dispatch_ipv6(struct template *tmpl, struct ip6_hdr *ip, u_short iplen)
honeyd_dispatch_ipv6(struct tuple *summary, struct template *tmpl, struct ip6_hdr *ip, u_short iplen)
{
struct tuple iphdr;
addr_pack(&iphdr.address_dst, ADDR_TYPE_IP6, IP6_ADDR_BITS, &ip->ip6_dst ,IP6_ADDR_LEN);
addr_pack(&iphdr.address_src, ADDR_TYPE_IP6, IP6_ADDR_BITS, &ip->ip6_src ,IP6_ADDR_LEN);
addr_pack(&summary->address_dst, ADDR_TYPE_IP6, IP6_ADDR_BITS, &ip->ip6_dst ,IP6_ADDR_LEN);
addr_pack(&summary->address_src, ADDR_TYPE_IP6, IP6_ADDR_BITS, &ip->ip6_src ,IP6_ADDR_LEN);

switch(ip->ip6_nxt) {
case IP_PROTO_TCP:
tcp_recv_cb(tmpl, (u_char *)ip + IP6_HDR_LEN, &iphdr, iplen - IP6_HDR_LEN);
tcp_recv_cb(tmpl, (u_char *)ip + IP6_HDR_LEN, summary, iplen - IP6_HDR_LEN);
break;
case IP_PROTO_UDP:
// TODO ipv6
//udp_recv_cb(tmpl, (u_char *)ip, iplen);
break;
case IP_PROTO_ICMPV6:
icmpv6_recv_cb(tmpl, (u_char*)ip + IP6_HDR_LEN, &iphdr, iplen - IP6_HDR_LEN);
icmpv6_recv_cb(tmpl, (u_char*)ip + IP6_HDR_LEN, summary, iplen - IP6_HDR_LEN);
break;
default:
// TODO ipv6
Expand Down Expand Up @@ -3328,7 +3327,13 @@ honeyd_recv_cb(u_char *ag, const struct pcap_pkthdr *pkthdr, const u_char *pkt)

addr_pack(&addr, ADDR_TYPE_IP6, IP6_ADDR_BITS, &ip6->ip6_dst ,IP6_ADDR_LEN);
struct template *t = template_find_best(addr_ntoa(&addr), NULL, 0);
honeyd_dispatch_ipv6(t, ip6, iplen);

struct tuple summary;
addr_pack(&summary.linkLayer_src, ADDR_TYPE_ETH, ETH_ADDR_BITS, &eth->eth_src,ETH_ADDR_LEN);
addr_pack(&summary.linkLayer_dst, ADDR_TYPE_ETH, ETH_ADDR_BITS, &eth->eth_dst,ETH_ADDR_LEN);
summary.inter = inter;

honeyd_dispatch_ipv6(&summary, t, ip6, iplen);

return;
}
Expand Down
2 changes: 1 addition & 1 deletion honeyd.h
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ struct tuple *tuple_find(struct tree *, struct tuple *);

void honeyd_ip_send(u_char *, u_int, struct spoof spoof);
void honeyd_dispatch(struct template *, struct ip_hdr *, u_short);
void honeyd_dispatch_ipv6(struct template *, struct ip6_hdr *, u_short);
void honeyd_dispatch_ipv6(struct tuple *summary, struct template *, struct ip6_hdr *, u_short);
char *honeyd_contoa(const struct tuple *);

void honeyd_input(const struct interface *, struct ip_hdr *, u_short);
Expand Down
15 changes: 15 additions & 0 deletions icmpv6.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ struct icmpv6_hdr {

#define ICMPV6_INFOTYPE(type) (((type) & 0x80) != 0)

#define ICMPV6_NAFLAGS_ROUTER 0x4
#define ICMPV6_NAFLAGS_SOLICITED 0x2
#define ICMPV6_NAFLAGS_OVERRIDE 0x1

/*
* Echo message data
*/
Expand Down Expand Up @@ -119,4 +123,15 @@ union icmpv6_msg {
memmove(&nd_pack_p->icmpv6_mac, &(srcmac), ETH_ADDR_LEN); \
} while (0)

#define icmpv6_pack_hdr_na_mac(hdr, targetip, targetmac) do { \
struct icmpv6_msg_nd *nd_pack_p = (struct icmpv6_msg_nd *) \
((uint8_t *)(hdr) + ICMPV6_HDR_LEN); \
icmpv6_pack_hdr(hdr, ICMPV6_NEIGHBOR_ADVERTISEMENT, 0); \
nd_pack_p->icmpv6_flags = 0 | ICMPV6_NAFLAGS_SOLICITED | ICMPV6_NAFLAGS_OVERRIDE; \
memmove(&nd_pack_p->icmpv6_target, &(targetip), IP6_ADDR_LEN); \
nd_pack_p->icmpv6_option_type = 2; \
nd_pack_p->icmpv6_option_length = 1; \
memmove(&nd_pack_p->icmpv6_mac, &(targetmac), ETH_ADDR_LEN); \
} while (0)

#endif /* DNET_ICMPV6_H */
74 changes: 70 additions & 4 deletions ndp.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,33 @@
#include "debug.h"

/* For the physical (IP) address */
static SPLAY_HEAD(pandptree, ndp_req) pa_ndp_reqs;
static SPLAY_HEAD(ndpTree, ndp_req) pa_ndp_reqs;

static int
pandp_compare(struct ndp_req *a, struct ndp_req *b)
{
return (addr_cmp(&a->pa, &b->pa));
}

SPLAY_PROTOTYPE(pandptree, ndp_req, next_pa, pandp_compare);
SPLAY_GENERATE(pandptree, ndp_req, next_pa, pandp_compare);
SPLAY_PROTOTYPE(ndpTree, ndp_req, next_pa, pandp_compare);
SPLAY_GENERATE(ndpTree, ndp_req, next_pa, pandp_compare);


struct ndp_req *
ndp_find(struct addr *addr)
{
struct ndp_req tmp, *res = NULL;

if (addr->addr_type == ADDR_TYPE_IP6) {
tmp.pa = *addr;
res = SPLAY_FIND(ndpTree, &pa_ndp_reqs, &tmp);
} else {
errx(1, "%s: lookup for unsupported address type", __func__);
}

return (res);
}


void
ndp_init(void)
Expand All @@ -104,7 +121,7 @@ ndp_new(struct interface *inter,

if (pa != NULL) {
req->pa = *pa;
SPLAY_INSERT(pandptree, &pa_ndp_reqs, req);
SPLAY_INSERT(ndpTree, &pa_ndp_reqs, req);
}

// TODO ipv6: Do we want another MAC -> thing tree here? Need to think about this. Maybe refactor the hardware mapping out.
Expand All @@ -123,11 +140,60 @@ ndp_new(struct interface *inter,
return (req);
}

void ndp_send_advertisement(eth_t *eth,
struct addr linkLayerSource, struct addr linkLayerDestination,
struct addr ipLayerSource, struct addr ipLayerDestination,
struct addr advertisementLinkTarget, struct addr advertisementIpTarget)
{

printf("Ndp advertisement details {\nipLayerSource: %s\nipLayerDestination: %s \nadvertisementLinkTarget: %s\nadvertisementIpTarget: %s\n}\n", addr_ntoa(&ipLayerSource), addr_ntoa(&ipLayerDestination), addr_ntoa(&advertisementLinkTarget), addr_ntoa(&advertisementIpTarget));
uint packetLength = ETH_HDR_LEN + IP6_HDR_LEN + ICMPV6_HDR_LEN + sizeof(struct icmpv6_msg_nd);
u_char pkt[packetLength];

eth_pack_hdr(pkt, linkLayerDestination.addr_eth, linkLayerSource.addr_eth, ETH_TYPE_IPV6);
ip6_pack_hdr(pkt + ETH_HDR_LEN, 0, 0, 32, IP_PROTO_ICMPV6, IP6_HLIM_MAX, ipLayerSource.__addr_u.__ip6, ipLayerDestination.__addr_u.__ip6);
icmpv6_pack_hdr_na_mac(pkt + ETH_HDR_LEN + IP6_HDR_LEN, advertisementIpTarget.__addr_u.__ip6, advertisementLinkTarget.__addr_u.__eth);

ip6_checksum(pkt + ETH_HDR_LEN, packetLength - ETH_HDR_LEN);

syslog(LOG_INFO, "ndp reply %s is-at %s", addr_ntoa(&advertisementIpTarget), addr_ntoa(&advertisementLinkTarget));

if (eth_send(eth, pkt, sizeof(pkt)) != sizeof(pkt))
syslog(LOG_ERR, "couldn't send packet: %m");
}

void
ndp_recv_cb(struct tuple *summary, const struct icmpv6_msg_nd *query)
{
struct template *tmpl;
struct addr *linkLayerSource;
struct addr queryIP;
struct ndp_req *req;
addr_pack(&queryIP, ADDR_TYPE_IP6, IP6_ADDR_BITS, &query->icmpv6_target ,IP6_ADDR_LEN);
printf("Got a request for IP %s\n", addr_ntoa(&queryIP));

tmpl = template_find(addr_ntoa(&queryIP));
req = ndp_find(&queryIP);

// Ignore it if isn't a template IP
if (req == NULL || tmpl == NULL)
{
return;
}

if (tmpl->ethernet_addr == NULL)
linkLayerSource = &summary->inter->if_ent.intf_link_addr;
else
linkLayerSource = tmpl->ethernet_addr;

printf("Creating reply now\n");

ndp_send_advertisement(summary->inter->if_eth,
*linkLayerSource, summary->linkLayer_src,
queryIP, summary->address_src,
*linkLayerSource, queryIP);


}


9 changes: 8 additions & 1 deletion ndp.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,17 @@ struct ndp_req {

void ndp_init();

struct ndp_req *ndp_new(struct interface *,
struct ndp_req *ndp_new(struct interface *inter,
struct addr *src_pa, struct addr *src_ha,
struct addr *pa, struct addr *ha);


void ndp_send_advertisement(eth_t *eth,
struct addr linkLayerSource, struct addr linkLayerDestination,
struct addr ipLayerSource, struct addr ipLayerDestination,
struct addr advertisementLinkTarget, struct addr advertisementIpTarget);

struct ndp_req * ndp_find(struct addr *addr);
void ndp_recv_cb(struct tuple *summary, const struct icmpv6_msg_nd *query);


Expand Down
11 changes: 10 additions & 1 deletion tuple.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#ifndef TUPLE_H_
#define TUPLE_H_


/*
* For subsystems, we need to be able to schedule a callback that hands
* the subsytem a file descriptor to the new connection. However, Honeyd
Expand All @@ -30,9 +29,19 @@ struct tuple {
SPLAY_ENTRY(tuple) node;
TAILQ_ENTRY(tuple) next;

// IP layer src/dst packet come from
struct addr address_src;
struct addr address_dst;

// Link layer src/dst packet came from
struct addr linkLayer_src;
struct addr linkLayer_dst;

// Interface packet came from
struct interface *inter;

// Used for TCP/UDP and ICMP
// TODO: Using this for ICMP is hackish. Make it a union for type/code.
uint16_t sport;
uint16_t dport;

Expand Down

0 comments on commit 6ad12c2

Please sign in to comment.