1
0
mirror of https://code.semirocket.science/wrapsix synced 2024-12-22 04:20:18 +02:00

A bit of code cleanup

This commit is contained in:
Michal Zima 2012-07-03 11:15:10 +02:00
parent 707eb6159b
commit 59fdab7ed8
13 changed files with 159 additions and 68 deletions

View File

@ -115,8 +115,8 @@ int icmp_ipv4(struct s_ethernet *eth4, struct s_ipv4 *ip4,
eth6->type = htons(ETHERTYPE_IPV6);
/* build IPv6 packet */
ip6->ver = 0x60;
ip6->traffic_class = 0x0;
ip6->ver = 0x60 | (ip4->tos >> 4);
ip6->traffic_class = ip4->tos << 4;
ip6->flow_label = 0x0;
ip6->len = htons(payload_size);
ip6->next_header = IPPROTO_ICMPV6;
@ -228,7 +228,8 @@ int icmp_ipv6(struct s_ethernet *eth6, struct s_ipv6 *ip6, char *payload)
/* build IPv4 packet */
ip4->ver_hdrlen = 0x45; /* ver 4, header length 20 B */
ip4->tos = 0x0;
ip4->tos = ((ip6->ver & 0x0f) << 4) |
((ip6->traffic_class & 0xf0) >> 4);
ip4->len = htons(sizeof(struct s_ipv4) + htons(ip6->len));
ip4->id = 0x0;
ip4->flags_offset = htons(IPV4_FLAG_DONT_FRAGMENT);
@ -250,7 +251,6 @@ int icmp_ipv6(struct s_ethernet *eth6, struct s_ipv6 *ip6, char *payload)
(unsigned char *) icmp);
/* send translated packet */
printf("[Debug] transmitting\n");
transmit_ipv4(&ip4->ip_dest, packet, htons(ip4->len));
/* clean-up */
@ -320,8 +320,7 @@ int icmp_ndp(struct s_ethernet *ethq, struct s_ipv6 *ipq,
/* ICMP */
icmp->type = ICMPV6_NDP_NA;
icmp->code = 0;
icmp->checksum = 0;
/* code = checksum = 0 by memset */
/* NDP NA */
ndp_na->flags = INNAF_S;

View File

@ -26,6 +26,15 @@
#include "udp.h"
#include "wrapper.h"
/**
* Processing of IPv4 packets.
*
* @param eth Ethernet header
* @param packet Packet data
*
* @return 0 for success
* @return 1 for failure
*/
int ipv4(struct s_ethernet *eth, char *packet)
{
struct s_ipv4 *ip;
@ -42,8 +51,6 @@ int ipv4(struct s_ethernet *eth, char *packet)
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;
@ -52,21 +59,16 @@ int ipv4(struct s_ethernet *eth, char *packet)
switch (ip->proto) {
case IPPROTO_TCP:
printf("[Debug] IPv4 Protocol: TCP\n");
tcp_ipv4(eth, ip, payload, data_size);
break;
return tcp_ipv4(eth, ip, payload, data_size);
case IPPROTO_UDP:
printf("[Debug] IPv4 Protocol: UDP\n");
udp_ipv4(eth, ip, payload, data_size);
break;
return udp_ipv4(eth, ip, payload, data_size);
case IPPROTO_ICMP:
printf("[Debug] IPv4 Protocol: ICMP\n");
icmp_ipv4(eth, ip, payload, data_size);
break;
return icmp_ipv4(eth, ip, payload, data_size);
default:
printf("[Debug] IPv4 Protocol: unknown [%d/0x%x]\n",
ip->proto, ip->proto);
return 1;
}
return 0;
}

View File

@ -26,6 +26,15 @@
#include "udp.h"
#include "wrapper.h"
/**
* Processing of IPv6 packets.
*
* @param eth Ethernet header
* @param packet Packet data
*
* @return 0 for success
* @return 1 for failure
*/
int ipv6(struct s_ethernet *eth, char *packet)
{
struct s_ipv6 *ip;
@ -45,21 +54,16 @@ int ipv6(struct s_ethernet *eth, char *packet)
switch (ip->next_header) {
case IPPROTO_TCP:
printf("[Debug] IPv6 Protocol: TCP\n");
tcp_ipv6(eth, ip, payload);
break;
return tcp_ipv6(eth, ip, payload);
case IPPROTO_UDP:
printf("[Debug] IPv6 Protocol: UDP\n");
udp_ipv6(eth, ip, payload);
break;
return udp_ipv6(eth, ip, payload);
case IPPROTO_ICMPV6:
printf("[Debug] IPv6 Protocol: ICMP\n");
icmp_ipv6(eth, ip, payload);
break;
return icmp_ipv6(eth, ip, payload);
default:
printf("[Debug] IPv6 Protocol: unknown [%d/0x%x]\n",
ip->next_header, ip->next_header);
return 1;
}
return 0;
}

View File

@ -1,6 +1,6 @@
/*
* WrapSix
* Copyright (C) 2008-2011 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
* it under the terms of the GNU Affero General Public License as
@ -50,6 +50,9 @@ radixtree_t *nat6_tcp, *nat6_udp, *nat6_icmp,
*nat4_tcp, *nat4_udp, *nat4_icmp,
*nat4_tcp_fragments;
/**
* Initialization of NAT tables.
*/
void nat_init(void)
{
nat6_tcp = radixtree_create();
@ -63,6 +66,9 @@ void nat_init(void)
nat4_tcp_fragments = radixtree_create();
}
/**
* Clean-up of NAT tables.
*/
void nat_quit(void)
{
/* 128 + 16 + 32 + 16 = 192 / 6 = 32 */
@ -79,6 +85,20 @@ void nat_quit(void)
radixtree_destroy(nat4_tcp_fragments, 8);
}
/**
* Lookup or create NAT connection for outgoing IPv6 packet.
*
* @param nat_proto6 IPv6 NAT table
* @param nat_proto4 IPv4 NAT table
* @param eth_src Source MAC address
* @param ipv6_src Source IPv6 address
* @param ipv6_dst Destination IPv6 address
* @param port_src Source port
* @param port_dst Destination port
*
* @return NULL when it wasn't possible to create connection
* @return pointer to connection structure otherwise
*/
struct s_nat *nat_out(radixtree_t *nat_proto6, radixtree_t *nat_proto4,
struct s_mac_addr eth_src,
struct s_ipv6_addr ipv6_src, struct s_ipv6_addr ipv6_dst,
@ -137,6 +157,17 @@ struct s_nat *nat_out(radixtree_t *nat_proto6, radixtree_t *nat_proto4,
}
}
/**
* Lookup NAT connection for incoming IPv4 packet.
*
* @param nat_proto4 NAT table
* @param ipv4_src Source IPv4 address
* @param port_src Source port
* @param port_dst Destination port
*
* @return NULL when no connection was found
* @return pointer to connection structure otherwise
*/
struct s_nat *nat_in(radixtree_t *nat_proto4, struct s_ipv4_addr ipv4_src,
unsigned short port_src, unsigned short port_dst)
{
@ -225,8 +256,8 @@ struct s_nat *nat_in_fragments(radixtree_t *nat_proto4,
* @param ipv4_src Source IPv4 address
* @param id Fragment identification
*/
void nat_in_fragments_clenup(radixtree_t *nat_proto4,
struct s_ipv4_addr ipv4_src, unsigned short id)
void nat_in_fragments_cleanup(radixtree_t *nat_proto4,
struct s_ipv4_addr ipv4_src, unsigned short id)
{
/* create structure to search in the tree */
struct s_radixtree_fragments4 radixsearch4;

View File

@ -1,6 +1,6 @@
/*
* WrapSix
* Copyright (C) 2008-2011 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
* it under the terms of the GNU Affero General Public License as
@ -53,7 +53,7 @@ struct s_nat *nat_in(radixtree_t *nat_proto4, struct s_ipv4_addr ipv4_src,
struct s_nat *nat_in_fragments(radixtree_t *nat_proto4,
struct s_ipv4_addr ipv4_src,
unsigned short id, struct s_nat *nat);
void nat_in_fragments_clenup(radixtree_t *nat_proto4,
struct s_ipv4_addr ipv4_src, unsigned short id);
void nat_in_fragments_cleanup(radixtree_t *nat_proto4,
struct s_ipv4_addr ipv4_src, unsigned short id);
#endif /* NAT_H */

View File

@ -22,6 +22,11 @@
#include "radixtree.h"
/**
* Creates root of radix tree.
*
* @return Root of new radix tree
*/
radixtree_t *radixtree_create(void)
{
radixtree_t *radixtree;
@ -36,21 +41,36 @@ radixtree_t *radixtree_create(void)
return radixtree;
}
void radixtree_destroy(radixtree_t *t, unsigned char depth)
/**
* Destroys a radix tree.
*
* @param root Root of the tree to destroy
* @param depth Depth of the tree
*/
void radixtree_destroy(radixtree_t *root, unsigned char depth)
{
unsigned char i;
for (i = 0; i < ARRAY_SIZE; i++) {
if (depth != 1 && t->array[i] != NULL) {
radixtree_destroy(t->array[i], depth - 1);
if (depth != 1 && root->array[i] != NULL) {
radixtree_destroy(root->array[i], depth - 1);
} else if (depth == 1) {
free(t->array[i]);
free(root->array[i]);
}
}
free(t);
free(root);
}
/**
* Inserts new data entry into the tree.
*
* @param root Root of the radix tree
* @param chunker Function to use to get chunks for indexing internal array
* @param search_data Key used to search in the tree
* @param size Length of the key
* @param data Data to store in the tree
*/
void radixtree_insert(radixtree_t *root,
unsigned char *(chunker)(void *data, unsigned char size, unsigned char *count),
void *search_data, unsigned char size, void *data)
@ -85,6 +105,14 @@ void radixtree_insert(radixtree_t *root,
free(chunks);
}
/**
* Deletes an entry from the tree.
*
* @param root Root of the radix tree
* @param chunker Function to use to get chunks for indexing internal array
* @param data Key used to search in the tree
* @param size Length of the key
*/
void radixtree_delete(radixtree_t *root,
unsigned char *(chunker)(void *data, unsigned char size, unsigned char *count),
void *data, unsigned char size)
@ -97,7 +125,7 @@ void radixtree_delete(radixtree_t *root,
chunks = chunker(data, size, &chunk_count);
for (i = 0, tmp = root; i < chunk_count && tmp != NULL; i++, tmp = tmp->array[chunks[i]]) {
for (i = 0, tmp = root; i < chunk_count && tmp != NULL; tmp = tmp->array[chunks[i++]]) {
flags = tmp->count == 1 ? flags | (0x1 << i) : 0;
if (i + 1 == chunk_count) {
@ -128,6 +156,14 @@ void radixtree_delete(radixtree_t *root,
free(chunks);
}
/**
* Lookups an entry in the tree.
*
* @param root Root of the radix tree
* @param chunker Function to use to get chunks for indexing internal array
* @param data Key used to search in the tree
* @param size Length of the key
*/
void *radixtree_lookup(radixtree_t *root,
unsigned char *(chunker)(void *data, unsigned char size, unsigned char *count),
void *data, unsigned char size)

View File

@ -1,6 +1,6 @@
/*
* WrapSix
* Copyright (C) 2008-2011 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
* it under the terms of the GNU Affero General Public License as
@ -28,7 +28,7 @@ typedef struct radixtree {
} radixtree_t;
radixtree_t *radixtree_create(void);
void radixtree_destroy(radixtree_t *t, unsigned char depth);
void radixtree_destroy(radixtree_t *root, unsigned char depth);
void radixtree_insert(radixtree_t *root,
unsigned char *(chunker)(void *data, unsigned char size, unsigned char *count),
void *search_data, unsigned char size, void *data);

View File

@ -57,12 +57,12 @@ int tcp_ipv4(struct s_ethernet *eth4, struct s_ipv4 *ip4, char *payload,
struct s_ipv6_fragment *frag;
/* full processing of unfragmented packet or the first fragment with
* TCP header with checksum field (this is safe)
* TCP header
*/
if ((ip4->flags_offset & htons(IPV4_FLAG_DONT_FRAGMENT)) ||
((ip4->flags_offset & htons(IPV4_FLAG_MORE_FRAGMENTS)) &&
(ip4->flags_offset & 0xff1f) == 0x0000 &&
payload_size >= sizeof(struct s_tcp) - 2)) {
payload_size >= sizeof(struct s_tcp))) {
/* parse TCP header */
tcp = (struct s_tcp *) payload;
@ -249,8 +249,8 @@ int tcp_ipv4(struct s_ethernet *eth4, struct s_ipv4 *ip4, char *payload,
sizeof(struct s_ipv6_fragment));
/* fill in missing IPv6 fragment header fields */
frag->offset_flag = htons((htons(ip4->flags_offset) << 3) |
IPV6_FLAG_MORE_FRAGMENTS);
frag->offset_flag = htons((htons(ip4->flags_offset) <<
3) | IPV6_FLAG_MORE_FRAGMENTS);
/* copy the payload data */
memcpy((unsigned char *) frag +
@ -264,7 +264,8 @@ int tcp_ipv4(struct s_ethernet *eth4, struct s_ipv4 *ip4, char *payload,
ip6->len = htons(payload_size +
sizeof(struct s_ipv6_fragment) -
FRAGMENT_LEN);
frag->offset_flag = htons((htons(ip4->flags_offset) +
frag->offset_flag = htons(((htons(ip4->flags_offset) &
0xfffc) +
FRAGMENT_LEN / 8) << 3);
if (ip4->flags_offset &
htons(IPV4_FLAG_MORE_FRAGMENTS)) {
@ -378,7 +379,8 @@ int tcp_ipv6(struct s_ethernet *eth6, struct s_ipv6 *ip6, char *payload)
/* build IPv4 packet */
ip4->ver_hdrlen = 0x45; /* ver 4, header length 20 B */
ip4->tos = 0x0;
ip4->tos = ((ip6->ver & 0x0f) << 4) |
((ip6->traffic_class & 0xf0) >> 4);
ip4->len = htons(sizeof(struct s_ipv4) + htons(ip6->len));
ip4->id = 0x0;
ip4->flags_offset = htons(IPV4_FLAG_DONT_FRAGMENT);

View File

@ -30,7 +30,6 @@ struct s_tcp {
unsigned char flags; /* 6 b; flags */
unsigned short window; /* 16 b; size of the receive window */
unsigned short checksum; /* 16 b */
unsigned short urgent_ptr; /* 16 b; ptr to last urgent data byte */
} __attribute__ ((__packed__));
int tcp_ipv4(struct s_ethernet *eth4, struct s_ipv4 *ip4, char *payload,

View File

@ -18,7 +18,8 @@
#include <net/if.h> /* struct ifreq */
#include <netinet/if_ether.h> /* {P,A}F_PACKET, ETH_P_*, socket, SOCK_RAW,
* setsockopt, SOL_SOCKET, SO_BINDTODEVICE, sendto */
* setsockopt, SOL_SOCKET, SO_BINDTODEVICE,
* sendto */
#include <netinet/in.h> /* htons */
#include <netpacket/packet.h> /* sockaddr_ll, PACKET_OTHERHOST */
#include <stdio.h> /* fprintf, stderr, perror */
@ -34,7 +35,8 @@ struct sockaddr_in socket_address_ipv4;
int sock, sock_ipv4;
/**
* Initialize socket and all needed properties. Should be called only once on program startup.
* Initialize sockets and all needed properties. Should be called only once on
* program startup.
*
* @return 0 for success
* @return 1 for failure
@ -45,10 +47,10 @@ int transmission_init(void)
/** RAW socket **/
/* prepare settings 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 = interface.ifr_ifindex; /* set index of the network device */
socket_address.sll_pkttype = PACKET_OTHERHOST; /* target host is another host */
socket_address.sll_family = PF_PACKET; /* raw communication */
socket_address.sll_protocol = htons(ETH_P_IP); /* L3 proto */
socket_address.sll_ifindex = interface.ifr_ifindex;
socket_address.sll_pkttype = PACKET_OTHERHOST;
/* initialize RAW socket */
if ((sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) {
@ -58,8 +60,10 @@ int transmission_init(void)
}
/* bind the socket to the interface */
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &interface, sizeof(struct ifreq)) == -1) {
fprintf(stderr, "[Error] Couldn't bind the socket to the interface.\n");
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &interface,
sizeof(struct ifreq)) == -1) {
fprintf(stderr, "[Error] Couldn't bind the socket to the "
"interface.\n");
perror("setsockopt()");
return 1;
}
@ -78,8 +82,10 @@ int transmission_init(void)
}
/* we will provide our own IPv4 header */
if (setsockopt(sock_ipv4, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) == -1) {
fprintf(stderr, "[Error] Couldn't apply the socket settings.\n");
if (setsockopt(sock_ipv4, IPPROTO_IP, IP_HDRINCL, &on,
sizeof(on)) == -1) {
fprintf(stderr, "[Error] Couldn't apply the socket "
"settings.\n");
perror("setsockopt()");
return 1;
}
@ -88,7 +94,7 @@ int transmission_init(void)
}
/**
* Close socket. Should be called only once on program shutdown.
* Close sockets. Should be called only once on program shutdown.
*
* @return 0 for success
* @return 1 for failure
@ -97,7 +103,8 @@ int transmission_quit(void)
{
/* close the socket */
if (close(sock) || close(sock_ipv4)) {
fprintf(stderr, "[Error] Couldn't close the transmission sockets.\n");
fprintf(stderr, "[Error] Couldn't close the transmission "
"sockets.\n");
perror("close()");
return 1;
} else {
@ -116,7 +123,8 @@ int transmission_quit(void)
*/
int transmit_raw(unsigned char *data, unsigned int length)
{
if (sendto(sock, data, length, 0, (struct sockaddr *) &socket_address, sizeof(struct sockaddr_ll)) != (int) length) {
if (sendto(sock, data, length, 0, (struct sockaddr *) &socket_address,
sizeof(struct sockaddr_ll)) != (int) length) {
fprintf(stderr, "[Error] Couldn't send a RAW packet.\n");
perror("sendto()");
return 1;
@ -129,18 +137,23 @@ int transmit_raw(unsigned char *data, unsigned int length)
* Send IPv4 packet with IPv4 header supplied. Ethernet header is added by OS.
*
* @param ip Destination IPv4 address
* @param data Raw packet data, excluding ethernet header, but including IPv4 header
* @param data Raw packet data, excluding ethernet header, but
* including IPv4 header
* @param length Length of the whole packet in bytes
*
* @return 0 for success
* @return 1 for failure
*/
int transmit_ipv4(struct s_ipv4_addr *ip, unsigned char *data, unsigned int length)
int transmit_ipv4(struct s_ipv4_addr *ip, unsigned char *data,
unsigned int length)
{
/* set the destination IPv4 address */
memcpy(&socket_address_ipv4.sin_addr.s_addr, ip, sizeof(struct s_ipv4_addr));
memcpy(&socket_address_ipv4.sin_addr.s_addr, ip,
sizeof(struct s_ipv4_addr));
if (sendto(sock_ipv4, data, length, 0, (struct sockaddr *) &socket_address_ipv4, sizeof(struct sockaddr)) != (int) length) {
if (sendto(sock_ipv4, data, length, 0,
(struct sockaddr *) &socket_address_ipv4,
sizeof(struct sockaddr)) != (int) length) {
fprintf(stderr, "[Error] Couldn't send an IPv4 packet.\n");
perror("sendto()");
return 1;

View File

@ -97,8 +97,8 @@ int udp_ipv4(struct s_ethernet *eth4, struct s_ipv4 *ip4, char *payload,
eth6->type = htons(ETHERTYPE_IPV6);
/* build IPv6 packet */
ip6->ver = 0x60;
ip6->traffic_class = 0x0;
ip6->ver = 0x60 | (ip4->tos >> 4);
ip6->traffic_class = ip4->tos << 4;
ip6->flow_label = 0x0;
ip6->len = htons(payload_size);
ip6->next_header = IPPROTO_UDP;
@ -193,7 +193,8 @@ int udp_ipv6(struct s_ethernet *eth6, struct s_ipv6 *ip6, char *payload)
/* build IPv4 packet */
ip4->ver_hdrlen = 0x45; /* ver 4, header length 20 B */
ip4->tos = 0x0;
ip4->tos = ((ip6->ver & 0x0f) << 4) |
((ip6->traffic_class & 0xf0) >> 4);
ip4->len = htons(sizeof(struct s_ipv4) + htons(ip6->len));
ip4->id = 0x0;
ip4->flags_offset = htons(IPV4_FLAG_DONT_FRAGMENT);

View File

@ -37,10 +37,12 @@
#include "transmitter.h"
#include "wrapper.h"
#define INTERFACE "eth0"
#define BUFFER_SIZE 65536
#define PREFIX "fd77::"
-/* +++ CONFIGURATION +++ */
#define INTERFACE "eth0" /* be sure to turn off generic-segmentation-offload! */
#define PREFIX "64:ff9b::"
#define IPV4_ADDR "192.168.0.111"
/* --- CONFIGURATION --- */
struct ifreq interface;
struct s_mac_addr mac;

View File

@ -22,7 +22,9 @@
#include "ipv4.h"
#include "ipv6.h"
/* +++ CONFIGURE +++ */
#define MTU 1280
/* --- CONFIGURE --- */
extern struct ifreq interface;
extern struct s_mac_addr mac;