tncattach/TAP.c

293 lines
11 KiB
C
Raw Normal View History

#include "TAP.h"
2020-05-26 17:59:56 +02:00
char tap_name[IFNAMSIZ];
extern bool verbose;
extern bool noipv6;
extern bool set_ipv4;
extern bool set_ipv6;
extern bool link_local_v6;
2020-05-26 17:59:56 +02:00
extern bool set_netmask;
extern bool noup;
extern int mtu;
extern int device_type;
extern char if_name[IFNAMSIZ];
extern char* ipv4_addr;
extern char* ipv6_addr;
extern long ipv6_prefixLen;
2020-05-26 17:59:56 +02:00
extern char* netmask;
extern void cleanup();
void trySixSet
(
int interfaceIndex,
struct in6_addr address,
int prefixLen
)
{
char ip_str[INET6_ADDRSTRLEN+1];
inet_ntop(AF_INET6, &address, ip_str, INET6_ADDRSTRLEN+1);
printf
(
"Adding IPv6 address of '%s/%d' to interface at if_index %d\n",
ip_str,
prefixLen,
interfaceIndex
);
2024-12-15 18:07:55 +02:00
int inet6 = socket(AF_INET6, SOCK_DGRAM, 0);
2024-12-15 18:19:07 +02:00
if(inet6 < 0)
{
printf("Error opening control socket for adding IPv6 address to interface\n");
cleanup();
exit(1);
}
struct in6_ifreq paramReq;
memset(&paramReq, 0, sizeof(struct in6_ifreq));
paramReq.ifr6_ifindex = interfaceIndex;
paramReq.ifr6_prefixlen = prefixLen;
paramReq.ifr6_addr = address;
// Try add the address
2024-12-15 18:07:55 +02:00
if(ioctl(inet6, SIOCSIFADDR, &paramReq) < 0)
{
printf
(
"There was an errror assigning address '%s/%d' to if_index %d\n",
ip_str,
prefixLen,
interfaceIndex
);
cleanup();
2024-12-15 18:07:55 +02:00
close(inet6);
exit(1);
}
printf("Address '%s/%d' added\n", ip_str, prefixLen);
2024-12-15 18:07:55 +02:00
close(inet6);
}
2020-05-26 17:59:56 +02:00
int open_tap(void) {
2020-06-24 14:22:42 +02:00
struct ifreq ifr;
int fd = open("/dev/net/tun", O_RDWR);
2020-05-26 17:59:56 +02:00
2020-06-24 14:22:42 +02:00
if (fd < 0) {
perror("Could not open clone device");
exit(1);
} else {
memset(&ifr, 0, sizeof(ifr));
// TODO: Enable PI header again?
2020-05-26 17:59:56 +02:00
2020-06-24 14:22:42 +02:00
if (device_type == IF_TAP) {
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
} else if (device_type == IF_TUN) {
ifr.ifr_flags = IFF_TUN;
} else {
printf("Error: Unsupported interface type\r\n");
cleanup();
exit(1);
}
2020-05-26 17:59:56 +02:00
2020-06-24 14:22:42 +02:00
strcpy(tap_name, "tnc%d");
strncpy(ifr.ifr_name, tap_name, IFNAMSIZ);
2020-05-26 17:59:56 +02:00
2020-06-24 14:22:42 +02:00
if (ioctl(fd, TUNSETIFF, &ifr) < 0) {
perror("Could not configure network interface");
exit(1);
} else {
strcpy(if_name, ifr.ifr_name);
2024-12-15 18:14:23 +02:00
int inet = socket(AF_INET, SOCK_DGRAM, 0);
2020-06-24 14:22:42 +02:00
if (inet == -1) {
2024-12-15 18:15:15 +02:00
perror("Could not open control socket");
2020-06-24 14:22:42 +02:00
cleanup();
exit(1);
} else {
if (ioctl(inet, SIOCGIFMTU, &ifr) < 0) {
perror("Could not get interface flags from kernel");
close(inet);
cleanup();
exit(1);
} else {
ifr.ifr_mtu = mtu;
if (ioctl(inet, SIOCSIFMTU, &ifr) < 0) {
perror("Could not configure interface MTU");
close(inet);
cleanup();
exit(1);
}
2020-05-26 17:59:56 +02:00
2020-06-24 14:22:42 +02:00
// Configure TX queue length
if (ioctl(inet, SIOCGIFTXQLEN, &ifr) < 0) {
perror("Could not get interface flags from kernel");
close(inet);
cleanup();
exit(1);
} else {
ifr.ifr_qlen = TXQUEUELEN;
if (ioctl(inet, SIOCSIFTXQLEN, &ifr) < 0) {
perror("Could not set interface TX queue length");
close(inet);
cleanup();
exit(1);
}
}
2020-06-24 14:22:42 +02:00
// Configure ARP characteristics
char path_buf[256];
if (device_type == IF_TAP) {
snprintf(path_buf, sizeof(path_buf), "/proc/sys/net/ipv4/neigh/%s/base_reachable_time_ms", ifr.ifr_name);
int arp_fd = open(path_buf, O_WRONLY);
if (arp_fd < 0) {
perror("Could not open proc entry for ARP parameters");
close(inet);
cleanup();
exit(1);
} else {
if (dprintf(arp_fd, "%d", ARP_BASE_REACHABLE_TIME*1000) <= 0) {
perror("Could not configure interface ARP parameter base_reachable_time_ms");
close(inet);
close(arp_fd);
cleanup();
exit(1);
} else {
close(arp_fd);
}
}
2020-06-01 22:54:15 +02:00
2020-06-24 14:22:42 +02:00
snprintf(path_buf, sizeof(path_buf), "/proc/sys/net/ipv4/neigh/%s/retrans_time_ms", ifr.ifr_name);
arp_fd = open(path_buf, O_WRONLY);
if (arp_fd < 0) {
perror("Could not open proc entry for ARP parameters");
close(inet);
cleanup();
exit(1);
} else {
if (dprintf(arp_fd, "%d", ARP_RETRANS_TIME*1000) <= 0) {
perror("Could not configure interface ARP parameter retrans_time_ms");
close(inet);
close(arp_fd);
cleanup();
exit(1);
} else {
close(arp_fd);
}
}
}
2020-06-01 22:54:15 +02:00
2020-06-24 14:22:42 +02:00
// Bring up if requested
if (!noup) {
if (ioctl(inet, SIOCGIFFLAGS, &ifr) < 0) {
perror("Could not get interface flags from kernel");
close(inet);
cleanup();
exit(1);
} else {
ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
if (ioctl(inet, SIOCSIFFLAGS, &ifr) < 0) {
perror("Could not bring up interface");
close(inet);
cleanup();
exit(1);
} else {
if (set_ipv4) {
struct ifreq a_ifr;
struct sockaddr_in addr, snm;
2020-05-26 17:59:56 +02:00
2020-06-24 14:22:42 +02:00
memset(&a_ifr, 0, sizeof(a_ifr));
memset(&addr, 0, sizeof(addr));
memset(&snm, 0, sizeof(addr));
strncpy(a_ifr.ifr_name, ifr.ifr_name, IFNAMSIZ);
addr.sin_family = AF_INET;
snm.sin_family = AF_INET;
2020-05-26 17:59:56 +02:00
2020-06-24 14:22:42 +02:00
int addr_conversion = inet_pton(AF_INET, ipv4_addr, &(addr.sin_addr));
if (addr_conversion != 1) {
printf("Error: Invalid IPv4 address specified\r\n");
close(inet);
cleanup();
exit(1);
} else {
a_ifr.ifr_addr = *(struct sockaddr*)&addr;
if (ioctl(inet, SIOCSIFADDR, &a_ifr) < 0) {
perror("Could not set IP-address");
close(inet);
cleanup();
exit(1);
} else {
if (set_netmask) {
int snm_conversion = inet_pton(AF_INET, netmask, &(snm.sin_addr));
if (snm_conversion != 1) {
printf("Error: Invalid subnet mask specified\r\n");
close(inet);
cleanup();
exit(1);
} else {
a_ifr.ifr_addr = *(struct sockaddr*)&snm;
if (ioctl(inet, SIOCSIFNETMASK, &a_ifr) < 0) {
perror("Could not set subnet mask");
close(inet);
cleanup();
exit(1);
}
}
}
}
}
}
if(set_ipv6)
2024-12-15 17:45:05 +02:00
{
// Firstly, obtain the interface index by `ifr_name`
2024-12-15 18:07:55 +02:00
int inet6 = socket(AF_INET6, SOCK_DGRAM, 0);
2024-12-15 18:19:59 +02:00
if(inet6 < 0)
{
printf("Error opening control socket for adding IPv6 address to interface\n");
cleanup();
exit(1);
}
2024-12-15 18:07:55 +02:00
if(ioctl(inet6, SIOCGIFINDEX, &ifr) < 0)
{
printf("Could not get interface index for interface '%s'\n", ifr.ifr_name);
2024-12-15 18:07:55 +02:00
close(inet6);
2024-12-15 17:46:26 +02:00
cleanup();
exit(1);
}
// Convert ASCII IPv6 address to ABI structure
struct in6_addr six_addr_itself;
memset(&six_addr_itself, 0, sizeof(struct in6_addr));
if(inet_pton(AF_INET6, ipv6_addr, &six_addr_itself) < 0)
{
printf("Error parsing IPv6 address '%s'\n", ipv6_addr);
close(inet6);
cleanup();
exit(1);
}
// Add user's requested address
trySixSet(ifr.ifr_ifindex, six_addr_itself, ipv6_prefixLen);
2024-12-15 18:11:46 +02:00
close(inet6);
}
2020-06-24 14:22:42 +02:00
}
}
}
}
}
2020-05-26 17:59:56 +02:00
2020-06-24 14:22:42 +02:00
return fd;
}
}
2020-05-26 17:59:56 +02:00
}
int close_tap(int tap_fd) {
2020-06-24 14:22:42 +02:00
return close(tap_fd);
}