mirror of
https://code.semirocket.science/wrapsix
synced 2024-12-22 04:20:18 +02:00
Reacting to exceeded TTL/HL
This commit is contained in:
parent
e722e80149
commit
5af1a5ca7c
154
src/icmp.c
154
src/icmp.c
@ -353,3 +353,157 @@ int icmp_ndp(struct s_ethernet *ethq, struct s_ipv6 *ipq,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends ICMPv4 error.
|
||||
*
|
||||
* @param ip_dest Destination IPv4 address
|
||||
* @param type Type of ICMP error
|
||||
* @param code Code of ICMP error
|
||||
* @param data Original packet
|
||||
* @param length Length of the original packet
|
||||
*
|
||||
* @return 0 for success
|
||||
* @return 1 for failure
|
||||
*/
|
||||
int icmp4_error(struct s_ipv4_addr ip_dest, unsigned char type,
|
||||
unsigned char code, unsigned char *data, unsigned short length)
|
||||
{
|
||||
unsigned char *packet, *payload;
|
||||
struct s_ipv4 *ip4;
|
||||
struct s_icmp *icmp;
|
||||
|
||||
/* 4 = unused space after ICMP header */
|
||||
unsigned short payload_size = length > 1500 - sizeof(struct s_ipv4) -
|
||||
sizeof(struct s_icmp) - 4 ?
|
||||
1500 - sizeof(struct s_ipv4) - sizeof(struct s_icmp) - 4 :
|
||||
length;
|
||||
|
||||
if ((packet = (unsigned char *) malloc(sizeof(struct s_ipv4) +
|
||||
sizeof(struct s_icmp) + 4 + payload_size)) == NULL) {
|
||||
log_error("Lack of free memory");
|
||||
return 1;
|
||||
}
|
||||
|
||||
ip4 = (struct s_ipv4 *) packet;
|
||||
icmp = (struct s_icmp *) (packet + sizeof(struct s_ipv4));
|
||||
payload = (unsigned char *) (packet + sizeof(struct s_ipv4) +
|
||||
sizeof(struct s_icmp) + 4);
|
||||
|
||||
/* build IPv4 packet */
|
||||
ip4->ver_hdrlen = 0x45; /* ver 4, header length 20 B */
|
||||
ip4->tos = 0x0;
|
||||
ip4->len = htons(sizeof(struct s_ipv4) +
|
||||
sizeof(struct s_icmp) + 4 + payload_size);
|
||||
ip4->id = 0x0;
|
||||
ip4->flags_offset = htons(IPV4_FLAG_DONT_FRAGMENT);
|
||||
ip4->ttl = 255;
|
||||
ip4->proto = IPPROTO_ICMP;
|
||||
ip4->ip_src = host_ipv4_addr;
|
||||
ip4->ip_dest = ip_dest;
|
||||
|
||||
/* build ICMP header */
|
||||
icmp->type = type;
|
||||
icmp->code = code;
|
||||
icmp->checksum = 0x0;
|
||||
|
||||
/* copy the payload data */
|
||||
memcpy(payload, data, payload_size);
|
||||
|
||||
/* compute ICMP checksum */
|
||||
icmp->checksum = checksum((unsigned char *) icmp,
|
||||
payload_size + 4 + sizeof(struct s_icmp));
|
||||
|
||||
/* compute IPv4 checksum */
|
||||
ip4->checksum = checksum_ipv4(ip4->ip_src, ip4->ip_dest,
|
||||
htons(ip4->len), IPPROTO_ICMP,
|
||||
(unsigned char *) icmp);
|
||||
|
||||
/* send packet */
|
||||
transmit_ipv4(&ip4->ip_dest, packet, htons(ip4->len));
|
||||
|
||||
/* clean-up */
|
||||
free(packet);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends ICMPv6 error.
|
||||
*
|
||||
* @param mac_dest Destination MAC address
|
||||
* @param ip_dest Destination IPv6 address
|
||||
* @param type Type of ICMP error
|
||||
* @param code Code of ICMP error
|
||||
* @param data Original packet
|
||||
* @param length Length of the original packet
|
||||
*
|
||||
* @return 0 for success
|
||||
* @return 1 for failure
|
||||
*/
|
||||
int icmp6_error(struct s_mac_addr mac_dest, struct s_ipv6_addr ip_dest,
|
||||
unsigned char type, unsigned char code, unsigned char *data,
|
||||
unsigned short length)
|
||||
{
|
||||
unsigned char *packet, *payload;
|
||||
struct s_ethernet *eth;
|
||||
struct s_ipv6 *ip6;
|
||||
struct s_icmp *icmp;
|
||||
|
||||
/* 4 = unused space after ICMP header */
|
||||
unsigned short payload_size = length > 1280 - sizeof(struct s_ipv6) -
|
||||
sizeof(struct s_icmp) - 4 ?
|
||||
1280 - sizeof(struct s_ipv6) - sizeof(struct s_icmp) - 4 :
|
||||
length;
|
||||
|
||||
if ((packet = (unsigned char *) malloc(sizeof(struct s_ethernet) +
|
||||
sizeof(struct s_ipv6) + sizeof(struct s_icmp) + 4 +
|
||||
payload_size)) == NULL) {
|
||||
log_error("Lack of free memory");
|
||||
return 1;
|
||||
}
|
||||
|
||||
eth = (struct s_ethernet *) packet;
|
||||
ip6 = (struct s_ipv6 *) (packet + sizeof(struct s_ethernet));
|
||||
icmp = (struct s_icmp *) (packet + sizeof(struct s_ethernet) +
|
||||
sizeof(struct s_ipv6));
|
||||
payload = (unsigned char *) (packet + sizeof(struct s_ethernet) +
|
||||
sizeof(struct s_ipv6) +
|
||||
sizeof(struct s_icmp) + 4);
|
||||
|
||||
/* ethernet */
|
||||
eth->dest = mac_dest;
|
||||
eth->src = mac;
|
||||
eth->type = htons(ETHERTYPE_IPV6);
|
||||
|
||||
/* IPv6 */
|
||||
ip6->ver = 0x60;
|
||||
ip6->len = htons(sizeof(struct s_icmp) + 4 + payload_size);
|
||||
ip6->next_header = IPPROTO_ICMPV6;
|
||||
ip6->hop_limit = 255;
|
||||
ip6->ip_src = host_ipv6_addr;
|
||||
ip6->ip_dest = ip_dest;
|
||||
|
||||
/* ICMP */
|
||||
icmp->type = type;
|
||||
icmp->code = code;
|
||||
icmp->checksum = 0x0;
|
||||
|
||||
/* copy the payload data */
|
||||
memcpy(payload, data, payload_size);
|
||||
|
||||
/* compute ICMP checksum */
|
||||
icmp->checksum = checksum_ipv6(host_ipv6_addr, ip_dest,
|
||||
sizeof(struct s_icmp) + 4 + payload_size,
|
||||
IPPROTO_ICMPV6,
|
||||
(unsigned char *) icmp);
|
||||
|
||||
/* send packet */
|
||||
transmit_raw(packet, sizeof(struct s_ethernet) + sizeof(struct s_ipv6) +
|
||||
sizeof(struct s_icmp) + 4 + payload_size);
|
||||
|
||||
/* clean-up */
|
||||
free(packet);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* WrapSix
|
||||
* Copyright (C) 2008-2012 Michal Zima <xhire@mujmalysvet.cz>
|
||||
* Copyright (C) 2008-2013 Michal Zima <xhire@mujmalysvet.cz>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -25,6 +25,7 @@
|
||||
/* ICMP types */
|
||||
#define ICMPV4_ECHO_REPLY 0x0
|
||||
#define ICMPV4_ECHO_REQUEST 0x8
|
||||
#define ICMPV4_TIME_EXCEEDED 0xb
|
||||
|
||||
/* ICMPv6 types */
|
||||
#define ICMPV6_DST_UNREACHABLE 0x1
|
||||
@ -80,4 +81,10 @@ 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);
|
||||
|
||||
int icmp4_error(struct s_ipv4_addr ip_dest, unsigned char type,
|
||||
unsigned char code, unsigned char *data, unsigned short length);
|
||||
int icmp6_error(struct s_mac_addr mac_dest, struct s_ipv6_addr ip_dest,
|
||||
unsigned char type, unsigned char code, unsigned char *data,
|
||||
unsigned short length);
|
||||
|
||||
#endif /* ICMP_H */
|
||||
|
17
src/ipv4.c
17
src/ipv4.c
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* WrapSix
|
||||
* Copyright (C) 2008-2012 Michal Zima <xhire@mujmalysvet.cz>
|
||||
* Copyright (C) 2008-2013 Michal Zima <xhire@mujmalysvet.cz>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -55,6 +55,21 @@ int ipv4(struct s_ethernet *eth, char *packet)
|
||||
data_size = htons(ip->len) - header_size;
|
||||
payload = packet + header_size;
|
||||
|
||||
/* check and decrease TTL */
|
||||
if (ip->ttl <= 1) {
|
||||
/* deny this error for ICMP (except ping/pong)
|
||||
* and for non-first fragments */
|
||||
if ((ip->proto != IPPROTO_ICMP || payload[0] & 0x0 ||
|
||||
payload[0] & 0x08) && !(ip->flags_offset & htons(0x1fff))) {
|
||||
/* code 0 = ttl exceeded in transmit */
|
||||
icmp4_error(ip->ip_src, ICMPV4_TIME_EXCEEDED, 0,
|
||||
(unsigned char *) packet, htons(ip->len));
|
||||
}
|
||||
return 1;
|
||||
} else {
|
||||
ip->ttl--;
|
||||
}
|
||||
|
||||
switch (ip->proto) {
|
||||
case IPPROTO_TCP:
|
||||
log_debug("IPv4 Protocol: TCP");
|
||||
|
16
src/ipv6.c
16
src/ipv6.c
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* WrapSix
|
||||
* Copyright (C) 2008-2012 Michal Zima <xhire@mujmalysvet.cz>
|
||||
* Copyright (C) 2008-2013 Michal Zima <xhire@mujmalysvet.cz>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -50,6 +50,20 @@ int ipv6(struct s_ethernet *eth, char *packet)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* check and decrease hop limit */
|
||||
if (ip->hop_limit <= 1) {
|
||||
/* deny this error for error ICMP messages */
|
||||
if (ip->next_header != IPPROTO_ICMPV6 || payload[0] & 0x80) {
|
||||
/* code 0 = hl exceeded in transmit */
|
||||
icmp6_error(eth->src, ip->ip_src, ICMPV6_TIME_EXCEEDED,
|
||||
0, (unsigned char *) packet,
|
||||
htons(ip->len) + sizeof(struct s_ipv6));
|
||||
}
|
||||
return 1;
|
||||
} else {
|
||||
ip->hop_limit--;
|
||||
}
|
||||
|
||||
switch (ip->next_header) {
|
||||
case IPPROTO_TCP:
|
||||
log_debug("IPv6 Protocol: TCP");
|
||||
|
@ -41,6 +41,8 @@
|
||||
#define INTERFACE "eth0" /* be sure to turn off generic-segmentation-offload! */
|
||||
#define PREFIX "64:ff9b::"
|
||||
#define IPV4_ADDR "192.168.0.111"
|
||||
#define HOST_IPV6_ADDR "fd77::1:0:1"
|
||||
#define HOST_IPV4_ADDR "192.168.0.19"
|
||||
/* --- CONFIGURATION --- */
|
||||
|
||||
|
||||
@ -49,6 +51,8 @@ struct s_mac_addr mac;
|
||||
struct s_ipv6_addr ndp_multicast_addr;
|
||||
struct s_ipv6_addr wrapsix_ipv6_prefix;
|
||||
struct s_ipv4_addr wrapsix_ipv4_addr;
|
||||
struct s_ipv6_addr host_ipv6_addr;
|
||||
struct s_ipv4_addr host_ipv4_addr;
|
||||
|
||||
int process(char *packet);
|
||||
|
||||
@ -115,6 +119,12 @@ int main(int argc, char **argv)
|
||||
/* compute binary IPv4 address of WrapSix */
|
||||
inet_pton(AF_INET, IPV4_ADDR, &wrapsix_ipv4_addr);
|
||||
|
||||
/* compute binary IPv6 address of WrapSix host */
|
||||
inet_pton(AF_INET6, HOST_IPV6_ADDR, &host_ipv6_addr);
|
||||
|
||||
/* compute binary IPv4 address of WrapSix host */
|
||||
inet_pton(AF_INET, HOST_IPV4_ADDR, &host_ipv4_addr);
|
||||
|
||||
/* initiate sending socket */
|
||||
if (transmission_init()) {
|
||||
log_error("Unable to initiate sending socket");
|
||||
|
@ -32,6 +32,8 @@ extern struct s_mac_addr mac;
|
||||
extern struct s_ipv6_addr ndp_multicast_addr;
|
||||
extern struct s_ipv6_addr wrapsix_ipv6_prefix;
|
||||
extern struct s_ipv4_addr wrapsix_ipv4_addr;
|
||||
extern struct s_ipv6_addr host_ipv6_addr;
|
||||
extern struct s_ipv4_addr host_ipv4_addr;
|
||||
|
||||
void ipv6_to_ipv4(struct s_ipv6_addr *ipv6_addr, struct s_ipv4_addr *ipv4_addr);
|
||||
void ipv4_to_ipv6(struct s_ipv4_addr *ipv4_addr, struct s_ipv6_addr *ipv6_addr);
|
||||
|
Loading…
Reference in New Issue
Block a user