1
0
mirror of https://code.semirocket.science/wrapsix synced 2024-09-19 15:01:06 +03:00

Autoconfiguration of host IP addresses & interface

Interface still can be configured manually
This commit is contained in:
xHire 2013-07-25 11:15:28 +02:00
parent f7af8f6805
commit 37cd198a45
5 changed files with 179 additions and 22 deletions

5
NEWS
View File

@ -1,6 +1,9 @@
WrapSix 0.2.1
=============
- custom configuration files and some autodetection
WrapSix 0.2.0
=============
- completely rewritten from scratch, but without DNS64 for now
- dropped all external dependencies
- cleaner design & implementation with emphasis on CPU & memory efficiency

View File

@ -16,11 +16,16 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h> /* inet_pton */
#include <ifaddrs.h> /* struct ifaddrs, getifaddrs, freeifaddrs */
#include <netdb.h> /* getnameinfo, NI_NUMERICHOST */
#include <stdio.h> /* FILE, fopen, getc, feof, fclose, perror */
#include <stdlib.h> /* exit */
#include <string.h> /* strcmp, strncpy */
#include "config.h"
#include "ipv4.h"
#include "ipv6.h"
#include "log.h"
#include "wrapper.h"
@ -36,9 +41,10 @@
}
#define C_DEFAULT_MTU 1280
#define C_DEFAULT_INTERFACE "eth0"
#define C_DEFAULT_PREFIX "64:ff9b::"
void cfg_guess_interface(char *cinterface);
/**
* Configuration file parser.
*
@ -48,6 +54,12 @@
* locally to init other things)
* @param init 0 or 1, whether or not to initialize
* configuration with defaults
*
* @return 0 for success
* @return 1 for failure in case of some syntax error when reloading
* configuration
* @return exit with code 1 in case of some syntax error when initializing
* configuration
*/
int cfg_parse(const char *config_file, unsigned short *cmtu,
struct s_cfg_opts *oto, unsigned char init)
@ -61,15 +73,14 @@ int cfg_parse(const char *config_file, unsigned short *cmtu,
/* set defaults */
*cmtu = C_DEFAULT_MTU;
/* TODO: get automatically the first available interface */
strncpy(oto->interface, C_DEFAULT_INTERFACE, sizeof(oto->interface));
oto->interface[0] = '\0';
cfg_guess_interface(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);
@ -181,3 +192,136 @@ int cfg_parse(const char *config_file, unsigned short *cmtu,
return 0;
}
/**
* Configures host IP addresses for usage in ICMP error messages. If some or
* both is not available, defaults are used.
*
* As a default in case of IPv4 is used IPv4 address assigned to WrapSix in
* configuration, in case of IPv6 is used made up address from default NAT64
* prefix -- WrapSix itself cannot act as a host so it doesn't matter.
*
* @param cinterface Name of the interface WrapSix sits on
* @param ipv6_addr Where to save host IPv6 address
* @param ipv4_addr Where to save host IPv4 address
* @param default_ipv4_addr IPv4 address assigned to WrapSix
*
* @return 0 for success
* @return 1 for failure
*/
int cfg_host_ips(char *cinterface, struct s_ipv6_addr *ipv6_addr,
struct s_ipv4_addr *ipv4_addr, char *default_ipv4_addr)
{
struct ifaddrs *ifaddr, *ifa;
/* 0x01 IPv6 from WrapSix' interface
* 0x02 IPv4 from WrapSix' interface
* 0x04 IPv6 from another interface
* 0x08 IPv4 from another interface
*/
char found = 0;
char ip_text[40];
if (getifaddrs(&ifaddr) == -1) {
perror("getifaddrs");
return 1;
}
/* Walk through linked list, maintaining head pointer so we can free
* list later */
/* first try to get addresses from the interface */
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == NULL) {
continue;
}
if (!strcmp(ifa->ifa_name, cinterface)) {
if (ifa->ifa_addr->sa_family == AF_INET6 &&
!(found & 0x01)) {
found |= 0x01;
getnameinfo(ifa->ifa_addr,
sizeof(struct sockaddr_in6),
ip_text, sizeof(ip_text), NULL, 0,
NI_NUMERICHOST);
inet_pton(AF_INET6, ip_text, ipv6_addr);
} else if (ifa->ifa_addr->sa_family == AF_INET &&
!(found & 0x02)) {
found |= 0x02;
getnameinfo(ifa->ifa_addr,
sizeof(struct sockaddr_in),
ip_text, sizeof(ip_text), NULL, 0,
NI_NUMERICHOST);
inet_pton(AF_INET, ip_text, ipv4_addr);
}
} else { /* look for addresses on other interfaces too */
if (ifa->ifa_addr->sa_family == AF_INET6 &&
!(found & 0x05)) {
found |= 0x04;
getnameinfo(ifa->ifa_addr,
sizeof(struct sockaddr_in6),
ip_text, sizeof(ip_text), NULL, 0,
NI_NUMERICHOST);
inet_pton(AF_INET6, ip_text, ipv6_addr);
} else if (ifa->ifa_addr->sa_family == AF_INET &&
!(found & 0x0a)) {
found |= 0x08;
getnameinfo(ifa->ifa_addr,
sizeof(struct sockaddr_in),
ip_text, sizeof(ip_text), NULL, 0,
NI_NUMERICHOST);
inet_pton(AF_INET, ip_text, ipv4_addr);
}
}
if ((found & 0x03) == 0x03) {
break;
}
}
/* no IPv4 address -> use default */
if (!(found & 0x0a)) {
inet_pton(AF_INET, default_ipv4_addr, ipv4_addr);
}
/* IPv6 default? huh... but we can't work without host IPv6 address */
if (!(found & 0x05)) {
/* FUN: try to decode it ;c) */
inet_pton(AF_INET6, "64:ff9b::E7ad:514", ipv6_addr);
}
freeifaddrs(ifaddr);
return 0;
}
/**
* Gets name of first non-loopback network interface.
*
* @param cinterface Where to save the interface name
*/
void cfg_guess_interface(char *cinterface)
{
struct ifaddrs *ifaddr, *ifa;
if (getifaddrs(&ifaddr) == -1) {
perror("getifaddrs");
return;
}
/* Walk through linked list, maintaining head pointer so we can free
* list later */
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == NULL) {
continue;
}
/* skip loopback */
if (strcmp(ifa->ifa_name, "lo")) {
strncpy(cinterface, ifa->ifa_name, sizeof(cinterface));
break;
}
}
freeifaddrs(ifaddr);
}

View File

@ -19,6 +19,9 @@
#ifndef CONFIG_H
#define CONFIG_H
#include "ipv4.h"
#include "ipv6.h"
struct s_cfg_opts {
char interface[128];
char prefix[128];
@ -27,5 +30,7 @@ struct s_cfg_opts {
int cfg_parse(const char *config_file, unsigned short *cmtu,
struct s_cfg_opts *oto, unsigned char init);
int cfg_host_ips(char *cinterface, struct s_ipv6_addr *ipv6_addr,
struct s_ipv4_addr *ipv4_addr, char *default_ipv4_addr);
#endif /* CONFIG_H */

View File

@ -43,11 +43,6 @@
#include "transmitter.h"
#include "wrapper.h"
/* +++ CONFIGURATION +++ */
#define HOST_IPV6_ADDR "fd77::1:0:1"
#define HOST_IPV4_ADDR "192.168.0.19"
/* --- CONFIGURATION --- */
unsigned short mtu;
struct ifreq interface;
@ -88,6 +83,22 @@ int main(int argc, char **argv)
log_info(" MTU %d", mtu);
log_info(" IPv4 address %s", cfg.ipv4_address);
/* get host IP addresses */
if (cfg_host_ips(cfg.interface, &host_ipv6_addr, &host_ipv4_addr,
cfg.ipv4_address)) {
log_error("Unable to get host IP addresses");
return 1;
}
/* using block because of the temporary variable */
{
char ip_text[40];
inet_ntop(AF_INET, &host_ipv4_addr, ip_text, sizeof(ip_text));
log_info(" host IPv4 address %s", ip_text);
inet_ntop(AF_INET6, &host_ipv6_addr, ip_text, sizeof(ip_text));
log_info(" host IPv6 address %s", ip_text);
}
/* initialize the socket for sniffing */
if ((sniff_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) ==
-1) {
@ -149,12 +160,6 @@ int main(int argc, char **argv)
/* compute binary IPv4 address of WrapSix */
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);
/* 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");

View File

@ -9,9 +9,9 @@
# Don't enter information about prefix length (/96).
#prefix 64:ff9b::
# WrapSix automatically detects first interface and uses it. Use this option to
# run WrapSix on different interace.
interface eth0
# WrapSix automatically detects first (non-loopback) interface and uses it. Use
# this option to run WrapSix on different interace.
#interface eth0
# Unassigned IPv4 address for sole usage by WrapSix. Even the OS mustn't have it
# assigned.