xtables.c revision 5a2208c3e62a150e6f6297abbfa63056ab4a8066
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> 353dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 365a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#ifndef NO_SHARED_LIBS 375a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#include <dlfcn.h> 385a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#endif 395a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger 400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#define NPROTO 255 410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 420b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#ifndef PROC_SYS_MODPROBE 430b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe" 440b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#endif 450b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIchar *lib_dir; 470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 480b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI/* the path to command to load kernel module */ 49dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardtconst char *modprobe_program = NULL; 500b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI/* Keeping track of external matches and targets: linked lists. */ 520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_match *xtables_matches; 530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_target *xtables_targets; 540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 553dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAIvoid *fw_calloc(size_t count, size_t size) 563dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI{ 573dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI void *p; 583dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 593dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI if ((p = calloc(count, size)) == NULL) { 603dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI perror("ip[6]tables: calloc failed"); 613dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI exit(1); 623dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI } 633dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 643dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI return p; 653dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI} 663dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 673dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAIvoid *fw_malloc(size_t size) 683dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI{ 693dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI void *p; 703dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 713dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI if ((p = malloc(size)) == NULL) { 723dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI perror("ip[6]tables: malloc failed"); 733dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI exit(1); 743dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI } 753dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 763dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI return p; 773dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI} 780b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 790b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAIstatic char *get_modprobe(void) 800b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI{ 810b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI int procfile; 820b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI char *ret; 830b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 840b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#define PROCFILE_BUFSIZ 1024 850b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI procfile = open(PROC_SYS_MODPROBE, O_RDONLY); 860b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (procfile < 0) 870b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return NULL; 880b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 890b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI ret = (char *) malloc(PROCFILE_BUFSIZ); 900b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (ret) { 910b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI memset(ret, 0, PROCFILE_BUFSIZ); 920b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI switch (read(procfile, ret, PROCFILE_BUFSIZ)) { 930b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI case -1: goto fail; 940b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI case PROCFILE_BUFSIZ: goto fail; /* Partial read. Wierd */ 950b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 960b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (ret[strlen(ret)-1]=='\n') 970b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI ret[strlen(ret)-1]=0; 980b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI close(procfile); 990b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return ret; 1000b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 1010b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI fail: 1020b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI free(ret); 1030b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI close(procfile); 1040b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return NULL; 1050b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI} 1060b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 1070b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAIint xtables_insmod(const char *modname, const char *modprobe, int quiet) 1080b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI{ 1090b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI char *buf = NULL; 1100b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI char *argv[4]; 1110b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI int status; 1120b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 1130b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI /* If they don't explicitly set it, read out of kernel */ 1140b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (!modprobe) { 1150b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI buf = get_modprobe(); 1160b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (!buf) 1170b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return -1; 1180b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI modprobe = buf; 1190b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 1200b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 1210b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI switch (fork()) { 1220b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI case 0: 1230b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[0] = (char *)modprobe; 1240b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[1] = (char *)modname; 1250b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (quiet) { 1260b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[2] = "-q"; 1270b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[3] = NULL; 1280b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } else { 1290b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[2] = NULL; 1300b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[3] = NULL; 1310b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 1320b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI execv(argv[0], argv); 1330b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 1340b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI /* not usually reached */ 1350b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI exit(1); 1360b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI case -1: 1370b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return -1; 1380b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 1390b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI default: /* parent */ 1400b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI wait(&status); 1410b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 1420b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 1430b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI free(buf); 1440b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (WIFEXITED(status) && WEXITSTATUS(status) == 0) 1450b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return 0; 1460b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return -1; 1470b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI} 1480b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 1490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIint load_xtables_ko(const char *modprobe, int quiet) 1500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 1510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI static int loaded = 0; 1520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI static int ret = -1; 1530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 1540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (!loaded) { 1550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ret = xtables_insmod(afinfo.kmod, modprobe, quiet); 1560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI loaded = (ret == 0); 1570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 1580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 1590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return ret; 1600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 1610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 16204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAIint string_to_number_ll(const char *s, unsigned long long min, 16304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI unsigned long long max, unsigned long long *ret) 16404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{ 16504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI unsigned long long number; 16604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI char *end; 16704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 16804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI /* Handle hex, octal, etc. */ 16904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI errno = 0; 17004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI number = strtoull(s, &end, 0); 17104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI if (*end == '\0' && end != s) { 17204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI /* we parsed a number, let's see if we want this */ 17304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI if (errno != ERANGE && min <= number && (!max || number <= max)) { 17404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI *ret = number; 17504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI return 0; 17604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } 17704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } 17804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI return -1; 17904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI} 18004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 18104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAIint string_to_number_l(const char *s, unsigned long min, unsigned long max, 18204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI unsigned long *ret) 18304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{ 18404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI int result; 18504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI unsigned long long number; 18604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 18704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI result = string_to_number_ll(s, min, max, &number); 18804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI *ret = (unsigned long)number; 18904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 19004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI return result; 19104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI} 19204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 19304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAIint string_to_number(const char *s, unsigned int min, unsigned int max, 19404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI unsigned int *ret) 19504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{ 19604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI int result; 19704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI unsigned long number; 19804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 19904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI result = string_to_number_l(s, min, max, &number); 20004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI *ret = (unsigned int)number; 20104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 20204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI return result; 20304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI} 20404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 205cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt/* 206cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt * strtonum{,l} - string to number conversion 207cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt * 208cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt * If @end is NULL, we assume the caller does not want 209cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt * a case like "15a", so reject it. 210cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt */ 211cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardtbool strtonuml(const char *s, char **end, unsigned long *value, 212cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt unsigned long min, unsigned long max) 213cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt{ 214cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt unsigned long v; 215cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt char *my_end; 216cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 217cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt errno = 0; 218cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt v = strtoul(s, &my_end, 0); 219cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 220cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (my_end == s) 221cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return false; 222cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (end != NULL) 223cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt *end = my_end; 224cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 225cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (errno != ERANGE && min <= v && (max == 0 || v <= max)) { 226cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (value != NULL) 227cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt *value = v; 228cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (end == NULL) 229cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return *my_end == '\0'; 230cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return true; 231cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt } 232cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 233cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return false; 234cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt} 235cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 236cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardtbool strtonum(const char *s, char **end, unsigned int *value, 237cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt unsigned int min, unsigned int max) 238cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt{ 239cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt unsigned long v; 240cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt bool ret; 241cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 242cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt ret = strtonuml(s, end, &v, min, max); 243cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (value != NULL) 244cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt *value = v; 245cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return ret; 246cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt} 247cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 24804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAIint service_to_port(const char *name, const char *proto) 24904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{ 25004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI struct servent *service; 25104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 25204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI if ((service = getservbyname(name, proto)) != NULL) 25304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI return ntohs((unsigned short) service->s_port); 25404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 25504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI return -1; 25604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI} 25704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 25804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAIu_int16_t parse_port(const char *port, const char *proto) 25904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{ 2607a236f4cc685a420c1a782a5db614a93baf37ccfJan Engelhardt unsigned int portnum; 26104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 26204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI if ((string_to_number(port, 0, 65535, &portnum)) != -1 || 2639ee386a1b6d7704b259460152c959ab0e79e02aaMax Kellermann (portnum = service_to_port(port, proto)) != (unsigned)-1) 26404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI return (u_int16_t)portnum; 26504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 26604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI exit_error(PARAMETER_PROBLEM, 26704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI "invalid port/service `%s' specified", port); 26804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI} 26904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 27004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAIvoid parse_interface(const char *arg, char *vianame, unsigned char *mask) 27104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{ 27204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI int vialen = strlen(arg); 27304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI unsigned int i; 27404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 27504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask, 0, IFNAMSIZ); 27604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(vianame, 0, IFNAMSIZ); 27704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 27804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI if (vialen + 1 > IFNAMSIZ) 27904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI exit_error(PARAMETER_PROBLEM, 28004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI "interface name `%s' must be shorter than IFNAMSIZ" 28104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI " (%i)", arg, IFNAMSIZ-1); 28204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 28304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI strcpy(vianame, arg); 28404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI if ((vialen == 0) || (vialen == 1 && vianame[0] == '+')) 28504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask, 0, IFNAMSIZ); 28604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI else if (vianame[vialen - 1] == '+') { 28704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask, 0xFF, vialen - 1); 28804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask + vialen - 1, 0, IFNAMSIZ - vialen + 1); 28904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI /* Don't remove `+' here! -HW */ 29004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } else { 29104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI /* Include nul-terminator in match */ 29204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask, 0xFF, vialen + 1); 29304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask + vialen + 1, 0, IFNAMSIZ - vialen - 1); 29404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI for (i = 0; vianame[i]; i++) { 29504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI if (vianame[i] == ':' || 29604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI vianame[i] == '!' || 29704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI vianame[i] == '*') { 298aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann fprintf(stderr, 299aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann "Warning: weird character in interface" 300aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann " `%s' (No aliases, :, ! or *).\n", 301aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann vianame); 30204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI break; 30304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } 30404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } 30504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } 30604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI} 30704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 308cb25af809a8734c4766b6bfa4cca99596cbf01dbJan Engelhardt#ifndef NO_SHARED_LIBS 30921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardtstatic void *load_extension(const char *search_path, const char *prefix, 31021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt const char *name, bool is_target) 31121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt{ 31221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt const char *dir = search_path, *next; 31321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt void *ptr = NULL; 31421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt struct stat sb; 31521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt char path[256]; 31621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 31721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt do { 31821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt next = strchr(dir, ':'); 31921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt if (next == NULL) 32021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt next = dir + strlen(dir); 32121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt snprintf(path, sizeof(path), "%.*s/libxt_%s.so", 3222c0a0c9eba1d1ab39dcde54bc822d4788f9531fcJan Engelhardt (unsigned int)(next - dir), dir, name); 32321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 32421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt if (dlopen(path, RTLD_NOW) != NULL) { 32521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt /* Found library. If it didn't register itself, 32621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt maybe they specified target as match. */ 32721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt if (is_target) 32821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt ptr = find_target(name, DONT_LOAD); 32921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt else 33021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt ptr = find_match(name, DONT_LOAD, NULL); 33121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt } else if (stat(path, &sb) == 0) { 33221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt fprintf(stderr, "%s: %s\n", path, dlerror()); 33321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt } 33421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 33521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt if (ptr != NULL) 33621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt return ptr; 33721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 33821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt snprintf(path, sizeof(path), "%.*s/%s%s.so", 3392c0a0c9eba1d1ab39dcde54bc822d4788f9531fcJan Engelhardt (unsigned int)(next - dir), dir, prefix, name); 34021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt if (dlopen(path, RTLD_NOW) != NULL) { 34121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt if (is_target) 34221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt ptr = find_target(name, DONT_LOAD); 34321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt else 34421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt ptr = find_match(name, DONT_LOAD, NULL); 34521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt } else if (stat(path, &sb) == 0) { 34621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt fprintf(stderr, "%s: %s\n", path, dlerror()); 34721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt } 34821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 34921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt if (ptr != NULL) 35021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt return ptr; 35121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 35221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt dir = next + 1; 35321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt } while (*next != '\0'); 35421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 35521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt return NULL; 35621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt} 357cb25af809a8734c4766b6bfa4cca99596cbf01dbJan Engelhardt#endif 35821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 3590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_match *find_match(const char *name, enum xt_tryload tryload, 3600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_rule_match **matches) 3610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 3620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_match *ptr; 3630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI const char *icmp6 = "icmp6"; 3640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* This is ugly as hell. Nonetheless, there is no way of changing 3660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI * this without hurting backwards compatibility */ 3670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if ( (strcmp(name,"icmpv6") == 0) || 3680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI (strcmp(name,"ipv6-icmp") == 0) || 3690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI (strcmp(name,"icmp6") == 0) ) 3700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI name = icmp6; 3710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (ptr = xtables_matches; ptr; ptr = ptr->next) { 3730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(name, ptr->name) == 0) { 3740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_match *clone; 3750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* First match of this type: */ 3770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr->m == NULL) 3780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI break; 3790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Second and subsequent clones */ 3810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI clone = fw_malloc(sizeof(struct xtables_match)); 3820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI memcpy(clone, ptr, sizeof(struct xtables_match)); 3830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI clone->mflags = 0; 3840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* This is a clone: */ 3850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI clone->next = clone; 3860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr = clone; 3880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI break; 3890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 3900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 3910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#ifndef NO_SHARED_LIBS 3930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (!ptr && tryload != DONT_LOAD && tryload != DURING_LOAD) { 39421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt ptr = load_extension(lib_dir, afinfo.libprefix, name, false); 395170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI 396170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI if (ptr == NULL && tryload == LOAD_MUST_SUCCEED) 3970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit_error(PARAMETER_PROBLEM, 3980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "Couldn't load match `%s':%s\n", 3990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI name, dlerror()); 4000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 4010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#else 4020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr && !ptr->loaded) { 4030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (tryload != DONT_LOAD) 4040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr->loaded = 1; 4050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI else 4060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr = NULL; 4070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 4080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if(!ptr && (tryload == LOAD_MUST_SUCCEED)) { 4090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit_error(PARAMETER_PROBLEM, 4100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "Couldn't find match `%s'\n", name); 4110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 4120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#endif 4130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr && matches) { 4150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_rule_match **i; 4160d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_rule_match *newentry; 4170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI newentry = fw_malloc(sizeof(struct xtables_rule_match)); 4190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (i = matches; *i; i = &(*i)->next) { 4210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(name, (*i)->match->name) == 0) 4220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI (*i)->completed = 1; 4230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 4240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI newentry->match = ptr; 4250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI newentry->completed = 0; 4260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI newentry->next = NULL; 4270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI *i = newentry; 4280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 4290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return ptr; 4310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 4320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_target *find_target(const char *name, enum xt_tryload tryload) 4350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 4360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_target *ptr; 4370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Standard target? */ 4390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(name, "") == 0 4400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI || strcmp(name, XTC_LABEL_ACCEPT) == 0 4410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI || strcmp(name, XTC_LABEL_DROP) == 0 4420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI || strcmp(name, XTC_LABEL_QUEUE) == 0 4430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI || strcmp(name, XTC_LABEL_RETURN) == 0) 4440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI name = "standard"; 4450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (ptr = xtables_targets; ptr; ptr = ptr->next) { 4470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(name, ptr->name) == 0) 4480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI break; 4490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 4500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#ifndef NO_SHARED_LIBS 4520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (!ptr && tryload != DONT_LOAD && tryload != DURING_LOAD) { 45321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt ptr = load_extension(lib_dir, afinfo.libprefix, name, true); 454170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI 455170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI if (ptr == NULL && tryload == LOAD_MUST_SUCCEED) 4560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit_error(PARAMETER_PROBLEM, 4570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "Couldn't load target `%s':%s\n", 4580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI name, dlerror()); 4590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 4600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#else 4610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr && !ptr->loaded) { 4620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (tryload != DONT_LOAD) 4630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr->loaded = 1; 4640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI else 4650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr = NULL; 4660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 4670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if(!ptr && (tryload == LOAD_MUST_SUCCEED)) { 4680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit_error(PARAMETER_PROBLEM, 4690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "Couldn't find target `%s'\n", name); 4700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 4710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#endif 4720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr) 4740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr->used = 1; 4750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return ptr; 4770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 4780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstatic int compatible_revision(const char *name, u_int8_t revision, int opt) 4800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 4810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xt_get_revision rev; 4820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI socklen_t s = sizeof(rev); 4830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI int max_rev, sockfd; 4840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI sockfd = socket(afinfo.family, SOCK_RAW, IPPROTO_RAW); 4860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (sockfd < 0) { 487df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy if (errno == EPERM) { 488df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy /* revision 0 is always supported. */ 489df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy if (revision != 0) 490df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy fprintf(stderr, "Could not determine whether " 491df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy "revision %u is supported, " 492df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy "assuming it is.\n", 493df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy revision); 494df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy return 1; 495df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy } 4960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "Could not open socket to kernel: %s\n", 4970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI strerror(errno)); 4980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 4990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 501dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt load_xtables_ko(modprobe_program, 1); 5020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI strcpy(rev.name, name); 5040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI rev.revision = revision; 5050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI max_rev = getsockopt(sockfd, afinfo.ipproto, opt, &rev, &s); 5070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (max_rev < 0) { 5080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Definitely don't support this? */ 5090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (errno == ENOENT || errno == EPROTONOSUPPORT) { 5100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI close(sockfd); 5110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return 0; 5120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } else if (errno == ENOPROTOOPT) { 5130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI close(sockfd); 5140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Assume only revision 0 support (old kernel) */ 5150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return (revision == 0); 5160d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } else { 5170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "getsockopt failed strangely: %s\n", 5180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI strerror(errno)); 5190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 5200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI close(sockfd); 5230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return 1; 5240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 5250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstatic int compatible_match_revision(const char *name, u_int8_t revision) 5280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 5290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return compatible_revision(name, revision, afinfo.so_rev_match); 5300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 5310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstatic int compatible_target_revision(const char *name, u_int8_t revision) 5330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 5340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return compatible_revision(name, revision, afinfo.so_rev_target); 5350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 5360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIvoid xtables_register_match(struct xtables_match *me) 5380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 5390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_match **i, *old; 5400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(me->version, program_version) != 0) { 5420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "%s: match `%s' v%s (I'm v%s).\n", 5430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI program_name, me->name, me->version, program_version); 5440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 5450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Revision field stole a char from name. */ 5480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strlen(me->name) >= XT_FUNCTION_MAXNAMELEN-1) { 5490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "%s: target `%s' has invalid name\n", 5500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI program_name, me->name); 5510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 5520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (me->family >= NPROTO) { 5550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, 5560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "%s: BUG: match %s has invalid protocol family\n", 5570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI program_name, me->name); 5580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 5590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* ignore not interested match */ 56223545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt if (me->family != afinfo.family && me->family != AF_UNSPEC) 5630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 5640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI old = find_match(me->name, DURING_LOAD, NULL); 5660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (old) { 56723545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt if (old->revision == me->revision && 56823545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt old->family == me->family) { 5690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, 5700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "%s: match `%s' already registered.\n", 5710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI program_name, me->name); 5720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 5730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Now we have two (or more) options, check compatibility. */ 5760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (compatible_match_revision(old->name, old->revision) 5770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI && old->revision > me->revision) 5780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 5790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 58023545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt /* See if new match can be used. */ 5810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (!compatible_match_revision(me->name, me->revision)) 5820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 5830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 58423545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt /* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */ 58523545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt if (old->revision == me->revision && me->family == AF_UNSPEC) 58623545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt return; 58723545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt 5880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Delete old one. */ 5890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (i = &xtables_matches; *i!=old; i = &(*i)->next); 5900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI *i = old->next; 5910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (me->size != XT_ALIGN(me->size)) { 5940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "%s: match `%s' has invalid size %u.\n", 5950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI program_name, me->name, (unsigned int)me->size); 5960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 5970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Append to list. */ 6000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (i = &xtables_matches; *i; i = &(*i)->next); 6010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->next = NULL; 6020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI *i = me; 6030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->m = NULL; 6050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->mflags = 0; 6060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 6070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIvoid xtables_register_target(struct xtables_target *me) 6090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 6100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_target *old; 6110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(me->version, program_version) != 0) { 6130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "%s: target `%s' v%s (I'm v%s).\n", 6140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI program_name, me->name, me->version, program_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", 6210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 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", 6280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 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 6360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI old = find_target(me->name, 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", 6440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 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", 6680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 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 */ 813bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (!strtonum(p, NULL, &onebyte, 0, 255)) 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'; 824bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (!strtonum(p, NULL, &onebyte, 0, 255)) 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 */ 832bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (!strtonum(p, NULL, &onebyte, 0, 255)) 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; 878bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addr = fw_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) { 895bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = fw_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; 920bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (string_to_number(mask, 0, 32, &bits) == -1) 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 101408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt a = k->s6_addr32[0]; 101508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt b = k->s6_addr32[1]; 101608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt c = k->s6_addr32[2]; 101708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt d = 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 */ 1091bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addr = fw_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) { 1117bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = fw_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; 1141bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (string_to_number(mask, 0, 128, &bits) == -1) 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