Add support for nftables
This commit is contained in:
		
							
								
								
									
										91
									
								
								helpers_c/ip46tables.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								helpers_c/ip46tables.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,91 @@
 | 
			
		||||
#include<ctype.h>
 | 
			
		||||
#include<errno.h>
 | 
			
		||||
#include<stdio.h>
 | 
			
		||||
#include<stdlib.h>
 | 
			
		||||
#include<string.h>
 | 
			
		||||
#include<unistd.h>
 | 
			
		||||
 | 
			
		||||
// If this programs
 | 
			
		||||
// - receives an ipv4 address in its arguments:
 | 
			
		||||
//   → it will executes iptables  with the same arguments in place.
 | 
			
		||||
//
 | 
			
		||||
// - receives an ipv6 address in its arguments:
 | 
			
		||||
//   → it will executes ip6tables with the same arguments in place.
 | 
			
		||||
//
 | 
			
		||||
// - doesn't receive an ipv4 or ipv6 address in its arguments:
 | 
			
		||||
//   → it will executes both, with the same arguments in place.
 | 
			
		||||
 | 
			
		||||
int isIPv4(char *tab) {
 | 
			
		||||
	int i,len;
 | 
			
		||||
	// IPv4 addresses are at least 7 chars long
 | 
			
		||||
	len = strlen(tab);
 | 
			
		||||
	if (len < 7 || !isdigit(tab[0]) || !isdigit(tab[len-1])) {
 | 
			
		||||
			return 0;
 | 
			
		||||
	}
 | 
			
		||||
	// Each char must be a digit or a dot between 2 digits
 | 
			
		||||
	for (i=1; i<len-1; i++) {
 | 
			
		||||
		if (!isdigit(tab[i]) && !(tab[i] == '.' && isdigit(tab[i-1]) && isdigit(tab[i+1]))) {
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int isIPv6(char *tab) {
 | 
			
		||||
	int i,len, twodots = 0;
 | 
			
		||||
	// IPv6 addresses are at least 3 chars long
 | 
			
		||||
	len = strlen(tab);
 | 
			
		||||
	if (len < 3) {
 | 
			
		||||
			return 0;
 | 
			
		||||
	}
 | 
			
		||||
	// Each char must be a digit, :, a-f, or A-F
 | 
			
		||||
	for (i=0; i<len; i++) {
 | 
			
		||||
		if (!isdigit(tab[i]) && tab[i] != ':' && !(tab[i] >= 'a' && tab[i] <= 'f') && !(tab[i] >= 'A' && tab[i] <= 'F')) {
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int guess_type(int len, char *tab[]) {
 | 
			
		||||
	int i;
 | 
			
		||||
	for (i=0; i<len; i++) {
 | 
			
		||||
		if (isIPv4(tab[i])) {
 | 
			
		||||
			return 4;
 | 
			
		||||
		} else if (isIPv6(tab[i])) {
 | 
			
		||||
			return 6;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int exec(char *str, char **argv) {
 | 
			
		||||
	argv[0] = str;
 | 
			
		||||
	execvp(str, argv);
 | 
			
		||||
	// returns only if fails
 | 
			
		||||
	printf("ip46tables: exec failed %d\n", errno);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char **argv) {
 | 
			
		||||
	if (argc < 2) {
 | 
			
		||||
		printf("ip46tables: At least one argument has to be given\n");
 | 
			
		||||
		exit(1);
 | 
			
		||||
	}
 | 
			
		||||
	int type;
 | 
			
		||||
	type = guess_type(argc, argv);
 | 
			
		||||
	if (type == 4) {
 | 
			
		||||
		exec("iptables", argv);
 | 
			
		||||
	} else if (type == 6) {
 | 
			
		||||
		exec("ip6tables", argv);
 | 
			
		||||
	} else {
 | 
			
		||||
		pid_t pid = fork();
 | 
			
		||||
		if (pid == -1) {
 | 
			
		||||
			printf("ip46tables: fork failed\n");
 | 
			
		||||
			exit(1);
 | 
			
		||||
		} else if (pid) {
 | 
			
		||||
			exec("iptables", argv);
 | 
			
		||||
		} else {
 | 
			
		||||
			exec("ip6tables", argv);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										97
									
								
								helpers_c/nft46.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								helpers_c/nft46.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,97 @@
 | 
			
		||||
#include<ctype.h>
 | 
			
		||||
#include<errno.h>
 | 
			
		||||
#include<stdio.h>
 | 
			
		||||
#include<stdlib.h>
 | 
			
		||||
#include<string.h>
 | 
			
		||||
#include<unistd.h>
 | 
			
		||||
 | 
			
		||||
// nft46 'add element inet reaction ipvXbans { 1.2.3.4 }' → nft 'add element inet reaction ipv4bans { 1.2.3.4 }'
 | 
			
		||||
// nft46 'add element inet reaction ipvXbans { a:b::c:d }' → nft 'add element inet reaction ipv6bans { a:b::c:d }'
 | 
			
		||||
//
 | 
			
		||||
// the character X is replaced by 4 or 6 depending on the address family of the specified IP
 | 
			
		||||
//
 | 
			
		||||
// Limitations:
 | 
			
		||||
// - nft46 must receive exactly one argument
 | 
			
		||||
// - only one IP must be given per command
 | 
			
		||||
// - the IP must be between { braces }
 | 
			
		||||
 | 
			
		||||
int isIPv4(char *tab, int len) {
 | 
			
		||||
	int i;
 | 
			
		||||
	// IPv4 addresses are at least 7 chars long
 | 
			
		||||
	if (len < 7 || !isdigit(tab[0]) || !isdigit(tab[len-1])) {
 | 
			
		||||
			return 0;
 | 
			
		||||
	}
 | 
			
		||||
	// Each char must be a digit or a dot between 2 digits
 | 
			
		||||
	for (i=1; i<len-1; i++) {
 | 
			
		||||
		if (!isdigit(tab[i]) && !(tab[i] == '.' && isdigit(tab[i-1]) && isdigit(tab[i+1]))) {
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int isIPv6(char *tab, int len) {
 | 
			
		||||
	int i;
 | 
			
		||||
	// IPv6 addresses are at least 3 chars long
 | 
			
		||||
	if (len < 3) {
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	// Each char must be a digit, :, a-f, or A-F
 | 
			
		||||
	for (i=0; i<len; i++) {
 | 
			
		||||
		if (!isdigit(tab[i]) && tab[i] != ':' && !(tab[i] >= 'a' && tab[i] <= 'f') && !(tab[i] >= 'A' && tab[i] <= 'F')) {
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int findchar(char *tab, char c, int i, int len) {
 | 
			
		||||
	while (i < len && tab[i] != c) i++;
 | 
			
		||||
	if (i == len) {
 | 
			
		||||
		printf("nft46: one %c must be present", c);
 | 
			
		||||
		exit(1);
 | 
			
		||||
	}
 | 
			
		||||
	return i;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void adapt_args(char *tab) {
 | 
			
		||||
	int i, len, X, startIP, endIP, startedIP;
 | 
			
		||||
	X = startIP = endIP = -1;
 | 
			
		||||
	startedIP = 0;
 | 
			
		||||
	len = strlen(tab);
 | 
			
		||||
	i = 0;
 | 
			
		||||
	X = i = findchar(tab, 'X', i, len);
 | 
			
		||||
	startIP = i = findchar(tab, '{', i, len);
 | 
			
		||||
	while (startIP + 1 <= (i = findchar(tab, ' ', i, len))) startIP = i + 1;
 | 
			
		||||
	i = startIP;
 | 
			
		||||
	endIP = i = findchar(tab, ' ', i, len) - 1;
 | 
			
		||||
 | 
			
		||||
	if (isIPv4(tab+startIP, endIP-startIP+1)) {
 | 
			
		||||
		tab[X] = '4';
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (isIPv6(tab+startIP, endIP-startIP+1)) {
 | 
			
		||||
		tab[X] = '6';
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	printf("nft46: no IP address found\n");
 | 
			
		||||
	exit(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int exec(char *str, char **argv) {
 | 
			
		||||
	argv[0] = str;
 | 
			
		||||
	execvp(str, argv);
 | 
			
		||||
	// returns only if fails
 | 
			
		||||
	printf("nft46: exec failed %d\n", errno);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char **argv) {
 | 
			
		||||
	if (argc != 2) {
 | 
			
		||||
		printf("nft46: Exactly one argument must be given\n");
 | 
			
		||||
		exit(1);
 | 
			
		||||
	}
 | 
			
		||||
	adapt_args(argv[1]);
 | 
			
		||||
	exec("nft", argv);
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user