xtables.c revision cd9e7aa106e80c44bd526af74b616701b0772d05
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> 22cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt#include <stdbool.h> 233dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI#include <stdio.h> 243dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI#include <stdlib.h> 250b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <string.h> 260b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <unistd.h> 270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#include <sys/socket.h> 280b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <sys/stat.h> 290b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <sys/types.h> 300b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <sys/wait.h> 313dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 325208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI#include <xtables.h> 333dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 345a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#ifndef NO_SHARED_LIBS 355a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#include <dlfcn.h> 365a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#endif 375a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger 380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#define NPROTO 255 390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 400b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#ifndef PROC_SYS_MODPROBE 410b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe" 420b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#endif 430b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIchar *lib_dir; 450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 460b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI/* the path to command to load kernel module */ 470b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAIconst char *modprobe = NULL; 480b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI/* Keeping track of external matches and targets: linked lists. */ 500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_match *xtables_matches; 510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_target *xtables_targets; 520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 533dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAIvoid *fw_calloc(size_t count, size_t size) 543dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI{ 553dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI void *p; 563dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 573dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI if ((p = calloc(count, size)) == NULL) { 583dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI perror("ip[6]tables: calloc failed"); 593dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI exit(1); 603dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI } 613dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 623dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI return p; 633dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI} 643dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 653dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAIvoid *fw_malloc(size_t size) 663dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI{ 673dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI void *p; 683dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 693dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI if ((p = malloc(size)) == NULL) { 703dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI perror("ip[6]tables: malloc failed"); 713dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI exit(1); 723dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI } 733dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 743dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI return p; 753dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI} 760b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 770b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAIstatic char *get_modprobe(void) 780b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI{ 790b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI int procfile; 800b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI char *ret; 810b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 820b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#define PROCFILE_BUFSIZ 1024 830b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI procfile = open(PROC_SYS_MODPROBE, O_RDONLY); 840b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (procfile < 0) 850b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return NULL; 860b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 870b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI ret = (char *) malloc(PROCFILE_BUFSIZ); 880b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (ret) { 890b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI memset(ret, 0, PROCFILE_BUFSIZ); 900b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI switch (read(procfile, ret, PROCFILE_BUFSIZ)) { 910b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI case -1: goto fail; 920b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI case PROCFILE_BUFSIZ: goto fail; /* Partial read. Wierd */ 930b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 940b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (ret[strlen(ret)-1]=='\n') 950b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI ret[strlen(ret)-1]=0; 960b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI close(procfile); 970b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return ret; 980b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 990b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI fail: 1000b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI free(ret); 1010b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI close(procfile); 1020b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return NULL; 1030b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI} 1040b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 1050b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAIint xtables_insmod(const char *modname, const char *modprobe, int quiet) 1060b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI{ 1070b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI char *buf = NULL; 1080b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI char *argv[4]; 1090b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI int status; 1100b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 1110b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI /* If they don't explicitly set it, read out of kernel */ 1120b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (!modprobe) { 1130b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI buf = get_modprobe(); 1140b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (!buf) 1150b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return -1; 1160b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI modprobe = buf; 1170b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 1180b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 1190b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI switch (fork()) { 1200b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI case 0: 1210b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[0] = (char *)modprobe; 1220b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[1] = (char *)modname; 1230b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (quiet) { 1240b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[2] = "-q"; 1250b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[3] = NULL; 1260b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } else { 1270b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[2] = NULL; 1280b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[3] = NULL; 1290b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 1300b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI execv(argv[0], argv); 1310b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 1320b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI /* not usually reached */ 1330b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI exit(1); 1340b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI case -1: 1350b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return -1; 1360b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 1370b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI default: /* parent */ 1380b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI wait(&status); 1390b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 1400b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 1410b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI free(buf); 1420b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (WIFEXITED(status) && WEXITSTATUS(status) == 0) 1430b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return 0; 1440b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return -1; 1450b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI} 1460b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 1470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIint load_xtables_ko(const char *modprobe, int quiet) 1480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 1490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI static int loaded = 0; 1500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI static int ret = -1; 1510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 1520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (!loaded) { 1530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ret = xtables_insmod(afinfo.kmod, modprobe, quiet); 1540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI loaded = (ret == 0); 1550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 1560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 1570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return ret; 1580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 1590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 16004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAIint string_to_number_ll(const char *s, unsigned long long min, 16104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI unsigned long long max, unsigned long long *ret) 16204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{ 16304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI unsigned long long number; 16404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI char *end; 16504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 16604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI /* Handle hex, octal, etc. */ 16704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI errno = 0; 16804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI number = strtoull(s, &end, 0); 16904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI if (*end == '\0' && end != s) { 17004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI /* we parsed a number, let's see if we want this */ 17104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI if (errno != ERANGE && min <= number && (!max || number <= max)) { 17204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI *ret = number; 17304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI return 0; 17404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } 17504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } 17604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI return -1; 17704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI} 17804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 17904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAIint string_to_number_l(const char *s, unsigned long min, unsigned long max, 18004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI unsigned long *ret) 18104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{ 18204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI int result; 18304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI unsigned long long number; 18404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 18504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI result = string_to_number_ll(s, min, max, &number); 18604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI *ret = (unsigned long)number; 18704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 18804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI return result; 18904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI} 19004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 19104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAIint string_to_number(const char *s, unsigned int min, unsigned int max, 19204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI unsigned int *ret) 19304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{ 19404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI int result; 19504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI unsigned long number; 19604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 19704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI result = string_to_number_l(s, min, max, &number); 19804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI *ret = (unsigned int)number; 19904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 20004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI return result; 20104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI} 20204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 203cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt/* 204cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt * strtonum{,l} - string to number conversion 205cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt * 206cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt * If @end is NULL, we assume the caller does not want 207cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt * a case like "15a", so reject it. 208cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt */ 209cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardtbool strtonuml(const char *s, char **end, unsigned long *value, 210cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt unsigned long min, unsigned long max) 211cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt{ 212cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt unsigned long v; 213cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt char *my_end; 214cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 215cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt errno = 0; 216cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt v = strtoul(s, &my_end, 0); 217cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 218cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (my_end == s) 219cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return false; 220cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (end != NULL) 221cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt *end = my_end; 222cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 223cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (errno != ERANGE && min <= v && (max == 0 || v <= max)) { 224cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (value != NULL) 225cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt *value = v; 226cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (end == NULL) 227cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return *my_end == '\0'; 228cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return true; 229cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt } 230cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 231cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return false; 232cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt} 233cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 234cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardtbool strtonum(const char *s, char **end, unsigned int *value, 235cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt unsigned int min, unsigned int max) 236cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt{ 237cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt unsigned long v; 238cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt bool ret; 239cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 240cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt ret = strtonuml(s, end, &v, min, max); 241cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (value != NULL) 242cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt *value = v; 243cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return ret; 244cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt} 245cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 24604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAIint service_to_port(const char *name, const char *proto) 24704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{ 24804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI struct servent *service; 24904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 25004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI if ((service = getservbyname(name, proto)) != NULL) 25104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI return ntohs((unsigned short) service->s_port); 25204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 25304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI return -1; 25404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI} 25504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 25604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAIu_int16_t parse_port(const char *port, const char *proto) 25704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{ 25804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI unsigned int portnum; 25904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 26004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI if ((string_to_number(port, 0, 65535, &portnum)) != -1 || 26104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI (portnum = service_to_port(port, proto)) != -1) 26204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI return (u_int16_t)portnum; 26304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 26404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI exit_error(PARAMETER_PROBLEM, 26504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI "invalid port/service `%s' specified", port); 26604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI} 26704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 26804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAIvoid parse_interface(const char *arg, char *vianame, unsigned char *mask) 26904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{ 27004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI int vialen = strlen(arg); 27104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI unsigned int i; 27204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 27304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask, 0, IFNAMSIZ); 27404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(vianame, 0, IFNAMSIZ); 27504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 27604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI if (vialen + 1 > IFNAMSIZ) 27704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI exit_error(PARAMETER_PROBLEM, 27804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI "interface name `%s' must be shorter than IFNAMSIZ" 27904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI " (%i)", arg, IFNAMSIZ-1); 28004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 28104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI strcpy(vianame, arg); 28204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI if ((vialen == 0) || (vialen == 1 && vianame[0] == '+')) 28304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask, 0, IFNAMSIZ); 28404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI else if (vianame[vialen - 1] == '+') { 28504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask, 0xFF, vialen - 1); 28604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask + vialen - 1, 0, IFNAMSIZ - vialen + 1); 28704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI /* Don't remove `+' here! -HW */ 28804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } else { 28904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI /* Include nul-terminator in match */ 29004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask, 0xFF, vialen + 1); 29104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask + vialen + 1, 0, IFNAMSIZ - vialen - 1); 29204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI for (i = 0; vianame[i]; i++) { 29304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI if (vianame[i] == ':' || 29404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI vianame[i] == '!' || 29504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI vianame[i] == '*') { 296aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann fprintf(stderr, 297aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann "Warning: weird character in interface" 298aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann " `%s' (No aliases, :, ! or *).\n", 299aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann vianame); 30004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI break; 30104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } 30204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } 30304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } 30404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI} 30504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 3060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_match *find_match(const char *name, enum xt_tryload tryload, 3070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_rule_match **matches) 3080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 3090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_match *ptr; 3100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI const char *icmp6 = "icmp6"; 3110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* This is ugly as hell. Nonetheless, there is no way of changing 3130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI * this without hurting backwards compatibility */ 3140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if ( (strcmp(name,"icmpv6") == 0) || 3150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI (strcmp(name,"ipv6-icmp") == 0) || 3160d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI (strcmp(name,"icmp6") == 0) ) 3170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI name = icmp6; 3180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (ptr = xtables_matches; ptr; ptr = ptr->next) { 3200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(name, ptr->name) == 0) { 3210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_match *clone; 3220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* First match of this type: */ 3240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr->m == NULL) 3250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI break; 3260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Second and subsequent clones */ 3280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI clone = fw_malloc(sizeof(struct xtables_match)); 3290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI memcpy(clone, ptr, sizeof(struct xtables_match)); 3300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI clone->mflags = 0; 3310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* This is a clone: */ 3320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI clone->next = clone; 3330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr = clone; 3350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI break; 3360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 3370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 3380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#ifndef NO_SHARED_LIBS 3400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (!ptr && tryload != DONT_LOAD && tryload != DURING_LOAD) { 3410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI char path[strlen(lib_dir) + sizeof("/.so") 3420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI + strlen(afinfo.libprefix) + strlen(name)]; 343170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI 344170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI sprintf(path, "%s/libxt_%s.so", lib_dir, name); 345170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI if (dlopen(path, RTLD_NOW) != NULL) 3460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Found library. If it didn't register itself, 3470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI maybe they specified target as match. */ 3480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr = find_match(name, DONT_LOAD, NULL); 3490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 350170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI if (ptr == NULL) { 351170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI sprintf(path, "%s/%s%s.so", lib_dir, afinfo.libprefix, 352170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI name); 353170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI if (dlopen(path, RTLD_NOW) != NULL) 354170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI ptr = find_match(name, DONT_LOAD, NULL); 355170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI } 356170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI 357170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI if (ptr == NULL && tryload == LOAD_MUST_SUCCEED) 3580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit_error(PARAMETER_PROBLEM, 3590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "Couldn't load match `%s':%s\n", 3600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI name, dlerror()); 3610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 3620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#else 3630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr && !ptr->loaded) { 3640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (tryload != DONT_LOAD) 3650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr->loaded = 1; 3660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI else 3670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr = NULL; 3680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 3690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if(!ptr && (tryload == LOAD_MUST_SUCCEED)) { 3700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit_error(PARAMETER_PROBLEM, 3710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "Couldn't find match `%s'\n", name); 3720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 3730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#endif 3740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr && matches) { 3760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_rule_match **i; 3770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_rule_match *newentry; 3780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI newentry = fw_malloc(sizeof(struct xtables_rule_match)); 3800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (i = matches; *i; i = &(*i)->next) { 3820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(name, (*i)->match->name) == 0) 3830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI (*i)->completed = 1; 3840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 3850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI newentry->match = ptr; 3860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI newentry->completed = 0; 3870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI newentry->next = NULL; 3880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI *i = newentry; 3890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 3900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return ptr; 3920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 3930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_target *find_target(const char *name, enum xt_tryload tryload) 3960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 3970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_target *ptr; 3980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Standard target? */ 4000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(name, "") == 0 4010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI || strcmp(name, XTC_LABEL_ACCEPT) == 0 4020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI || strcmp(name, XTC_LABEL_DROP) == 0 4030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI || strcmp(name, XTC_LABEL_QUEUE) == 0 4040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI || strcmp(name, XTC_LABEL_RETURN) == 0) 4050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI name = "standard"; 4060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (ptr = xtables_targets; ptr; ptr = ptr->next) { 4080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(name, ptr->name) == 0) 4090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI break; 4100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 4110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#ifndef NO_SHARED_LIBS 4130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (!ptr && tryload != DONT_LOAD && tryload != DURING_LOAD) { 4140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI char path[strlen(lib_dir) + sizeof("/.so") 4150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI + strlen(afinfo.libprefix) + strlen(name)]; 416170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI 417170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI sprintf(path, "%s/libxt_%s.so", lib_dir, name); 418170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI if (dlopen(path, RTLD_NOW) != NULL) 4190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Found library. If it didn't register itself, 4200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI maybe they specified match as a target. */ 4210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr = find_target(name, DONT_LOAD); 422170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI 423170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI if (ptr == NULL) { 424170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI sprintf(path, "%s/%s%s.so", lib_dir, afinfo.libprefix, 425170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI name); 426170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI if (dlopen(path, RTLD_NOW) != NULL) 427170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI ptr = find_target(name, DONT_LOAD); 428170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI } 429170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI if (ptr == NULL && tryload == LOAD_MUST_SUCCEED) 4300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit_error(PARAMETER_PROBLEM, 4310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "Couldn't load target `%s':%s\n", 4320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI name, dlerror()); 4330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 4340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#else 4350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr && !ptr->loaded) { 4360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (tryload != DONT_LOAD) 4370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr->loaded = 1; 4380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI else 4390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr = NULL; 4400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 4410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if(!ptr && (tryload == LOAD_MUST_SUCCEED)) { 4420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit_error(PARAMETER_PROBLEM, 4430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "Couldn't find target `%s'\n", name); 4440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 4450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#endif 4460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr) 4480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr->used = 1; 4490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return ptr; 4510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 4520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstatic int compatible_revision(const char *name, u_int8_t revision, int opt) 4540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 4550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xt_get_revision rev; 4560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI socklen_t s = sizeof(rev); 4570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI int max_rev, sockfd; 4580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI sockfd = socket(afinfo.family, SOCK_RAW, IPPROTO_RAW); 4600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (sockfd < 0) { 461df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy if (errno == EPERM) { 462df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy /* revision 0 is always supported. */ 463df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy if (revision != 0) 464df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy fprintf(stderr, "Could not determine whether " 465df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy "revision %u is supported, " 466df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy "assuming it is.\n", 467df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy revision); 468df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy return 1; 469df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy } 4700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "Could not open socket to kernel: %s\n", 4710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI strerror(errno)); 4720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 4730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 4740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI load_xtables_ko(modprobe, 1); 4760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI strcpy(rev.name, name); 4780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI rev.revision = revision; 4790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI max_rev = getsockopt(sockfd, afinfo.ipproto, opt, &rev, &s); 4810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (max_rev < 0) { 4820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Definitely don't support this? */ 4830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (errno == ENOENT || errno == EPROTONOSUPPORT) { 4840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI close(sockfd); 4850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return 0; 4860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } else if (errno == ENOPROTOOPT) { 4870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI close(sockfd); 4880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Assume only revision 0 support (old kernel) */ 4890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return (revision == 0); 4900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } else { 4910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "getsockopt failed strangely: %s\n", 4920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI strerror(errno)); 4930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 4940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 4950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 4960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI close(sockfd); 4970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return 1; 4980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 4990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstatic int compatible_match_revision(const char *name, u_int8_t revision) 5020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 5030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return compatible_revision(name, revision, afinfo.so_rev_match); 5040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 5050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstatic int compatible_target_revision(const char *name, u_int8_t revision) 5070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 5080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return compatible_revision(name, revision, afinfo.so_rev_target); 5090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 5100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIvoid xtables_register_match(struct xtables_match *me) 5120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 5130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_match **i, *old; 5140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(me->version, program_version) != 0) { 5160d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "%s: match `%s' v%s (I'm v%s).\n", 5170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI program_name, me->name, me->version, program_version); 5180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 5190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Revision field stole a char from name. */ 5220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strlen(me->name) >= XT_FUNCTION_MAXNAMELEN-1) { 5230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "%s: target `%s' has invalid name\n", 5240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI program_name, me->name); 5250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 5260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (me->family >= NPROTO) { 5290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, 5300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "%s: BUG: match %s has invalid protocol family\n", 5310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI program_name, me->name); 5320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 5330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* ignore not interested match */ 5360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (me->family != afinfo.family) 5370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 5380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI old = find_match(me->name, DURING_LOAD, NULL); 5400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (old) { 5410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (old->revision == me->revision) { 5420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, 5430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "%s: match `%s' already registered.\n", 5440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI program_name, me->name); 5450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 5460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Now we have two (or more) options, check compatibility. */ 5490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (compatible_match_revision(old->name, old->revision) 5500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI && old->revision > me->revision) 5510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 5520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Replace if compatible. */ 5540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (!compatible_match_revision(me->name, me->revision)) 5550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 5560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Delete old one. */ 5580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (i = &xtables_matches; *i!=old; i = &(*i)->next); 5590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI *i = old->next; 5600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (me->size != XT_ALIGN(me->size)) { 5630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "%s: match `%s' has invalid size %u.\n", 5640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI program_name, me->name, (unsigned int)me->size); 5650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 5660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Append to list. */ 5690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (i = &xtables_matches; *i; i = &(*i)->next); 5700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->next = NULL; 5710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI *i = me; 5720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->m = NULL; 5740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->mflags = 0; 5750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 5760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIvoid xtables_register_target(struct xtables_target *me) 5780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 5790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_target *old; 5800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(me->version, program_version) != 0) { 5820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "%s: target `%s' v%s (I'm v%s).\n", 5830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI program_name, me->name, me->version, program_version); 5840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 5850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Revision field stole a char from name. */ 5880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strlen(me->name) >= XT_FUNCTION_MAXNAMELEN-1) { 5890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "%s: target `%s' has invalid name\n", 5900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI program_name, me->name); 5910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 5920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (me->family >= NPROTO) { 5950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, 5960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "%s: BUG: target %s has invalid protocol family\n", 5970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI program_name, me->name); 5980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 5990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* ignore not interested target */ 6020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (me->family != afinfo.family) 6030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 6040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI old = find_target(me->name, DURING_LOAD); 6060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (old) { 6070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_target **i; 6080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (old->revision == me->revision) { 6100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, 6110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "%s: target `%s' already registered.\n", 6120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI program_name, me->name); 6130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 6140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6160d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Now we have two (or more) options, check compatibility. */ 6170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (compatible_target_revision(old->name, old->revision) 6180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI && old->revision > me->revision) 6190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 6200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Replace if compatible. */ 6220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (!compatible_target_revision(me->name, me->revision)) 6230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 6240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Delete old one. */ 6260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (i = &xtables_targets; *i!=old; i = &(*i)->next); 6270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI *i = old->next; 6280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (me->size != XT_ALIGN(me->size)) { 6310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "%s: target `%s' has invalid size %u.\n", 6320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI program_name, me->name, (unsigned int)me->size); 6330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 6340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Prepend to list. */ 6370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->next = xtables_targets; 6380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI xtables_targets = me; 6390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->t = NULL; 6400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->tflags = 0; 6410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 642