mirror of
https://code.semirocket.science/wrapsix
synced 2024-11-22 07:43:10 +02:00
Full processing of ICMP packets (v4 and v6); NDP
IPv4 header and pseudoheader Basic preprocessing of IPv4 packets
This commit is contained in:
parent
4b6a373019
commit
1196c33bee
@ -3,8 +3,9 @@ wrapsix_dnsproxy_SOURCES = dnsproxy.c
|
|||||||
wrapsix_wrapper_SOURCES = \
|
wrapsix_wrapper_SOURCES = \
|
||||||
arp.c arp.h \
|
arp.c arp.h \
|
||||||
checksum.c checksum.h \
|
checksum.c checksum.h \
|
||||||
|
icmp.c icmp.h \
|
||||||
|
ipv4.c ipv4.h \
|
||||||
ipv6.c ipv6.h \
|
ipv6.c ipv6.h \
|
||||||
ipv4.h \
|
|
||||||
nat.c nat.h \
|
nat.c nat.h \
|
||||||
radixtree.c radixtree.h \
|
radixtree.c radixtree.h \
|
||||||
transmitter.c transmitter.h \
|
transmitter.c transmitter.h \
|
||||||
|
345
src/icmp.c
Normal file
345
src/icmp.c
Normal file
@ -0,0 +1,345 @@
|
|||||||
|
/*
|
||||||
|
* WrapSix
|
||||||
|
* Copyright (C) 2008-2012 Michal Zima <xhire@mujmalysvet.cz>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <net/ethernet.h> /* ETHERTYPE_* */
|
||||||
|
#include <netinet/in.h> /* htons */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h> /* malloc */
|
||||||
|
#include <string.h> /* memcpy, memset */
|
||||||
|
|
||||||
|
#include "checksum.h"
|
||||||
|
#include "icmp.h"
|
||||||
|
#include "ipv6.h"
|
||||||
|
#include "nat.h"
|
||||||
|
#include "transmitter.h"
|
||||||
|
#include "wrapper.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processing of incoming ICMPv4 packets. Directly sends translated ICMPv6
|
||||||
|
* packets.
|
||||||
|
*
|
||||||
|
* @param eth4 Ethernet header
|
||||||
|
* @param ip4 IPv4 header
|
||||||
|
* @param payload ICMPv4 data
|
||||||
|
* @param payload_size Size of payload; needed because IPv4 header has
|
||||||
|
* dynamic length
|
||||||
|
*
|
||||||
|
* @return 0 for success
|
||||||
|
* @return 1 for failure
|
||||||
|
*/
|
||||||
|
int icmp_ipv4(struct s_ethernet *eth4, struct s_ipv4 *ip4,
|
||||||
|
char *payload, unsigned short payload_size)
|
||||||
|
{
|
||||||
|
struct s_icmp *icmp;
|
||||||
|
unsigned char *icmp_data;
|
||||||
|
struct s_nat *connection;
|
||||||
|
unsigned short orig_checksum;
|
||||||
|
unsigned char *packet;
|
||||||
|
|
||||||
|
struct s_icmp_echo *echo;
|
||||||
|
struct s_ethernet *eth6;
|
||||||
|
struct s_ipv6 *ip6;
|
||||||
|
|
||||||
|
icmp = (struct s_icmp *) payload;
|
||||||
|
icmp_data = (unsigned char *) (payload + sizeof(struct s_icmp));
|
||||||
|
|
||||||
|
/* ICMP checksum recheck */
|
||||||
|
orig_checksum = icmp->checksum;
|
||||||
|
icmp->checksum = 0;
|
||||||
|
icmp->checksum = checksum((unsigned char *) icmp, payload_size);
|
||||||
|
|
||||||
|
if (icmp->checksum != orig_checksum) {
|
||||||
|
/* packet is corrupted and shouldn't be processed */
|
||||||
|
printf("[Debug] Wrong checksum\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (icmp->type) {
|
||||||
|
case ICMPV4_ECHO_REQUEST:
|
||||||
|
/* this is pretty non-sense situation */
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case ICMPV4_ECHO_REPLY:
|
||||||
|
echo = (struct s_icmp_echo *) icmp_data;
|
||||||
|
|
||||||
|
connection = nat_in(nat4_icmp, ip4->ip_src,
|
||||||
|
0, echo->id);
|
||||||
|
|
||||||
|
if (connection == NULL) {
|
||||||
|
printf("[Debug] Incoming connection wasn't "
|
||||||
|
"found in NAT\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo->id = connection->ipv6_port_src;
|
||||||
|
|
||||||
|
/* override information in original ICMP header */
|
||||||
|
icmp->type = ICMPV6_ECHO_REPLY;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf("[Debug] ICMPv4 Type: unknown [%d/0x%x]\n",
|
||||||
|
icmp->type, icmp->type);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate memory for translated packet */
|
||||||
|
if ((packet = (unsigned char *) malloc(sizeof(struct s_ethernet) +
|
||||||
|
sizeof(struct s_ipv6) +
|
||||||
|
payload_size)) == NULL) {
|
||||||
|
fprintf(stderr, "[Error] Lack of free memory\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
eth6 = (struct s_ethernet *) packet;
|
||||||
|
ip6 = (struct s_ipv6 *) (packet + sizeof(struct s_ethernet));
|
||||||
|
|
||||||
|
/* build ethernet header */
|
||||||
|
eth6->dest = connection->mac;
|
||||||
|
eth6->src = mac;
|
||||||
|
eth6->type = htons(ETHERTYPE_IPV6);
|
||||||
|
|
||||||
|
/* build IPv6 packet */
|
||||||
|
ip6->ver = 0x60;
|
||||||
|
ip6->traffic_class = 0x0;
|
||||||
|
ip6->flow_label = 0x0;
|
||||||
|
ip6->len = htons(payload_size);
|
||||||
|
ip6->next_header = IPPROTO_ICMPV6;
|
||||||
|
ip6->hop_limit = ip4->ttl;
|
||||||
|
ipv4_to_ipv6(&ip4->ip_src, &ip6->ip_src);
|
||||||
|
memcpy(&ip6->ip_dest, &connection->ipv6, sizeof(struct s_ipv6_addr));
|
||||||
|
|
||||||
|
/* compute ICMP checksum */
|
||||||
|
icmp->checksum = 0x0;
|
||||||
|
icmp->checksum = checksum_ipv6(ip6->ip_src, ip6->ip_dest, payload_size,
|
||||||
|
IPPROTO_ICMPV6, (unsigned char *) icmp);
|
||||||
|
|
||||||
|
/* copy the payload data (with new checksum) */
|
||||||
|
memcpy(packet + sizeof(struct s_ethernet) + sizeof(struct s_ipv6), payload,
|
||||||
|
payload_size);
|
||||||
|
|
||||||
|
/* send translated packet */
|
||||||
|
transmit_raw(packet, sizeof(struct s_ethernet) + sizeof(struct s_ipv6) +
|
||||||
|
payload_size);
|
||||||
|
|
||||||
|
/* clean-up */
|
||||||
|
free(packet);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processing of outgoing ICMPv6 packets. Directly sends translated ICMPv4
|
||||||
|
* packets.
|
||||||
|
*
|
||||||
|
* @param eth6 Ethernet header
|
||||||
|
* @param ip6 IPv6 header
|
||||||
|
* @param payload ICMPv6 data
|
||||||
|
*
|
||||||
|
* @return 0 for success
|
||||||
|
* @return 1 for failure
|
||||||
|
*/
|
||||||
|
int icmp_ipv6(struct s_ethernet *eth6, struct s_ipv6 *ip6, char *payload)
|
||||||
|
{
|
||||||
|
struct s_icmp *icmp;
|
||||||
|
unsigned char *icmp_data;
|
||||||
|
struct s_nat *connection;
|
||||||
|
unsigned short orig_checksum;
|
||||||
|
unsigned char *packet;
|
||||||
|
|
||||||
|
struct s_icmp_echo *echo;
|
||||||
|
struct s_ipv4 *ip4;
|
||||||
|
|
||||||
|
icmp = (struct s_icmp *) payload;
|
||||||
|
icmp_data = (unsigned char *) (payload + sizeof(struct s_icmp));
|
||||||
|
|
||||||
|
/* checksum recheck */
|
||||||
|
orig_checksum = icmp->checksum;
|
||||||
|
icmp->checksum = 0;
|
||||||
|
icmp->checksum = checksum_ipv6(ip6->ip_src, ip6->ip_dest,
|
||||||
|
htons(ip6->len), IPPROTO_ICMPV6,
|
||||||
|
(unsigned char *) icmp);
|
||||||
|
|
||||||
|
if (icmp->checksum != orig_checksum) {
|
||||||
|
/* packet is corrupted and shouldn't be processed */
|
||||||
|
printf("[Debug] Wrong checksum\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* decide the type of the ICMP packet */
|
||||||
|
switch (icmp->type) {
|
||||||
|
case ICMPV6_ECHO_REQUEST:
|
||||||
|
echo = (struct s_icmp_echo *) icmp_data;
|
||||||
|
|
||||||
|
connection = nat_out(nat6_icmp, nat4_icmp,
|
||||||
|
eth6->src,
|
||||||
|
ip6->ip_src, ip6->ip_dest,
|
||||||
|
echo->id, 0);
|
||||||
|
|
||||||
|
if (connection == NULL) {
|
||||||
|
printf("[Debug] Error! Outgoing connection "
|
||||||
|
"wasn't found/created in NAT!\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo->id = connection->ipv4_port_src;
|
||||||
|
|
||||||
|
/* override information in original ICMP header */
|
||||||
|
icmp->type = ICMPV4_ECHO_REQUEST;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ICMPV6_ECHO_REPLY:
|
||||||
|
/* this is pretty non-sense situation */
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case ICMPV6_NDP_NS:
|
||||||
|
return icmp_ndp(eth6, ip6,
|
||||||
|
(struct s_icmp_ndp_ns *) icmp_data);
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf("[Debug] ICMPv6 Type: unknown [%d/0x%x]\n",
|
||||||
|
icmp->type, icmp->type);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate memory for translated packet */
|
||||||
|
if ((packet = (unsigned char *) malloc(sizeof(struct s_ipv4) +
|
||||||
|
htons(ip6->len))) == NULL) {
|
||||||
|
fprintf(stderr, "[Error] Lack of free memory\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
ip4 = (struct s_ipv4 *) packet;
|
||||||
|
|
||||||
|
/* build IPv4 packet */
|
||||||
|
ip4->ver_hdrlen = 0x45; /* ver 4, header length 20 B */
|
||||||
|
ip4->tos = 0x0;
|
||||||
|
ip4->len = htons(sizeof(struct s_ipv4) + htons(ip6->len));
|
||||||
|
ip4->id = 0x0;
|
||||||
|
ip4->flags_offset = htons(IPV4_FLAG_DONT_FRAGMENT);
|
||||||
|
ip4->ttl = ip6->hop_limit;
|
||||||
|
ip4->proto = IPPROTO_ICMP;
|
||||||
|
ipv6_to_ipv4(&ip6->ip_dest, &ip4->ip_dest);
|
||||||
|
memcpy(&ip4->ip_src, &wrapsix_ipv4_addr, sizeof(struct s_ipv4_addr));
|
||||||
|
|
||||||
|
/* compute ICMP checksum */
|
||||||
|
icmp->checksum = 0x0;
|
||||||
|
icmp->checksum = checksum((unsigned char *) icmp, htons(ip6->len));
|
||||||
|
|
||||||
|
/* copy the payload data (with new checksum) */
|
||||||
|
memcpy(packet + sizeof(struct s_ipv4), payload, htons(ip6->len));
|
||||||
|
|
||||||
|
/* compute IPv4 checksum */
|
||||||
|
ip4->checksum = checksum_ipv4(ip4->ip_src, ip4->ip_dest,
|
||||||
|
htons(ip4->len), IPPROTO_ICMP,
|
||||||
|
(unsigned char *) icmp);
|
||||||
|
|
||||||
|
/* send translated packet */
|
||||||
|
printf("[Debug] transmitting\n");
|
||||||
|
transmit_ipv4(&ip4->ip_dest, packet, htons(ip4->len));
|
||||||
|
|
||||||
|
/* clean-up */
|
||||||
|
free(packet);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes NDP NS packets and sends NDP NA.
|
||||||
|
*
|
||||||
|
* @param ethq Ethernet header
|
||||||
|
* @param ipq IPv6 header
|
||||||
|
* @param ndp_ns NDP NS data
|
||||||
|
*
|
||||||
|
* @return 0 for success
|
||||||
|
* @return 1 for failure
|
||||||
|
*/
|
||||||
|
int icmp_ndp(struct s_ethernet *ethq, struct s_ipv6 *ipq,
|
||||||
|
struct s_icmp_ndp_ns *ndp_ns)
|
||||||
|
{
|
||||||
|
unsigned char *packet;
|
||||||
|
struct s_ethernet *ethr;
|
||||||
|
struct s_ipv6 *ipr;
|
||||||
|
struct s_icmp *icmp;
|
||||||
|
struct s_icmp_ndp_na *ndp_na;
|
||||||
|
|
||||||
|
/* first check whether the request belongs to us */
|
||||||
|
if (memcmp(&wrapsix_ipv6_prefix, &ndp_ns->target, 12) != 0) {
|
||||||
|
printf("[Debug] [NDP] This is unfamiliar packet\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate memory for reply packet */
|
||||||
|
#define NDP_PACKET_SIZE sizeof(struct s_ethernet) + \
|
||||||
|
sizeof(struct s_ipv6) + \
|
||||||
|
sizeof(struct s_icmp) + \
|
||||||
|
sizeof(struct s_icmp_ndp_na)
|
||||||
|
if ((packet = (unsigned char *) malloc(NDP_PACKET_SIZE)) == NULL) {
|
||||||
|
fprintf(stderr, "[Error] Lack of free memory\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
memset(packet, 0x0, NDP_PACKET_SIZE);
|
||||||
|
|
||||||
|
/* divide reply packet into parts */
|
||||||
|
ethr = (struct s_ethernet *) packet;
|
||||||
|
ipr = (struct s_ipv6 *) (packet + sizeof(struct s_ethernet));
|
||||||
|
icmp = (struct s_icmp *) (packet + sizeof(struct s_ethernet) +
|
||||||
|
sizeof(struct s_ipv6));
|
||||||
|
ndp_na = (struct s_icmp_ndp_na *) (packet + sizeof(struct s_ethernet) +
|
||||||
|
sizeof(struct s_ipv6) +
|
||||||
|
sizeof(struct s_icmp));
|
||||||
|
|
||||||
|
/* ethernet */
|
||||||
|
ethr->dest = ethq->src;
|
||||||
|
ethr->src = mac;
|
||||||
|
ethr->type = ethq->type;
|
||||||
|
|
||||||
|
/* IPv6 */
|
||||||
|
ipr->ver = 0x60;
|
||||||
|
ipr->len = htons(sizeof(struct s_icmp) + sizeof(struct s_icmp_ndp_na));
|
||||||
|
ipr->next_header = IPPROTO_ICMPV6;
|
||||||
|
/* hop limit 255 is required by RFC 4861, section 7.1.2. */
|
||||||
|
ipr->hop_limit = 255;
|
||||||
|
ipr->ip_src = ndp_ns->target;
|
||||||
|
ipr->ip_dest = ipq->ip_src;
|
||||||
|
|
||||||
|
/* ICMP */
|
||||||
|
icmp->type = ICMPV6_NDP_NA;
|
||||||
|
icmp->code = 0;
|
||||||
|
icmp->checksum = 0;
|
||||||
|
|
||||||
|
/* NDP NA */
|
||||||
|
ndp_na->flags = INNAF_S;
|
||||||
|
ndp_na->target = ndp_ns->target;
|
||||||
|
ndp_na->opt_type = 2;
|
||||||
|
ndp_na->opt_len = 1;
|
||||||
|
ndp_na->opt_tlla = ethr->src;
|
||||||
|
|
||||||
|
/* compute ICMP checksum */
|
||||||
|
icmp->checksum = checksum_ipv6(ipr->ip_src, ipr->ip_dest,
|
||||||
|
htons(ipr->len), IPPROTO_ICMPV6,
|
||||||
|
(unsigned char *) icmp);
|
||||||
|
|
||||||
|
/* send NDP reply */
|
||||||
|
transmit_raw(packet, NDP_PACKET_SIZE);
|
||||||
|
|
||||||
|
/* clean-up */
|
||||||
|
free(packet);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
83
src/icmp.h
Normal file
83
src/icmp.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* WrapSix
|
||||||
|
* Copyright (C) 2008-2012 Michal Zima <xhire@mujmalysvet.cz>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ICMP_H
|
||||||
|
#define ICMP_H
|
||||||
|
|
||||||
|
#include "ipv4.h"
|
||||||
|
#include "ipv6.h"
|
||||||
|
|
||||||
|
/* ICMP types */
|
||||||
|
#define ICMPV4_ECHO_REPLY 0x0
|
||||||
|
#define ICMPV4_ECHO_REQUEST 0x8
|
||||||
|
|
||||||
|
/* ICMPv6 types */
|
||||||
|
#define ICMPV6_DST_UNREACHABLE 0x1
|
||||||
|
#define ICMPV6_PKT_TOO_BIG 0x2
|
||||||
|
#define ICMPV6_TIME_EXCEEDED 0x3
|
||||||
|
#define ICMPV6_PARAM_PROBLEM 0x4
|
||||||
|
#define ICMPV6_ECHO_REQUEST 0x80
|
||||||
|
#define ICMPV6_ECHO_REPLY 0x81
|
||||||
|
#define ICMPV6_NDP_RS 0x85
|
||||||
|
#define ICMPV6_NDP_RA 0x86
|
||||||
|
#define ICMPV6_NDP_NS 0x87
|
||||||
|
#define ICMPV6_NDP_NA 0x88
|
||||||
|
#define ICMPV6_NDP_RM 0x89
|
||||||
|
|
||||||
|
/* ICMP NDP NA Flag (INNAF) */
|
||||||
|
#define INNAF_R 0x80 /* router flag */
|
||||||
|
#define INNAF_S 0x40 /* solicited flag */
|
||||||
|
#define INNAF_O 0x20 /* override flag */
|
||||||
|
|
||||||
|
/* ICMP header structure */
|
||||||
|
struct s_icmp {
|
||||||
|
unsigned char type; /* 8 b; ICMP type */
|
||||||
|
unsigned char code; /* 8 b; subtype of ICMP type */
|
||||||
|
unsigned short checksum; /* 16 b */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ICMP echo structure */
|
||||||
|
struct s_icmp_echo {
|
||||||
|
unsigned short id; /* 16 b; ID value */
|
||||||
|
unsigned short seq; /* 16 b; sequence number */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ICMP NDP NS structure */
|
||||||
|
struct s_icmp_ndp_ns {
|
||||||
|
unsigned int zeros; /* 32 b; reserved section */
|
||||||
|
struct s_ipv6_addr target; /* 128 b; target IP address */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ICMP NDP NA structure */
|
||||||
|
struct s_icmp_ndp_na {
|
||||||
|
unsigned char flags; /* 8 b; 3 flags */
|
||||||
|
unsigned int zeros:24; /* 24 b; reserved section */
|
||||||
|
struct s_ipv6_addr target; /* 128 b; target IP address */
|
||||||
|
unsigned char opt_type; /* 8 b; option -- type */
|
||||||
|
unsigned char opt_len; /* 8 b; option -- length */
|
||||||
|
struct s_mac_addr opt_tlla; /* 48 b; option -- target
|
||||||
|
link-layer address */
|
||||||
|
};
|
||||||
|
|
||||||
|
int icmp_ipv4(struct s_ethernet *eth, struct s_ipv4 *ip4, char *payload,
|
||||||
|
unsigned short payload_size);
|
||||||
|
int icmp_ipv6(struct s_ethernet *eth, struct s_ipv6 *ip6, char *payload);
|
||||||
|
int icmp_ndp(struct s_ethernet *ethq, struct s_ipv6 *ipq,
|
||||||
|
struct s_icmp_ndp_ns *ndp_ns);
|
||||||
|
|
||||||
|
#endif /* ICMP_H */
|
70
src/ipv4.c
Normal file
70
src/ipv4.c
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* WrapSix
|
||||||
|
* Copyright (C) 2008-2012 Michal Zima <xhire@mujmalysvet.cz>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <netinet/in.h> /* IPPROTO_* */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h> /* memcmp */
|
||||||
|
|
||||||
|
#include "icmp.h"
|
||||||
|
#include "ipv4.h"
|
||||||
|
#include "wrapper.h"
|
||||||
|
|
||||||
|
int ipv4(struct s_ethernet *eth, char *packet)
|
||||||
|
{
|
||||||
|
struct s_ipv4 *ip;
|
||||||
|
char *payload;
|
||||||
|
unsigned short header_size;
|
||||||
|
unsigned short data_size;
|
||||||
|
|
||||||
|
/* load IP header */
|
||||||
|
ip = (struct s_ipv4 *) packet;
|
||||||
|
|
||||||
|
/* test if this packet belongs to us */
|
||||||
|
if (memcmp(&wrapsix_ipv4_addr, &ip->ip_dest, 4) != 0) {
|
||||||
|
printf("[Debug] [IPv4] This is unfamiliar packet\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: verify checksum */
|
||||||
|
|
||||||
|
/* compute sizes and get payload */
|
||||||
|
header_size = (ip->ver_hdrlen & 0x0f) * 4; /* # of 4 byte words */
|
||||||
|
data_size = htons(ip->len) - header_size;
|
||||||
|
payload = packet + header_size;
|
||||||
|
|
||||||
|
switch (ip->proto) {
|
||||||
|
case IPPROTO_TCP:
|
||||||
|
printf("[Debug] IPv4 Protocol: TCP\n");
|
||||||
|
/*ipv4_tcp(eth, ip, payload, data_size);*/
|
||||||
|
break;
|
||||||
|
case IPPROTO_UDP:
|
||||||
|
printf("[Debug] IPv4 Protocol: UDP\n");
|
||||||
|
/*ipv4_udp(eth, ip, payload, data_size);*/
|
||||||
|
break;
|
||||||
|
case IPPROTO_ICMP:
|
||||||
|
printf("[Debug] IPv4 Protocol: ICMP\n");
|
||||||
|
icmp_ipv4(eth, ip, payload, data_size);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("[Debug] IPv4 Protocol: unknown [%d/0x%x]\n",
|
||||||
|
ip->proto, ip->proto);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
36
src/ipv4.h
36
src/ipv4.h
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* WrapSix
|
* WrapSix
|
||||||
* Copyright (C) 2008-2010 Michal Zima <xhire@mujmalysvet.cz>
|
* Copyright (C) 2008-2012 Michal Zima <xhire@mujmalysvet.cz>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Affero General Public License as
|
* it under the terms of the GNU Affero General Public License as
|
||||||
@ -19,9 +19,43 @@
|
|||||||
#ifndef IPV4_H
|
#ifndef IPV4_H
|
||||||
#define IPV4_H
|
#define IPV4_H
|
||||||
|
|
||||||
|
#include "ethernet.h"
|
||||||
|
|
||||||
|
/* IPv4 flags */
|
||||||
|
#define IPV4_FLAG_DONT_FRAGMENT 0x4000
|
||||||
|
#define IPV4_FLAG_MORE_FRAGMENTS 0x2000
|
||||||
|
|
||||||
/* IPv4 address structure */
|
/* IPv4 address structure */
|
||||||
struct s_ipv4_addr {
|
struct s_ipv4_addr {
|
||||||
unsigned char addr[4];
|
unsigned char addr[4];
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
/* IPv4 header structure */
|
||||||
|
struct s_ipv4 {
|
||||||
|
unsigned char ver_hdrlen; /* 4 b; version,
|
||||||
|
4 b; header length in 4 B */
|
||||||
|
unsigned char tos; /* 8 b; type of service */
|
||||||
|
unsigned short len; /* 16 b; total packet length */
|
||||||
|
unsigned short id; /* 16 b; id of the packet
|
||||||
|
(for fragmentation) */
|
||||||
|
unsigned short flags_offset; /* 3 b; flags,
|
||||||
|
13 b; fragment offset in B */
|
||||||
|
unsigned char ttl; /* 8 b; time to live */
|
||||||
|
unsigned char proto; /* 8 b; protocol in payload */
|
||||||
|
unsigned short checksum; /* 16 b */
|
||||||
|
struct s_ipv4_addr ip_src; /* 32 b; source address */
|
||||||
|
struct s_ipv4_addr ip_dest; /* 32 b; destination address */
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
/* IPv4 pseudoheader structure for checksum */
|
||||||
|
struct s_ipv4_pseudo {
|
||||||
|
struct s_ipv4_addr ip_src; /* 32 b; source address */
|
||||||
|
struct s_ipv4_addr ip_dest; /* 32 b; destination address */
|
||||||
|
unsigned char zeros; /* 8 b */
|
||||||
|
unsigned char proto; /* 8 b; protocol in payload */
|
||||||
|
unsigned int len; /* 32 b; payload length */
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
int ipv4(struct s_ethernet *eth, char *packet);
|
||||||
|
|
||||||
#endif /* IPV4_H */
|
#endif /* IPV4_H */
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h> /* memcmp */
|
#include <string.h> /* memcmp */
|
||||||
|
|
||||||
|
#include "icmp.h"
|
||||||
#include "ipv6.h"
|
#include "ipv6.h"
|
||||||
#include "wrapper.h"
|
#include "wrapper.h"
|
||||||
|
|
||||||
@ -35,7 +36,7 @@ int ipv6(struct s_ethernet *eth, char *packet)
|
|||||||
/* test if this packet belongs to us */
|
/* test if this packet belongs to us */
|
||||||
if (memcmp(&wrapsix_ipv6_prefix, &ip->ip_dest, 12) != 0 &&
|
if (memcmp(&wrapsix_ipv6_prefix, &ip->ip_dest, 12) != 0 &&
|
||||||
memcmp(&ndp_multicast_addr, &ip->ip_dest, 13) != 0) {
|
memcmp(&ndp_multicast_addr, &ip->ip_dest, 13) != 0) {
|
||||||
printf("[Debug] This is unfamiliar packet\n");
|
printf("[Debug] [IPv6] This is unfamiliar packet\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,7 +51,7 @@ int ipv6(struct s_ethernet *eth, char *packet)
|
|||||||
break;
|
break;
|
||||||
case IPPROTO_ICMPV6:
|
case IPPROTO_ICMPV6:
|
||||||
printf("[Debug] IPv6 Protocol: ICMP\n");
|
printf("[Debug] IPv6 Protocol: ICMP\n");
|
||||||
/*ipv6_icmp(eth, ip, payload);*/
|
icmp_ipv6(eth, ip, payload);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("[Debug] IPv6 Protocol: unknown [%d/0x%x]\n",
|
printf("[Debug] IPv6 Protocol: unknown [%d/0x%x]\n",
|
||||||
|
@ -30,10 +30,10 @@ struct s_ipv6_addr {
|
|||||||
struct s_ipv6 {
|
struct s_ipv6 {
|
||||||
unsigned char ver; /* 4 b; version */
|
unsigned char ver; /* 4 b; version */
|
||||||
unsigned char traffic_class; /* 8 b; traffic class */
|
unsigned char traffic_class; /* 8 b; traffic class */
|
||||||
unsigned short flow_label; /* 20 b; flow label (qos) */
|
unsigned short flow_label; /* 20 b; flow label (QOS) */
|
||||||
unsigned short len; /* 16 b; payload length */
|
unsigned short len; /* 16 b; payload length */
|
||||||
unsigned char next_header; /* 8 b; next header */
|
unsigned char next_header; /* 8 b; next header */
|
||||||
unsigned char hop_limit; /* 8 b; hop limit (replaces ttl) */
|
unsigned char hop_limit; /* 8 b; hop limit (aka TTL) */
|
||||||
struct s_ipv6_addr ip_src; /* 128 b; source address */
|
struct s_ipv6_addr ip_src; /* 128 b; source address */
|
||||||
struct s_ipv6_addr ip_dest; /* 128 b; destination address */
|
struct s_ipv6_addr ip_dest; /* 128 b; destination address */
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
@ -47,7 +47,6 @@ struct s_ipv6_pseudo {
|
|||||||
unsigned char next_header; /* 8 b; next header */
|
unsigned char next_header; /* 8 b; next header */
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
|
||||||
int ipv6(struct s_ethernet *eth, char *packet);
|
int ipv6(struct s_ethernet *eth, char *packet);
|
||||||
|
|
||||||
#endif /* IPV6_H */
|
#endif /* IPV6_H */
|
||||||
|
@ -161,7 +161,7 @@ int process(char *packet)
|
|||||||
switch (htons(eth->type)) {
|
switch (htons(eth->type)) {
|
||||||
case ETHERTYPE_IP:
|
case ETHERTYPE_IP:
|
||||||
printf("[Debug] HW Protocol: IPv4\n");
|
printf("[Debug] HW Protocol: IPv4\n");
|
||||||
return -1;
|
return ipv4(eth, payload);
|
||||||
case ETHERTYPE_IPV6:
|
case ETHERTYPE_IPV6:
|
||||||
printf("[Debug] HW Protocol: IPv6\n");
|
printf("[Debug] HW Protocol: IPv6\n");
|
||||||
return ipv6(eth, payload);
|
return ipv6(eth, payload);
|
||||||
|
Loading…
Reference in New Issue
Block a user