mirror of
https://code.semirocket.science/wrapsix
synced 2024-12-22 04:20:18 +02:00
Autoconfiguration of host IP addresses & interface
Interface still can be configured manually
This commit is contained in:
parent
f7af8f6805
commit
37cd198a45
5
NEWS
5
NEWS
@ -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
|
||||
|
158
src/config.c
158
src/config.c
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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");
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user