xtables.c revision 30290aea009cf3fd76f27336fb4370be3467c4da
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> 354e41854423b529d3107c23b85434d50a75d08057Jan Engelhardt#include <limits.h> /* INT_MAX in ip_tables.h/ip6_tables.h */ 3677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt#include <linux/netfilter_ipv4/ip_tables.h> 3777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt#include <linux/netfilter_ipv6/ip6_tables.h> 38ef18e8147903885708d1c264904129af4fb636d6Jan Engelhardt#include <libiptc/libxtc.h> 393dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 405a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#ifndef NO_SHARED_LIBS 415a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#include <dlfcn.h> 425a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#endif 43c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#ifndef IPT_SO_GET_REVISION_MATCH /* Old kernel source. */ 44c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt# define IPT_SO_GET_REVISION_MATCH (IPT_BASE_CTL + 2) 45c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt# define IPT_SO_GET_REVISION_TARGET (IPT_BASE_CTL + 3) 46c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#endif 47c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#ifndef IP6T_SO_GET_REVISION_MATCH /* Old kernel source. */ 48c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt# define IP6T_SO_GET_REVISION_MATCH 68 49c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt# define IP6T_SO_GET_REVISION_TARGET 69 50c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#endif 5170581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim#include <getopt.h> 52c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt 535a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger 540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#define NPROTO 255 550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 560b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#ifndef PROC_SYS_MODPROBE 570b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe" 580b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#endif 590b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 608b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salimvoid basic_exit_err(enum xtables_exittype status, const char *msg, ...) __attribute__((noreturn, format(printf,2,3))); 618b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim 6240a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salimstruct xtables_globals *xt_params = NULL; 6340a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim 648b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salimvoid basic_exit_err(enum xtables_exittype status, const char *msg, ...) 6540a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim{ 6640a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim va_list args; 6740a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim 6840a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim va_start(args, msg); 6940a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim fprintf(stderr, "%s v%s: ", xt_params->program_name, xt_params->program_version); 7040a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim vfprintf(stderr, msg, args); 7140a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim va_end(args); 7240a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim fprintf(stderr, "\n"); 7340a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim exit(status); 7440a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim} 7540a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim 768b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim 77139b3fe4bd5121501e60fe07963ea527d7f0bd36Jamal Hadi Salimvoid xtables_free_opts(int reset_offset) 7884c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim{ 79139b3fe4bd5121501e60fe07963ea527d7f0bd36Jamal Hadi Salim if (xt_params->opts != xt_params->orig_opts) { 80139b3fe4bd5121501e60fe07963ea527d7f0bd36Jamal Hadi Salim free(xt_params->opts); 81139b3fe4bd5121501e60fe07963ea527d7f0bd36Jamal Hadi Salim xt_params->opts = xt_params->orig_opts; 8284c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim if (reset_offset) 8384c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim xt_params->option_offset = 0; 8484c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim } 8584c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim} 8684c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim 8770581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salimstruct option *xtables_merge_options(struct option *oldopts, 8870581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim const struct option *newopts, 8970581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim unsigned int *option_offset) 9070581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim{ 9170581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim unsigned int num_old, num_new, i; 9270581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim struct option *merge; 9370581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim 9470581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim if (newopts == NULL) 9570581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim return oldopts; 9670581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim 9770581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim for (num_old = 0; oldopts[num_old].name; num_old++) ; 9870581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim for (num_new = 0; newopts[num_new].name; num_new++) ; 9970581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim 100bddcb92d1f0f76d21c4469b1667c8199c9fab126Jan Engelhardt xt_params->option_offset += 256; 10170581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim *option_offset = xt_params->option_offset; 10270581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim 10370581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim merge = malloc(sizeof(struct option) * (num_new + num_old + 1)); 10470581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim if (merge == NULL) 10570581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim return NULL; 10670581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim memcpy(merge, oldopts, num_old * sizeof(struct option)); 10770581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim xtables_free_opts(0); /* Release any old options merged */ 10870581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim for (i = 0; i < num_new; i++) { 10970581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim merge[num_old + i] = newopts[i]; 11070581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim merge[num_old + i].val += *option_offset; 11170581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim } 11270581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim memset(merge + num_old + num_new, 0, sizeof(struct option)); 11370581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim 11470581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim return merge; 11570581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim} 11670581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim 117853322131026d62df3f8d77d67e5c63be496303cJamal Hadi Salimvoid xtables_set_revision(char *name, u_int8_t revision) 118853322131026d62df3f8d77d67e5c63be496303cJamal Hadi Salim{ 119853322131026d62df3f8d77d67e5c63be496303cJamal Hadi Salim /* Old kernel sources don't have ".revision" field, 120853322131026d62df3f8d77d67e5c63be496303cJamal Hadi Salim * but we stole a byte from name. */ 121853322131026d62df3f8d77d67e5c63be496303cJamal Hadi Salim name[XT_FUNCTION_MAXNAMELEN - 2] = '\0'; 122853322131026d62df3f8d77d67e5c63be496303cJamal Hadi Salim name[XT_FUNCTION_MAXNAMELEN - 1] = revision; 123853322131026d62df3f8d77d67e5c63be496303cJamal Hadi Salim} 124853322131026d62df3f8d77d67e5c63be496303cJamal Hadi Salim 125dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt/** 12677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * xtables_afinfo - protocol family dependent information 12777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * @kmod: kernel module basename (e.g. "ip_tables") 12877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * @libprefix: prefix of .so library name (e.g. "libipt_") 12977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * @family: nfproto family 13077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * @ipproto: used by setsockopt (e.g. IPPROTO_IP) 13177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * @so_rev_match: optname to check revision support of match 13277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * @so_rev_target: optname to check revision support of target 13377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt */ 13477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtstruct xtables_afinfo { 13577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt const char *kmod; 13677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt const char *libprefix; 13777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt uint8_t family; 13877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt uint8_t ipproto; 13977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt int so_rev_match; 14077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt int so_rev_target; 14177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt}; 14277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt 14377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtstatic const struct xtables_afinfo afinfo_ipv4 = { 14477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .kmod = "ip_tables", 14577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .libprefix = "libipt_", 14677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .family = NFPROTO_IPV4, 14777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .ipproto = IPPROTO_IP, 14877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .so_rev_match = IPT_SO_GET_REVISION_MATCH, 14977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .so_rev_target = IPT_SO_GET_REVISION_TARGET, 15077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt}; 15177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt 15277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtstatic const struct xtables_afinfo afinfo_ipv6 = { 15377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .kmod = "ip6_tables", 15477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .libprefix = "libip6t_", 15577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .family = NFPROTO_IPV6, 15677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .ipproto = IPPROTO_IPV6, 15777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .so_rev_match = IP6T_SO_GET_REVISION_MATCH, 15877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .so_rev_target = IP6T_SO_GET_REVISION_TARGET, 15977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt}; 16077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt 16177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtstatic const struct xtables_afinfo *afinfo; 16277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt 16339bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt/* Search path for Xtables .so files */ 16439bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardtstatic const char *xtables_libdir; 1650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 1660b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI/* the path to command to load kernel module */ 167c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtconst char *xtables_modprobe_program; 1680b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 1690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI/* Keeping track of external matches and targets: linked lists. */ 1700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_match *xtables_matches; 1710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_target *xtables_targets; 1720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 17339bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardtvoid xtables_init(void) 17439bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt{ 17539bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt xtables_libdir = getenv("XTABLES_LIBDIR"); 17639bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt if (xtables_libdir != NULL) 17739bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt return; 17839bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt xtables_libdir = getenv("IPTABLES_LIB_DIR"); 17939bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt if (xtables_libdir != NULL) { 18039bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt fprintf(stderr, "IPTABLES_LIB_DIR is deprecated, " 18139bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt "use XTABLES_LIBDIR.\n"); 18239bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt return; 18339bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt } 184ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt /* 185ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt * Well yes, IP6TABLES_LIB_DIR is of lower priority over 186ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt * IPTABLES_LIB_DIR since this moved to libxtables; I think that is ok 187ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt * for these env vars are deprecated anyhow, and in light of the 188ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt * (shared) libxt_*.so files, makes less sense to have 189ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt * IPTABLES_LIB_DIR != IP6TABLES_LIB_DIR. 190ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt */ 191ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt xtables_libdir = getenv("IP6TABLES_LIB_DIR"); 192ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt if (xtables_libdir != NULL) { 193ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt fprintf(stderr, "IP6TABLES_LIB_DIR is deprecated, " 194ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt "use XTABLES_LIBDIR.\n"); 195ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt return; 196ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt } 19739bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt xtables_libdir = XTABLES_LIBDIR; 19839bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt} 19939bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt 20077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtvoid xtables_set_nfproto(uint8_t nfproto) 20177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt{ 20277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt switch (nfproto) { 20377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt case NFPROTO_IPV4: 20477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt afinfo = &afinfo_ipv4; 20577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt break; 20677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt case NFPROTO_IPV6: 20777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt afinfo = &afinfo_ipv6; 20877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt break; 20977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt default: 21077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt fprintf(stderr, "libxtables: unhandled NFPROTO in %s\n", 21177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt __func__); 21277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt } 21377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt} 21477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt 215630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt/** 2167e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * xtables_set_params - set the global parameters used by xtables 2177e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * @xtp: input xtables_globals structure 2187e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * 2197e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * The app is expected to pass a valid xtables_globals data-filled 2207e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * with proper values 2217e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * @xtp cannot be NULL 2227e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * 2237e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * Returns -1 on failure to set and 0 on success 2247e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim */ 2257e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salimint xtables_set_params(struct xtables_globals *xtp) 2267e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim{ 2277e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim if (!xtp) { 2287e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim fprintf(stderr, "%s: Illegal global params\n",__func__); 2297e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim return -1; 2307e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim } 2317e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim 2327e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim xt_params = xtp; 2337e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim 2347e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim if (!xt_params->exit_err) 2357e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim xt_params->exit_err = basic_exit_err; 2367e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim 2377e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim return 0; 2387e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim} 2397e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim 2407e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salimint xtables_init_all(struct xtables_globals *xtp, uint8_t nfproto) 2417e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim{ 2427e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim xtables_init(); 2437e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim xtables_set_nfproto(nfproto); 2447e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim return xtables_set_params(xtp); 2457e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim} 2467e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim 2477e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim/** 248630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt * xtables_*alloc - wrappers that exit on failure 249630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt */ 250630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardtvoid *xtables_calloc(size_t count, size_t size) 2513dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI{ 2523dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI void *p; 2533dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 2543dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI if ((p = calloc(count, size)) == NULL) { 2553dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI perror("ip[6]tables: calloc failed"); 2563dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI exit(1); 2573dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI } 2583dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 2593dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI return p; 2603dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI} 2613dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 262630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardtvoid *xtables_malloc(size_t size) 2633dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI{ 2643dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI void *p; 2653dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 2663dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI if ((p = malloc(size)) == NULL) { 2673dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI perror("ip[6]tables: malloc failed"); 2683dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI exit(1); 2693dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI } 2703dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 2713dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI return p; 2723dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI} 2730b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 274332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowvoid *xtables_realloc(void *ptr, size_t size) 275332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow{ 276332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow void *p; 277332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 278332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if ((p = realloc(ptr, size)) == NULL) { 279332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow perror("ip[6]tables: realloc failed"); 280332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow exit(1); 281332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 282332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 283332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow return p; 284332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow} 285332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 2860b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAIstatic char *get_modprobe(void) 2870b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI{ 2880b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI int procfile; 2890b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI char *ret; 2900b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 2910b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#define PROCFILE_BUFSIZ 1024 2920b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI procfile = open(PROC_SYS_MODPROBE, O_RDONLY); 2930b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (procfile < 0) 2940b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return NULL; 2950b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 2960b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI ret = (char *) malloc(PROCFILE_BUFSIZ); 2970b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (ret) { 2980b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI memset(ret, 0, PROCFILE_BUFSIZ); 2990b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI switch (read(procfile, ret, PROCFILE_BUFSIZ)) { 3000b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI case -1: goto fail; 3010b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI case PROCFILE_BUFSIZ: goto fail; /* Partial read. Wierd */ 3020b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 3030b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (ret[strlen(ret)-1]=='\n') 3040b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI ret[strlen(ret)-1]=0; 3050b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI close(procfile); 3060b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return ret; 3070b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 3080b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI fail: 3090b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI free(ret); 3100b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI close(procfile); 3110b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return NULL; 3120b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI} 3130b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 314c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtint xtables_insmod(const char *modname, const char *modprobe, bool quiet) 3150b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI{ 3160b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI char *buf = NULL; 3170b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI char *argv[4]; 3180b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI int status; 3190b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 3200b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI /* If they don't explicitly set it, read out of kernel */ 3210b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (!modprobe) { 3220b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI buf = get_modprobe(); 3230b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (!buf) 3240b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return -1; 3250b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI modprobe = buf; 3260b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 3270b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 328c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt /* 329c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt * Need to flush the buffer, or the child may output it again 330c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt * when switching the program thru execv. 331c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt */ 332c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt fflush(stdout); 333c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt 33494aa2ea67d7b8a669e8541f094661a1dc89722a3Jan Engelhardt switch (vfork()) { 3350b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI case 0: 3360b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[0] = (char *)modprobe; 3370b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[1] = (char *)modname; 3380b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (quiet) { 3390b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[2] = "-q"; 3400b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[3] = NULL; 3410b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } else { 3420b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[2] = NULL; 3430b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[3] = NULL; 3440b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 3450b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI execv(argv[0], argv); 3460b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 3470b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI /* not usually reached */ 3480b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI exit(1); 3490b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI case -1: 3500b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return -1; 3510b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 3520b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI default: /* parent */ 3530b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI wait(&status); 3540b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 3550b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 3560b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI free(buf); 3570b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (WIFEXITED(status) && WEXITSTATUS(status) == 0) 3580b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return 0; 3590b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return -1; 3600b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI} 3610b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 362c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtint xtables_load_ko(const char *modprobe, bool quiet) 3630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 364c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardt static bool loaded = false; 3650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI static int ret = -1; 3660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (!loaded) { 36877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt ret = xtables_insmod(afinfo->kmod, modprobe, quiet); 3690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI loaded = (ret == 0); 3700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 3710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return ret; 3730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 3740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3755f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt/** 3765f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * xtables_strtou{i,l} - string to number conversion 3775f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @s: input string 3785f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @end: like strtoul's "end" pointer 3795f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @value: pointer for result 3805f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @min: minimum accepted value 3815f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @max: maximum accepted value 3825f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * 3835f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * If @end is NULL, we assume the caller wants a "strict strtoul", and hence 3845f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * "15a" is rejected. 3855f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * In either case, the value obtained is compared for min-max compliance. 3865f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * Base is always 0, i.e. autodetect depending on @s. 387cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt * 3885f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * Returns true/false whether number was accepted. On failure, *value has 3895f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * undefined contents. 390cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt */ 3915f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardtbool xtables_strtoul(const char *s, char **end, unsigned long *value, 3925f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt unsigned long min, unsigned long max) 393cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt{ 394cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt unsigned long v; 395cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt char *my_end; 396cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 397cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt errno = 0; 398cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt v = strtoul(s, &my_end, 0); 399cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 400cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (my_end == s) 401cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return false; 402cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (end != NULL) 403cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt *end = my_end; 404cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 405cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (errno != ERANGE && min <= v && (max == 0 || v <= max)) { 406cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (value != NULL) 407cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt *value = v; 408cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (end == NULL) 409cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return *my_end == '\0'; 410cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return true; 411cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt } 412cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 413cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return false; 414cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt} 415cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 4165f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardtbool xtables_strtoui(const char *s, char **end, unsigned int *value, 4175f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt unsigned int min, unsigned int max) 418cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt{ 419cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt unsigned long v; 420cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt bool ret; 421cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 4225f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt ret = xtables_strtoul(s, end, &v, min, max); 423cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (value != NULL) 424cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt *value = v; 425cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return ret; 426cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt} 427cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 428aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardtint xtables_service_to_port(const char *name, const char *proto) 42904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{ 43004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI struct servent *service; 43104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 43204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI if ((service = getservbyname(name, proto)) != NULL) 43304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI return ntohs((unsigned short) service->s_port); 43404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 43504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI return -1; 43604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI} 43704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 438aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardtu_int16_t xtables_parse_port(const char *port, const char *proto) 43904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{ 4407a236f4cc685a420c1a782a5db614a93baf37ccfJan Engelhardt unsigned int portnum; 44104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 4425f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt if (xtables_strtoui(port, NULL, &portnum, 0, UINT16_MAX) || 443aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardt (portnum = xtables_service_to_port(port, proto)) != (unsigned)-1) 444213e185afbb298e6708881e4c2adffdc47a8b6daJan Engelhardt return portnum; 44504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 4468b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 44704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI "invalid port/service `%s' specified", port); 44804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI} 44904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 450aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardtvoid xtables_parse_interface(const char *arg, char *vianame, 451aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardt unsigned char *mask) 45204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{ 453fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt unsigned int vialen = strlen(arg); 45404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI unsigned int i; 45504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 45604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask, 0, IFNAMSIZ); 45704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(vianame, 0, IFNAMSIZ); 45804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 45904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI if (vialen + 1 > IFNAMSIZ) 4608b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 46104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI "interface name `%s' must be shorter than IFNAMSIZ" 46204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI " (%i)", arg, IFNAMSIZ-1); 46304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 46404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI strcpy(vianame, arg); 465fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt if (vialen == 0) 46604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask, 0, IFNAMSIZ); 46704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI else if (vianame[vialen - 1] == '+') { 46804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask, 0xFF, vialen - 1); 46904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask + vialen - 1, 0, IFNAMSIZ - vialen + 1); 47004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI /* Don't remove `+' here! -HW */ 47104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } else { 47204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI /* Include nul-terminator in match */ 47304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask, 0xFF, vialen + 1); 47404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask + vialen + 1, 0, IFNAMSIZ - vialen - 1); 47504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI for (i = 0; vianame[i]; i++) { 476fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt if (vianame[i] == '/' || 477fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt vianame[i] == ' ') { 478aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann fprintf(stderr, 479aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann "Warning: weird character in interface" 480fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt " `%s' ('/' and ' ' are not allowed by the kernel).\n", 481aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann vianame); 48204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI break; 48304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } 48404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } 48504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } 48604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI} 48704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 488cb25af809a8734c4766b6bfa4cca99596cbf01dbJan Engelhardt#ifndef NO_SHARED_LIBS 48921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardtstatic void *load_extension(const char *search_path, const char *prefix, 49021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt const char *name, bool is_target) 49121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt{ 49221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt const char *dir = search_path, *next; 49321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt void *ptr = NULL; 49421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt struct stat sb; 49521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt char path[256]; 49621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 49721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt do { 49821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt next = strchr(dir, ':'); 49921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt if (next == NULL) 50021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt next = dir + strlen(dir); 50121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt snprintf(path, sizeof(path), "%.*s/libxt_%s.so", 5022c0a0c9eba1d1ab39dcde54bc822d4788f9531fcJan Engelhardt (unsigned int)(next - dir), dir, name); 50321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 50421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt if (dlopen(path, RTLD_NOW) != NULL) { 50521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt /* Found library. If it didn't register itself, 50621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt maybe they specified target as match. */ 50721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt if (is_target) 5082338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt ptr = xtables_find_target(name, XTF_DONT_LOAD); 50921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt else 5102338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt ptr = xtables_find_match(name, 5112338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt XTF_DONT_LOAD, NULL); 51221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt } else if (stat(path, &sb) == 0) { 51321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt fprintf(stderr, "%s: %s\n", path, dlerror()); 51421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt } 51521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 51621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt if (ptr != NULL) 51721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt return ptr; 51821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 51921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt snprintf(path, sizeof(path), "%.*s/%s%s.so", 5202c0a0c9eba1d1ab39dcde54bc822d4788f9531fcJan Engelhardt (unsigned int)(next - dir), dir, prefix, name); 52121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt if (dlopen(path, RTLD_NOW) != NULL) { 52221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt if (is_target) 5232338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt ptr = xtables_find_target(name, XTF_DONT_LOAD); 52421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt else 5252338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt ptr = xtables_find_match(name, 5262338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt XTF_DONT_LOAD, NULL); 52721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt } else if (stat(path, &sb) == 0) { 52821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt fprintf(stderr, "%s: %s\n", path, dlerror()); 52921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt } 53021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 53121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt if (ptr != NULL) 53221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt return ptr; 53321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 53421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt dir = next + 1; 53521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt } while (*next != '\0'); 53621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 53721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt return NULL; 53821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt} 539cb25af809a8734c4766b6bfa4cca99596cbf01dbJan Engelhardt#endif 54021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 5412338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtstruct xtables_match * 5422338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtxtables_find_match(const char *name, enum xtables_tryload tryload, 5432338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt struct xtables_rule_match **matches) 5440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 5450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_match *ptr; 5460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI const char *icmp6 = "icmp6"; 5470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 54821d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt if (strlen(name) > XT_FUNCTION_MAXNAMELEN - 1) 54921d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt xtables_error(PARAMETER_PROBLEM, 55021d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt "Invalid match name \"%s\" (%u chars max)", 55121d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt name, XT_FUNCTION_MAXNAMELEN - 1); 55221d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt 5530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* This is ugly as hell. Nonetheless, there is no way of changing 5540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI * this without hurting backwards compatibility */ 5550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if ( (strcmp(name,"icmpv6") == 0) || 5560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI (strcmp(name,"ipv6-icmp") == 0) || 5570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI (strcmp(name,"icmp6") == 0) ) 5580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI name = icmp6; 5590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (ptr = xtables_matches; ptr; ptr = ptr->next) { 5610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(name, ptr->name) == 0) { 5620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_match *clone; 5630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* First match of this type: */ 5650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr->m == NULL) 5660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI break; 5670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Second and subsequent clones */ 569630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt clone = xtables_malloc(sizeof(struct xtables_match)); 5700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI memcpy(clone, ptr, sizeof(struct xtables_match)); 5710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI clone->mflags = 0; 5720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* This is a clone: */ 5730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI clone->next = clone; 5740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr = clone; 5760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI break; 5770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#ifndef NO_SHARED_LIBS 5812338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) { 58277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt ptr = load_extension(xtables_libdir, afinfo->libprefix, 58339bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt name, false); 584170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI 5852338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) 5868b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 5870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "Couldn't load match `%s':%s\n", 5880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI name, dlerror()); 5890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#else 5910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr && !ptr->loaded) { 5922338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if (tryload != XTF_DONT_LOAD) 5930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr->loaded = 1; 5940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI else 5950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr = NULL; 5960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5972338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if(!ptr && (tryload == XTF_LOAD_MUST_SUCCEED)) { 5988b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 5990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "Couldn't find match `%s'\n", name); 6000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#endif 6020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr && matches) { 6040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_rule_match **i; 6050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_rule_match *newentry; 6060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 607630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt newentry = xtables_malloc(sizeof(struct xtables_rule_match)); 6080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (i = matches; *i; i = &(*i)->next) { 6100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(name, (*i)->match->name) == 0) 6112338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt (*i)->completed = true; 6120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI newentry->match = ptr; 6142338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt newentry->completed = false; 6150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI newentry->next = NULL; 6160d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI *i = newentry; 6170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return ptr; 6200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 6210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6222338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtstruct xtables_target * 6232338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtxtables_find_target(const char *name, enum xtables_tryload tryload) 6240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 6250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_target *ptr; 6260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Standard target? */ 6280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(name, "") == 0 6290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI || strcmp(name, XTC_LABEL_ACCEPT) == 0 6300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI || strcmp(name, XTC_LABEL_DROP) == 0 6310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI || strcmp(name, XTC_LABEL_QUEUE) == 0 6320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI || strcmp(name, XTC_LABEL_RETURN) == 0) 6330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI name = "standard"; 6340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (ptr = xtables_targets; ptr; ptr = ptr->next) { 6360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(name, ptr->name) == 0) 6370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI break; 6380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#ifndef NO_SHARED_LIBS 6412338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) { 64277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt ptr = load_extension(xtables_libdir, afinfo->libprefix, 64339bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt name, true); 644170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI 6452338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) 6468b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 6470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "Couldn't load target `%s':%s\n", 6480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI name, dlerror()); 6490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#else 6510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr && !ptr->loaded) { 6522338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if (tryload != XTF_DONT_LOAD) 6530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr->loaded = 1; 6540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI else 6550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr = NULL; 6560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 657854d2d9bd7556cfd8a676b0bc18dc059a9a2dd25Peter Volkov if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) { 6588b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 6590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "Couldn't find target `%s'\n", name); 6600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#endif 6620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr) 6640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr->used = 1; 6650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return ptr; 6670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 6680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstatic int compatible_revision(const char *name, u_int8_t revision, int opt) 6700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 6710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xt_get_revision rev; 6720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI socklen_t s = sizeof(rev); 6730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI int max_rev, sockfd; 6740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 67577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt sockfd = socket(afinfo->family, SOCK_RAW, IPPROTO_RAW); 6760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (sockfd < 0) { 677df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy if (errno == EPERM) { 678df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy /* revision 0 is always supported. */ 679df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy if (revision != 0) 680df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy fprintf(stderr, "Could not determine whether " 681df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy "revision %u is supported, " 682df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy "assuming it is.\n", 683df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy revision); 684df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy return 1; 685df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy } 6860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "Could not open socket to kernel: %s\n", 6870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI strerror(errno)); 6880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 6890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 691c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardt xtables_load_ko(xtables_modprobe_program, true); 6920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI strcpy(rev.name, name); 6940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI rev.revision = revision; 6950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 69677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt max_rev = getsockopt(sockfd, afinfo->ipproto, opt, &rev, &s); 6970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (max_rev < 0) { 6980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Definitely don't support this? */ 6990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (errno == ENOENT || errno == EPROTONOSUPPORT) { 7000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI close(sockfd); 7010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return 0; 7020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } else if (errno == ENOPROTOOPT) { 7030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI close(sockfd); 7040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Assume only revision 0 support (old kernel) */ 7050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return (revision == 0); 7060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } else { 7070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "getsockopt failed strangely: %s\n", 7080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI strerror(errno)); 7090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 7100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 7110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 7120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI close(sockfd); 7130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return 1; 7140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 7150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7160d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstatic int compatible_match_revision(const char *name, u_int8_t revision) 7180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 71977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt return compatible_revision(name, revision, afinfo->so_rev_match); 7200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 7210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstatic int compatible_target_revision(const char *name, u_int8_t revision) 7230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 72477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt return compatible_revision(name, revision, afinfo->so_rev_target); 7250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 7260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIvoid xtables_register_match(struct xtables_match *me) 7280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 7290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_match **i, *old; 7300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 731c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt if (me->version == NULL) { 732c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt fprintf(stderr, "%s: match %s<%u> is missing a version\n", 733c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt xt_params->program_name, me->name, me->revision); 734c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt exit(1); 735c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt } 736dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt if (strcmp(me->version, XTABLES_VERSION) != 0) { 737dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt fprintf(stderr, "%s: match \"%s\" has version \"%s\", " 738dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt "but \"%s\" is required.\n", 7395dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name, 740dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt me->version, XTABLES_VERSION); 7410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 7420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 7430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Revision field stole a char from name. */ 7450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strlen(me->name) >= XT_FUNCTION_MAXNAMELEN-1) { 7460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "%s: target `%s' has invalid name\n", 7475dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name); 7480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 7490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 7500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (me->family >= NPROTO) { 7520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, 7530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "%s: BUG: match %s has invalid protocol family\n", 7545dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name); 7550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 7560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 7570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* ignore not interested match */ 75977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt if (me->family != afinfo->family && me->family != AF_UNSPEC) 7600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 7610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7622338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt old = xtables_find_match(me->name, XTF_DURING_LOAD, NULL); 7630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (old) { 76423545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt if (old->revision == me->revision && 76523545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt old->family == me->family) { 7660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, 7670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "%s: match `%s' already registered.\n", 7685dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name); 7690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 7700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 7710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Now we have two (or more) options, check compatibility. */ 7730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (compatible_match_revision(old->name, old->revision) 7740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI && old->revision > me->revision) 7750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 7760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 77723545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt /* See if new match can be used. */ 7780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (!compatible_match_revision(me->name, me->revision)) 7790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 7800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 78123545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt /* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */ 78223545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt if (old->revision == me->revision && me->family == AF_UNSPEC) 78323545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt return; 78423545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt 7850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Delete old one. */ 7860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (i = &xtables_matches; *i!=old; i = &(*i)->next); 7870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI *i = old->next; 7880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 7890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (me->size != XT_ALIGN(me->size)) { 7910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "%s: match `%s' has invalid size %u.\n", 7925dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name, 7935dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim (unsigned int)me->size); 7940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 7950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 7960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Append to list. */ 7980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (i = &xtables_matches; *i; i = &(*i)->next); 7990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->next = NULL; 8000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI *i = me; 8010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->m = NULL; 8030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->mflags = 0; 8040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 8050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8069a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardtvoid xtables_register_matches(struct xtables_match *match, unsigned int n) 8079a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt{ 8089a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt do { 8099a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt xtables_register_match(&match[--n]); 8109a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt } while (n > 0); 8119a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt} 8129a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt 8130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIvoid xtables_register_target(struct xtables_target *me) 8140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 8150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_target *old; 8160d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 817c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt if (me->version == NULL) { 818c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt fprintf(stderr, "%s: target %s<%u> is missing a version\n", 819c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt xt_params->program_name, me->name, me->revision); 820c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt exit(1); 821c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt } 822dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt if (strcmp(me->version, XTABLES_VERSION) != 0) { 823dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt fprintf(stderr, "%s: target \"%s\" has version \"%s\", " 824dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt "but \"%s\" is required.\n", 8255dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name, 826dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt me->version, XTABLES_VERSION); 8270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 8280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 8290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Revision field stole a char from name. */ 8310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strlen(me->name) >= XT_FUNCTION_MAXNAMELEN-1) { 8320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "%s: target `%s' has invalid name\n", 8335dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name); 8340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 8350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 8360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (me->family >= NPROTO) { 8380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, 8390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "%s: BUG: target %s has invalid protocol family\n", 8405dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name); 8410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 8420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 8430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* ignore not interested target */ 84577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt if (me->family != afinfo->family && me->family != AF_UNSPEC) 8460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 8470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8482338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt old = xtables_find_target(me->name, XTF_DURING_LOAD); 8490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (old) { 8500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_target **i; 8510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 85223545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt if (old->revision == me->revision && 85323545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt old->family == me->family) { 8540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, 8550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "%s: target `%s' already registered.\n", 8565dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name); 8570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 8580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 8590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Now we have two (or more) options, check compatibility. */ 8610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (compatible_target_revision(old->name, old->revision) 8620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI && old->revision > me->revision) 8630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 8640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 86523545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt /* See if new target can be used. */ 8660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (!compatible_target_revision(me->name, me->revision)) 8670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 8680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 86923545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt /* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */ 87023545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt if (old->revision == me->revision && me->family == AF_UNSPEC) 87123545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt return; 87223545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt 8730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Delete old one. */ 8740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (i = &xtables_targets; *i!=old; i = &(*i)->next); 8750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI *i = old->next; 8760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 8770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (me->size != XT_ALIGN(me->size)) { 8790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "%s: target `%s' has invalid size %u.\n", 8805dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name, 8815dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim (unsigned int)me->size); 8820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 8830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 8840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Prepend to list. */ 8860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->next = xtables_targets; 8870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI xtables_targets = me; 8880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->t = NULL; 8890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->tflags = 0; 8900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 891aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt 8929a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardtvoid xtables_register_targets(struct xtables_target *target, unsigned int n) 8939a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt{ 8949a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt do { 8959a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt xtables_register_target(&target[--n]); 8969a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt } while (n > 0); 8979a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt} 8989a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt 899a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt/** 900a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * xtables_param_act - act on condition 901a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @status: a constant from enum xtables_exittype 902a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * 903a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_ONLY_ONCE: print error message that option may only be used once. 904a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1: module name (e.g. "mark") 905a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2(...): option in conflict (e.g. "--mark") 906a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3(...): condition to match on (see extensions/ for examples) 907a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * 908a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_NO_INVERT: option does not support inversion 909a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1: module name 910a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2: option in conflict 911a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3: condition to match on 912a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * 913a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_BAD_VALUE: bad value for option 914a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1: module name 915a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2: option with which the problem occured (e.g. "--mark") 916a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3: string the user passed in (e.g. "99999999999999") 917a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * 918a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_ONE_ACTION: two mutually exclusive actions have been specified 919a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1: module name 920a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * 921a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * Displays an error message and exits the program. 922a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt */ 923a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardtvoid xtables_param_act(unsigned int status, const char *p1, ...) 924aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt{ 925aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt const char *p2, *p3; 926aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt va_list args; 927aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt bool b; 928aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt 929aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt va_start(args, p1); 930aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt 931aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt switch (status) { 932a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt case XTF_ONLY_ONCE: 933aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt p2 = va_arg(args, const char *); 934aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt b = va_arg(args, unsigned int); 935aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt if (!b) 936aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt return; 9378b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 938aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt "%s: \"%s\" option may only be specified once", 939aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt p1, p2); 940aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt break; 941a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt case XTF_NO_INVERT: 942aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt p2 = va_arg(args, const char *); 943aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt b = va_arg(args, unsigned int); 944aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt if (!b) 945aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt return; 9468b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 947aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt "%s: \"%s\" option cannot be inverted", p1, p2); 948aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt break; 949a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt case XTF_BAD_VALUE: 950aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt p2 = va_arg(args, const char *); 951aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt p3 = va_arg(args, const char *); 9528b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 953aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt "%s: Bad value for \"%s\" option: \"%s\"", 954aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt p1, p2, p3); 955aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt break; 956a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt case XTF_ONE_ACTION: 957aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt b = va_arg(args, unsigned int); 958aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt if (!b) 959aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt return; 9608b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 961aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt "%s: At most one action is possible", p1); 962aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt break; 963aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt default: 9648b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(status, p1, args); 965aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt break; 966aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt } 967aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt 968aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt va_end(args); 969aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt} 97008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 971e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ipaddr_to_numeric(const struct in_addr *addrp) 97208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 97308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt static char buf[20]; 97408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt const unsigned char *bytep = (const void *)&addrp->s_addr; 97508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 97608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt sprintf(buf, "%u.%u.%u.%u", bytep[0], bytep[1], bytep[2], bytep[3]); 97708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return buf; 97808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 97908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 98008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ipaddr_to_host(const struct in_addr *addr) 98108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 98208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt struct hostent *host; 98308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 98408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt host = gethostbyaddr(addr, sizeof(struct in_addr), AF_INET); 98508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if (host == NULL) 98608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return NULL; 98708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 98808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return host->h_name; 98908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 99008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 99108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ipaddr_to_network(const struct in_addr *addr) 99208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 99308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt struct netent *net; 99408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 99508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if ((net = getnetbyaddr(ntohl(addr->s_addr), AF_INET)) != NULL) 99608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return net->n_name; 99708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 99808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return NULL; 99908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 100008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 1001e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ipaddr_to_anyname(const struct in_addr *addr) 100208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 100308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt const char *name; 100408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 100508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if ((name = ipaddr_to_host(addr)) != NULL || 100608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt (name = ipaddr_to_network(addr)) != NULL) 100708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return name; 100808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 1009e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt return xtables_ipaddr_to_numeric(addr); 101008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 101108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 1012e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ipmask_to_numeric(const struct in_addr *mask) 101308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 101408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt static char buf[20]; 101508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt uint32_t maskaddr, bits; 101608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt int i; 101708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 101808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt maskaddr = ntohl(mask->s_addr); 101908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 102008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if (maskaddr == 0xFFFFFFFFL) 102108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt /* we don't want to see "/32" */ 102208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return ""; 102308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 102408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt i = 32; 102508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt bits = 0xFFFFFFFEL; 102608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt while (--i >= 0 && maskaddr != bits) 102708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt bits <<= 1; 102808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if (i >= 0) 102908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt sprintf(buf, "/%d", i); 103008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt else 103108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt /* mask was not a decent combination of 1's and 0's */ 1032e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt sprintf(buf, "/%s", xtables_ipaddr_to_numeric(mask)); 103308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 103408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return buf; 103508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 103608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 1037bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *__numeric_to_ipaddr(const char *dotted, bool is_mask) 1038bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1039bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt static struct in_addr addr; 1040bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned char *addrp; 1041bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned int onebyte; 1042bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt char buf[20], *p, *q; 1043bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt int i; 1044bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1045bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* copy dotted string, because we need to modify it */ 1046bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt strncpy(buf, dotted, sizeof(buf) - 1); 1047bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt buf[sizeof(buf) - 1] = '\0'; 1048bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = (void *)&addr.s_addr; 1049bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1050bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt p = buf; 1051bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (i = 0; i < 3; ++i) { 1052bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((q = strchr(p, '.')) == NULL) { 1053bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (is_mask) 1054bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1055bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1056bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* autocomplete, this is a network address */ 10575f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX)) 1058bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1059bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1060bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp[i] = onebyte; 1061bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt while (i < 3) 1062bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp[++i] = 0; 1063bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1064bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &addr; 1065bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1066bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1067bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *q = '\0'; 10685f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX)) 1069bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1070bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1071bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp[i] = onebyte; 1072bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt p = q + 1; 1073bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1074bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1075bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* we have checked 3 bytes, now we check the last one */ 10765f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX)) 1077bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1078bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1079bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp[3] = onebyte; 1080bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &addr; 1081bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1082bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 10831e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in_addr *xtables_numeric_to_ipaddr(const char *dotted) 1084bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1085bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return __numeric_to_ipaddr(dotted, false); 1086bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1087bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 10881e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in_addr *xtables_numeric_to_ipmask(const char *dotted) 1089bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1090bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return __numeric_to_ipaddr(dotted, true); 1091bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1092bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1093bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *network_to_ipaddr(const char *name) 1094bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1095bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt static struct in_addr addr; 1096bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct netent *net; 1097bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1098bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((net = getnetbyname(name)) != NULL) { 1099bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (net->n_addrtype != AF_INET) 1100bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1101bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addr.s_addr = htonl(net->n_net); 1102bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &addr; 1103bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1104bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1105bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1106bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1107bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1108bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *host_to_ipaddr(const char *name, unsigned int *naddr) 1109bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1110bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct hostent *host; 1111bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in_addr *addr; 1112bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned int i; 1113bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1114bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *naddr = 0; 1115bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((host = gethostbyname(name)) != NULL) { 1116bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (host->h_addrtype != AF_INET || 1117bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt host->h_length != sizeof(struct in_addr)) 1118bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1119bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1120bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt while (host->h_addr_list[*naddr] != NULL) 1121bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt ++*naddr; 1122630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt addr = xtables_calloc(*naddr, sizeof(struct in_addr) * *naddr); 1123bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (i = 0; i < *naddr; i++) 1124bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memcpy(&addr[i], host->h_addr_list[i], 1125bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt sizeof(struct in_addr)); 1126bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addr; 1127bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1128bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1129bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1130bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1131bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1132bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr * 1133bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtipparse_hostnetwork(const char *name, unsigned int *naddrs) 1134bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1135bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in_addr *addrptmp, *addrp; 1136bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 11371e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt if ((addrptmp = xtables_numeric_to_ipaddr(name)) != NULL || 1138bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt (addrptmp = network_to_ipaddr(name)) != NULL) { 1139630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt addrp = xtables_malloc(sizeof(struct in_addr)); 1140bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memcpy(addrp, addrptmp, sizeof(*addrp)); 1141bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *naddrs = 1; 1142bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addrp; 1143bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1144bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((addrptmp = host_to_ipaddr(name, naddrs)) != NULL) 1145bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addrptmp; 1146bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 11478b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name); 1148bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1149bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1150bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *parse_ipmask(const char *mask) 1151bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1152bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt static struct in_addr maskaddr; 1153bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in_addr *addrp; 1154bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned int bits; 1155bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1156bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (mask == NULL) { 1157bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* no mask at all defaults to 32 bits */ 1158bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt maskaddr.s_addr = 0xFFFFFFFF; 1159bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &maskaddr; 1160bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 11611e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt if ((addrp = xtables_numeric_to_ipmask(mask)) != NULL) 1162bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* dotted_to_addr already returns a network byte order addr */ 1163bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addrp; 11645f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt if (!xtables_strtoui(mask, NULL, &bits, 0, 32)) 11658b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 1166bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt "invalid mask `%s' specified", mask); 1167bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (bits != 0) { 1168bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt maskaddr.s_addr = htonl(0xFFFFFFFF << (32 - bits)); 1169bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &maskaddr; 1170bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1171bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1172bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt maskaddr.s_addr = 0U; 1173bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &maskaddr; 1174bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1175bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1176332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowvoid xtables_ipparse_multiple(const char *name, struct in_addr **addrpp, 1177332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow struct in_addr **maskpp, unsigned int *naddrs) 1178332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow{ 1179332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow struct in_addr *addrp; 1180332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow char buf[256], *p; 1181332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow unsigned int len, i, j, n, count = 1; 1182332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow const char *loop = name; 1183332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1184332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow while ((loop = strchr(loop, ',')) != NULL) { 1185332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow ++count; 1186332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow ++loop; /* skip ',' */ 1187332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1188332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1189332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *addrpp = xtables_malloc(sizeof(struct in_addr) * count); 1190332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *maskpp = xtables_malloc(sizeof(struct in_addr) * count); 1191332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1192332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow loop = name; 1193332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1194332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow for (i = 0; i < count; ++i) { 1195332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (loop == NULL) 1196332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow break; 1197332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (*loop == ',') 1198332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow ++loop; 1199332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (*loop == '\0') 1200332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow break; 1201332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow p = strchr(loop, ','); 1202332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (p != NULL) 1203332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow len = p - loop; 1204332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow else 1205332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow len = strlen(loop); 1206332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (len == 0 || sizeof(buf) - 1 < len) 1207332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow break; 1208332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1209332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow strncpy(buf, loop, len); 1210332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow buf[len] = '\0'; 1211332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow loop += len; 1212332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if ((p = strrchr(buf, '/')) != NULL) { 1213332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *p = '\0'; 1214332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow addrp = parse_ipmask(p + 1); 1215332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } else { 1216332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow addrp = parse_ipmask(NULL); 1217332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1218332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*maskpp + i, addrp, sizeof(*addrp)); 1219332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1220332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* if a null mask is given, the name is ignored, like in "any/0" */ 1221332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if ((*maskpp + i)->s_addr == 0) 1222332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* 1223332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow * A bit pointless to process multiple addresses 1224332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow * in this case... 1225332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow */ 1226332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow strcpy(buf, "0.0.0.0"); 1227332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1228332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow addrp = ipparse_hostnetwork(buf, &n); 1229332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (n > 1) { 1230332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow count += n - 1; 1231332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *addrpp = xtables_realloc(*addrpp, 1232332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(struct in_addr) * count); 1233332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *maskpp = xtables_realloc(*maskpp, 1234332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(struct in_addr) * count); 1235332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow for (j = 0; j < n; ++j) 1236332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* for each new addr */ 1237332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*addrpp + i + j, addrp + j, 1238332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(*addrp)); 1239332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow for (j = 1; j < n; ++j) 1240332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* for each new mask */ 1241332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*maskpp + i + j, *maskpp + i, 1242332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(*addrp)); 1243332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow i += n - 1; 1244332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } else { 1245332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*addrpp + i, addrp, sizeof(*addrp)); 1246332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1247332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* free what ipparse_hostnetwork had allocated: */ 1248332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow free(addrp); 1249332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1250332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *naddrs = count; 1251332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow for (i = 0; i < n; ++i) 1252332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow (*addrpp+i)->s_addr &= (*maskpp+i)->s_addr; 1253332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow} 1254332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1255332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1256a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt/** 1257a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * xtables_ipparse_any - transform arbitrary name to in_addr 1258a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * 1259a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * Possible inputs (pseudo regex): 1260a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * m{^($hostname|$networkname|$ipaddr)(/$mask)?} 1261a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * "1.2.3.4/5", "1.2.3.4", "hostname", "networkname" 1262a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt */ 1263a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_ipparse_any(const char *name, struct in_addr **addrpp, 1264a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt struct in_addr *maskp, unsigned int *naddrs) 1265bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1266bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned int i, j, k, n; 1267bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in_addr *addrp; 1268bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt char buf[256], *p; 1269bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1270bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt strncpy(buf, name, sizeof(buf) - 1); 1271bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt buf[sizeof(buf) - 1] = '\0'; 1272bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((p = strrchr(buf, '/')) != NULL) { 1273bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *p = '\0'; 1274bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = parse_ipmask(p + 1); 1275bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } else { 1276bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = parse_ipmask(NULL); 1277bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1278bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memcpy(maskp, addrp, sizeof(*maskp)); 1279bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1280bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* if a null mask is given, the name is ignored, like in "any/0" */ 1281bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (maskp->s_addr == 0U) 1282bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt strcpy(buf, "0.0.0.0"); 1283bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1284bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = *addrpp = ipparse_hostnetwork(buf, naddrs); 1285bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt n = *naddrs; 1286bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (i = 0, j = 0; i < n; ++i) { 1287bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp[j++].s_addr &= maskp->s_addr; 1288bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (k = 0; k < j - 1; ++k) 1289bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (addrp[k].s_addr == addrp[j-1].s_addr) { 1290bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt --*naddrs; 1291bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt --j; 1292bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt break; 1293bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1294bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1295bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1296bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1297e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6addr_to_numeric(const struct in6_addr *addrp) 129808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 129908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt /* 0000:0000:0000:0000:0000:000.000.000.000 130008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt * 0000:0000:0000:0000:0000:0000:0000:0000 */ 130108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt static char buf[50+1]; 130208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return inet_ntop(AF_INET6, addrp, buf, sizeof(buf)); 130308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 130408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 130508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ip6addr_to_host(const struct in6_addr *addr) 130608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 130708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt static char hostname[NI_MAXHOST]; 130808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt struct sockaddr_in6 saddr; 130908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt int err; 131008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 131108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt memset(&saddr, 0, sizeof(struct sockaddr_in6)); 131208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt memcpy(&saddr.sin6_addr, addr, sizeof(*addr)); 131308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt saddr.sin6_family = AF_INET6; 131408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 131508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt err = getnameinfo((const void *)&saddr, sizeof(struct sockaddr_in6), 131608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt hostname, sizeof(hostname) - 1, NULL, 0, 0); 131708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if (err != 0) { 131808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#ifdef DEBUG 131908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt fprintf(stderr,"IP2Name: %s\n",gai_strerror(err)); 132008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#endif 132108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return NULL; 132208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt } 132308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 132408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#ifdef DEBUG 132508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt fprintf (stderr, "\naddr2host: %s\n", hostname); 132608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#endif 132708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return hostname; 132808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 132908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 1330e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6addr_to_anyname(const struct in6_addr *addr) 133108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 133208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt const char *name; 133308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 133408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if ((name = ip6addr_to_host(addr)) != NULL) 133508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return name; 133608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 1337e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt return xtables_ip6addr_to_numeric(addr); 133808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 133908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 134008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic int ip6addr_prefix_length(const struct in6_addr *k) 134108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 134208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt unsigned int bits = 0; 134308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt uint32_t a, b, c, d; 134408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 134548607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt a = ntohl(k->s6_addr32[0]); 134648607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt b = ntohl(k->s6_addr32[1]); 134748607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt c = ntohl(k->s6_addr32[2]); 134848607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt d = ntohl(k->s6_addr32[3]); 134908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt while (a & 0x80000000U) { 135008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt ++bits; 135108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt a <<= 1; 135208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt a |= (b >> 31) & 1; 135308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt b <<= 1; 135408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt b |= (c >> 31) & 1; 135508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt c <<= 1; 135608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt c |= (d >> 31) & 1; 135708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt d <<= 1; 135808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt } 135908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if (a != 0 || b != 0 || c != 0 || d != 0) 136008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return -1; 136108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return bits; 136208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 136308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 1364e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6mask_to_numeric(const struct in6_addr *addrp) 136508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 136608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt static char buf[50+2]; 136708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt int l = ip6addr_prefix_length(addrp); 136808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 136908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if (l == -1) { 137008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt strcpy(buf, "/"); 1371e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt strcat(buf, xtables_ip6addr_to_numeric(addrp)); 137208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return buf; 137308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt } 137408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt sprintf(buf, "/%d", l); 137508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return buf; 137608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 1377bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 13781e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in6_addr *xtables_numeric_to_ip6addr(const char *num) 1379bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1380bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt static struct in6_addr ap; 1381bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt int err; 1382bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1383bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((err = inet_pton(AF_INET6, num, &ap)) == 1) 1384bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return ≈ 1385bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG 1386bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt fprintf(stderr, "\nnumeric2addr: %d\n", err); 1387bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif 1388bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1389bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1390bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1391bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr * 1392bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardthost_to_ip6addr(const char *name, unsigned int *naddr) 1393bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1394bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt static struct in6_addr *addr; 1395bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct addrinfo hints; 1396bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct addrinfo *res; 1397bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt int err; 1398bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1399bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memset(&hints, 0, sizeof(hints)); 1400bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt hints.ai_flags = AI_CANONNAME; 1401bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt hints.ai_family = AF_INET6; 1402bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt hints.ai_socktype = SOCK_RAW; 1403bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt hints.ai_protocol = IPPROTO_IPV6; 1404bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt hints.ai_next = NULL; 1405bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1406bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *naddr = 0; 1407bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((err = getaddrinfo(name, NULL, &hints, &res)) != 0) { 1408bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG 1409bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt fprintf(stderr,"Name2IP: %s\n",gai_strerror(err)); 1410bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif 1411bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1412bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } else { 1413bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (res->ai_family != AF_INET6 || 1414bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt res->ai_addrlen != sizeof(struct sockaddr_in6)) 1415bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1416bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1417bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG 1418bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt fprintf(stderr, "resolved: len=%d %s ", res->ai_addrlen, 141930290aea009cf3fd76f27336fb4370be3467c4daPatrick McHardy xtables_ip6addr_to_numeric(&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr)); 1420bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif 1421bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* Get the first element of the address-chain */ 1422630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt addr = xtables_malloc(sizeof(struct in6_addr)); 1423bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memcpy(addr, &((const struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 1424bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt sizeof(struct in6_addr)); 1425bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt freeaddrinfo(res); 1426bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *naddr = 1; 1427bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addr; 1428bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1429bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1430bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1431bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1432bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1433bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *network_to_ip6addr(const char *name) 1434bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1435bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* abort();*/ 1436bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* TODO: not implemented yet, but the exception breaks the 1437bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt * name resolvation */ 1438bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1439bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1440bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1441bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr * 1442bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtip6parse_hostnetwork(const char *name, unsigned int *naddrs) 1443bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1444bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in6_addr *addrp, *addrptmp; 1445bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 14461e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt if ((addrptmp = xtables_numeric_to_ip6addr(name)) != NULL || 1447bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt (addrptmp = network_to_ip6addr(name)) != NULL) { 1448630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt addrp = xtables_malloc(sizeof(struct in6_addr)); 1449bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memcpy(addrp, addrptmp, sizeof(*addrp)); 1450bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *naddrs = 1; 1451bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addrp; 1452bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1453bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((addrp = host_to_ip6addr(name, naddrs)) != NULL) 1454bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addrp; 1455bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 14568b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name); 1457bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1458bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1459bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *parse_ip6mask(char *mask) 1460bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1461bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt static struct in6_addr maskaddr; 1462bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in6_addr *addrp; 1463bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned int bits; 1464bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1465bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (mask == NULL) { 1466bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* no mask at all defaults to 128 bits */ 1467bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memset(&maskaddr, 0xff, sizeof maskaddr); 1468bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &maskaddr; 1469bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 14701e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt if ((addrp = xtables_numeric_to_ip6addr(mask)) != NULL) 1471bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addrp; 14725f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt if (!xtables_strtoui(mask, NULL, &bits, 0, 128)) 14738b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 1474bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt "invalid mask `%s' specified", mask); 1475bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (bits != 0) { 1476bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt char *p = (void *)&maskaddr; 1477bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memset(p, 0xff, bits / 8); 1478bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memset(p + (bits / 8) + 1, 0, (128 - bits) / 8); 1479bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt p[bits/8] = 0xff << (8 - (bits & 7)); 1480bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &maskaddr; 1481bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1482bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1483bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memset(&maskaddr, 0, sizeof(maskaddr)); 1484bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &maskaddr; 1485bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1486bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1487332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowvoid 1488332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowxtables_ip6parse_multiple(const char *name, struct in6_addr **addrpp, 1489332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow struct in6_addr **maskpp, unsigned int *naddrs) 1490332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow{ 149158df90174164fd673e8c4103f7ce0c4e55ef1aecOlaf Rempel static const struct in6_addr zero_addr; 1492332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow struct in6_addr *addrp; 1493332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow char buf[256], *p; 1494332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow unsigned int len, i, j, n, count = 1; 1495332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow const char *loop = name; 1496332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1497332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow while ((loop = strchr(loop, ',')) != NULL) { 1498332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow ++count; 1499332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow ++loop; /* skip ',' */ 1500332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1501332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1502332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *addrpp = xtables_malloc(sizeof(struct in6_addr) * count); 1503332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *maskpp = xtables_malloc(sizeof(struct in6_addr) * count); 1504332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1505332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow loop = name; 1506332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1507332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow for (i = 0; i < count /*NB: count can grow*/; ++i) { 1508332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (loop == NULL) 1509332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow break; 1510332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (*loop == ',') 1511332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow ++loop; 1512332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (*loop == '\0') 1513332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow break; 1514332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow p = strchr(loop, ','); 1515332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (p != NULL) 1516332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow len = p - loop; 1517332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow else 1518332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow len = strlen(loop); 1519332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (len == 0 || sizeof(buf) - 1 < len) 1520332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow break; 1521332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1522332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow strncpy(buf, loop, len); 1523332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow buf[len] = '\0'; 1524332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow loop += len; 1525332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if ((p = strrchr(buf, '/')) != NULL) { 1526332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *p = '\0'; 1527332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow addrp = parse_ip6mask(p + 1); 1528332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } else { 1529332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow addrp = parse_ip6mask(NULL); 1530332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1531332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*maskpp + i, addrp, sizeof(*addrp)); 1532332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1533332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* if a null mask is given, the name is ignored, like in "any/0" */ 153458df90174164fd673e8c4103f7ce0c4e55ef1aecOlaf Rempel if (memcmp(*maskpp + i, &zero_addr, sizeof(zero_addr)) == 0) 1535332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow strcpy(buf, "::"); 1536332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1537332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow addrp = ip6parse_hostnetwork(buf, &n); 1538332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* ip6parse_hostnetwork only ever returns one IP 1539332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow address (it exits if the resolution fails). 1540332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow Therefore, n will always be 1 here. Leaving the 1541332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow code below in anyway in case ip6parse_hostnetwork 1542332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow is improved some day to behave like 1543332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow ipparse_hostnetwork: */ 1544332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (n > 1) { 1545332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow count += n - 1; 1546332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *addrpp = xtables_realloc(*addrpp, 1547332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(struct in6_addr) * count); 1548332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *maskpp = xtables_realloc(*maskpp, 1549332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(struct in6_addr) * count); 1550332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow for (j = 0; j < n; ++j) 1551332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* for each new addr */ 1552332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*addrpp + i + j, addrp + j, 1553332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(*addrp)); 1554332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow for (j = 1; j < n; ++j) 1555332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* for each new mask */ 1556332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*maskpp + i + j, *maskpp + i, 1557332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(*addrp)); 1558332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow i += n - 1; 1559332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } else { 1560332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*addrpp + i, addrp, sizeof(*addrp)); 1561332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1562332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* free what ip6parse_hostnetwork had allocated: */ 1563332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow free(addrp); 1564332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1565332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *naddrs = count; 1566332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow for (i = 0; i < n; ++i) 1567332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow for (j = 0; j < 4; ++j) 1568332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow (*addrpp+i)->s6_addr32[j] &= (*maskpp+i)->s6_addr32[j]; 1569332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow} 1570332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1571a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_ip6parse_any(const char *name, struct in6_addr **addrpp, 1572a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt struct in6_addr *maskp, unsigned int *naddrs) 1573bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 15749c0fa7d8c84dc2478bd36d31b328b697fbe4d0afJan Engelhardt static const struct in6_addr zero_addr; 1575bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in6_addr *addrp; 1576bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned int i, j, k, n; 1577bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt char buf[256], *p; 1578bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1579bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt strncpy(buf, name, sizeof(buf) - 1); 1580bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt buf[sizeof(buf)-1] = '\0'; 1581bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((p = strrchr(buf, '/')) != NULL) { 1582bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *p = '\0'; 1583bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = parse_ip6mask(p + 1); 1584bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } else { 1585bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = parse_ip6mask(NULL); 1586bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1587bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memcpy(maskp, addrp, sizeof(*maskp)); 1588bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1589bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* if a null mask is given, the name is ignored, like in "any/0" */ 15909c0fa7d8c84dc2478bd36d31b328b697fbe4d0afJan Engelhardt if (memcmp(maskp, &zero_addr, sizeof(zero_addr)) == 0) 1591bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt strcpy(buf, "::"); 1592bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1593bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = *addrpp = ip6parse_hostnetwork(buf, naddrs); 1594bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt n = *naddrs; 1595bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (i = 0, j = 0; i < n; ++i) { 1596bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (k = 0; k < 4; ++k) 15975a2208c3e62a150e6f6297abbfa63056ab4a8066Yasuyuki Kozakai addrp[j].s6_addr32[k] &= maskp->s6_addr32[k]; 1598bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt ++j; 1599bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (k = 0; k < j - 1; ++k) 1600bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (IN6_ARE_ADDR_EQUAL(&addrp[k], &addrp[j - 1])) { 1601bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt --*naddrs; 1602bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt --j; 1603bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt break; 1604bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1605bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1606bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1607a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann 1608a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_save_string(const char *value) 1609a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann{ 1610a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann static const char no_quote_chars[] = "_-0123456789" 1611a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann "abcdefghijklmnopqrstuvwxyz" 1612a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 1613a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann static const char escape_chars[] = "\"\\'"; 1614a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann size_t length; 1615a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann const char *p; 1616a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann 1617a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann length = strcspn(value, no_quote_chars); 1618a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann if (length > 0 && value[length] == 0) { 1619a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann /* no quoting required */ 1620a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann fputs(value, stdout); 1621a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann putchar(' '); 1622a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann } else { 1623a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann /* there is at least one dangerous character in the 1624a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann value, which we have to quote. Write double quotes 1625a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann around the value and escape special characters with 1626a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann a backslash */ 1627a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann putchar('"'); 1628a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann 1629a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann for (p = strpbrk(value, escape_chars); p != NULL; 1630a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann p = strpbrk(value, escape_chars)) { 1631a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann if (p > value) 1632a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann fwrite(value, 1, p - value, stdout); 1633a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann putchar('\\'); 1634a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann putchar(*p); 1635a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann value = p + 1; 1636a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann } 1637a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann 1638a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann /* print the rest and finish the double quoted 1639a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann string */ 1640a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann fputs(value, stdout); 1641a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann printf("\" "); 1642a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann } 1643a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann} 16440f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt 16450f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt/** 16460f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt * Check for option-intrapositional negation. 16470f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt * Do not use in new code. 16480f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt */ 16490f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardtint xtables_check_inverse(const char option[], int *invert, 1650bf97128c7262f17a02fec41cdae75b472ba77f88Jan Engelhardt int *my_optind, int argc, char **argv) 16510f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt{ 16522be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt if (option == NULL || strcmp(option, "!") != 0) 16532be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt return false; 16540f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt 16552be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt fprintf(stderr, "Using intrapositioned negation " 16562be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt "(`--option ! this`) is deprecated in favor of " 16572be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt "extrapositioned (`! --option this`).\n"); 16580f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt 16592be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt if (*invert) 16602be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 16612be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt "Multiple `!' flags not allowed"); 16622be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt *invert = true; 16632be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt if (my_optind != NULL) { 1664bf97128c7262f17a02fec41cdae75b472ba77f88Jan Engelhardt optarg = argv[*my_optind]; 16652be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt ++*my_optind; 16662be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt if (argc && *my_optind > argc) 16672be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 16682be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt "no argument following `!'"); 16690f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt } 16702be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt 16712be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt return true; 16720f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt} 16731de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt 16741de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardtconst struct xtables_pprot xtables_chain_protos[] = { 16751de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"tcp", IPPROTO_TCP}, 16761de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"sctp", IPPROTO_SCTP}, 16771de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"udp", IPPROTO_UDP}, 16781de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"udplite", IPPROTO_UDPLITE}, 16791de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"icmp", IPPROTO_ICMP}, 16801de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"icmpv6", IPPROTO_ICMPV6}, 16811de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"ipv6-icmp", IPPROTO_ICMPV6}, 16821de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"esp", IPPROTO_ESP}, 16831de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"ah", IPPROTO_AH}, 16841de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"ipv6-mh", IPPROTO_MH}, 16851de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"mh", IPPROTO_MH}, 16861de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"all", 0}, 16871de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {NULL}, 16881de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt}; 16891de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt 16901de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardtu_int16_t 16911de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardtxtables_parse_protocol(const char *s) 16921de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt{ 16931de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt unsigned int proto; 16941de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt 16951de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt if (!xtables_strtoui(s, NULL, &proto, 0, UINT8_MAX)) { 16961de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt struct protoent *pent; 16971de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt 16981de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt /* first deal with the special case of 'all' to prevent 16991de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt * people from being able to redefine 'all' in nsswitch 17001de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt * and/or provoke expensive [not working] ldap/nis/... 17011de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt * lookups */ 17021de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt if (!strcmp(s, "all")) 17031de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt return 0; 17041de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt 17051de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt if ((pent = getprotobyname(s))) 17061de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt proto = pent->p_proto; 17071de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt else { 17081de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt unsigned int i; 17091de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt for (i = 0; i < ARRAY_SIZE(xtables_chain_protos); ++i) { 1710e55cc4aaa6e35448c14370e5261c3387d26b257dPablo Neira Ayuso if (xtables_chain_protos[i].name == NULL) 1711e55cc4aaa6e35448c14370e5261c3387d26b257dPablo Neira Ayuso continue; 1712e55cc4aaa6e35448c14370e5261c3387d26b257dPablo Neira Ayuso 17131de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt if (strcmp(s, xtables_chain_protos[i].name) == 0) { 17141de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt proto = xtables_chain_protos[i].num; 17151de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt break; 17161de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt } 17171de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt } 17181de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt if (i == ARRAY_SIZE(xtables_chain_protos)) 17198b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 17201de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt "unknown protocol `%s' specified", 17211de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt s); 17221de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt } 17231de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt } 17241de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt 17251de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt return proto; 17261de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt} 1727