mirror of
https://code.semirocket.science/wrapsix
synced 2024-11-23 22:14:59 +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
|
WrapSix 0.2.0
|
||||||
=============
|
=============
|
||||||
|
|
||||||
- completely rewritten from scratch, but without DNS64 for now
|
- completely rewritten from scratch, but without DNS64 for now
|
||||||
- dropped all external dependencies
|
- dropped all external dependencies
|
||||||
- cleaner design & implementation with emphasis on CPU & memory efficiency
|
- 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/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <arpa/inet.h> /* inet_pton */
|
||||||
#include <stdlib.h>
|
#include <ifaddrs.h> /* struct ifaddrs, getifaddrs, freeifaddrs */
|
||||||
#include <string.h>
|
#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 "config.h"
|
||||||
|
#include "ipv4.h"
|
||||||
|
#include "ipv6.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "wrapper.h"
|
#include "wrapper.h"
|
||||||
|
|
||||||
@ -36,9 +41,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define C_DEFAULT_MTU 1280
|
#define C_DEFAULT_MTU 1280
|
||||||
#define C_DEFAULT_INTERFACE "eth0"
|
|
||||||
#define C_DEFAULT_PREFIX "64:ff9b::"
|
#define C_DEFAULT_PREFIX "64:ff9b::"
|
||||||
|
|
||||||
|
void cfg_guess_interface(char *cinterface);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration file parser.
|
* Configuration file parser.
|
||||||
*
|
*
|
||||||
@ -48,6 +54,12 @@
|
|||||||
* locally to init other things)
|
* locally to init other things)
|
||||||
* @param init 0 or 1, whether or not to initialize
|
* @param init 0 or 1, whether or not to initialize
|
||||||
* configuration with defaults
|
* 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,
|
int cfg_parse(const char *config_file, unsigned short *cmtu,
|
||||||
struct s_cfg_opts *oto, unsigned char init)
|
struct s_cfg_opts *oto, unsigned char init)
|
||||||
@ -61,15 +73,14 @@ int cfg_parse(const char *config_file, unsigned short *cmtu,
|
|||||||
|
|
||||||
/* set defaults */
|
/* set defaults */
|
||||||
*cmtu = C_DEFAULT_MTU;
|
*cmtu = C_DEFAULT_MTU;
|
||||||
/* TODO: get automatically the first available interface */
|
oto->interface[0] = '\0';
|
||||||
strncpy(oto->interface, C_DEFAULT_INTERFACE, sizeof(oto->interface));
|
cfg_guess_interface(oto->interface);
|
||||||
strncpy(oto->prefix, C_DEFAULT_PREFIX, sizeof(oto->prefix));
|
strncpy(oto->prefix, C_DEFAULT_PREFIX, sizeof(oto->prefix));
|
||||||
oto->ipv4_address[0] = '\0';
|
oto->ipv4_address[0] = '\0';
|
||||||
|
|
||||||
f = fopen(config_file, "r");
|
f = fopen(config_file, "r");
|
||||||
|
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
/* set defaults */
|
|
||||||
log_warn("Configuration file %s doesn't exist, using defaults",
|
log_warn("Configuration file %s doesn't exist, using defaults",
|
||||||
config_file);
|
config_file);
|
||||||
|
|
||||||
@ -181,3 +192,136 @@ int cfg_parse(const char *config_file, unsigned short *cmtu,
|
|||||||
|
|
||||||
return 0;
|
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
|
#ifndef CONFIG_H
|
||||||
#define CONFIG_H
|
#define CONFIG_H
|
||||||
|
|
||||||
|
#include "ipv4.h"
|
||||||
|
#include "ipv6.h"
|
||||||
|
|
||||||
struct s_cfg_opts {
|
struct s_cfg_opts {
|
||||||
char interface[128];
|
char interface[128];
|
||||||
char prefix[128];
|
char prefix[128];
|
||||||
@ -27,5 +30,7 @@ struct s_cfg_opts {
|
|||||||
|
|
||||||
int cfg_parse(const char *config_file, unsigned short *cmtu,
|
int cfg_parse(const char *config_file, unsigned short *cmtu,
|
||||||
struct s_cfg_opts *oto, unsigned char init);
|
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 */
|
#endif /* CONFIG_H */
|
||||||
|
@ -43,11 +43,6 @@
|
|||||||
#include "transmitter.h"
|
#include "transmitter.h"
|
||||||
#include "wrapper.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;
|
unsigned short mtu;
|
||||||
|
|
||||||
struct ifreq interface;
|
struct ifreq interface;
|
||||||
@ -88,6 +83,22 @@ int main(int argc, char **argv)
|
|||||||
log_info(" MTU %d", mtu);
|
log_info(" MTU %d", mtu);
|
||||||
log_info(" IPv4 address %s", cfg.ipv4_address);
|
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 */
|
/* initialize the socket for sniffing */
|
||||||
if ((sniff_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) ==
|
if ((sniff_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) ==
|
||||||
-1) {
|
-1) {
|
||||||
@ -149,12 +160,6 @@ int main(int argc, char **argv)
|
|||||||
/* compute binary IPv4 address of WrapSix */
|
/* compute binary IPv4 address of WrapSix */
|
||||||
inet_pton(AF_INET, cfg.ipv4_address, &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);
|
|
||||||
|
|
||||||
/* compute binary IPv4 address of WrapSix host */
|
|
||||||
inet_pton(AF_INET, HOST_IPV4_ADDR, &host_ipv4_addr);
|
|
||||||
|
|
||||||
/* initiate sending socket */
|
/* initiate sending socket */
|
||||||
if (transmission_init()) {
|
if (transmission_init()) {
|
||||||
log_error("Unable to initiate sending socket");
|
log_error("Unable to initiate sending socket");
|
||||||
|
@ -9,9 +9,9 @@
|
|||||||
# Don't enter information about prefix length (/96).
|
# Don't enter information about prefix length (/96).
|
||||||
#prefix 64:ff9b::
|
#prefix 64:ff9b::
|
||||||
|
|
||||||
# WrapSix automatically detects first interface and uses it. Use this option to
|
# WrapSix automatically detects first (non-loopback) interface and uses it. Use
|
||||||
# run WrapSix on different interace.
|
# this option to run WrapSix on different interace.
|
||||||
interface eth0
|
#interface eth0
|
||||||
|
|
||||||
# Unassigned IPv4 address for sole usage by WrapSix. Even the OS mustn't have it
|
# Unassigned IPv4 address for sole usage by WrapSix. Even the OS mustn't have it
|
||||||
# assigned.
|
# assigned.
|
||||||
|
Loading…
Reference in New Issue
Block a user