197 lines
6.4 KiB
C
197 lines
6.4 KiB
C
/*
|
|
ifconfig.c -- Generate platform specific interface configuration commands
|
|
Copyright (C) 2016 Guus Sliepen <guus@tinc-vpn.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 2 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, write to the Free Software Foundation, Inc.,
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
#include "system.h"
|
|
|
|
#include "conf.h"
|
|
#include "ifconfig.h"
|
|
#include "subnet.h"
|
|
|
|
static long start;
|
|
|
|
#ifndef HAVE_MINGW
|
|
void ifconfig_header(FILE *out) {
|
|
fprintf(out, "#!/bin/sh\n");
|
|
start = ftell(out);
|
|
}
|
|
|
|
void ifconfig_dhcp(FILE *out) {
|
|
fprintf(out, "dhclient -nw \"$INTERFACE\"\n");
|
|
}
|
|
|
|
void ifconfig_dhcp6(FILE *out) {
|
|
fprintf(out, "dhclient -6 -nw \"$INTERFACE\"\n");
|
|
}
|
|
|
|
void ifconfig_slaac(FILE *out) {
|
|
#ifdef HAVE_LINUX
|
|
fprintf(out, "echo 1 >\"/proc/sys/net/ipv6/conf/$INTERFACE/accept_ra\"\n");
|
|
fprintf(out, "echo 1 >\"/proc/sys/net/ipv6/conf/$INTERFACE/autoconf\"\n");
|
|
#else
|
|
fprintf(out, "rtsol \"$INTERFACE\" &\n");
|
|
#endif
|
|
}
|
|
|
|
bool ifconfig_footer(FILE *out) {
|
|
if(ftell(out) == start) {
|
|
fprintf(out, "echo 'Unconfigured tinc-up script, please edit '$0'!'\n\n#ifconfig $INTERFACE <your vpn IP address> netmask <netmask of whole VPN>\n");
|
|
return false;
|
|
} else {
|
|
#ifdef HAVE_LINUX
|
|
fprintf(out, "ip link set \"$INTERFACE\" up\n");
|
|
#else
|
|
fprintf(out, "ifconfig \"$INTERFACE\" up\n");
|
|
#endif
|
|
return true;
|
|
}
|
|
}
|
|
#else
|
|
void ifconfig_header(FILE *out) {
|
|
start = ftell(out);
|
|
}
|
|
|
|
void ifconfig_dhcp(FILE *out) {
|
|
fprintf(out, "netsh interface ipv4 set address \"%%INTERFACE%%\" dhcp\n");
|
|
}
|
|
|
|
void ifconfig_dhcp6(FILE *out) {
|
|
fprintf(stderr, "DHCPv6 requested, but not supported by tinc on this platform\n");
|
|
}
|
|
|
|
void ifconfig_slaac(FILE *out) {
|
|
// It's the default?
|
|
}
|
|
|
|
bool ifconfig_footer(FILE *out) {
|
|
return ftell(out) != start;
|
|
}
|
|
#endif
|
|
|
|
static subnet_t ipv4, ipv6;
|
|
|
|
void ifconfig_address(FILE *out, const char *value) {
|
|
subnet_t address = {};
|
|
char address_str[MAXNETSTR];
|
|
if(!str2net(&address, value) || !net2str(address_str, sizeof address_str, &address)) {
|
|
fprintf(stderr, "Could not parse address in Ifconfig statement\n");
|
|
return;
|
|
}
|
|
switch(address.type) {
|
|
case SUBNET_IPV4: ipv4 = address; break;
|
|
case SUBNET_IPV6: ipv6 = address; break;
|
|
default: return;
|
|
}
|
|
#if defined(HAVE_LINUX)
|
|
switch(address.type) {
|
|
case SUBNET_MAC: fprintf(out, "ip link set \"$INTERFACE\" address %s\n", address_str); break;
|
|
case SUBNET_IPV4: fprintf(out, "ip addr replace %s dev \"$INTERFACE\"\n", address_str); break;
|
|
case SUBNET_IPV6: fprintf(out, "ip addr replace %s dev \"$INTERFACE\"\n", address_str); break;
|
|
default: return;
|
|
}
|
|
#elif defined(HAVE_MINGW) || defined(HAVE_CYGWIN)
|
|
switch(address.type) {
|
|
case SUBNET_MAC: fprintf(out, "ip link set \"$INTERFACE\" address %s\n", address_str); break;
|
|
case SUBNET_IPV4: fprintf(out, "netsh inetface ipv4 set address \"$INTERFACE\" static %s\n", address_str); break;
|
|
case SUBNET_IPV6: fprintf(out, "netsh inetface ipv6 set address \"$INTERFACE\" static %s\n", address_str); break;
|
|
default: return;
|
|
}
|
|
#else // assume BSD
|
|
switch(address.type) {
|
|
case SUBNET_MAC: fprintf(out, "ifconfig \"$INTERFACE\" link %s\n", address_str); break;
|
|
case SUBNET_IPV4: fprintf(out, "ifconfig \"$INTERFACE\" %s\n", address_str); break;
|
|
case SUBNET_IPV6: fprintf(out, "ifconfig \"$INTERFACE\" inet6 %s\n", address_str); break;
|
|
default: return;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void ifconfig_route(FILE *out, const char *value) {
|
|
subnet_t subnet = {}, gateway = {};
|
|
char subnet_str[MAXNETSTR] = "", gateway_str[MAXNETSTR] = "";
|
|
char *sep = strchr(value, ' ');
|
|
if(sep)
|
|
*sep++ = 0;
|
|
if(!str2net(&subnet, value) || !net2str(subnet_str, sizeof subnet_str, &subnet) || subnet.type == SUBNET_MAC) {
|
|
fprintf(stderr, "Could not parse subnet in Route statement\n");
|
|
return;
|
|
}
|
|
if(sep) {
|
|
if(!str2net(&gateway, sep) || !net2str(gateway_str, sizeof gateway_str, &gateway) || gateway.type != subnet.type) {
|
|
fprintf(stderr, "Could not parse gateway in Route statement\n");
|
|
return;
|
|
}
|
|
char *slash = strchr(gateway_str, '/'); if(slash) *slash = 0;
|
|
}
|
|
#if defined(HAVE_LINUX)
|
|
if(*gateway_str) {
|
|
switch(subnet.type) {
|
|
case SUBNET_IPV4: fprintf(out, "ip route add %s via %s dev \"$INTERFACE\"\n", subnet_str, gateway_str); break;
|
|
case SUBNET_IPV6: fprintf(out, "ip route add %s via %s dev \"$INTERFACE\"\n", subnet_str, gateway_str); break;
|
|
default: return;
|
|
}
|
|
} else {
|
|
switch(subnet.type) {
|
|
case SUBNET_IPV4: fprintf(out, "ip route add %s dev \"$INTERFACE\"\n", subnet_str); break;
|
|
case SUBNET_IPV6: fprintf(out, "ip route add %s dev \"$INTERFACE\"\n", subnet_str); break;
|
|
default: return;
|
|
}
|
|
}
|
|
#elif defined(HAVE_MINGW) || defined(HAVE_CYGWIN)
|
|
if(*gateway_str) {
|
|
switch(subnet.type) {
|
|
case SUBNET_IPV4: fprintf(out, "netsh inetface ipv4 add route %s \"%%INTERFACE%%\" %s\n", subnet_str, gateway_str); break;
|
|
case SUBNET_IPV6: fprintf(out, "netsh inetface ipv6 add route %s \"%%INTERFACE%%\" %s\n", subnet_str, gateway_str); break;
|
|
default: return;
|
|
}
|
|
} else {
|
|
switch(subnet.type) {
|
|
case SUBNET_IPV4: fprintf(out, "netsh inetface ipv4 add route %s \"%%INTERFACE%%\"\n", subnet_str); break;
|
|
case SUBNET_IPV6: fprintf(out, "netsh inetface ipv6 add route %s \"%%INTERFACE%%\"\n", subnet_str); break;
|
|
default: return;
|
|
}
|
|
}
|
|
#else // assume BSD
|
|
if(!*gateway_str) {
|
|
switch(subnet.type) {
|
|
case SUBNET_IPV4:
|
|
if(!ipv4.type) {
|
|
fprintf(stderr, "Route requested but no Ifconfig\n");
|
|
return;
|
|
}
|
|
net2str(gateway_str, sizeof gateway_str, &ipv4);
|
|
break;
|
|
case SUBNET_IPV6:
|
|
if(!ipv6.type) {
|
|
fprintf(stderr, "Route requested but no Ifconfig\n");
|
|
return;
|
|
}
|
|
net2str(gateway_str, sizeof gateway_str, &ipv6);
|
|
break;
|
|
default: return;
|
|
}
|
|
char *slash = strchr(gateway_str, '/'); if(slash) *slash = 0;
|
|
}
|
|
|
|
switch(subnet.type) {
|
|
case SUBNET_IPV4: fprintf(out, "route add %s %s\n", subnet_str, gateway_str); break;
|
|
case SUBNET_IPV6: fprintf(out, "route add -inet6 %s %s\n", subnet_str, gateway_str); break;
|
|
default: return;
|
|
}
|
|
#endif
|
|
}
|