mirror of
https://code.semirocket.science/wrapsix
synced 2024-11-10 08:10:59 +02:00
Completed the implementation of NDP
This commit is contained in:
parent
322eeabefb
commit
39ba6988c0
@ -2,7 +2,7 @@ CC = gcc
|
|||||||
CFLAGS = -Wall -O0
|
CFLAGS = -Wall -O0
|
||||||
LDFLAGS = -L/usr/lib -lpcap
|
LDFLAGS = -L/usr/lib -lpcap
|
||||||
|
|
||||||
all: wrapper.o process.o translate_ip.o connections.o checksum.o
|
all: wrapper.o process.o translate_ip.o connections.o checksum.o if.o
|
||||||
$(CC) $(CFLAGS) $(LDFLAGS) *.o -o wrapper
|
$(CC) $(CFLAGS) $(LDFLAGS) *.o -o wrapper
|
||||||
|
|
||||||
wrapper.o: wrapper.c wrapper.h
|
wrapper.o: wrapper.c wrapper.h
|
||||||
@ -20,5 +20,8 @@ connections.o: connections.c wrapper.h
|
|||||||
checksum.o: checksum.c
|
checksum.o: checksum.c
|
||||||
$(CC) $(CFLAGS) -c checksum.c -o checksum.o
|
$(CC) $(CFLAGS) -c checksum.c -o checksum.o
|
||||||
|
|
||||||
|
if.o: if.c wrapper.h
|
||||||
|
$(CC) $(CFLAGS) -c if.c -o if.o
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f wrapper *.o
|
rm -f wrapper *.o
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
#include <unistd.h>
|
#include <net/if.h> /* ifreq */
|
||||||
|
#include <netinet/if_ether.h> /* ETH_P_IP, ETH_P_ALL */
|
||||||
|
#include <netpacket/packet.h> /* sockaddr_ll, PACKET_OTHERHOST */
|
||||||
|
|
||||||
#include "wrapper.h"
|
#include "wrapper.h"
|
||||||
|
|
||||||
@ -21,3 +23,47 @@ void send_there(struct in_addr ip4_addr, unsigned char ttl, unsigned int type, u
|
|||||||
|
|
||||||
close(sock);
|
close(sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void send_ndp(struct ip6_hdr *ip, unsigned char *packet, int packet_size)
|
||||||
|
{
|
||||||
|
struct sockaddr_ll socket_address; /* target address */
|
||||||
|
struct ifreq ifr; /* interface */
|
||||||
|
|
||||||
|
int sock;
|
||||||
|
|
||||||
|
/* prepare data for RAW socket */
|
||||||
|
socket_address.sll_family = PF_PACKET; /* RAW communication */
|
||||||
|
socket_address.sll_protocol = htons(ETH_P_IP); /* protocol above the ethernet layer */
|
||||||
|
socket_address.sll_ifindex = get_dev_index(dev); /* set index of the network device */
|
||||||
|
socket_address.sll_pkttype = PACKET_OTHERHOST; /* target host is another host */
|
||||||
|
|
||||||
|
/* initialize with zeros */
|
||||||
|
memset(&ifr, 0, sizeof(struct ifreq));
|
||||||
|
|
||||||
|
/* set device */
|
||||||
|
strncpy(ifr.ifr_name, dev, strlen(dev));
|
||||||
|
|
||||||
|
/* initialize raw socket */
|
||||||
|
if ((sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) {
|
||||||
|
fprintf(stderr, "Couldn't open RAW socket.\n");
|
||||||
|
perror("socket()");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* bind the socket to the interface */
|
||||||
|
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(struct ifreq)) == -1){
|
||||||
|
fprintf(stderr, "Couldn't bind the socket to the interface.\n");
|
||||||
|
perror("setsockopt()");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send the NDP packet */
|
||||||
|
if (sendto(sock, packet, packet_size, 0, (struct sockaddr *) &socket_address, sizeof(struct sockaddr_ll)) != packet_size) {
|
||||||
|
fprintf(stderr, " Error: Couldn't send NDP packet.\n");
|
||||||
|
perror("sendto()");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* close the socket */
|
||||||
|
close(sock);
|
||||||
|
}
|
||||||
|
57
wrapper/if.c
Normal file
57
wrapper/if.c
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
|
||||||
|
#include "wrapper.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the MAC (ie, ethernet hardware) address
|
||||||
|
*/
|
||||||
|
int get_mac_addr(const char *dev, struct s_mac_addr *addr)
|
||||||
|
{
|
||||||
|
struct ifreq ifr;
|
||||||
|
int s, ret;
|
||||||
|
|
||||||
|
if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&ifr, 0x00, sizeof(ifr));
|
||||||
|
strcpy(ifr.ifr_name, dev);
|
||||||
|
|
||||||
|
if (ioctl(s, SIOCGIFHWADDR, &ifr) == 0) {
|
||||||
|
memcpy(addr, &ifr.ifr_hwaddr.sa_data, sizeof(struct s_mac_addr));
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(s);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return device index
|
||||||
|
*/
|
||||||
|
int get_dev_index(const char *dev)
|
||||||
|
{
|
||||||
|
struct ifreq ifr;
|
||||||
|
int s;
|
||||||
|
|
||||||
|
memset(&ifr, 0x00, sizeof(ifr));
|
||||||
|
|
||||||
|
if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy((char *) ifr.ifr_name, dev, IFNAMSIZ);
|
||||||
|
if ((ioctl(s, SIOCGIFINDEX, &ifr)) == -1) {
|
||||||
|
printf("Error getting Interface index !\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(s);
|
||||||
|
|
||||||
|
return ifr.ifr_ifindex;
|
||||||
|
}
|
@ -1,13 +1,14 @@
|
|||||||
#include "wrapper.h"
|
#include "wrapper.h"
|
||||||
#include "translate_ip.h"
|
#include "translate_ip.h"
|
||||||
|
|
||||||
|
struct in6_addr ip6addr_wrapsix;
|
||||||
|
|
||||||
void process_packet6(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
|
void process_packet6(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
|
||||||
{
|
{
|
||||||
const struct s_ethernet *ethernet; /* the ethernet header */
|
const struct s_ethernet *ethernet; /* the ethernet header */
|
||||||
const struct s_ip6 *ip; /* the IP header */
|
const struct s_ip6 *ip; /* the IP header */
|
||||||
const unsigned char *payload; /* packet payload */
|
const unsigned char *payload; /* packet payload */
|
||||||
|
|
||||||
struct in6_addr ip6addr_wrapsix;
|
|
||||||
struct in6_addr ip6addr_ndp_multicast;
|
struct in6_addr ip6addr_ndp_multicast;
|
||||||
|
|
||||||
/* define ethernet header */
|
/* define ethernet header */
|
||||||
@ -19,6 +20,13 @@ void process_packet6(u_char *args, const struct pcap_pkthdr *header, const u_cha
|
|||||||
/* define/compute IP payload offset */
|
/* define/compute IP payload offset */
|
||||||
payload = packet + SIZE_ETHERNET + SIZE_IP6;
|
payload = packet + SIZE_ETHERNET + SIZE_IP6;
|
||||||
|
|
||||||
|
/* DEBUG: print source and destination IP addresses */
|
||||||
|
char ip6addr[INET6_ADDRSTRLEN];
|
||||||
|
inet_ntop(AF_INET6, &ip->ip_src, ip6addr, sizeof(ip6addr));
|
||||||
|
printf("\n From: %s\n", ip6addr);
|
||||||
|
inet_ntop(AF_INET6, &ip->ip_dest, ip6addr, sizeof(ip6addr));
|
||||||
|
printf(" To: %s\n", ip6addr);
|
||||||
|
|
||||||
/* check if this packet is ours - partially hardcoded for now */
|
/* check if this packet is ours - partially hardcoded for now */
|
||||||
inet_pton(AF_INET6, "fc00:1::", &ip6addr_wrapsix);
|
inet_pton(AF_INET6, "fc00:1::", &ip6addr_wrapsix);
|
||||||
inet_pton(AF_INET6, "ff02::1:ff00:0", &ip6addr_ndp_multicast);
|
inet_pton(AF_INET6, "ff02::1:ff00:0", &ip6addr_ndp_multicast);
|
||||||
@ -29,13 +37,6 @@ void process_packet6(u_char *args, const struct pcap_pkthdr *header, const u_cha
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* DEBUG: print source and destination IP addresses */
|
|
||||||
char ip6addr[INET6_ADDRSTRLEN];
|
|
||||||
inet_ntop(AF_INET6, &ip->ip_src, ip6addr, sizeof(ip6addr));
|
|
||||||
printf("\n From: %s\n", ip6addr);
|
|
||||||
inet_ntop(AF_INET6, &ip->ip_dest, ip6addr, sizeof(ip6addr));
|
|
||||||
printf(" To: %s\n", ip6addr);
|
|
||||||
|
|
||||||
/* determine protocol */
|
/* determine protocol */
|
||||||
switch (ip->next_header) {
|
switch (ip->next_header) {
|
||||||
case IPPROTO_TCP:
|
case IPPROTO_TCP:
|
||||||
@ -47,7 +48,7 @@ void process_packet6(u_char *args, const struct pcap_pkthdr *header, const u_cha
|
|||||||
break;
|
break;
|
||||||
case IPPROTO_ICMPV6:
|
case IPPROTO_ICMPV6:
|
||||||
printf(" Protocol: ICMPv6\n");
|
printf(" Protocol: ICMPv6\n");
|
||||||
process_icmp6((struct s_ip6 *) ip, payload);
|
process_icmp6((const struct s_ethernet *) ethernet, (struct s_ip6 *) ip, payload);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf(" Protocol: unknown\n");
|
printf(" Protocol: unknown\n");
|
||||||
@ -56,39 +57,30 @@ void process_packet6(u_char *args, const struct pcap_pkthdr *header, const u_cha
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void process_icmp6(const struct s_ip6 *ip, const unsigned char *payload)
|
void process_icmp6(const struct s_ethernet *eth, struct s_ip6 *ip, const unsigned char *payload)
|
||||||
{
|
{
|
||||||
struct s_icmp *icmp;
|
struct s_icmp *icmp;
|
||||||
struct in_addr ip4_addr;
|
struct in_addr ip4_addr;
|
||||||
|
|
||||||
const unsigned char *icmp_data;
|
unsigned char *icmp_data;
|
||||||
unsigned char *icmp_packet;
|
unsigned char *icmp_packet;
|
||||||
|
|
||||||
int packet_size;
|
int packet_size = htons(ip->len);
|
||||||
|
|
||||||
/* define ICMP header */
|
/* define ICMP header */
|
||||||
icmp = (struct s_icmp *) (payload);
|
icmp = (struct s_icmp *) (payload);
|
||||||
/* define/compute ICMP data offset */
|
/* define/compute ICMP data offset */
|
||||||
icmp_data = (unsigned char *) (payload + sizeof(struct s_icmp));
|
icmp_data = (unsigned char *) (payload + sizeof(struct s_icmp));
|
||||||
/* the checksum has to be zeros before we have data for its computation */
|
|
||||||
icmp->checksum = 0;
|
|
||||||
|
|
||||||
/* create one big ICMP packet */
|
|
||||||
packet_size = htons(ip->len);
|
|
||||||
icmp_packet = (unsigned char *) malloc(packet_size);
|
|
||||||
|
|
||||||
if (icmp_packet == NULL) {
|
|
||||||
fprintf(stderr, "Fatal error! Lack of free memory!\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* decide what type of ICMP we have */
|
/* decide what type of ICMP we have */
|
||||||
switch (icmp->type) {
|
switch (icmp->type) {
|
||||||
/* NDP */
|
/* NDP */
|
||||||
case ICMP6_NDP_NS:
|
case ICMP6_NDP_NS:
|
||||||
printf(" ICMP: [NDP] Neighbor Solicitation\n");
|
printf(" ICMP: [NDP] Neighbor Solicitation\n");
|
||||||
|
|
||||||
|
process_ndp(eth, ip, icmp_data);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
break;
|
|
||||||
/* ping */
|
/* ping */
|
||||||
case ICMP6_ECHO_REQUEST:
|
case ICMP6_ECHO_REQUEST:
|
||||||
printf(" ICMP: Echo Request\n");
|
printf(" ICMP: Echo Request\n");
|
||||||
@ -113,10 +105,20 @@ void process_icmp6(const struct s_ip6 *ip, const unsigned char *payload)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* create one big ICMP packet */
|
||||||
|
icmp_packet = (unsigned char *) malloc(packet_size);
|
||||||
|
|
||||||
|
if (icmp_packet == NULL) {
|
||||||
|
fprintf(stderr, "Fatal error! Lack of free memory!\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the checksum has to be zeros before we have data for its computation */
|
||||||
|
icmp->checksum = 0;
|
||||||
|
|
||||||
/* copy data into the packet */
|
/* copy data into the packet */
|
||||||
memcpy(icmp_packet, icmp, sizeof(struct s_icmp));
|
memcpy(icmp_packet, icmp, sizeof(struct s_icmp));
|
||||||
memcpy(icmp_packet + sizeof(struct s_icmp), icmp_data,
|
memcpy(icmp_packet + sizeof(struct s_icmp), icmp_data, packet_size - sizeof(struct s_icmp));
|
||||||
packet_size - sizeof(struct s_icmp));
|
|
||||||
|
|
||||||
/* compute the checksum */
|
/* compute the checksum */
|
||||||
icmp->checksum = checksum(icmp_packet, packet_size);
|
icmp->checksum = checksum(icmp_packet, packet_size);
|
||||||
@ -134,6 +136,101 @@ void process_icmp6(const struct s_ip6 *ip, const unsigned char *payload)
|
|||||||
/* free allocated memory */
|
/* free allocated memory */
|
||||||
free(icmp_packet);
|
free(icmp_packet);
|
||||||
icmp_packet = NULL;
|
icmp_packet = NULL;
|
||||||
|
}
|
||||||
return;
|
|
||||||
|
void process_ndp(const struct s_ethernet *eth_hdr, struct s_ip6 *ip_hdr, unsigned char *icmp_data)
|
||||||
|
{
|
||||||
|
unsigned char *packet;
|
||||||
|
struct s_ethernet *eth;
|
||||||
|
struct ip6_hdr *ip;
|
||||||
|
struct s_icmp *icmp;
|
||||||
|
struct s_icmp_ndp_ns *ndp_ns;
|
||||||
|
struct s_icmp_ndp_na *ndp_na;
|
||||||
|
|
||||||
|
unsigned char *buf_ip6_pseudo;
|
||||||
|
struct s_ip6_pseudo *ip6_pseudo;
|
||||||
|
|
||||||
|
int packet_size;
|
||||||
|
|
||||||
|
/* get the NDP data */
|
||||||
|
ndp_ns = (struct s_icmp_ndp_ns *) icmp_data;
|
||||||
|
|
||||||
|
/* check if the requested address is ours */
|
||||||
|
if (memcmp(&ip6addr_wrapsix, &ndp_ns->target, 12) != 0) {
|
||||||
|
printf("==> This NDP is not ours! <==\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate memory for the packet */
|
||||||
|
packet_size = SIZE_ETHERNET + SIZE_IP6 + sizeof(struct s_icmp) + sizeof(struct s_icmp_ndp_na);
|
||||||
|
packet = (unsigned char *) malloc(packet_size);
|
||||||
|
|
||||||
|
if (packet == NULL) {
|
||||||
|
fprintf(stderr, "Fatal error! Lack of free memory!\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse the packet into structures */
|
||||||
|
eth = (struct s_ethernet *) packet;
|
||||||
|
ip = (struct ip6_hdr *) (packet + SIZE_ETHERNET);
|
||||||
|
icmp = (struct s_icmp *) (packet + SIZE_ETHERNET + SIZE_IP6);
|
||||||
|
ndp_na = (struct s_icmp_ndp_na *) (packet + SIZE_ETHERNET + SIZE_IP6 + sizeof(struct s_icmp));
|
||||||
|
|
||||||
|
/* assemble the ethernet header */
|
||||||
|
memcpy(ð->src, mac, sizeof(struct s_mac_addr));
|
||||||
|
eth->dest = eth_hdr->src;
|
||||||
|
eth->type = eth_hdr->type;
|
||||||
|
|
||||||
|
/* assemble the IPv6 header */
|
||||||
|
ip->ip6_src = ndp_ns->target;
|
||||||
|
ip->ip6_dst = ip_hdr->ip_src;
|
||||||
|
ip->ip6_flow = 0;
|
||||||
|
ip->ip6_vfc = 0x60;
|
||||||
|
ip->ip6_plen = htons(sizeof(struct s_icmp) + sizeof(struct s_icmp_ndp_na));
|
||||||
|
ip->ip6_nxt = IPPROTO_ICMPV6;
|
||||||
|
ip->ip6_hlim = 255;
|
||||||
|
|
||||||
|
/* assemble the ICMP header */
|
||||||
|
icmp->type = ICMP6_NDP_NA;
|
||||||
|
icmp->code = 0;
|
||||||
|
icmp->checksum = 0;
|
||||||
|
|
||||||
|
/* assemble the NDP */
|
||||||
|
//ndp_na->flags |= INNAF_S;
|
||||||
|
//ndp_na->flags |= INNAF_O;
|
||||||
|
ndp_na->zeros = 0;
|
||||||
|
ndp_na->flags = 0x60;
|
||||||
|
ndp_na->target = ndp_ns->target;
|
||||||
|
ndp_na->o_type = 2;
|
||||||
|
ndp_na->o_len = 1;
|
||||||
|
memcpy(&ndp_na->o_tlla, mac, sizeof(struct s_mac_addr));
|
||||||
|
|
||||||
|
/* compute the ICMP checksum */
|
||||||
|
buf_ip6_pseudo = (unsigned char *) malloc(sizeof(struct s_ip6_pseudo) + htons(ip->ip6_plen));
|
||||||
|
|
||||||
|
if (buf_ip6_pseudo == NULL) {
|
||||||
|
fprintf(stderr, "Fatal error! Lack of free memory!\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ip6_pseudo = (struct s_ip6_pseudo *) buf_ip6_pseudo;
|
||||||
|
|
||||||
|
ip6_pseudo->ip_src = ip->ip6_src;
|
||||||
|
ip6_pseudo->ip_dest = ip->ip6_dst;
|
||||||
|
ip6_pseudo->len = ip->ip6_plen;
|
||||||
|
ip6_pseudo->zeros = 0x0;
|
||||||
|
ip6_pseudo->next_header = ip->ip6_nxt;
|
||||||
|
|
||||||
|
memcpy(buf_ip6_pseudo + sizeof(struct s_ip6_pseudo), icmp, htons(ip->ip6_plen));
|
||||||
|
|
||||||
|
icmp->checksum = checksum(buf_ip6_pseudo, sizeof(struct s_ip6_pseudo) + htons(ip->ip6_plen));
|
||||||
|
|
||||||
|
/* send the packet */
|
||||||
|
send_ndp(ip, packet, packet_size);
|
||||||
|
|
||||||
|
/* free allocated memory */
|
||||||
|
free(packet);
|
||||||
|
free(buf_ip6_pseudo);
|
||||||
|
packet = NULL;
|
||||||
|
buf_ip6_pseudo = NULL;
|
||||||
}
|
}
|
||||||
|
@ -1,33 +1,28 @@
|
|||||||
#include "wrapper.h"
|
#include "wrapper.h"
|
||||||
|
|
||||||
|
struct s_mac_addr *mac; /* MAC address of the device */
|
||||||
|
char *dev; /* capture device name */
|
||||||
|
int dev_index; /* capture device index */
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
|
||||||
char *dev = NULL; /* capture device name */
|
|
||||||
char errbuf[PCAP_ERRBUF_SIZE]; /* error buffer */
|
char errbuf[PCAP_ERRBUF_SIZE]; /* error buffer */
|
||||||
pcap_t *handle; /* packet capture handle */
|
pcap_t *handle; /* packet capture handle */
|
||||||
|
|
||||||
//char filter_exp[] = "ip6"; /* filter expression */
|
//char filter_exp[] = "ip6"; /* filter expression */
|
||||||
char filter_exp[] = "icmp6"; /* filter expression */
|
char filter_exp[] = "icmp6"; /* filter expression */
|
||||||
struct bpf_program fp; /* compiled filter program (expression) */
|
struct bpf_program fp; /* compiled filter program (expression) */
|
||||||
bpf_u_int32 mask; /* subnet mask */
|
int num_packets = 0; /* number of packets to capture; 0 = infinite */
|
||||||
bpf_u_int32 net; /* ip */
|
|
||||||
int num_packets = 0; /* number of packets to capture */
|
|
||||||
|
|
||||||
/* find a capture device */
|
/* find a capture device */
|
||||||
|
dev = NULL;
|
||||||
dev = pcap_lookupdev(errbuf);
|
dev = pcap_lookupdev(errbuf);
|
||||||
if (dev == NULL) {
|
if (dev == NULL) {
|
||||||
fprintf(stderr, "Couldn't find default device: %s\n", errbuf);
|
fprintf(stderr, "Couldn't find default device: %s\n", errbuf);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get network number and mask associated with capture device */
|
|
||||||
if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1) {
|
|
||||||
fprintf(stderr, "Couldn't get netmask for device %s: %s\n", dev, errbuf);
|
|
||||||
net = 0;
|
|
||||||
mask = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* print capture info */
|
/* print capture info */
|
||||||
printf("Device: %s\n", dev);
|
printf("Device: %s\n", dev);
|
||||||
printf("Number of packets: %d\n", num_packets);
|
printf("Number of packets: %d\n", num_packets);
|
||||||
@ -46,17 +41,25 @@ int main(int argc, char **argv)
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* obtain MAC address of the device */
|
||||||
|
mac = (struct s_mac_addr *) malloc(sizeof(struct s_mac_addr));
|
||||||
|
if (get_mac_addr(dev, mac) != 0) {
|
||||||
|
fprintf(stderr, "Couldn't get device MAC address\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get index of the device */
|
||||||
|
dev_index = get_dev_index(dev);
|
||||||
|
|
||||||
/* compile the filter expression */
|
/* compile the filter expression */
|
||||||
if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) {
|
if (pcap_compile(handle, &fp, filter_exp, 0, 0) == -1) {
|
||||||
fprintf(stderr, "Couldn't parse filter %s: %s\n",
|
fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(handle));
|
||||||
filter_exp, pcap_geterr(handle));
|
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* apply the compiled filter */
|
/* apply the compiled filter */
|
||||||
if (pcap_setfilter(handle, &fp) == -1) {
|
if (pcap_setfilter(handle, &fp) == -1) {
|
||||||
fprintf(stderr, "Couldn't install filter %s: %s\n",
|
fprintf(stderr, "Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(handle));
|
||||||
filter_exp, pcap_geterr(handle));
|
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,12 +5,14 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/ip6.h> /* ip6_hdr */
|
||||||
|
|
||||||
/* Default snap length (maximum bytes per packet to capture) */
|
/* Default snap length (maximum bytes per packet to capture) */
|
||||||
#define SNAP_LEN BUFSIZ
|
#define SNAP_LEN BUFSIZ
|
||||||
@ -18,22 +20,29 @@
|
|||||||
/* Ethernet headers are always exactly 14 bytes */
|
/* Ethernet headers are always exactly 14 bytes */
|
||||||
#define SIZE_ETHERNET 14
|
#define SIZE_ETHERNET 14
|
||||||
|
|
||||||
/* Ethernet addresses are 6 bytes */
|
|
||||||
#define ETHER_ADDR_LEN 6
|
|
||||||
|
|
||||||
/* IPv6 headers are always exactly 40 bytes */
|
/* IPv6 headers are always exactly 40 bytes */
|
||||||
#define SIZE_IP6 40
|
#define SIZE_IP6 40
|
||||||
|
|
||||||
/* Ethernet header */
|
/* MAC address structure */
|
||||||
struct s_ethernet {
|
struct s_mac_addr {
|
||||||
u_char ether_dhost[ETHER_ADDR_LEN]; /* destination host address */
|
unsigned char a;
|
||||||
u_char ether_shost[ETHER_ADDR_LEN]; /* source host address */
|
unsigned char b;
|
||||||
u_short ether_type; /* IP/ARP/RARP/... */
|
unsigned char c;
|
||||||
|
unsigned char d;
|
||||||
|
unsigned char e;
|
||||||
|
unsigned char f;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* IPv4 header */
|
/* Ethernet header structure */
|
||||||
|
struct s_ethernet {
|
||||||
|
struct s_mac_addr dest; /* 48 b; destination host (MAC) address */
|
||||||
|
struct s_mac_addr src; /* 48 b; source host (MAC) address */
|
||||||
|
unsigned short type; /* 16 b; IP/ARP/RARP/... */
|
||||||
|
};
|
||||||
|
|
||||||
/* IPv6 header */
|
/* IPv4 header structure */
|
||||||
|
|
||||||
|
/* IPv6 header structure */
|
||||||
struct s_ip6 {
|
struct s_ip6 {
|
||||||
unsigned char ver; /* 8 b; version */
|
unsigned char ver; /* 8 b; version */
|
||||||
unsigned char traffic_class; /* 8 b; traffic class */
|
unsigned char traffic_class; /* 8 b; traffic class */
|
||||||
@ -45,6 +54,17 @@ struct s_ip6 {
|
|||||||
struct in6_addr ip_dest; /* 128 b; destination address */
|
struct in6_addr ip_dest; /* 128 b; destination address */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* pseudo IPv6 header for checksum */
|
||||||
|
struct s_ip6_pseudo {
|
||||||
|
//unsigned short ip_src[8];
|
||||||
|
//unsigned short ip_dest[8];
|
||||||
|
struct in6_addr ip_src; /* 128 b; source address */
|
||||||
|
struct in6_addr ip_dest; /* 128 b; destination address */
|
||||||
|
unsigned short len; /* 16 b; payload length */
|
||||||
|
unsigned int zeros:24; /* 24 b; reserved */
|
||||||
|
unsigned char next_header; /* 8 b; next header */
|
||||||
|
};
|
||||||
|
|
||||||
/* TCP structure - only needed fields! */
|
/* TCP structure - only needed fields! */
|
||||||
struct s_tcp {
|
struct s_tcp {
|
||||||
unsigned short port_src; /* 16 b; source port */
|
unsigned short port_src; /* 16 b; source port */
|
||||||
@ -69,15 +89,31 @@ struct s_icmp_ping {
|
|||||||
unsigned short seq; /* 16 b; sequence value for ECHO REPLY */
|
unsigned short seq; /* 16 b; sequence value for ECHO REPLY */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* ICMPv6 - NDP option structure */
|
||||||
|
struct s_icmp_ndp_option {
|
||||||
|
unsigned char type; /* 8 b; type of the option */
|
||||||
|
unsigned char len; /* 8 b; length of the option (including this header!) */
|
||||||
|
};
|
||||||
|
|
||||||
/* ICMPv6 - NDP NS structure */
|
/* ICMPv6 - NDP NS structure */
|
||||||
struct s_icmp_ndp_ns {
|
struct s_icmp_ndp_ns {
|
||||||
unsigned int zeros; /* 32 b; reserved section */
|
unsigned int zeros; /* 32 b; reserved section */
|
||||||
struct in6_addr target; /* 128 b; target IP address */
|
struct in6_addr target; /* 128 b; target IP address */
|
||||||
};
|
};
|
||||||
struct s_icmp_ndp_option {
|
|
||||||
unsigned char type; /* 8 b; type of the option */
|
/* ICMPv6 - NDP NA structure */
|
||||||
unsigned char len; /* 8 b; length of the option (including this header!) */
|
struct s_icmp_ndp_na {
|
||||||
|
unsigned char flags; /* 8 b; 3 flags */
|
||||||
|
unsigned int zeros:24; /* 24 b; reserved section */
|
||||||
|
struct in6_addr target; /* 128 b; target IP address */
|
||||||
|
unsigned char o_type; /* 8 b; option - type */
|
||||||
|
unsigned char o_len; /* 8 b; option - length */
|
||||||
|
struct s_mac_addr o_tlla; /* 48 b; option - target link-layer address */
|
||||||
};
|
};
|
||||||
|
/* INNAF = ICMPv6 NDP NA Flag */
|
||||||
|
#define INNAF_R 0x80 /* router flag */
|
||||||
|
#define INNAF_S 0x40 /* solicited flag */
|
||||||
|
#define INNAF_O 0x20 /* override flag */
|
||||||
|
|
||||||
/* ICMP types */
|
/* ICMP types */
|
||||||
#define ICMP4_ECHO_REQUEST 0x8
|
#define ICMP4_ECHO_REQUEST 0x8
|
||||||
@ -93,11 +129,21 @@ struct s_icmp_ndp_option {
|
|||||||
#define ICMP6_NDP_RM 0x89
|
#define ICMP6_NDP_RM 0x89
|
||||||
|
|
||||||
/* Prototypes */
|
/* Prototypes */
|
||||||
|
int get_mac_addr(const char *dev, struct s_mac_addr *addr);
|
||||||
|
int get_dev_index(const char *dev);
|
||||||
|
|
||||||
void process_packet6(u_char *args, const struct pcap_pkthdr *header, const u_char *packet);
|
void process_packet6(u_char *args, const struct pcap_pkthdr *header, const u_char *packet);
|
||||||
void process_icmp6(const struct s_ip6 *ip, const unsigned char *payload);
|
void process_icmp6(const struct s_ethernet *eth, struct s_ip6 *ip, const unsigned char *payload);
|
||||||
|
void process_ndp(const struct s_ethernet *eth_hdr, struct s_ip6 *ip_hdr, unsigned char *icmp_data);
|
||||||
|
|
||||||
void send_there(struct in_addr ip4_addr, unsigned char ttl, unsigned int type, unsigned char *payload, unsigned int paylen);
|
void send_there(struct in_addr ip4_addr, unsigned char ttl, unsigned int type, unsigned char *payload, unsigned int paylen);
|
||||||
|
void send_ndp(struct ip6_hdr *ip, unsigned char *packet, int packet_size);
|
||||||
|
|
||||||
unsigned short checksum(const void *_buf, int len);
|
unsigned short checksum(const void *_buf, int len);
|
||||||
|
|
||||||
|
/* Variables */
|
||||||
|
extern struct s_mac_addr *mac; /* MAC address of the device */
|
||||||
|
extern char *dev; /* capture device name */
|
||||||
|
extern int dev_index; /* capture device index */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user