1
0
mirror of https://code.semirocket.science/wrapsix synced 2024-11-24 01:10:18 +02:00

Parsing and using configuration file

This commit is contained in:
xHire 2013-07-16 08:28:14 +02:00
parent a75aa2966b
commit ab9b37be9f
10 changed files with 280 additions and 44 deletions

4
.gitignore vendored
View File

@ -14,6 +14,10 @@ src/Makefile.in
Makefile
src/Makefile
INSTALL
src/autoconfig.h.in.in
src/autoconfig.h.in
src/autoconfig.h
src/stamp-h1
# build
*.o

16
README
View File

@ -5,25 +5,17 @@ About
-----
WrapSix is a fast NAT64 implementation. You also need a DNS64 server (e.g. BIND).
Before compiling, don't forget to configure Wrapsix in files src/wrapper.c and
src/wrapper.h.
Before compiling, don't forget to configure Wrapsix in files src/wrapper.c.
Configuration
-------------
INTERFACE Interface on which WrapSix should operate, e.g. eth0.
PREFIX NAT64 prefix; at least /96, the default is standard
64:ff9b::/96. Input it without the information about prefix
length, i.e. just 64:ff9b::.
IPV4_ADDR IPv4 address which is dedicated for WrapSix and is not assigned
to the host operating system.
HOST_IPV6_ADDR IPv6 address which represents the host, i.e. which is assigned
to the operating system. It's used in ICMP error messages.
HOST_IPV4_ADDR IPv4 address which represents the host, i.e. which is assigned
to the operating system. It's used in ICMP error messages.
MTU Minimum MTU in your IPv6 network; default is 1280, but you can
set it to a greater value (up to 1500).
PACKET_BUFFER Size of a buffer for incoming packets; it's strongly recommended
to leave its value as is (i.e. 1514).
WrapSix uses configuration file wrapsix.conf from configuration directory set in
"./configure" phase, which is by default /usr/local/etc.
Installation
------------

View File

@ -14,6 +14,7 @@ AC_CONFIG_FILES([
src/Makefile
])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADER([src/autoconfig.h.in])
###
# Configuration options
@ -26,11 +27,14 @@ AC_ARG_ENABLE([debug],
if test "x$debug" = "xyes"; then
AS_COMPILER_FLAGS(AM_CFLAGS, "-g -ggdb -O0 -pipe -pedantic -Wshadow -Wall -Wextra -Wno-missing-field-initializers -Wno-unused-parameter -Wold-style-definition -Wdeclaration-after-statement -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wmissing-noreturn -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Winline -Wformat-nonliteral -Wformat-security -Wswitch-enum -Winit-self -Wmissing-include-dirs -Wundef -Waggregate-return -Wnested-externs -Wunsafe-loop-optimizations -Winvalid-pch")
AC_DEFINE([DEBUG])
AC_DEFINE([DEBUG], [], [Turn on debug mode])
else
AS_COMPILER_FLAGS(AM_CFLAGS, "-O2")
fi
AC_DEFINE([SYSCONFDIR], "--sysconfdir--", [Configuration files directory])
###
# Final commands
###

View File

@ -1,7 +1,9 @@
sbin_PROGRAMS = wrapsix
wrapsix_SOURCES = \
arp.c arp.h \
autoconfig.h \
checksum.c checksum.h \
config.c config.h \
ethernet.h \
icmp.c icmp.h \
ipv4.c ipv4.h \
@ -14,3 +16,6 @@ wrapsix_SOURCES = \
transmitter.c transmitter.h \
udp.c udp.h \
wrapper.c wrapper.h
autoconfig.h:
sed -e 's|--sysconfdir--|$(sysconfdir)|' autoconfig.h.in > autoconfig.h

183
src/config.c Normal file
View File

@ -0,0 +1,183 @@
/*
* WrapSix
* Copyright (C) 2008-2013 xHire <xhire@wrapsix.org>
*
* 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
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "log.h"
#include "wrapper.h"
#define SYNTAX_ERROR(file, line, pos, fatal) { \
log_error("Syntax error in configuration file %s on " \
"line %d, position %d", file, line, pos); \
fclose(f); \
if (fatal) { \
exit(1); \
} else { \
return 1; \
} \
}
#define C_DEFAULT_MTU 1280
#define C_DEFAULT_INTERFACE "eth0"
#define C_DEFAULT_PREFIX "64:ff9b::"
/**
* Configuration file parser.
*
* @param config_file Configuration file (with path) to parse
* @param cmtu Pointer to variable where to save MTU
* @param oto One-time configuration options (used only
* locally to init other things)
* @param init 0 or 1, whether or not to initialize
* configuration with defaults
*/
int cfg_parse(const char *config_file, unsigned short *cmtu,
struct s_cfg_opts *oto, unsigned char init)
{
FILE *f;
unsigned int ln = 0;
char c;
unsigned short opt_len, wht_len, val_len;
char tmp_opt[32], tmp_val[128];
/* set defaults */
*cmtu = C_DEFAULT_MTU;
/* TODO: get automatically the first available interface */
strncpy(oto->interface, C_DEFAULT_INTERFACE, sizeof(oto->interface));
strncpy(oto->prefix, C_DEFAULT_PREFIX, sizeof(oto->prefix));
oto->ipv4_address[0] = '\0';
f = fopen(config_file, "r");
if (f == NULL) {
/* set defaults */
log_warn("Configuration file %s doesn't exist, using defaults",
config_file);
if (init) {
log_error("IPv4 address unconfigured! Exiting");
exit(1);
}
return 0;
}
while (c = getc(f), !feof(f)) {
ln++;
/* comments */
if (c == '#') {
/* skip this line */
while (c = getc(f), c != '\n');
continue;
}
/* empty lines */
if (c == '\n') {
continue;
}
/* option is only of small letters */
if (c < 'a' || c > 'z') {
SYNTAX_ERROR(config_file, ln, 0, init);
}
/* read option */
for (opt_len = 0; c != ' ' && c != '\t'; opt_len++,
c = getc(f)) {
if (feof(f) || !((c >= 'a' && c <= 'z') || c == '_' ||
(c >= '0' && c <= '9'))) {
SYNTAX_ERROR(config_file, ln, opt_len, init);
}
if (opt_len < 32 - 1) {
tmp_opt[opt_len] = c;
} else {
SYNTAX_ERROR(config_file, ln, opt_len, init);
}
}
tmp_opt[opt_len] = '\0';
/* skip white space */
for (wht_len = 0; c == ' ' || c == '\t'; wht_len++,
c = getc(f)) {
if (feof(f)) {
SYNTAX_ERROR(config_file, ln, opt_len + wht_len,
init);
}
}
/* read value */
for (val_len = 0; c != ' ' && c != '\t' && c != '\n'; val_len++,
c = getc(f)) {
if (feof(f)) {
SYNTAX_ERROR(config_file, ln, opt_len, init);
}
if (val_len < 128 - 1) {
tmp_val[val_len] = c;
} else {
SYNTAX_ERROR(config_file, ln, opt_len, init);
}
}
tmp_val[val_len] = '\0';
/* skip rest of this line */
if (c != '\n') {
while (c = getc(f), c != '\n');
}
/* recognize the option */
if (!strcmp(tmp_opt, "mtu")) {
*cmtu = atoi(tmp_val);
if (*cmtu > MAX_MTU) {
log_warn("MTU setting is over maximum (%d), "
"falling to default value (%d)",
MAX_MTU, C_DEFAULT_MTU);
*cmtu = C_DEFAULT_MTU;
}
} else if (!strcmp(tmp_opt, "interface")) {
strncpy(oto->interface, tmp_val, sizeof(oto->interface));
} else if (!strcmp(tmp_opt, "prefix")) {
strncpy(oto->prefix, tmp_val, sizeof(oto->prefix));
} else if (!strcmp(tmp_opt, "ipv4_address")) {
if (val_len < sizeof(oto->ipv4_address)) {
strncpy(oto->ipv4_address, tmp_val, sizeof(oto->ipv4_address));
} else {
SYNTAX_ERROR(config_file, ln, opt_len + wht_len, init);
}
} else {
log_error("Unknown configuration option");
SYNTAX_ERROR(config_file, ln, 0, init);
}
}
fclose(f);
if (init && oto->ipv4_address[0] == '\0') {
log_error("IPv4 address unconfigured! Exiting");
exit(1);
}
return 0;
}

31
src/config.h Normal file
View File

@ -0,0 +1,31 @@
/*
* WrapSix
* Copyright (C) 2008-2013 xHire <xhire@wrapsix.org>
*
* 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
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CONFIG_H
#define CONFIG_H
struct s_cfg_opts {
char interface[128];
char prefix[128];
char ipv4_address[16];
};
int cfg_parse(const char *config_file, unsigned short *cmtu,
struct s_cfg_opts *oto, unsigned char init);
#endif /* CONFIG_H */

View File

@ -1,6 +1,6 @@
/*
* WrapSix
* Copyright (C) 2008-2013 Michal Zima <xhire@mujmalysvet.cz>
* Copyright (C) 2008-2013 xHire <xhire@wrapsix.org>
*
* 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
@ -64,7 +64,7 @@ int icmp_ipv4(struct s_ethernet *eth4, struct s_ipv4 *ip4,
unsigned char *icmp_data;
struct s_nat *connection;
unsigned short orig_checksum;
unsigned char packet[MTU + sizeof(struct s_ethernet)];
unsigned char packet[PACKET_BUFFER];
unsigned short new_len = sizeof(struct s_ethernet) +
sizeof(struct s_ipv6);
@ -119,15 +119,15 @@ int icmp_ipv4(struct s_ethernet *eth4, struct s_ipv4 *ip4,
icmp->type = ICMPV6_ECHO_REPLY;
/* copy the payload data */
if (payload_size < MTU - sizeof(struct s_ipv6)) {
if (payload_size < mtu - sizeof(struct s_ipv6)) {
memcpy(&packet[new_len], payload, payload_size);
icmp = (struct s_icmp *) &packet[new_len];
new_len += payload_size;
} else {
memcpy(&packet[new_len], payload, MTU -
memcpy(&packet[new_len], payload, mtu -
sizeof(struct s_ipv6));
icmp = (struct s_icmp *) &packet[new_len];
new_len += MTU - sizeof(struct s_ipv6);
new_len += mtu - sizeof(struct s_ipv6);
}
break;
@ -174,9 +174,9 @@ int icmp_ipv4(struct s_ethernet *eth4, struct s_ipv4 *ip4,
if (ntohs(*icmp_extra_s) < 68) {
*icmp_extra = htonl(
*icmp_extra_s + 20 <
MTU ? (unsigned int)
mtu ? (unsigned int)
*icmp_extra_s + 20 :
MTU);
(unsigned int) mtu);
} else {
/* RFC1191 */
/* NOTE: >= would cause infinite
@ -1063,10 +1063,10 @@ int sub_icmp4_error(unsigned char *payload, unsigned short payload_size,
/* copy payload, aligned to MTU */
/* we can afford to use full MTU instead of just 1280 B as admin
* warrants this to us */
if (payload_size > MTU + sizeof(struct s_ethernet) - *packet_len) {
if (payload_size > mtu + sizeof(struct s_ethernet) - *packet_len) {
memcpy(&packet[*packet_len], payload,
MTU + sizeof(struct s_ethernet) - *packet_len);
*packet_len = MTU;
mtu + sizeof(struct s_ethernet) - *packet_len);
*packet_len = mtu;
} else {
memcpy(&packet[*packet_len], payload, payload_size);
*packet_len += payload_size;

View File

@ -1,6 +1,6 @@
/*
* WrapSix
* Copyright (C) 2008-2013 Michal Zima <xhire@mujmalysvet.cz>
* Copyright (C) 2008-2013 xHire <xhire@wrapsix.org>
*
* 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
@ -199,8 +199,8 @@ int tcp_ipv4(struct s_ethernet *eth4, struct s_ipv4 *ip4, char *payload,
/* allocate enough memory for translated packet */
if ((packet = (unsigned char *) malloc(
payload_size > MTU - sizeof(struct s_ipv6) ?
MTU + sizeof(struct s_ethernet) :
payload_size > mtu - sizeof(struct s_ipv6) ?
mtu + sizeof(struct s_ethernet) :
sizeof(struct s_ethernet) + sizeof(struct s_ipv6) +
payload_size)) == NULL) {
log_error("Lack of free memory");
@ -233,9 +233,9 @@ int tcp_ipv4(struct s_ethernet *eth4, struct s_ipv4 *ip4, char *payload,
connection->ipv6_port_src);
/* fragment it or not? */
if (payload_size > MTU - sizeof(struct s_ipv6)) {
if (payload_size > mtu - sizeof(struct s_ipv6)) {
/* 1st fragments' payload size must be 8-byte aligned */
#define FRAGMENT_LEN (((MTU - sizeof(struct s_ipv6) - \
#define FRAGMENT_LEN (((mtu - sizeof(struct s_ipv6) - \
sizeof(struct s_ipv6_fragment)) / 8) * 8)
/* fill in missing IPv6 header fields */
@ -341,9 +341,9 @@ int tcp_ipv4(struct s_ethernet *eth4, struct s_ipv4 *ip4, char *payload,
/* allocate enough memory for translated packet */
if ((packet = (unsigned char *) malloc(
payload_size > MTU - sizeof(struct s_ipv6) -
payload_size > mtu - sizeof(struct s_ipv6) -
sizeof(struct s_ipv6_fragment) ?
MTU + sizeof(struct s_ethernet) :
mtu + sizeof(struct s_ethernet) :
sizeof(struct s_ethernet) + sizeof(struct s_ipv6) +
sizeof(struct s_ipv6_fragment) + payload_size)) == NULL) {
log_error("Lack of free memory");
@ -374,7 +374,7 @@ int tcp_ipv4(struct s_ethernet *eth4, struct s_ipv4 *ip4, char *payload,
frag->id = htonl(htons(ip4->id));
/* fragment the fragment or not? */
if (payload_size > MTU - sizeof(struct s_ipv6) -
if (payload_size > mtu - sizeof(struct s_ipv6) -
sizeof(struct s_ipv6_fragment)) {
/* fill in missing IPv6 header fields */
ip6->len = htons(FRAGMENT_LEN +
@ -391,7 +391,7 @@ int tcp_ipv4(struct s_ethernet *eth4, struct s_ipv4 *ip4, char *payload,
payload, FRAGMENT_LEN);
/* send translated packet */
transmit_raw(packet, sizeof(struct s_ethernet) + MTU);
transmit_raw(packet, sizeof(struct s_ethernet) + mtu);
/* create the second fragment */
ip6->len = htons(payload_size +

View File

@ -1,6 +1,6 @@
/*
* WrapSix
* Copyright (C) 2008-2013 Michal Zima <xhire@mujmalysvet.cz>
* Copyright (C) 2008-2013 xHire <xhire@wrapsix.org>
*
* 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
@ -31,6 +31,10 @@
#include <unistd.h> /* close */
#include "arp.h"
#ifdef HAVE_CONFIG_H
#include "autoconfig.h"
#endif /* HAVE_CONFIG_H */
#include "config.h"
#include "ethernet.h"
#include "ipv4.h"
#include "ipv6.h"
@ -40,13 +44,11 @@
#include "wrapper.h"
/* +++ CONFIGURATION +++ */
#define INTERFACE "eth0"
#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 --- */
unsigned short mtu;
struct ifreq interface;
struct s_mac_addr mac;
@ -60,6 +62,8 @@ int process(char *packet);
int main(int argc, char **argv)
{
struct s_cfg_opts cfg;
struct packet_mreq pmr;
struct ethtool_value ethtool;
@ -72,6 +76,18 @@ int main(int argc, char **argv)
log_info(PACKAGE_STRING " is starting");
/* load configuration */
if (argc == 1) {
cfg_parse(SYSCONFDIR "/wrapsix.conf", &mtu, &cfg, 1);
} else {
cfg_parse(argv[1], &mtu, &cfg, 1);
}
log_info("Using: interface %s", cfg.interface);
log_info(" prefix %s", cfg.prefix);
log_info(" MTU %d", mtu);
log_info(" IPv4 address %s", cfg.ipv4_address);
/* initialize the socket for sniffing */
if ((sniff_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) ==
-1) {
@ -80,9 +96,9 @@ int main(int argc, char **argv)
}
/* get the interface */
strncpy(interface.ifr_name, INTERFACE, IFNAMSIZ);
strncpy(interface.ifr_name, cfg.interface, IFNAMSIZ);
if (ioctl(sniff_sock, SIOCGIFINDEX, &interface) == -1) {
log_error("Unable to get the interface");
log_error("Unable to get the interface %s", cfg.interface);
return 1;
}
@ -128,10 +144,10 @@ int main(int argc, char **argv)
inet_pton(AF_INET6, "ff02::1:ff00:0", &ndp_multicast_addr);
/* compute binary IPv6 address of WrapSix prefix */
inet_pton(AF_INET6, PREFIX, &wrapsix_ipv6_prefix);
inet_pton(AF_INET6, cfg.prefix, &wrapsix_ipv6_prefix);
/* compute binary IPv4 address of WrapSix */
inet_pton(AF_INET, IPV4_ADDR, &wrapsix_ipv4_addr);
inet_pton(AF_INET, cfg.ipv4_address, &wrapsix_ipv4_addr);
/* compute binary IPv6 address of WrapSix host */
inet_pton(AF_INET6, HOST_IPV6_ADDR, &host_ipv6_addr);

View File

@ -1,6 +1,6 @@
/*
* WrapSix
* Copyright (C) 2008-2012 Michal Zima <xhire@mujmalysvet.cz>
* Copyright (C) 2008-2013 xHire <xhire@wrapsix.org>
*
* 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
@ -22,11 +22,12 @@
#include "ipv4.h"
#include "ipv6.h"
/* +++ CONFIGURE +++ */
#define MTU 1280 /* MTU on IPv6 side */
/* +++ INTERNAL CONFIGURATION +++ */
#define MAX_MTU 1500 /* maximum MTU on IPv6 side */
#define PACKET_BUFFER 1514 /* buffer for any packet */
/* --- CONFIGURE --- */
/* --- INTERNAL CONFIGURATION --- */
extern unsigned short mtu;
extern struct ifreq interface;
extern struct s_mac_addr mac;
extern struct s_ipv6_addr ndp_multicast_addr;