xtables.c revision dacafa55379fd98212031d8c559096c91d7ce93b
15208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI/* 25208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI * (C) 2000-2006 by the netfilter coreteam <coreteam@netfilter.org>: 35208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI * 45208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI * This program is free software; you can redistribute it and/or modify 55208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI * it under the terms of the GNU General Public License as published by 65208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI * the Free Software Foundation; either version 2 of the License, or 75208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI * (at your option) any later version. 85208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI * 95208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI * This program is distributed in the hope that it will be useful, 105208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI * but WITHOUT ANY WARRANTY; without even the implied warranty of 115208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 125208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI * GNU General Public License for more details. 135208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI * 145208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI * You should have received a copy of the GNU General Public License 155208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI * along with this program; if not, write to the Free Software 165208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 175208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI */ 185208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI 193dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI#include <errno.h> 200b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <fcntl.h> 2104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI#include <netdb.h> 22aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt#include <stdarg.h> 23cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt#include <stdbool.h> 243dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI#include <stdio.h> 253dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI#include <stdlib.h> 260b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <string.h> 270b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <unistd.h> 280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#include <sys/socket.h> 290b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <sys/stat.h> 300b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <sys/types.h> 310b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <sys/wait.h> 3208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#include <arpa/inet.h> 333dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 345208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI#include <xtables.h> 35ef18e8147903885708d1c264904129af4fb636d6Jan Engelhardt#include <libiptc/libxtc.h> 363dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 375a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#ifndef NO_SHARED_LIBS 385a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#include <dlfcn.h> 395a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#endif 405a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger 410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#define NPROTO 255 420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 430b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#ifndef PROC_SYS_MODPROBE 440b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe" 450b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#endif 460b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 47dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt/** 48dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt * Program will set this to its own name. 49dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt */ 50dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardtconst char *xtables_program_name; 51dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt 5239bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt/* Search path for Xtables .so files */ 5339bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardtstatic const char *xtables_libdir; 540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 550b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI/* the path to command to load kernel module */ 56c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtconst char *xtables_modprobe_program; 570b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI/* Keeping track of external matches and targets: linked lists. */ 590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_match *xtables_matches; 600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_target *xtables_targets; 610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6239bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardtvoid xtables_init(void) 6339bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt{ 6439bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt xtables_libdir = getenv("XTABLES_LIBDIR"); 6539bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt if (xtables_libdir != NULL) 6639bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt return; 6739bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt xtables_libdir = getenv("IPTABLES_LIB_DIR"); 6839bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt if (xtables_libdir != NULL) { 6939bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt fprintf(stderr, "IPTABLES_LIB_DIR is deprecated, " 7039bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt "use XTABLES_LIBDIR.\n"); 7139bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt return; 7239bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt } 7339bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt xtables_libdir = XTABLES_LIBDIR; 7439bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt} 7539bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt 76630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt/** 77630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt * xtables_*alloc - wrappers that exit on failure 78630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt */ 79630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardtvoid *xtables_calloc(size_t count, size_t size) 803dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI{ 813dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI void *p; 823dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 833dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI if ((p = calloc(count, size)) == NULL) { 843dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI perror("ip[6]tables: calloc failed"); 853dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI exit(1); 863dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI } 873dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 883dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI return p; 893dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI} 903dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 91630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardtvoid *xtables_malloc(size_t size) 923dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI{ 933dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI void *p; 943dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 953dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI if ((p = malloc(size)) == NULL) { 963dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI perror("ip[6]tables: malloc failed"); 973dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI exit(1); 983dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI } 993dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 1003dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI return p; 1013dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI} 1020b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 1030b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAIstatic char *get_modprobe(void) 1040b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI{ 1050b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI int procfile; 1060b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI char *ret; 1070b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 1080b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#define PROCFILE_BUFSIZ 1024 1090b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI procfile = open(PROC_SYS_MODPROBE, O_RDONLY); 1100b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (procfile < 0) 1110b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return NULL; 1120b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 1130b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI ret = (char *) malloc(PROCFILE_BUFSIZ); 1140b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (ret) { 1150b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI memset(ret, 0, PROCFILE_BUFSIZ); 1160b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI switch (read(procfile, ret, PROCFILE_BUFSIZ)) { 1170b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI case -1: goto fail; 1180b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI case PROCFILE_BUFSIZ: goto fail; /* Partial read. Wierd */ 1190b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 1200b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (ret[strlen(ret)-1]=='\n') 1210b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI ret[strlen(ret)-1]=0; 1220b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI close(procfile); 1230b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return ret; 1240b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 1250b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI fail: 1260b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI free(ret); 1270b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI close(procfile); 1280b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return NULL; 1290b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI} 1300b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 131c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtint xtables_insmod(const char *modname, const char *modprobe, bool quiet) 1320b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI{ 1330b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI char *buf = NULL; 1340b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI char *argv[4]; 1350b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI int status; 1360b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 1370b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI /* If they don't explicitly set it, read out of kernel */ 1380b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (!modprobe) { 1390b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI buf = get_modprobe(); 1400b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (!buf) 1410b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return -1; 1420b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI modprobe = buf; 1430b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 1440b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 1450b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI switch (fork()) { 1460b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI case 0: 1470b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[0] = (char *)modprobe; 1480b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[1] = (char *)modname; 1490b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (quiet) { 1500b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[2] = "-q"; 1510b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[3] = NULL; 1520b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } else { 1530b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[2] = NULL; 1540b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[3] = NULL; 1550b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 1560b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI execv(argv[0], argv); 1570b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 1580b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI /* not usually reached */ 1590b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI exit(1); 1600b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI case -1: 1610b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return -1; 1620b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 1630b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI default: /* parent */ 1640b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI wait(&status); 1650b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 1660b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 1670b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI free(buf); 1680b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (WIFEXITED(status) && WEXITSTATUS(status) == 0) 1690b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return 0; 1700b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return -1; 1710b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI} 1720b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 173c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtint xtables_load_ko(const char *modprobe, bool quiet) 1740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 175c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardt static bool loaded = false; 1760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI static int ret = -1; 1770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 1780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (!loaded) { 1790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ret = xtables_insmod(afinfo.kmod, modprobe, quiet); 1800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI loaded = (ret == 0); 1810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 1820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 1830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return ret; 1840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 1850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 1865f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt/** 1875f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * xtables_strtou{i,l} - string to number conversion 1885f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @s: input string 1895f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @end: like strtoul's "end" pointer 1905f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @value: pointer for result 1915f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @min: minimum accepted value 1925f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @max: maximum accepted value 1935f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * 1945f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * If @end is NULL, we assume the caller wants a "strict strtoul", and hence 1955f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * "15a" is rejected. 1965f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * In either case, the value obtained is compared for min-max compliance. 1975f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * Base is always 0, i.e. autodetect depending on @s. 198cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt * 1995f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * Returns true/false whether number was accepted. On failure, *value has 2005f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * undefined contents. 201cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt */ 2025f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardtbool xtables_strtoul(const char *s, char **end, unsigned long *value, 2035f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt unsigned long min, unsigned long max) 204cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt{ 205cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt unsigned long v; 206cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt char *my_end; 207cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 208cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt errno = 0; 209cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt v = strtoul(s, &my_end, 0); 210cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 211cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (my_end == s) 212cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return false; 213cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (end != NULL) 214cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt *end = my_end; 215cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 216cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (errno != ERANGE && min <= v && (max == 0 || v <= max)) { 217cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (value != NULL) 218cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt *value = v; 219cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (end == NULL) 220cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return *my_end == '\0'; 221cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return true; 222cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt } 223cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 224cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return false; 225cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt} 226cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 2275f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardtbool xtables_strtoui(const char *s, char **end, unsigned int *value, 2285f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt unsigned int min, unsigned int max) 229cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt{ 230cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt unsigned long v; 231cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt bool ret; 232cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 2335f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt ret = xtables_strtoul(s, end, &v, min, max); 234cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (value != NULL) 235cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt *value = v; 236cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return ret; 237cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt} 238cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 23904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAIint service_to_port(const char *name, const char *proto) 24004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{ 24104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI struct servent *service; 24204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 24304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI if ((service = getservbyname(name, proto)) != NULL) 24404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI return ntohs((unsigned short) service->s_port); 24504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 24604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI return -1; 24704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI} 24804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 24904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAIu_int16_t parse_port(const char *port, const char *proto) 25004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{ 2517a236f4cc685a420c1a782a5db614a93baf37ccfJan Engelhardt unsigned int portnum; 25204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 2535f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt if (xtables_strtoui(port, NULL, &portnum, 0, UINT16_MAX) || 2549ee386a1b6d7704b259460152c959ab0e79e02aaMax Kellermann (portnum = service_to_port(port, proto)) != (unsigned)-1) 255213e185afbb298e6708881e4c2adffdc47a8b6daJan Engelhardt return portnum; 25604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 25704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI exit_error(PARAMETER_PROBLEM, 25804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI "invalid port/service `%s' specified", port); 25904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI} 26004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 26104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAIvoid parse_interface(const char *arg, char *vianame, unsigned char *mask) 26204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{ 26304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI int vialen = strlen(arg); 26404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI unsigned int i; 26504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 26604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask, 0, IFNAMSIZ); 26704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(vianame, 0, IFNAMSIZ); 26804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 26904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI if (vialen + 1 > IFNAMSIZ) 27004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI exit_error(PARAMETER_PROBLEM, 27104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI "interface name `%s' must be shorter than IFNAMSIZ" 27204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI " (%i)", arg, IFNAMSIZ-1); 27304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 27404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI strcpy(vianame, arg); 27504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI if ((vialen == 0) || (vialen == 1 && vianame[0] == '+')) 27604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask, 0, IFNAMSIZ); 27704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI else if (vianame[vialen - 1] == '+') { 27804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask, 0xFF, vialen - 1); 27904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask + vialen - 1, 0, IFNAMSIZ - vialen + 1); 28004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI /* Don't remove `+' here! -HW */ 28104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } else { 28204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI /* Include nul-terminator in match */ 28304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask, 0xFF, vialen + 1); 28404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask + vialen + 1, 0, IFNAMSIZ - vialen - 1); 28504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI for (i = 0; vianame[i]; i++) { 28604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI if (vianame[i] == ':' || 28704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI vianame[i] == '!' || 28804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI vianame[i] == '*') { 289aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann fprintf(stderr, 290aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann "Warning: weird character in interface" 291aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann " `%s' (No aliases, :, ! or *).\n", 292aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann vianame); 29304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI break; 29404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } 29504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } 29604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } 29704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI} 29804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 299cb25af809a8734c4766b6bfa4cca99596cbf01dbJan Engelhardt#ifndef NO_SHARED_LIBS 30021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardtstatic void *load_extension(const char *search_path, const char *prefix, 30121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt const char *name, bool is_target) 30221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt{ 30321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt const char *dir = search_path, *next; 30421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt void *ptr = NULL; 30521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt struct stat sb; 30621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt char path[256]; 30721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 30821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt do { 30921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt next = strchr(dir, ':'); 31021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt if (next == NULL) 31121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt next = dir + strlen(dir); 31221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt snprintf(path, sizeof(path), "%.*s/libxt_%s.so", 3132c0a0c9eba1d1ab39dcde54bc822d4788f9531fcJan Engelhardt (unsigned int)(next - dir), dir, name); 31421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 31521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt if (dlopen(path, RTLD_NOW) != NULL) { 31621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt /* Found library. If it didn't register itself, 31721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt maybe they specified target as match. */ 31821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt if (is_target) 3192338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt ptr = xtables_find_target(name, XTF_DONT_LOAD); 32021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt else 3212338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt ptr = xtables_find_match(name, 3222338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt XTF_DONT_LOAD, NULL); 32321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt } else if (stat(path, &sb) == 0) { 32421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt fprintf(stderr, "%s: %s\n", path, dlerror()); 32521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt } 32621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 32721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt if (ptr != NULL) 32821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt return ptr; 32921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 33021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt snprintf(path, sizeof(path), "%.*s/%s%s.so", 3312c0a0c9eba1d1ab39dcde54bc822d4788f9531fcJan Engelhardt (unsigned int)(next - dir), dir, prefix, name); 33221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt if (dlopen(path, RTLD_NOW) != NULL) { 33321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt if (is_target) 3342338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt ptr = xtables_find_target(name, XTF_DONT_LOAD); 33521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt else 3362338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt ptr = xtables_find_match(name, 3372338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt XTF_DONT_LOAD, NULL); 33821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt } else if (stat(path, &sb) == 0) { 33921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt fprintf(stderr, "%s: %s\n", path, dlerror()); 34021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt } 34121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 34221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt if (ptr != NULL) 34321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt return ptr; 34421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 34521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt dir = next + 1; 34621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt } while (*next != '\0'); 34721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 34821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt return NULL; 34921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt} 350cb25af809a8734c4766b6bfa4cca99596cbf01dbJan Engelhardt#endif 35121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 3522338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtstruct xtables_match * 3532338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtxtables_find_match(const char *name, enum xtables_tryload tryload, 3542338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt struct xtables_rule_match **matches) 3550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 3560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_match *ptr; 3570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI const char *icmp6 = "icmp6"; 3580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* This is ugly as hell. Nonetheless, there is no way of changing 3600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI * this without hurting backwards compatibility */ 3610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if ( (strcmp(name,"icmpv6") == 0) || 3620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI (strcmp(name,"ipv6-icmp") == 0) || 3630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI (strcmp(name,"icmp6") == 0) ) 3640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI name = icmp6; 3650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (ptr = xtables_matches; ptr; ptr = ptr->next) { 3670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(name, ptr->name) == 0) { 3680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_match *clone; 3690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* First match of this type: */ 3710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr->m == NULL) 3720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI break; 3730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Second and subsequent clones */ 375630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt clone = xtables_malloc(sizeof(struct xtables_match)); 3760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI memcpy(clone, ptr, sizeof(struct xtables_match)); 3770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI clone->mflags = 0; 3780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* This is a clone: */ 3790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI clone->next = clone; 3800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr = clone; 3820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI break; 3830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 3840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 3850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#ifndef NO_SHARED_LIBS 3872338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) { 38839bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt ptr = load_extension(xtables_libdir, afinfo.libprefix, 38939bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt name, false); 390170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI 3912338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) 3920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit_error(PARAMETER_PROBLEM, 3930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "Couldn't load match `%s':%s\n", 3940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI name, dlerror()); 3950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 3960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#else 3970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr && !ptr->loaded) { 3982338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if (tryload != XTF_DONT_LOAD) 3990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr->loaded = 1; 4000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI else 4010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr = NULL; 4020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 4032338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if(!ptr && (tryload == XTF_LOAD_MUST_SUCCEED)) { 4040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit_error(PARAMETER_PROBLEM, 4050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "Couldn't find match `%s'\n", name); 4060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 4070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#endif 4080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr && matches) { 4100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_rule_match **i; 4110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_rule_match *newentry; 4120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 413630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt newentry = xtables_malloc(sizeof(struct xtables_rule_match)); 4140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (i = matches; *i; i = &(*i)->next) { 4160d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(name, (*i)->match->name) == 0) 4172338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt (*i)->completed = true; 4180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 4190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI newentry->match = ptr; 4202338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt newentry->completed = false; 4210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI newentry->next = NULL; 4220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI *i = newentry; 4230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 4240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return ptr; 4260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 4270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4282338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtstruct xtables_target * 4292338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtxtables_find_target(const char *name, enum xtables_tryload tryload) 4300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 4310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_target *ptr; 4320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Standard target? */ 4340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(name, "") == 0 4350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI || strcmp(name, XTC_LABEL_ACCEPT) == 0 4360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI || strcmp(name, XTC_LABEL_DROP) == 0 4370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI || strcmp(name, XTC_LABEL_QUEUE) == 0 4380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI || strcmp(name, XTC_LABEL_RETURN) == 0) 4390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI name = "standard"; 4400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (ptr = xtables_targets; ptr; ptr = ptr->next) { 4420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(name, ptr->name) == 0) 4430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI break; 4440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 4450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#ifndef NO_SHARED_LIBS 4472338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) { 44839bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt ptr = load_extension(xtables_libdir, afinfo.libprefix, 44939bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt name, true); 450170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI 4512338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) 4520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit_error(PARAMETER_PROBLEM, 4530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "Couldn't load target `%s':%s\n", 4540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI name, dlerror()); 4550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 4560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#else 4570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr && !ptr->loaded) { 4582338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if (tryload != XTF_DONT_LOAD) 4590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr->loaded = 1; 4600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI else 4610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr = NULL; 4620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 4630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if(!ptr && (tryload == LOAD_MUST_SUCCEED)) { 4640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit_error(PARAMETER_PROBLEM, 4650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "Couldn't find target `%s'\n", name); 4660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 4670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#endif 4680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr) 4700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr->used = 1; 4710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return ptr; 4730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 4740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstatic int compatible_revision(const char *name, u_int8_t revision, int opt) 4760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 4770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xt_get_revision rev; 4780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI socklen_t s = sizeof(rev); 4790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI int max_rev, sockfd; 4800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI sockfd = socket(afinfo.family, SOCK_RAW, IPPROTO_RAW); 4820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (sockfd < 0) { 483df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy if (errno == EPERM) { 484df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy /* revision 0 is always supported. */ 485df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy if (revision != 0) 486df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy fprintf(stderr, "Could not determine whether " 487df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy "revision %u is supported, " 488df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy "assuming it is.\n", 489df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy revision); 490df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy return 1; 491df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy } 4920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "Could not open socket to kernel: %s\n", 4930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI strerror(errno)); 4940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 4950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 4960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 497c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardt xtables_load_ko(xtables_modprobe_program, true); 4980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI strcpy(rev.name, name); 5000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI rev.revision = revision; 5010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI max_rev = getsockopt(sockfd, afinfo.ipproto, opt, &rev, &s); 5030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (max_rev < 0) { 5040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Definitely don't support this? */ 5050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (errno == ENOENT || errno == EPROTONOSUPPORT) { 5060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI close(sockfd); 5070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return 0; 5080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } else if (errno == ENOPROTOOPT) { 5090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI close(sockfd); 5100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Assume only revision 0 support (old kernel) */ 5110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return (revision == 0); 5120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } else { 5130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "getsockopt failed strangely: %s\n", 5140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI strerror(errno)); 5150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 5160d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI close(sockfd); 5190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return 1; 5200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 5210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstatic int compatible_match_revision(const char *name, u_int8_t revision) 5240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 5250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return compatible_revision(name, revision, afinfo.so_rev_match); 5260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 5270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstatic int compatible_target_revision(const char *name, u_int8_t revision) 5290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 5300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return compatible_revision(name, revision, afinfo.so_rev_target); 5310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 5320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIvoid xtables_register_match(struct xtables_match *me) 5340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 5350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_match **i, *old; 5360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 537dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt if (strcmp(me->version, XTABLES_VERSION) != 0) { 538dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt fprintf(stderr, "%s: match \"%s\" has version \"%s\", " 539dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt "but \"%s\" is required.\n", 540dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt xtables_program_name, me->name, 541dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt me->version, XTABLES_VERSION); 5420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 5430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Revision field stole a char from name. */ 5460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strlen(me->name) >= XT_FUNCTION_MAXNAMELEN-1) { 5470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "%s: target `%s' has invalid name\n", 548dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt xtables_program_name, me->name); 5490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 5500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (me->family >= NPROTO) { 5530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, 5540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "%s: BUG: match %s has invalid protocol family\n", 555dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt xtables_program_name, me->name); 5560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 5570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* ignore not interested match */ 56023545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt if (me->family != afinfo.family && me->family != AF_UNSPEC) 5610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 5620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5632338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt old = xtables_find_match(me->name, XTF_DURING_LOAD, NULL); 5640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (old) { 56523545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt if (old->revision == me->revision && 56623545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt old->family == me->family) { 5670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, 5680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "%s: match `%s' already registered.\n", 569dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt xtables_program_name, me->name); 5700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 5710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Now we have two (or more) options, check compatibility. */ 5740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (compatible_match_revision(old->name, old->revision) 5750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI && old->revision > me->revision) 5760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 5770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 57823545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt /* See if new match can be used. */ 5790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (!compatible_match_revision(me->name, me->revision)) 5800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 5810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 58223545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt /* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */ 58323545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt if (old->revision == me->revision && me->family == AF_UNSPEC) 58423545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt return; 58523545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt 5860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Delete old one. */ 5870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (i = &xtables_matches; *i!=old; i = &(*i)->next); 5880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI *i = old->next; 5890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (me->size != XT_ALIGN(me->size)) { 5920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "%s: match `%s' has invalid size %u.\n", 593dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt xtables_program_name, me->name, (unsigned int)me->size); 5940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 5950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Append to list. */ 5980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (i = &xtables_matches; *i; i = &(*i)->next); 5990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->next = NULL; 6000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI *i = me; 6010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->m = NULL; 6030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->mflags = 0; 6040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 6050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIvoid xtables_register_target(struct xtables_target *me) 6070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 6080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_target *old; 6090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 610dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt if (strcmp(me->version, XTABLES_VERSION) != 0) { 611dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt fprintf(stderr, "%s: target \"%s\" has version \"%s\", " 612dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt "but \"%s\" is required.\n", 613dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt xtables_program_name, me->name, 614dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt me->version, XTABLES_VERSION); 6150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 6160d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Revision field stole a char from name. */ 6190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strlen(me->name) >= XT_FUNCTION_MAXNAMELEN-1) { 6200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "%s: target `%s' has invalid name\n", 621dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt xtables_program_name, me->name); 6220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 6230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (me->family >= NPROTO) { 6260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, 6270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "%s: BUG: target %s has invalid protocol family\n", 628dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt xtables_program_name, me->name); 6290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 6300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* ignore not interested target */ 63323545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt if (me->family != afinfo.family && me->family != AF_UNSPEC) 6340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 6350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6362338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt old = xtables_find_target(me->name, XTF_DURING_LOAD); 6370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (old) { 6380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_target **i; 6390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 64023545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt if (old->revision == me->revision && 64123545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt old->family == me->family) { 6420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, 6430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "%s: target `%s' already registered.\n", 644dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt xtables_program_name, me->name); 6450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 6460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Now we have two (or more) options, check compatibility. */ 6490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (compatible_target_revision(old->name, old->revision) 6500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI && old->revision > me->revision) 6510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 6520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 65323545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt /* See if new target can be used. */ 6540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (!compatible_target_revision(me->name, me->revision)) 6550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 6560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 65723545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt /* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */ 65823545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt if (old->revision == me->revision && me->family == AF_UNSPEC) 65923545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt return; 66023545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt 6610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Delete old one. */ 6620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (i = &xtables_targets; *i!=old; i = &(*i)->next); 6630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI *i = old->next; 6640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (me->size != XT_ALIGN(me->size)) { 6670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "%s: target `%s' has invalid size %u.\n", 668dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt xtables_program_name, me->name, (unsigned int)me->size); 6690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 6700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Prepend to list. */ 6730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->next = xtables_targets; 6740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI xtables_targets = me; 6750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->t = NULL; 6760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->tflags = 0; 6770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 678aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt 679aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardtvoid param_act(unsigned int status, const char *p1, ...) 680aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt{ 681aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt const char *p2, *p3; 682aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt va_list args; 683aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt bool b; 684aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt 685aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt va_start(args, p1); 686aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt 687aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt switch (status) { 688aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt case P_ONLY_ONCE: 689aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt p2 = va_arg(args, const char *); 690aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt b = va_arg(args, unsigned int); 691aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt if (!b) 692aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt return; 693aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt exit_error(PARAMETER_PROBLEM, 694aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt "%s: \"%s\" option may only be specified once", 695aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt p1, p2); 696aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt break; 697aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt case P_NO_INVERT: 698aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt p2 = va_arg(args, const char *); 699aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt b = va_arg(args, unsigned int); 700aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt if (!b) 701aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt return; 702aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt exit_error(PARAMETER_PROBLEM, 703aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt "%s: \"%s\" option cannot be inverted", p1, p2); 704aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt break; 705aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt case P_BAD_VALUE: 706aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt p2 = va_arg(args, const char *); 707aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt p3 = va_arg(args, const char *); 708aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt exit_error(PARAMETER_PROBLEM, 709aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt "%s: Bad value for \"%s\" option: \"%s\"", 710aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt p1, p2, p3); 711aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt break; 712aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt case P_ONE_ACTION: 713aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt b = va_arg(args, unsigned int); 714aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt if (!b) 715aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt return; 716aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt exit_error(PARAMETER_PROBLEM, 717aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt "%s: At most one action is possible", p1); 718aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt break; 719aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt default: 720aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt exit_error(status, p1, args); 721aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt break; 722aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt } 723aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt 724aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt va_end(args); 725aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt} 72608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 72708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtconst char *ipaddr_to_numeric(const struct in_addr *addrp) 72808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 72908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt static char buf[20]; 73008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt const unsigned char *bytep = (const void *)&addrp->s_addr; 73108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 73208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt sprintf(buf, "%u.%u.%u.%u", bytep[0], bytep[1], bytep[2], bytep[3]); 73308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return buf; 73408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 73508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 73608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ipaddr_to_host(const struct in_addr *addr) 73708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 73808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt struct hostent *host; 73908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 74008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt host = gethostbyaddr(addr, sizeof(struct in_addr), AF_INET); 74108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if (host == NULL) 74208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return NULL; 74308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 74408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return host->h_name; 74508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 74608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 74708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ipaddr_to_network(const struct in_addr *addr) 74808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 74908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt struct netent *net; 75008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 75108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if ((net = getnetbyaddr(ntohl(addr->s_addr), AF_INET)) != NULL) 75208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return net->n_name; 75308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 75408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return NULL; 75508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 75608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 75708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtconst char *ipaddr_to_anyname(const struct in_addr *addr) 75808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 75908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt const char *name; 76008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 76108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if ((name = ipaddr_to_host(addr)) != NULL || 76208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt (name = ipaddr_to_network(addr)) != NULL) 76308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return name; 76408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 76508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return ipaddr_to_numeric(addr); 76608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 76708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 76808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtconst char *ipmask_to_numeric(const struct in_addr *mask) 76908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 77008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt static char buf[20]; 77108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt uint32_t maskaddr, bits; 77208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt int i; 77308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 77408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt maskaddr = ntohl(mask->s_addr); 77508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 77608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if (maskaddr == 0xFFFFFFFFL) 77708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt /* we don't want to see "/32" */ 77808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return ""; 77908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 78008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt i = 32; 78108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt bits = 0xFFFFFFFEL; 78208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt while (--i >= 0 && maskaddr != bits) 78308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt bits <<= 1; 78408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if (i >= 0) 78508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt sprintf(buf, "/%d", i); 78608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt else 78708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt /* mask was not a decent combination of 1's and 0's */ 78808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt sprintf(buf, "/%s", ipaddr_to_numeric(mask)); 78908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 79008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return buf; 79108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 79208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 793bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *__numeric_to_ipaddr(const char *dotted, bool is_mask) 794bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 795bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt static struct in_addr addr; 796bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned char *addrp; 797bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned int onebyte; 798bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt char buf[20], *p, *q; 799bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt int i; 800bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 801bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* copy dotted string, because we need to modify it */ 802bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt strncpy(buf, dotted, sizeof(buf) - 1); 803bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt buf[sizeof(buf) - 1] = '\0'; 804bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = (void *)&addr.s_addr; 805bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 806bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt p = buf; 807bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (i = 0; i < 3; ++i) { 808bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((q = strchr(p, '.')) == NULL) { 809bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (is_mask) 810bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 811bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 812bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* autocomplete, this is a network address */ 8135f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX)) 814bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 815bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 816bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp[i] = onebyte; 817bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt while (i < 3) 818bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp[++i] = 0; 819bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 820bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &addr; 821bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 822bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 823bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *q = '\0'; 8245f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX)) 825bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 826bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 827bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp[i] = onebyte; 828bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt p = q + 1; 829bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 830bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 831bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* we have checked 3 bytes, now we check the last one */ 8325f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX)) 833bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 834bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 835bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp[3] = onebyte; 836bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &addr; 837bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 838bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 839bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstruct in_addr *numeric_to_ipaddr(const char *dotted) 840bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 841bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return __numeric_to_ipaddr(dotted, false); 842bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 843bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 844bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstruct in_addr *numeric_to_ipmask(const char *dotted) 845bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 846bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return __numeric_to_ipaddr(dotted, true); 847bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 848bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 849bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *network_to_ipaddr(const char *name) 850bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 851bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt static struct in_addr addr; 852bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct netent *net; 853bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 854bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((net = getnetbyname(name)) != NULL) { 855bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (net->n_addrtype != AF_INET) 856bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 857bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addr.s_addr = htonl(net->n_net); 858bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &addr; 859bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 860bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 861bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 862bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 863bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 864bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *host_to_ipaddr(const char *name, unsigned int *naddr) 865bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 866bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct hostent *host; 867bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in_addr *addr; 868bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned int i; 869bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 870bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *naddr = 0; 871bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((host = gethostbyname(name)) != NULL) { 872bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (host->h_addrtype != AF_INET || 873bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt host->h_length != sizeof(struct in_addr)) 874bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 875bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 876bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt while (host->h_addr_list[*naddr] != NULL) 877bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt ++*naddr; 878630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt addr = xtables_calloc(*naddr, sizeof(struct in_addr) * *naddr); 879bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (i = 0; i < *naddr; i++) 880bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memcpy(&addr[i], host->h_addr_list[i], 881bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt sizeof(struct in_addr)); 882bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addr; 883bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 884bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 885bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 886bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 887bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 888bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr * 889bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtipparse_hostnetwork(const char *name, unsigned int *naddrs) 890bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 891bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in_addr *addrptmp, *addrp; 892bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 893bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((addrptmp = numeric_to_ipaddr(name)) != NULL || 894bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt (addrptmp = network_to_ipaddr(name)) != NULL) { 895630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt addrp = xtables_malloc(sizeof(struct in_addr)); 896bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memcpy(addrp, addrptmp, sizeof(*addrp)); 897bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *naddrs = 1; 898bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addrp; 899bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 900bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((addrptmp = host_to_ipaddr(name, naddrs)) != NULL) 901bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addrptmp; 902bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 903bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt exit_error(PARAMETER_PROBLEM, "host/network `%s' not found", name); 904bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 905bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 906bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *parse_ipmask(const char *mask) 907bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 908bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt static struct in_addr maskaddr; 909bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in_addr *addrp; 910bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned int bits; 911bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 912bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (mask == NULL) { 913bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* no mask at all defaults to 32 bits */ 914bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt maskaddr.s_addr = 0xFFFFFFFF; 915bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &maskaddr; 916bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 917bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((addrp = numeric_to_ipmask(mask)) != NULL) 918bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* dotted_to_addr already returns a network byte order addr */ 919bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addrp; 9205f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt if (!xtables_strtoui(mask, NULL, &bits, 0, 32)) 921bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt exit_error(PARAMETER_PROBLEM, 922bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt "invalid mask `%s' specified", mask); 923bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (bits != 0) { 924bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt maskaddr.s_addr = htonl(0xFFFFFFFF << (32 - bits)); 925bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &maskaddr; 926bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 927bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 928bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt maskaddr.s_addr = 0U; 929bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &maskaddr; 930bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 931bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 932bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtvoid ipparse_hostnetworkmask(const char *name, struct in_addr **addrpp, 933bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in_addr *maskp, unsigned int *naddrs) 934bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 935bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned int i, j, k, n; 936bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in_addr *addrp; 937bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt char buf[256], *p; 938bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 939bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt strncpy(buf, name, sizeof(buf) - 1); 940bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt buf[sizeof(buf) - 1] = '\0'; 941bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((p = strrchr(buf, '/')) != NULL) { 942bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *p = '\0'; 943bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = parse_ipmask(p + 1); 944bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } else { 945bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = parse_ipmask(NULL); 946bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 947bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memcpy(maskp, addrp, sizeof(*maskp)); 948bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 949bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* if a null mask is given, the name is ignored, like in "any/0" */ 950bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (maskp->s_addr == 0U) 951bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt strcpy(buf, "0.0.0.0"); 952bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 953bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = *addrpp = ipparse_hostnetwork(buf, naddrs); 954bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt n = *naddrs; 955bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (i = 0, j = 0; i < n; ++i) { 956bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp[j++].s_addr &= maskp->s_addr; 957bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (k = 0; k < j - 1; ++k) 958bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (addrp[k].s_addr == addrp[j-1].s_addr) { 959bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt --*naddrs; 960bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt --j; 961bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt break; 962bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 963bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 964bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 965bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 96608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtconst char *ip6addr_to_numeric(const struct in6_addr *addrp) 96708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 96808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt /* 0000:0000:0000:0000:0000:000.000.000.000 96908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt * 0000:0000:0000:0000:0000:0000:0000:0000 */ 97008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt static char buf[50+1]; 97108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return inet_ntop(AF_INET6, addrp, buf, sizeof(buf)); 97208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 97308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 97408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ip6addr_to_host(const struct in6_addr *addr) 97508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 97608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt static char hostname[NI_MAXHOST]; 97708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt struct sockaddr_in6 saddr; 97808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt int err; 97908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 98008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt memset(&saddr, 0, sizeof(struct sockaddr_in6)); 98108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt memcpy(&saddr.sin6_addr, addr, sizeof(*addr)); 98208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt saddr.sin6_family = AF_INET6; 98308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 98408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt err = getnameinfo((const void *)&saddr, sizeof(struct sockaddr_in6), 98508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt hostname, sizeof(hostname) - 1, NULL, 0, 0); 98608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if (err != 0) { 98708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#ifdef DEBUG 98808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt fprintf(stderr,"IP2Name: %s\n",gai_strerror(err)); 98908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#endif 99008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return NULL; 99108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt } 99208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 99308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#ifdef DEBUG 99408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt fprintf (stderr, "\naddr2host: %s\n", hostname); 99508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#endif 99608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return hostname; 99708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 99808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 99908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtconst char *ip6addr_to_anyname(const struct in6_addr *addr) 100008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 100108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt const char *name; 100208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 100308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if ((name = ip6addr_to_host(addr)) != NULL) 100408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return name; 100508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 100608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return ip6addr_to_numeric(addr); 100708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 100808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 100908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic int ip6addr_prefix_length(const struct in6_addr *k) 101008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 101108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt unsigned int bits = 0; 101208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt uint32_t a, b, c, d; 101308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 101448607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt a = ntohl(k->s6_addr32[0]); 101548607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt b = ntohl(k->s6_addr32[1]); 101648607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt c = ntohl(k->s6_addr32[2]); 101748607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt d = ntohl(k->s6_addr32[3]); 101808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt while (a & 0x80000000U) { 101908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt ++bits; 102008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt a <<= 1; 102108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt a |= (b >> 31) & 1; 102208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt b <<= 1; 102308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt b |= (c >> 31) & 1; 102408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt c <<= 1; 102508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt c |= (d >> 31) & 1; 102608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt d <<= 1; 102708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt } 102808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if (a != 0 || b != 0 || c != 0 || d != 0) 102908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return -1; 103008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return bits; 103108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 103208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 103308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtconst char *ip6mask_to_numeric(const struct in6_addr *addrp) 103408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 103508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt static char buf[50+2]; 103608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt int l = ip6addr_prefix_length(addrp); 103708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 103808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if (l == -1) { 103908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt strcpy(buf, "/"); 104008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt strcat(buf, ip6addr_to_numeric(addrp)); 104108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return buf; 104208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt } 104308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt sprintf(buf, "/%d", l); 104408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return buf; 104508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 1046bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1047bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstruct in6_addr *numeric_to_ip6addr(const char *num) 1048bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1049bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt static struct in6_addr ap; 1050bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt int err; 1051bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1052bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((err = inet_pton(AF_INET6, num, &ap)) == 1) 1053bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return ≈ 1054bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG 1055bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt fprintf(stderr, "\nnumeric2addr: %d\n", err); 1056bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif 1057bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1058bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1059bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1060bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr * 1061bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardthost_to_ip6addr(const char *name, unsigned int *naddr) 1062bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1063bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt static struct in6_addr *addr; 1064bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct addrinfo hints; 1065bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct addrinfo *res; 1066bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt int err; 1067bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1068bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memset(&hints, 0, sizeof(hints)); 1069bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt hints.ai_flags = AI_CANONNAME; 1070bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt hints.ai_family = AF_INET6; 1071bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt hints.ai_socktype = SOCK_RAW; 1072bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt hints.ai_protocol = IPPROTO_IPV6; 1073bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt hints.ai_next = NULL; 1074bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1075bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *naddr = 0; 1076bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((err = getaddrinfo(name, NULL, &hints, &res)) != 0) { 1077bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG 1078bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt fprintf(stderr,"Name2IP: %s\n",gai_strerror(err)); 1079bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif 1080bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1081bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } else { 1082bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (res->ai_family != AF_INET6 || 1083bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt res->ai_addrlen != sizeof(struct sockaddr_in6)) 1084bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1085bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1086bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG 1087bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt fprintf(stderr, "resolved: len=%d %s ", res->ai_addrlen, 1088bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt ip6addr_to_numeric(&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr)); 1089bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif 1090bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* Get the first element of the address-chain */ 1091630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt addr = xtables_malloc(sizeof(struct in6_addr)); 1092bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memcpy(addr, &((const struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 1093bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt sizeof(struct in6_addr)); 1094bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt freeaddrinfo(res); 1095bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *naddr = 1; 1096bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addr; 1097bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1098bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1099bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1100bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1101bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1102bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *network_to_ip6addr(const char *name) 1103bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1104bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* abort();*/ 1105bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* TODO: not implemented yet, but the exception breaks the 1106bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt * name resolvation */ 1107bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1108bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1109bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1110bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr * 1111bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtip6parse_hostnetwork(const char *name, unsigned int *naddrs) 1112bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1113bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in6_addr *addrp, *addrptmp; 1114bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1115bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((addrptmp = numeric_to_ip6addr(name)) != NULL || 1116bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt (addrptmp = network_to_ip6addr(name)) != NULL) { 1117630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt addrp = xtables_malloc(sizeof(struct in6_addr)); 1118bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memcpy(addrp, addrptmp, sizeof(*addrp)); 1119bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *naddrs = 1; 1120bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addrp; 1121bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1122bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((addrp = host_to_ip6addr(name, naddrs)) != NULL) 1123bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addrp; 1124bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1125bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt exit_error(PARAMETER_PROBLEM, "host/network `%s' not found", name); 1126bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1127bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1128bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *parse_ip6mask(char *mask) 1129bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1130bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt static struct in6_addr maskaddr; 1131bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in6_addr *addrp; 1132bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned int bits; 1133bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1134bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (mask == NULL) { 1135bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* no mask at all defaults to 128 bits */ 1136bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memset(&maskaddr, 0xff, sizeof maskaddr); 1137bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &maskaddr; 1138bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1139bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((addrp = numeric_to_ip6addr(mask)) != NULL) 1140bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addrp; 11415f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt if (!xtables_strtoui(mask, NULL, &bits, 0, 128)) 1142bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt exit_error(PARAMETER_PROBLEM, 1143bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt "invalid mask `%s' specified", mask); 1144bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (bits != 0) { 1145bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt char *p = (void *)&maskaddr; 1146bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memset(p, 0xff, bits / 8); 1147bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memset(p + (bits / 8) + 1, 0, (128 - bits) / 8); 1148bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt p[bits/8] = 0xff << (8 - (bits & 7)); 1149bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &maskaddr; 1150bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1151bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1152bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memset(&maskaddr, 0, sizeof(maskaddr)); 1153bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &maskaddr; 1154bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1155bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1156bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtvoid ip6parse_hostnetworkmask(const char *name, struct in6_addr **addrpp, 1157bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in6_addr *maskp, unsigned int *naddrs) 1158bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1159bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in6_addr *addrp; 1160bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned int i, j, k, n; 1161bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt char buf[256], *p; 1162bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1163bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt strncpy(buf, name, sizeof(buf) - 1); 1164bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt buf[sizeof(buf)-1] = '\0'; 1165bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((p = strrchr(buf, '/')) != NULL) { 1166bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *p = '\0'; 1167bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = parse_ip6mask(p + 1); 1168bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } else { 1169bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = parse_ip6mask(NULL); 1170bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1171bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memcpy(maskp, addrp, sizeof(*maskp)); 1172bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1173bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* if a null mask is given, the name is ignored, like in "any/0" */ 1174bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (memcmp(maskp, &in6addr_any, sizeof(in6addr_any)) == 0) 1175bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt strcpy(buf, "::"); 1176bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1177bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = *addrpp = ip6parse_hostnetwork(buf, naddrs); 1178bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt n = *naddrs; 1179bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (i = 0, j = 0; i < n; ++i) { 1180bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (k = 0; k < 4; ++k) 11815a2208c3e62a150e6f6297abbfa63056ab4a8066Yasuyuki Kozakai addrp[j].s6_addr32[k] &= maskp->s6_addr32[k]; 1182bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt ++j; 1183bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (k = 0; k < j - 1; ++k) 1184bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (IN6_ARE_ADDR_EQUAL(&addrp[k], &addrp[j - 1])) { 1185bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt --*naddrs; 1186bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt --j; 1187bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt break; 1188bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1189bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1190bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1191a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann 1192a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermannvoid save_string(const char *value) 1193a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann{ 1194a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann static const char no_quote_chars[] = "_-0123456789" 1195a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann "abcdefghijklmnopqrstuvwxyz" 1196a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 1197a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann static const char escape_chars[] = "\"\\'"; 1198a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann size_t length; 1199a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann const char *p; 1200a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann 1201a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann length = strcspn(value, no_quote_chars); 1202a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann if (length > 0 && value[length] == 0) { 1203a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann /* no quoting required */ 1204a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann fputs(value, stdout); 1205a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann putchar(' '); 1206a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann } else { 1207a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann /* there is at least one dangerous character in the 1208a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann value, which we have to quote. Write double quotes 1209a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann around the value and escape special characters with 1210a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann a backslash */ 1211a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann putchar('"'); 1212a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann 1213a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann for (p = strpbrk(value, escape_chars); p != NULL; 1214a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann p = strpbrk(value, escape_chars)) { 1215a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann if (p > value) 1216a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann fwrite(value, 1, p - value, stdout); 1217a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann putchar('\\'); 1218a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann putchar(*p); 1219a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann value = p + 1; 1220a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann } 1221a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann 1222a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann /* print the rest and finish the double quoted 1223a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann string */ 1224a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann fputs(value, stdout); 1225a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann printf("\" "); 1226a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann } 1227a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann} 1228