xtables.c revision cf3e52d00b7d3fedf98ef7710c337c441270d936
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> 521e128bd804b676ee91beca48312de9b251845d09Jan Engelhardt#include "xshared.h" 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 76600f38db82548a683775fd89b6e136673e924097Jan Engelhardtvoid xtables_free_opts(int unused) 7784c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim{ 78df288236cd254798be3759fef4cbc3e535f5a1c3Jan Engelhardt if (xt_params->opts != xt_params->orig_opts) { 7959e8114c6792242e80785f4461d5e663fb9a3d64Jan Engelhardt free(xt_params->opts); 80df288236cd254798be3759fef4cbc3e535f5a1c3Jan Engelhardt xt_params->opts = NULL; 81df288236cd254798be3759fef4cbc3e535f5a1c3Jan Engelhardt } 8284c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim} 8384c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim 84600f38db82548a683775fd89b6e136673e924097Jan Engelhardtstruct option *xtables_merge_options(struct option *orig_opts, 85600f38db82548a683775fd89b6e136673e924097Jan Engelhardt struct option *oldopts, 8670581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim const struct option *newopts, 8770581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim unsigned int *option_offset) 8870581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim{ 89600f38db82548a683775fd89b6e136673e924097Jan Engelhardt unsigned int num_oold = 0, num_old = 0, num_new = 0, i; 90600f38db82548a683775fd89b6e136673e924097Jan Engelhardt struct option *merge, *mp; 9170581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim 9270581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim if (newopts == NULL) 9370581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim return oldopts; 9470581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim 95600f38db82548a683775fd89b6e136673e924097Jan Engelhardt for (num_oold = 0; orig_opts[num_oold].name; num_oold++) ; 96600f38db82548a683775fd89b6e136673e924097Jan Engelhardt if (oldopts != NULL) 97600f38db82548a683775fd89b6e136673e924097Jan Engelhardt 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 1001dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt /* 1011dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt * Since @oldopts also has @orig_opts already (and does so at the 1021dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt * start), skip these entries. 1031dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt */ 1041dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt oldopts += num_oold; 1051dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt num_old -= num_oold; 1061dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt 107600f38db82548a683775fd89b6e136673e924097Jan Engelhardt merge = malloc(sizeof(*mp) * (num_oold + num_old + num_new + 1)); 108600f38db82548a683775fd89b6e136673e924097Jan Engelhardt if (merge == NULL) 109600f38db82548a683775fd89b6e136673e924097Jan Engelhardt return NULL; 110600f38db82548a683775fd89b6e136673e924097Jan Engelhardt 111600f38db82548a683775fd89b6e136673e924097Jan Engelhardt /* Let the base options -[ADI...] have precedence over everything */ 112600f38db82548a683775fd89b6e136673e924097Jan Engelhardt memcpy(merge, orig_opts, sizeof(*mp) * num_oold); 113600f38db82548a683775fd89b6e136673e924097Jan Engelhardt mp = merge + num_oold; 114600f38db82548a683775fd89b6e136673e924097Jan Engelhardt 115600f38db82548a683775fd89b6e136673e924097Jan Engelhardt /* Second, the new options */ 1161e128bd804b676ee91beca48312de9b251845d09Jan Engelhardt xt_params->option_offset += XT_OPTION_OFFSET_SCALE; 11770581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim *option_offset = xt_params->option_offset; 118600f38db82548a683775fd89b6e136673e924097Jan Engelhardt memcpy(mp, newopts, sizeof(*mp) * num_new); 11970581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim 120600f38db82548a683775fd89b6e136673e924097Jan Engelhardt for (i = 0; i < num_new; ++i, ++mp) 121600f38db82548a683775fd89b6e136673e924097Jan Engelhardt mp->val += *option_offset; 122600f38db82548a683775fd89b6e136673e924097Jan Engelhardt 123600f38db82548a683775fd89b6e136673e924097Jan Engelhardt /* Third, the old options */ 124600f38db82548a683775fd89b6e136673e924097Jan Engelhardt memcpy(mp, oldopts, sizeof(*mp) * num_old); 125600f38db82548a683775fd89b6e136673e924097Jan Engelhardt mp += num_old; 126600f38db82548a683775fd89b6e136673e924097Jan Engelhardt xtables_free_opts(0); 12770581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim 128600f38db82548a683775fd89b6e136673e924097Jan Engelhardt /* Clear trailing entry */ 129600f38db82548a683775fd89b6e136673e924097Jan Engelhardt memset(mp, 0, sizeof(*mp)); 13070581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim return merge; 13170581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim} 13270581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim 133dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt/** 13477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * xtables_afinfo - protocol family dependent information 13577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * @kmod: kernel module basename (e.g. "ip_tables") 13677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * @libprefix: prefix of .so library name (e.g. "libipt_") 13777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * @family: nfproto family 13877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * @ipproto: used by setsockopt (e.g. IPPROTO_IP) 13977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * @so_rev_match: optname to check revision support of match 14077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt * @so_rev_target: optname to check revision support of target 14177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt */ 14277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtstruct xtables_afinfo { 14377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt const char *kmod; 14477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt const char *libprefix; 14577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt uint8_t family; 14677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt uint8_t ipproto; 14777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt int so_rev_match; 14877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt int so_rev_target; 14977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt}; 15077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt 15177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtstatic const struct xtables_afinfo afinfo_ipv4 = { 15277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .kmod = "ip_tables", 15377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .libprefix = "libipt_", 15477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .family = NFPROTO_IPV4, 15577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .ipproto = IPPROTO_IP, 15677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .so_rev_match = IPT_SO_GET_REVISION_MATCH, 15777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .so_rev_target = IPT_SO_GET_REVISION_TARGET, 15877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt}; 15977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt 16077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtstatic const struct xtables_afinfo afinfo_ipv6 = { 16177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .kmod = "ip6_tables", 16277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .libprefix = "libip6t_", 16377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .family = NFPROTO_IPV6, 16477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .ipproto = IPPROTO_IPV6, 16577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .so_rev_match = IP6T_SO_GET_REVISION_MATCH, 16677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .so_rev_target = IP6T_SO_GET_REVISION_TARGET, 16777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt}; 16877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt 16977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtstatic const struct xtables_afinfo *afinfo; 17077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt 17139bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt/* Search path for Xtables .so files */ 17239bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardtstatic const char *xtables_libdir; 1730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 1740b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI/* the path to command to load kernel module */ 175c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtconst char *xtables_modprobe_program; 1760b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 1770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI/* Keeping track of external matches and targets: linked lists. */ 1780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_match *xtables_matches; 1790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_target *xtables_targets; 1800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 18139bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardtvoid xtables_init(void) 18239bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt{ 18339bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt xtables_libdir = getenv("XTABLES_LIBDIR"); 18439bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt if (xtables_libdir != NULL) 18539bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt return; 18639bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt xtables_libdir = getenv("IPTABLES_LIB_DIR"); 18739bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt if (xtables_libdir != NULL) { 18839bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt fprintf(stderr, "IPTABLES_LIB_DIR is deprecated, " 18939bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt "use XTABLES_LIBDIR.\n"); 19039bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt return; 19139bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt } 192ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt /* 193ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt * Well yes, IP6TABLES_LIB_DIR is of lower priority over 194ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt * IPTABLES_LIB_DIR since this moved to libxtables; I think that is ok 195ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt * for these env vars are deprecated anyhow, and in light of the 196ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt * (shared) libxt_*.so files, makes less sense to have 197ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt * IPTABLES_LIB_DIR != IP6TABLES_LIB_DIR. 198ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt */ 199ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt xtables_libdir = getenv("IP6TABLES_LIB_DIR"); 200ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt if (xtables_libdir != NULL) { 201ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt fprintf(stderr, "IP6TABLES_LIB_DIR is deprecated, " 202ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt "use XTABLES_LIBDIR.\n"); 203ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt return; 204ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt } 20539bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt xtables_libdir = XTABLES_LIBDIR; 20639bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt} 20739bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt 20877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtvoid xtables_set_nfproto(uint8_t nfproto) 20977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt{ 21077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt switch (nfproto) { 21177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt case NFPROTO_IPV4: 21277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt afinfo = &afinfo_ipv4; 21377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt break; 21477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt case NFPROTO_IPV6: 21577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt afinfo = &afinfo_ipv6; 21677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt break; 21777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt default: 21877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt fprintf(stderr, "libxtables: unhandled NFPROTO in %s\n", 21977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt __func__); 22077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt } 22177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt} 22277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt 223630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt/** 2247e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * xtables_set_params - set the global parameters used by xtables 2257e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * @xtp: input xtables_globals structure 2267e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * 2277e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * The app is expected to pass a valid xtables_globals data-filled 2287e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * with proper values 2297e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * @xtp cannot be NULL 2307e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * 2317e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * Returns -1 on failure to set and 0 on success 2327e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim */ 2337e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salimint xtables_set_params(struct xtables_globals *xtp) 2347e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim{ 2357e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim if (!xtp) { 2367e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim fprintf(stderr, "%s: Illegal global params\n",__func__); 2377e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim return -1; 2387e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim } 2397e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim 2407e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim xt_params = xtp; 2417e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim 2427e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim if (!xt_params->exit_err) 2437e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim xt_params->exit_err = basic_exit_err; 2447e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim 2457e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim return 0; 2467e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim} 2477e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim 2487e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salimint xtables_init_all(struct xtables_globals *xtp, uint8_t nfproto) 2497e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim{ 2507e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim xtables_init(); 2517e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim xtables_set_nfproto(nfproto); 2527e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim return xtables_set_params(xtp); 2537e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim} 2547e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim 2557e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim/** 256630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt * xtables_*alloc - wrappers that exit on failure 257630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt */ 258630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardtvoid *xtables_calloc(size_t count, size_t size) 2593dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI{ 2603dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI void *p; 2613dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 2623dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI if ((p = calloc(count, size)) == NULL) { 2633dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI perror("ip[6]tables: calloc failed"); 2643dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI exit(1); 2653dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI } 2663dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 2673dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI return p; 2683dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI} 2693dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 270630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardtvoid *xtables_malloc(size_t size) 2713dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI{ 2723dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI void *p; 2733dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 2743dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI if ((p = malloc(size)) == NULL) { 2753dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI perror("ip[6]tables: malloc failed"); 2763dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI exit(1); 2773dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI } 2783dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 2793dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI return p; 2803dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI} 2810b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 282332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowvoid *xtables_realloc(void *ptr, size_t size) 283332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow{ 284332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow void *p; 285332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 286332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if ((p = realloc(ptr, size)) == NULL) { 287332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow perror("ip[6]tables: realloc failed"); 288332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow exit(1); 289332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 290332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 291332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow return p; 292332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow} 293332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 2940b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAIstatic char *get_modprobe(void) 2950b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI{ 2960b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI int procfile; 2970b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI char *ret; 2980b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 2990b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#define PROCFILE_BUFSIZ 1024 3000b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI procfile = open(PROC_SYS_MODPROBE, O_RDONLY); 3010b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (procfile < 0) 3020b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return NULL; 303a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski if (fcntl(procfile, F_SETFD, FD_CLOEXEC) == -1) { 304a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski fprintf(stderr, "Could not set close on exec: %s\n", 305a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski strerror(errno)); 306a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski exit(1); 307a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski } 3080b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 309371cea299f0b2eb100b9fc9fb99089640d2d606fJan Engelhardt ret = malloc(PROCFILE_BUFSIZ); 3100b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (ret) { 3110b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI memset(ret, 0, PROCFILE_BUFSIZ); 3120b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI switch (read(procfile, ret, PROCFILE_BUFSIZ)) { 3130b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI case -1: goto fail; 3140b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI case PROCFILE_BUFSIZ: goto fail; /* Partial read. Wierd */ 3150b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 3160b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (ret[strlen(ret)-1]=='\n') 3170b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI ret[strlen(ret)-1]=0; 3180b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI close(procfile); 3190b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return ret; 3200b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 3210b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI fail: 3220b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI free(ret); 3230b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI close(procfile); 3240b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return NULL; 3250b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI} 3260b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 327c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtint xtables_insmod(const char *modname, const char *modprobe, bool quiet) 3280b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI{ 3290b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI char *buf = NULL; 3300b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI char *argv[4]; 3310b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI int status; 3320b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 3330b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI /* If they don't explicitly set it, read out of kernel */ 3340b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (!modprobe) { 3350b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI buf = get_modprobe(); 3360b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (!buf) 3370b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return -1; 3380b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI modprobe = buf; 3390b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 3400b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 341c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt /* 342c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt * Need to flush the buffer, or the child may output it again 343c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt * when switching the program thru execv. 344c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt */ 345c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt fflush(stdout); 346c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt 34794aa2ea67d7b8a669e8541f094661a1dc89722a3Jan Engelhardt switch (vfork()) { 3480b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI case 0: 3490b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[0] = (char *)modprobe; 3500b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[1] = (char *)modname; 3510b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (quiet) { 3520b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[2] = "-q"; 3530b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[3] = NULL; 3540b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } else { 3550b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[2] = NULL; 3560b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[3] = NULL; 3570b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 3580b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI execv(argv[0], argv); 3590b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 3600b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI /* not usually reached */ 3610b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI exit(1); 3620b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI case -1: 3630b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return -1; 3640b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 3650b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI default: /* parent */ 3660b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI wait(&status); 3670b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 3680b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 3690b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI free(buf); 3700b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (WIFEXITED(status) && WEXITSTATUS(status) == 0) 3710b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return 0; 3720b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return -1; 3730b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI} 3740b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 375c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtint xtables_load_ko(const char *modprobe, bool quiet) 3760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 377c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardt static bool loaded = false; 3780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI static int ret = -1; 3790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (!loaded) { 38177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt ret = xtables_insmod(afinfo->kmod, modprobe, quiet); 3820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI loaded = (ret == 0); 3830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 3840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return ret; 3860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 3870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3885f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt/** 3895f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * xtables_strtou{i,l} - string to number conversion 3905f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @s: input string 3915f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @end: like strtoul's "end" pointer 3925f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @value: pointer for result 3935f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @min: minimum accepted value 3945f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @max: maximum accepted value 3955f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * 3965f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * If @end is NULL, we assume the caller wants a "strict strtoul", and hence 3975f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * "15a" is rejected. 3985f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * In either case, the value obtained is compared for min-max compliance. 3995f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * Base is always 0, i.e. autodetect depending on @s. 400cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt * 4015f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * Returns true/false whether number was accepted. On failure, *value has 4025f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * undefined contents. 403cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt */ 4045f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardtbool xtables_strtoul(const char *s, char **end, unsigned long *value, 4055f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt unsigned long min, unsigned long max) 406cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt{ 407cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt unsigned long v; 408cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt char *my_end; 409cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 410cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt errno = 0; 411cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt v = strtoul(s, &my_end, 0); 412cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 413cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (my_end == s) 414cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return false; 415cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (end != NULL) 416cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt *end = my_end; 417cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 418cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (errno != ERANGE && min <= v && (max == 0 || v <= max)) { 419cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (value != NULL) 420cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt *value = v; 421cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (end == NULL) 422cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return *my_end == '\0'; 423cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return true; 424cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt } 425cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 426cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return false; 427cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt} 428cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 4295f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardtbool xtables_strtoui(const char *s, char **end, unsigned int *value, 4305f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt unsigned int min, unsigned int max) 431cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt{ 432cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt unsigned long v; 433cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt bool ret; 434cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 4355f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt ret = xtables_strtoul(s, end, &v, min, max); 436cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (value != NULL) 437cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt *value = v; 438cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return ret; 439cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt} 440cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 441aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardtint xtables_service_to_port(const char *name, const char *proto) 44204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{ 44304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI struct servent *service; 44404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 44504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI if ((service = getservbyname(name, proto)) != NULL) 44604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI return ntohs((unsigned short) service->s_port); 44704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 44804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI return -1; 44904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI} 45004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 4517ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtuint16_t xtables_parse_port(const char *port, const char *proto) 45204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{ 4537a236f4cc685a420c1a782a5db614a93baf37ccfJan Engelhardt unsigned int portnum; 45404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 4555f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt if (xtables_strtoui(port, NULL, &portnum, 0, UINT16_MAX) || 456aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardt (portnum = xtables_service_to_port(port, proto)) != (unsigned)-1) 457213e185afbb298e6708881e4c2adffdc47a8b6daJan Engelhardt return portnum; 45804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 4598b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 46004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI "invalid port/service `%s' specified", port); 46104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI} 46204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 463aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardtvoid xtables_parse_interface(const char *arg, char *vianame, 464aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardt unsigned char *mask) 46504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{ 466fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt unsigned int vialen = strlen(arg); 46704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI unsigned int i; 46804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 46904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask, 0, IFNAMSIZ); 47004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(vianame, 0, IFNAMSIZ); 47104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 47204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI if (vialen + 1 > IFNAMSIZ) 4738b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 47404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI "interface name `%s' must be shorter than IFNAMSIZ" 47504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI " (%i)", arg, IFNAMSIZ-1); 47604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 47704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI strcpy(vianame, arg); 478fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt if (vialen == 0) 47904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask, 0, IFNAMSIZ); 48004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI else if (vianame[vialen - 1] == '+') { 48104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask, 0xFF, vialen - 1); 48204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask + vialen - 1, 0, IFNAMSIZ - vialen + 1); 48304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI /* Don't remove `+' here! -HW */ 48404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } else { 48504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI /* Include nul-terminator in match */ 48604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask, 0xFF, vialen + 1); 48704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask + vialen + 1, 0, IFNAMSIZ - vialen - 1); 48804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI for (i = 0; vianame[i]; i++) { 489fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt if (vianame[i] == '/' || 490fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt vianame[i] == ' ') { 491aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann fprintf(stderr, 492aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann "Warning: weird character in interface" 493fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt " `%s' ('/' and ' ' are not allowed by the kernel).\n", 494aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann vianame); 49504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI break; 49604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } 49704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } 49804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } 49904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI} 50004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 501cb25af809a8734c4766b6bfa4cca99596cbf01dbJan Engelhardt#ifndef NO_SHARED_LIBS 502927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardtstatic void *load_extension(const char *search_path, const char *af_prefix, 50321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt const char *name, bool is_target) 50421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt{ 505927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt const char *all_prefixes[] = {"libxt_", af_prefix, NULL}; 506927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt const char **prefix; 50721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt const char *dir = search_path, *next; 50821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt void *ptr = NULL; 50921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt struct stat sb; 51021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt char path[256]; 51121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 51221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt do { 51321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt next = strchr(dir, ':'); 51421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt if (next == NULL) 51521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt next = dir + strlen(dir); 51621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 517927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt for (prefix = all_prefixes; *prefix != NULL; ++prefix) { 518927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt snprintf(path, sizeof(path), "%.*s/%s%s.so", 519927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt (unsigned int)(next - dir), dir, 520927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt *prefix, name); 521927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt 522927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt if (stat(path, &sb) != 0) { 523927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt if (errno == ENOENT) 524927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt continue; 525927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt fprintf(stderr, "%s: %s\n", path, 526927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt strerror(errno)); 527927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt return NULL; 528927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt } 529927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt if (dlopen(path, RTLD_NOW) == NULL) { 530927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt fprintf(stderr, "%s: %s\n", path, dlerror()); 531927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt break; 532927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt } 53321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 53421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt if (is_target) 5352338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt ptr = xtables_find_target(name, XTF_DONT_LOAD); 53621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt else 5372338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt ptr = xtables_find_match(name, 5382338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt XTF_DONT_LOAD, NULL); 53921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 540927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt if (ptr != NULL) 541927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt return ptr; 54221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 543927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt fprintf(stderr, "%s: no \"%s\" extension found for " 544927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt "this protocol\n", path, name); 545927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt errno = ENOENT; 546927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt return NULL; 547927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt } 54821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt dir = next + 1; 54921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt } while (*next != '\0'); 55021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 55121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt return NULL; 55221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt} 553cb25af809a8734c4766b6bfa4cca99596cbf01dbJan Engelhardt#endif 55421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 5552338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtstruct xtables_match * 5562338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtxtables_find_match(const char *name, enum xtables_tryload tryload, 5572338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt struct xtables_rule_match **matches) 5580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 5590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_match *ptr; 5600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI const char *icmp6 = "icmp6"; 5610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5620cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt if (strlen(name) >= XT_EXTENSION_MAXNAMELEN) 56321d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt xtables_error(PARAMETER_PROBLEM, 56421d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt "Invalid match name \"%s\" (%u chars max)", 5650cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt name, XT_EXTENSION_MAXNAMELEN - 1); 56621d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt 5670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* This is ugly as hell. Nonetheless, there is no way of changing 5680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI * this without hurting backwards compatibility */ 5690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if ( (strcmp(name,"icmpv6") == 0) || 5700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI (strcmp(name,"ipv6-icmp") == 0) || 5710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI (strcmp(name,"icmp6") == 0) ) 5720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI name = icmp6; 5730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (ptr = xtables_matches; ptr; ptr = ptr->next) { 5750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(name, ptr->name) == 0) { 5760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_match *clone; 5770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* First match of this type: */ 5790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr->m == NULL) 5800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI break; 5810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Second and subsequent clones */ 583630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt clone = xtables_malloc(sizeof(struct xtables_match)); 5840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI memcpy(clone, ptr, sizeof(struct xtables_match)); 5850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI clone->mflags = 0; 5860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* This is a clone: */ 5870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI clone->next = clone; 5880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr = clone; 5900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI break; 5910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#ifndef NO_SHARED_LIBS 5952338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) { 59677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt ptr = load_extension(xtables_libdir, afinfo->libprefix, 59739bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt name, false); 598170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI 5992338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) 6008b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 6010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "Couldn't load match `%s':%s\n", 602927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt name, strerror(errno)); 6030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#else 6050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr && !ptr->loaded) { 6062338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if (tryload != XTF_DONT_LOAD) 6070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr->loaded = 1; 6080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI else 6090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr = NULL; 6100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6112338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if(!ptr && (tryload == XTF_LOAD_MUST_SUCCEED)) { 6128b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 6130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "Couldn't find match `%s'\n", name); 6140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#endif 6160d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr && matches) { 6180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_rule_match **i; 6190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_rule_match *newentry; 6200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 621630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt newentry = xtables_malloc(sizeof(struct xtables_rule_match)); 6220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (i = matches; *i; i = &(*i)->next) { 6240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(name, (*i)->match->name) == 0) 6252338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt (*i)->completed = true; 6260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI newentry->match = ptr; 6282338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt newentry->completed = false; 6290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI newentry->next = NULL; 6300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI *i = newentry; 6310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return ptr; 6340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 6350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6362338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtstruct xtables_target * 6372338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtxtables_find_target(const char *name, enum xtables_tryload tryload) 6380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 6390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_target *ptr; 6400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Standard target? */ 6420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(name, "") == 0 6430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI || strcmp(name, XTC_LABEL_ACCEPT) == 0 6440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI || strcmp(name, XTC_LABEL_DROP) == 0 6450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI || strcmp(name, XTC_LABEL_QUEUE) == 0 6460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI || strcmp(name, XTC_LABEL_RETURN) == 0) 6470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI name = "standard"; 6480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (ptr = xtables_targets; ptr; ptr = ptr->next) { 6500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(name, ptr->name) == 0) 6510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI break; 6520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#ifndef NO_SHARED_LIBS 6552338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) { 65677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt ptr = load_extension(xtables_libdir, afinfo->libprefix, 65739bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt name, true); 658170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI 6592338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) 6608b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 6610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "Couldn't load target `%s':%s\n", 662927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt name, strerror(errno)); 6630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#else 6650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr && !ptr->loaded) { 6662338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if (tryload != XTF_DONT_LOAD) 6670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr->loaded = 1; 6680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI else 6690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr = NULL; 6700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 671854d2d9bd7556cfd8a676b0bc18dc059a9a2dd25Peter Volkov if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) { 6728b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 6730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "Couldn't find target `%s'\n", name); 6740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#endif 6760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr) 6780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr->used = 1; 6790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return ptr; 6810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 6820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6837ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtstatic int compatible_revision(const char *name, uint8_t revision, int opt) 6840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 6850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xt_get_revision rev; 6860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI socklen_t s = sizeof(rev); 6870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI int max_rev, sockfd; 6880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 68977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt sockfd = socket(afinfo->family, SOCK_RAW, IPPROTO_RAW); 6900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (sockfd < 0) { 691df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy if (errno == EPERM) { 692df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy /* revision 0 is always supported. */ 693df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy if (revision != 0) 694df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy fprintf(stderr, "Could not determine whether " 695df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy "revision %u is supported, " 696df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy "assuming it is.\n", 697df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy revision); 698df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy return 1; 699df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy } 7000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "Could not open socket to kernel: %s\n", 7010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI strerror(errno)); 7020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 7030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 7040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 705a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski if (fcntl(sockfd, F_SETFD, FD_CLOEXEC) == -1) { 706a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski fprintf(stderr, "Could not set close on exec: %s\n", 707a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski strerror(errno)); 708a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski exit(1); 709a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski } 710a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski 711c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardt xtables_load_ko(xtables_modprobe_program, true); 7120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI strcpy(rev.name, name); 7140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI rev.revision = revision; 7150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 71677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt max_rev = getsockopt(sockfd, afinfo->ipproto, opt, &rev, &s); 7170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (max_rev < 0) { 7180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Definitely don't support this? */ 7190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (errno == ENOENT || errno == EPROTONOSUPPORT) { 7200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI close(sockfd); 7210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return 0; 7220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } else if (errno == ENOPROTOOPT) { 7230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI close(sockfd); 7240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Assume only revision 0 support (old kernel) */ 7250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return (revision == 0); 7260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } else { 7270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "getsockopt failed strangely: %s\n", 7280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI strerror(errno)); 7290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 7300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 7310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 7320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI close(sockfd); 7330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return 1; 7340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 7350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7377ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtstatic int compatible_match_revision(const char *name, uint8_t revision) 7380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 73977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt return compatible_revision(name, revision, afinfo->so_rev_match); 7400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 7410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7427ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtstatic int compatible_target_revision(const char *name, uint8_t revision) 7430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 74477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt return compatible_revision(name, revision, afinfo->so_rev_target); 7450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 7460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 747dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardtstatic void xtables_check_options(const char *name, const struct option *opt) 748dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt{ 749dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt for (; opt->name != NULL; ++opt) 750dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt if (opt->val < 0 || opt->val >= XT_OPTION_OFFSET_SCALE) { 751dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt fprintf(stderr, "%s: Extension %s uses invalid " 752dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt "option value %d\n",xt_params->program_name, 753dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt name, opt->val); 754dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt exit(1); 755dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt } 756dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt} 757dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt 7580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIvoid xtables_register_match(struct xtables_match *me) 7590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 7600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_match **i, *old; 7610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 762c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt if (me->version == NULL) { 763c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt fprintf(stderr, "%s: match %s<%u> is missing a version\n", 764c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt xt_params->program_name, me->name, me->revision); 765c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt exit(1); 766c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt } 767dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt if (strcmp(me->version, XTABLES_VERSION) != 0) { 768dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt fprintf(stderr, "%s: match \"%s\" has version \"%s\", " 769dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt "but \"%s\" is required.\n", 7705dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name, 771dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt me->version, XTABLES_VERSION); 7720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 7730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 7740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7750cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) { 776281439ba6b96b729ef1400a49ec53eda298bb9f8Li Yewang fprintf(stderr, "%s: match `%s' has invalid name\n", 7775dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name); 7780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 7790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 7800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (me->family >= NPROTO) { 7820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, 7830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "%s: BUG: match %s has invalid protocol family\n", 7845dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name); 7850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 7860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 7870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 788dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt if (me->extra_opts != NULL) 789dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt xtables_check_options(me->name, me->extra_opts); 790dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt 7910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* ignore not interested match */ 79277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt if (me->family != afinfo->family && me->family != AF_UNSPEC) 7930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 7940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7952338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt old = xtables_find_match(me->name, XTF_DURING_LOAD, NULL); 7960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (old) { 79723545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt if (old->revision == me->revision && 79823545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt old->family == me->family) { 7990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, 8000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "%s: match `%s' already registered.\n", 8015dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name); 8020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 8030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 8040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Now we have two (or more) options, check compatibility. */ 8060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (compatible_match_revision(old->name, old->revision) 8070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI && old->revision > me->revision) 8080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 8090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 81023545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt /* See if new match can be used. */ 8110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (!compatible_match_revision(me->name, me->revision)) 8120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 8130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 81423545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt /* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */ 81523545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt if (old->revision == me->revision && me->family == AF_UNSPEC) 81623545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt return; 81723545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt 8180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Delete old one. */ 8190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (i = &xtables_matches; *i!=old; i = &(*i)->next); 8200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI *i = old->next; 8210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 8220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (me->size != XT_ALIGN(me->size)) { 8240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "%s: match `%s' has invalid size %u.\n", 8255dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name, 8265dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim (unsigned int)me->size); 8270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 8280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 8290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Append to list. */ 8310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (i = &xtables_matches; *i; i = &(*i)->next); 8320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->next = NULL; 8330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI *i = me; 8340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->m = NULL; 8360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->mflags = 0; 8370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 8380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8399a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardtvoid xtables_register_matches(struct xtables_match *match, unsigned int n) 8409a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt{ 8419a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt do { 8429a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt xtables_register_match(&match[--n]); 8439a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt } while (n > 0); 8449a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt} 8459a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt 8460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIvoid xtables_register_target(struct xtables_target *me) 8470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 8480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_target *old; 8490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 850c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt if (me->version == NULL) { 851c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt fprintf(stderr, "%s: target %s<%u> is missing a version\n", 852c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt xt_params->program_name, me->name, me->revision); 853c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt exit(1); 854c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt } 855dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt if (strcmp(me->version, XTABLES_VERSION) != 0) { 856dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt fprintf(stderr, "%s: target \"%s\" has version \"%s\", " 857dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt "but \"%s\" is required.\n", 8585dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name, 859dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt me->version, XTABLES_VERSION); 8600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 8610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 8620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8630cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) { 8640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "%s: target `%s' has invalid name\n", 8655dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name); 8660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 8670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 8680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (me->family >= NPROTO) { 8700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, 8710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "%s: BUG: target %s has invalid protocol family\n", 8725dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name); 8730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 8740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 8750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 876dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt if (me->extra_opts != NULL) 877dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt xtables_check_options(me->name, me->extra_opts); 878dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt 8790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* ignore not interested target */ 88077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt if (me->family != afinfo->family && me->family != AF_UNSPEC) 8810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 8820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8832338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt old = xtables_find_target(me->name, XTF_DURING_LOAD); 8840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (old) { 8850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_target **i; 8860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 88723545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt if (old->revision == me->revision && 88823545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt old->family == me->family) { 8890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, 8900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "%s: target `%s' already registered.\n", 8915dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name); 8920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 8930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 8940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Now we have two (or more) options, check compatibility. */ 8960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (compatible_target_revision(old->name, old->revision) 8970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI && old->revision > me->revision) 8980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 8990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 90023545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt /* See if new target can be used. */ 9010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (!compatible_target_revision(me->name, me->revision)) 9020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 9030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 90423545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt /* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */ 90523545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt if (old->revision == me->revision && me->family == AF_UNSPEC) 90623545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt return; 90723545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt 9080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Delete old one. */ 9090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (i = &xtables_targets; *i!=old; i = &(*i)->next); 9100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI *i = old->next; 9110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 9120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 9130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (me->size != XT_ALIGN(me->size)) { 9140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "%s: target `%s' has invalid size %u.\n", 9155dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name, 9165dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim (unsigned int)me->size); 9170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 9180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 9190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 9200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Prepend to list. */ 9210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->next = xtables_targets; 9220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI xtables_targets = me; 9230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->t = NULL; 9240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->tflags = 0; 9250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 926aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt 9279a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardtvoid xtables_register_targets(struct xtables_target *target, unsigned int n) 9289a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt{ 9299a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt do { 9309a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt xtables_register_target(&target[--n]); 9319a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt } while (n > 0); 9329a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt} 9339a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt 934a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt/** 935a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * xtables_param_act - act on condition 936a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @status: a constant from enum xtables_exittype 937a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * 938a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_ONLY_ONCE: print error message that option may only be used once. 939a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1: module name (e.g. "mark") 940a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2(...): option in conflict (e.g. "--mark") 941a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3(...): condition to match on (see extensions/ for examples) 942a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * 943a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_NO_INVERT: option does not support inversion 944a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1: module name 945a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2: option in conflict 946a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3: condition to match on 947a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * 948a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_BAD_VALUE: bad value for option 949a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1: module name 950a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2: option with which the problem occured (e.g. "--mark") 951a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3: string the user passed in (e.g. "99999999999999") 952a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * 953a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_ONE_ACTION: two mutually exclusive actions have been specified 954a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1: module name 955a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * 956a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * Displays an error message and exits the program. 957a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt */ 958a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardtvoid xtables_param_act(unsigned int status, const char *p1, ...) 959aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt{ 960aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt const char *p2, *p3; 961aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt va_list args; 962aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt bool b; 963aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt 964aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt va_start(args, p1); 965aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt 966aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt switch (status) { 967a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt case XTF_ONLY_ONCE: 968aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt p2 = va_arg(args, const char *); 969aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt b = va_arg(args, unsigned int); 970aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt if (!b) 971aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt return; 9728b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 973aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt "%s: \"%s\" option may only be specified once", 974aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt p1, p2); 975aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt break; 976a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt case XTF_NO_INVERT: 977aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt p2 = va_arg(args, const char *); 978aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt b = va_arg(args, unsigned int); 979aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt if (!b) 980aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt return; 9818b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 982aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt "%s: \"%s\" option cannot be inverted", p1, p2); 983aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt break; 984a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt case XTF_BAD_VALUE: 985aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt p2 = va_arg(args, const char *); 986aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt p3 = va_arg(args, const char *); 9878b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 988aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt "%s: Bad value for \"%s\" option: \"%s\"", 989aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt p1, p2, p3); 990aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt break; 991a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt case XTF_ONE_ACTION: 992aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt b = va_arg(args, unsigned int); 993aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt if (!b) 994aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt return; 9958b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 996aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt "%s: At most one action is possible", p1); 997aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt break; 998aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt default: 9998b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(status, p1, args); 1000aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt break; 1001aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt } 1002aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt 1003aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt va_end(args); 1004aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt} 100508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 1006e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ipaddr_to_numeric(const struct in_addr *addrp) 100708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 100808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt static char buf[20]; 100908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt const unsigned char *bytep = (const void *)&addrp->s_addr; 101008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 101108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt sprintf(buf, "%u.%u.%u.%u", bytep[0], bytep[1], bytep[2], bytep[3]); 101208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return buf; 101308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 101408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 101508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ipaddr_to_host(const struct in_addr *addr) 101608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 101708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt struct hostent *host; 101808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 101908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt host = gethostbyaddr(addr, sizeof(struct in_addr), AF_INET); 102008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if (host == NULL) 102108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return NULL; 102208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 102308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return host->h_name; 102408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 102508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 102608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ipaddr_to_network(const struct in_addr *addr) 102708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 102808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt struct netent *net; 102908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 103008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if ((net = getnetbyaddr(ntohl(addr->s_addr), AF_INET)) != NULL) 103108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return net->n_name; 103208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 103308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return NULL; 103408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 103508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 1036e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ipaddr_to_anyname(const struct in_addr *addr) 103708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 103808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt const char *name; 103908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 104008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if ((name = ipaddr_to_host(addr)) != NULL || 104108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt (name = ipaddr_to_network(addr)) != NULL) 104208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return name; 104308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 1044e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt return xtables_ipaddr_to_numeric(addr); 104508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 104608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 1047e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ipmask_to_numeric(const struct in_addr *mask) 104808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 104908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt static char buf[20]; 105008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt uint32_t maskaddr, bits; 105108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt int i; 105208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 105308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt maskaddr = ntohl(mask->s_addr); 105408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 105508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if (maskaddr == 0xFFFFFFFFL) 105608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt /* we don't want to see "/32" */ 105708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return ""; 105808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 105908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt i = 32; 106008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt bits = 0xFFFFFFFEL; 106108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt while (--i >= 0 && maskaddr != bits) 106208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt bits <<= 1; 106308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if (i >= 0) 106408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt sprintf(buf, "/%d", i); 106508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt else 106608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt /* mask was not a decent combination of 1's and 0's */ 1067e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt sprintf(buf, "/%s", xtables_ipaddr_to_numeric(mask)); 106808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 106908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return buf; 107008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 107108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 1072bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *__numeric_to_ipaddr(const char *dotted, bool is_mask) 1073bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1074bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt static struct in_addr addr; 1075bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned char *addrp; 1076bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned int onebyte; 1077bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt char buf[20], *p, *q; 1078bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt int i; 1079bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1080bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* copy dotted string, because we need to modify it */ 1081bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt strncpy(buf, dotted, sizeof(buf) - 1); 1082bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt buf[sizeof(buf) - 1] = '\0'; 1083bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = (void *)&addr.s_addr; 1084bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1085bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt p = buf; 1086bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (i = 0; i < 3; ++i) { 1087bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((q = strchr(p, '.')) == NULL) { 1088bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (is_mask) 1089bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1090bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1091bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* autocomplete, this is a network address */ 10925f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX)) 1093bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1094bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1095bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp[i] = onebyte; 1096bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt while (i < 3) 1097bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp[++i] = 0; 1098bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1099bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &addr; 1100bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1101bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1102bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *q = '\0'; 11035f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX)) 1104bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1105bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1106bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp[i] = onebyte; 1107bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt p = q + 1; 1108bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1109bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1110bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* we have checked 3 bytes, now we check the last one */ 11115f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX)) 1112bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1113bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1114bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp[3] = onebyte; 1115bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &addr; 1116bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1117bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 11181e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in_addr *xtables_numeric_to_ipaddr(const char *dotted) 1119bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1120bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return __numeric_to_ipaddr(dotted, false); 1121bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1122bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 11231e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in_addr *xtables_numeric_to_ipmask(const char *dotted) 1124bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1125bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return __numeric_to_ipaddr(dotted, true); 1126bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1127bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1128bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *network_to_ipaddr(const char *name) 1129bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1130bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt static struct in_addr addr; 1131bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct netent *net; 1132bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1133bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((net = getnetbyname(name)) != NULL) { 1134bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (net->n_addrtype != AF_INET) 1135bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1136bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addr.s_addr = htonl(net->n_net); 1137bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &addr; 1138bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1139bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1140bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1141bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1142bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1143bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *host_to_ipaddr(const char *name, unsigned int *naddr) 1144bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1145bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct hostent *host; 1146bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in_addr *addr; 1147bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned int i; 1148bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1149bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *naddr = 0; 1150bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((host = gethostbyname(name)) != NULL) { 1151bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (host->h_addrtype != AF_INET || 1152bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt host->h_length != sizeof(struct in_addr)) 1153bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1154bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1155bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt while (host->h_addr_list[*naddr] != NULL) 1156bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt ++*naddr; 115711e250ba02349cb1e34058673db3d0b54eb56c44Wes Campaigne addr = xtables_calloc(*naddr, sizeof(struct in_addr)); 1158bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (i = 0; i < *naddr; i++) 1159bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memcpy(&addr[i], host->h_addr_list[i], 1160bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt sizeof(struct in_addr)); 1161bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addr; 1162bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1163bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1164bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1165bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1166bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1167bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr * 1168bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtipparse_hostnetwork(const char *name, unsigned int *naddrs) 1169bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1170bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in_addr *addrptmp, *addrp; 1171bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 11721e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt if ((addrptmp = xtables_numeric_to_ipaddr(name)) != NULL || 1173bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt (addrptmp = network_to_ipaddr(name)) != NULL) { 1174630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt addrp = xtables_malloc(sizeof(struct in_addr)); 1175bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memcpy(addrp, addrptmp, sizeof(*addrp)); 1176bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *naddrs = 1; 1177bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addrp; 1178bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1179bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((addrptmp = host_to_ipaddr(name, naddrs)) != NULL) 1180bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addrptmp; 1181bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 11828b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name); 1183bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1184bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1185bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *parse_ipmask(const char *mask) 1186bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1187bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt static struct in_addr maskaddr; 1188bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in_addr *addrp; 1189bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned int bits; 1190bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1191bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (mask == NULL) { 1192bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* no mask at all defaults to 32 bits */ 1193bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt maskaddr.s_addr = 0xFFFFFFFF; 1194bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &maskaddr; 1195bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 11961e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt if ((addrp = xtables_numeric_to_ipmask(mask)) != NULL) 1197bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* dotted_to_addr already returns a network byte order addr */ 1198bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addrp; 11995f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt if (!xtables_strtoui(mask, NULL, &bits, 0, 32)) 12008b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 1201bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt "invalid mask `%s' specified", mask); 1202bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (bits != 0) { 1203bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt maskaddr.s_addr = htonl(0xFFFFFFFF << (32 - bits)); 1204bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &maskaddr; 1205bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1206bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1207bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt maskaddr.s_addr = 0U; 1208bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &maskaddr; 1209bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1210bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1211332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowvoid xtables_ipparse_multiple(const char *name, struct in_addr **addrpp, 1212332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow struct in_addr **maskpp, unsigned int *naddrs) 1213332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow{ 1214332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow struct in_addr *addrp; 1215332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow char buf[256], *p; 1216332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow unsigned int len, i, j, n, count = 1; 1217332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow const char *loop = name; 1218332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1219332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow while ((loop = strchr(loop, ',')) != NULL) { 1220332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow ++count; 1221332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow ++loop; /* skip ',' */ 1222332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1223332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1224332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *addrpp = xtables_malloc(sizeof(struct in_addr) * count); 1225332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *maskpp = xtables_malloc(sizeof(struct in_addr) * count); 1226332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1227332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow loop = name; 1228332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1229332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow for (i = 0; i < count; ++i) { 1230332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (loop == NULL) 1231332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow break; 1232332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (*loop == ',') 1233332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow ++loop; 1234332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (*loop == '\0') 1235332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow break; 1236332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow p = strchr(loop, ','); 1237332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (p != NULL) 1238332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow len = p - loop; 1239332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow else 1240332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow len = strlen(loop); 1241332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (len == 0 || sizeof(buf) - 1 < len) 1242332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow break; 1243332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1244332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow strncpy(buf, loop, len); 1245332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow buf[len] = '\0'; 1246332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow loop += len; 1247332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if ((p = strrchr(buf, '/')) != NULL) { 1248332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *p = '\0'; 1249332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow addrp = parse_ipmask(p + 1); 1250332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } else { 1251332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow addrp = parse_ipmask(NULL); 1252332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1253332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*maskpp + i, addrp, sizeof(*addrp)); 1254332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1255332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* if a null mask is given, the name is ignored, like in "any/0" */ 1256332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if ((*maskpp + i)->s_addr == 0) 1257332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* 1258332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow * A bit pointless to process multiple addresses 1259332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow * in this case... 1260332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow */ 1261332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow strcpy(buf, "0.0.0.0"); 1262332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1263332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow addrp = ipparse_hostnetwork(buf, &n); 1264332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (n > 1) { 1265332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow count += n - 1; 1266332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *addrpp = xtables_realloc(*addrpp, 1267332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(struct in_addr) * count); 1268332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *maskpp = xtables_realloc(*maskpp, 1269332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(struct in_addr) * count); 1270332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow for (j = 0; j < n; ++j) 1271332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* for each new addr */ 1272332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*addrpp + i + j, addrp + j, 1273332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(*addrp)); 1274332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow for (j = 1; j < n; ++j) 1275332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* for each new mask */ 1276332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*maskpp + i + j, *maskpp + i, 1277332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(*addrp)); 1278332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow i += n - 1; 1279332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } else { 1280332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*addrpp + i, addrp, sizeof(*addrp)); 1281332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1282332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* free what ipparse_hostnetwork had allocated: */ 1283332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow free(addrp); 1284332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1285332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *naddrs = count; 12864b110b426df7bf486a3e7884c56ebb3487023601Jan Engelhardt for (i = 0; i < count; ++i) 1287332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow (*addrpp+i)->s_addr &= (*maskpp+i)->s_addr; 1288332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow} 1289332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1290332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1291a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt/** 1292a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * xtables_ipparse_any - transform arbitrary name to in_addr 1293a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * 1294a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * Possible inputs (pseudo regex): 1295a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * m{^($hostname|$networkname|$ipaddr)(/$mask)?} 1296a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * "1.2.3.4/5", "1.2.3.4", "hostname", "networkname" 1297a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt */ 1298a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_ipparse_any(const char *name, struct in_addr **addrpp, 1299a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt struct in_addr *maskp, unsigned int *naddrs) 1300bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1301bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned int i, j, k, n; 1302bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in_addr *addrp; 1303bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt char buf[256], *p; 1304bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1305bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt strncpy(buf, name, sizeof(buf) - 1); 1306bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt buf[sizeof(buf) - 1] = '\0'; 1307bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((p = strrchr(buf, '/')) != NULL) { 1308bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *p = '\0'; 1309bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = parse_ipmask(p + 1); 1310bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } else { 1311bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = parse_ipmask(NULL); 1312bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1313bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memcpy(maskp, addrp, sizeof(*maskp)); 1314bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1315bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* if a null mask is given, the name is ignored, like in "any/0" */ 1316bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (maskp->s_addr == 0U) 1317bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt strcpy(buf, "0.0.0.0"); 1318bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1319bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = *addrpp = ipparse_hostnetwork(buf, naddrs); 1320bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt n = *naddrs; 1321bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (i = 0, j = 0; i < n; ++i) { 1322bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp[j++].s_addr &= maskp->s_addr; 1323bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (k = 0; k < j - 1; ++k) 1324bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (addrp[k].s_addr == addrp[j-1].s_addr) { 1325adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne /* 1326adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne * Nuke the dup by copying an address from the 1327adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne * tail here, and check the current position 1328adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne * again (--j). 1329adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne */ 1330adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne memcpy(&addrp[--j], &addrp[--*naddrs], 1331adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne sizeof(struct in_addr)); 1332bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt break; 1333bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1334bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1335bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1336bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1337e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6addr_to_numeric(const struct in6_addr *addrp) 133808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 1339cf3e52d00b7d3fedf98ef7710c337c441270d936Maciej Zenczykowski /* 0000:0000:0000:0000:0000:0000:000.000.000.000 134008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt * 0000:0000:0000:0000:0000:0000:0000:0000 */ 134108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt static char buf[50+1]; 134208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return inet_ntop(AF_INET6, addrp, buf, sizeof(buf)); 134308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 134408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 134508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ip6addr_to_host(const struct in6_addr *addr) 134608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 134708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt static char hostname[NI_MAXHOST]; 134808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt struct sockaddr_in6 saddr; 134908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt int err; 135008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 135108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt memset(&saddr, 0, sizeof(struct sockaddr_in6)); 135208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt memcpy(&saddr.sin6_addr, addr, sizeof(*addr)); 135308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt saddr.sin6_family = AF_INET6; 135408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 135508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt err = getnameinfo((const void *)&saddr, sizeof(struct sockaddr_in6), 135608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt hostname, sizeof(hostname) - 1, NULL, 0, 0); 135708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if (err != 0) { 135808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#ifdef DEBUG 135908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt fprintf(stderr,"IP2Name: %s\n",gai_strerror(err)); 136008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#endif 136108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return NULL; 136208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt } 136308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 136408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#ifdef DEBUG 136508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt fprintf (stderr, "\naddr2host: %s\n", hostname); 136608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#endif 136708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return hostname; 136808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 136908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 1370e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6addr_to_anyname(const struct in6_addr *addr) 137108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 137208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt const char *name; 137308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 137408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if ((name = ip6addr_to_host(addr)) != NULL) 137508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return name; 137608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 1377e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt return xtables_ip6addr_to_numeric(addr); 137808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 137908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 138008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic int ip6addr_prefix_length(const struct in6_addr *k) 138108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 138208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt unsigned int bits = 0; 138308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt uint32_t a, b, c, d; 138408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 138548607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt a = ntohl(k->s6_addr32[0]); 138648607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt b = ntohl(k->s6_addr32[1]); 138748607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt c = ntohl(k->s6_addr32[2]); 138848607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt d = ntohl(k->s6_addr32[3]); 138908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt while (a & 0x80000000U) { 139008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt ++bits; 139108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt a <<= 1; 139208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt a |= (b >> 31) & 1; 139308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt b <<= 1; 139408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt b |= (c >> 31) & 1; 139508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt c <<= 1; 139608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt c |= (d >> 31) & 1; 139708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt d <<= 1; 139808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt } 139908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if (a != 0 || b != 0 || c != 0 || d != 0) 140008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return -1; 140108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return bits; 140208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 140308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 1404e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6mask_to_numeric(const struct in6_addr *addrp) 140508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 140608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt static char buf[50+2]; 140708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt int l = ip6addr_prefix_length(addrp); 140808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 140908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if (l == -1) { 141008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt strcpy(buf, "/"); 1411e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt strcat(buf, xtables_ip6addr_to_numeric(addrp)); 141208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return buf; 141308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt } 141408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt sprintf(buf, "/%d", l); 141508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return buf; 141608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 1417bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 14181e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in6_addr *xtables_numeric_to_ip6addr(const char *num) 1419bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1420bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt static struct in6_addr ap; 1421bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt int err; 1422bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1423bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((err = inet_pton(AF_INET6, num, &ap)) == 1) 1424bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return ≈ 1425bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG 1426bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt fprintf(stderr, "\nnumeric2addr: %d\n", err); 1427bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif 1428bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1429bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1430bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1431bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr * 1432bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardthost_to_ip6addr(const char *name, unsigned int *naddr) 1433bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 14342ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne struct in6_addr *addr; 1435bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct addrinfo hints; 14362ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne struct addrinfo *res, *p; 1437bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt int err; 14382ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne unsigned int i; 1439bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1440bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memset(&hints, 0, sizeof(hints)); 1441bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt hints.ai_flags = AI_CANONNAME; 1442bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt hints.ai_family = AF_INET6; 1443bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt hints.ai_socktype = SOCK_RAW; 1444bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1445bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *naddr = 0; 1446bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((err = getaddrinfo(name, NULL, &hints, &res)) != 0) { 1447bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG 1448bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt fprintf(stderr,"Name2IP: %s\n",gai_strerror(err)); 1449bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif 1450bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1451bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } else { 14522ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne /* Find length of address chain */ 14532ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne for (p = res; p != NULL; p = p->ai_next) 14542ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne ++*naddr; 1455bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG 1456bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt fprintf(stderr, "resolved: len=%d %s ", res->ai_addrlen, 145730290aea009cf3fd76f27336fb4370be3467c4daPatrick McHardy xtables_ip6addr_to_numeric(&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr)); 1458bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif 14592ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne /* Copy each element of the address chain */ 14602ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne addr = xtables_calloc(*naddr, sizeof(struct in6_addr)); 14612ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne for (i = 0, p = res; p != NULL; p = p->ai_next) 14622ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne memcpy(&addr[i++], 14632ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne &((const struct sockaddr_in6 *)p->ai_addr)->sin6_addr, 14642ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne sizeof(struct in6_addr)); 1465bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt freeaddrinfo(res); 1466bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addr; 1467bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1468bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1469bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1470bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1471bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1472bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *network_to_ip6addr(const char *name) 1473bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1474bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* abort();*/ 1475bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* TODO: not implemented yet, but the exception breaks the 1476bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt * name resolvation */ 1477bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1478bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1479bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1480bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr * 1481bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtip6parse_hostnetwork(const char *name, unsigned int *naddrs) 1482bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1483bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in6_addr *addrp, *addrptmp; 1484bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 14851e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt if ((addrptmp = xtables_numeric_to_ip6addr(name)) != NULL || 1486bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt (addrptmp = network_to_ip6addr(name)) != NULL) { 1487630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt addrp = xtables_malloc(sizeof(struct in6_addr)); 1488bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memcpy(addrp, addrptmp, sizeof(*addrp)); 1489bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *naddrs = 1; 1490bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addrp; 1491bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1492bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((addrp = host_to_ip6addr(name, naddrs)) != NULL) 1493bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addrp; 1494bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 14958b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name); 1496bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1497bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1498bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *parse_ip6mask(char *mask) 1499bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1500bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt static struct in6_addr maskaddr; 1501bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in6_addr *addrp; 1502bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned int bits; 1503bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1504bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (mask == NULL) { 1505bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* no mask at all defaults to 128 bits */ 1506bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memset(&maskaddr, 0xff, sizeof maskaddr); 1507bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &maskaddr; 1508bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 15091e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt if ((addrp = xtables_numeric_to_ip6addr(mask)) != NULL) 1510bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addrp; 15115f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt if (!xtables_strtoui(mask, NULL, &bits, 0, 128)) 15128b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 1513bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt "invalid mask `%s' specified", mask); 1514bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (bits != 0) { 1515bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt char *p = (void *)&maskaddr; 1516bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memset(p, 0xff, bits / 8); 1517bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memset(p + (bits / 8) + 1, 0, (128 - bits) / 8); 1518bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt p[bits/8] = 0xff << (8 - (bits & 7)); 1519bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &maskaddr; 1520bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1521bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1522bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memset(&maskaddr, 0, sizeof(maskaddr)); 1523bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &maskaddr; 1524bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1525bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1526332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowvoid 1527332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowxtables_ip6parse_multiple(const char *name, struct in6_addr **addrpp, 1528332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow struct in6_addr **maskpp, unsigned int *naddrs) 1529332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow{ 153058df90174164fd673e8c4103f7ce0c4e55ef1aecOlaf Rempel static const struct in6_addr zero_addr; 1531332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow struct in6_addr *addrp; 1532332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow char buf[256], *p; 1533332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow unsigned int len, i, j, n, count = 1; 1534332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow const char *loop = name; 1535332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1536332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow while ((loop = strchr(loop, ',')) != NULL) { 1537332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow ++count; 1538332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow ++loop; /* skip ',' */ 1539332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1540332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1541332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *addrpp = xtables_malloc(sizeof(struct in6_addr) * count); 1542332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *maskpp = xtables_malloc(sizeof(struct in6_addr) * count); 1543332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1544332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow loop = name; 1545332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1546332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow for (i = 0; i < count /*NB: count can grow*/; ++i) { 1547332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (loop == NULL) 1548332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow break; 1549332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (*loop == ',') 1550332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow ++loop; 1551332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (*loop == '\0') 1552332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow break; 1553332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow p = strchr(loop, ','); 1554332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (p != NULL) 1555332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow len = p - loop; 1556332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow else 1557332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow len = strlen(loop); 1558332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (len == 0 || sizeof(buf) - 1 < len) 1559332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow break; 1560332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1561332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow strncpy(buf, loop, len); 1562332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow buf[len] = '\0'; 1563332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow loop += len; 1564332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if ((p = strrchr(buf, '/')) != NULL) { 1565332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *p = '\0'; 1566332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow addrp = parse_ip6mask(p + 1); 1567332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } else { 1568332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow addrp = parse_ip6mask(NULL); 1569332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1570332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*maskpp + i, addrp, sizeof(*addrp)); 1571332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1572332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* if a null mask is given, the name is ignored, like in "any/0" */ 157358df90174164fd673e8c4103f7ce0c4e55ef1aecOlaf Rempel if (memcmp(*maskpp + i, &zero_addr, sizeof(zero_addr)) == 0) 1574332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow strcpy(buf, "::"); 1575332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1576332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow addrp = ip6parse_hostnetwork(buf, &n); 1577332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (n > 1) { 1578332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow count += n - 1; 1579332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *addrpp = xtables_realloc(*addrpp, 1580332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(struct in6_addr) * count); 1581332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *maskpp = xtables_realloc(*maskpp, 1582332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(struct in6_addr) * count); 1583332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow for (j = 0; j < n; ++j) 1584332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* for each new addr */ 1585332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*addrpp + i + j, addrp + j, 1586332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(*addrp)); 1587332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow for (j = 1; j < n; ++j) 1588332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* for each new mask */ 1589332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*maskpp + i + j, *maskpp + i, 1590332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(*addrp)); 1591332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow i += n - 1; 1592332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } else { 1593332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*addrpp + i, addrp, sizeof(*addrp)); 1594332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1595332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* free what ip6parse_hostnetwork had allocated: */ 1596332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow free(addrp); 1597332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1598332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *naddrs = count; 15994b110b426df7bf486a3e7884c56ebb3487023601Jan Engelhardt for (i = 0; i < count; ++i) 1600332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow for (j = 0; j < 4; ++j) 1601332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow (*addrpp+i)->s6_addr32[j] &= (*maskpp+i)->s6_addr32[j]; 1602332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow} 1603332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1604a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_ip6parse_any(const char *name, struct in6_addr **addrpp, 1605a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt struct in6_addr *maskp, unsigned int *naddrs) 1606bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 16079c0fa7d8c84dc2478bd36d31b328b697fbe4d0afJan Engelhardt static const struct in6_addr zero_addr; 1608bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in6_addr *addrp; 1609bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned int i, j, k, n; 1610bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt char buf[256], *p; 1611bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1612bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt strncpy(buf, name, sizeof(buf) - 1); 1613bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt buf[sizeof(buf)-1] = '\0'; 1614bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((p = strrchr(buf, '/')) != NULL) { 1615bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *p = '\0'; 1616bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = parse_ip6mask(p + 1); 1617bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } else { 1618bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = parse_ip6mask(NULL); 1619bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1620bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memcpy(maskp, addrp, sizeof(*maskp)); 1621bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1622bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* if a null mask is given, the name is ignored, like in "any/0" */ 16239c0fa7d8c84dc2478bd36d31b328b697fbe4d0afJan Engelhardt if (memcmp(maskp, &zero_addr, sizeof(zero_addr)) == 0) 1624bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt strcpy(buf, "::"); 1625bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1626bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = *addrpp = ip6parse_hostnetwork(buf, naddrs); 1627bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt n = *naddrs; 1628bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (i = 0, j = 0; i < n; ++i) { 1629bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (k = 0; k < 4; ++k) 16305a2208c3e62a150e6f6297abbfa63056ab4a8066Yasuyuki Kozakai addrp[j].s6_addr32[k] &= maskp->s6_addr32[k]; 1631bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt ++j; 1632bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (k = 0; k < j - 1; ++k) 1633bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (IN6_ARE_ADDR_EQUAL(&addrp[k], &addrp[j - 1])) { 1634adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne /* 1635adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne * Nuke the dup by copying an address from the 1636adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne * tail here, and check the current position 1637adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne * again (--j). 1638adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne */ 1639adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne memcpy(&addrp[--j], &addrp[--*naddrs], 1640adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne sizeof(struct in_addr)); 1641bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt break; 1642bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1643bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1644bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1645a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann 1646a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_save_string(const char *value) 1647a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann{ 1648a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann static const char no_quote_chars[] = "_-0123456789" 1649a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann "abcdefghijklmnopqrstuvwxyz" 1650a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 1651a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann static const char escape_chars[] = "\"\\'"; 1652a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann size_t length; 1653a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann const char *p; 1654a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann 165587dc7c4c842deb1e2e3d38089ffcad9f238d98deMax Kellerman length = strspn(value, no_quote_chars); 1656a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann if (length > 0 && value[length] == 0) { 1657a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann /* no quoting required */ 1658a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann putchar(' '); 165973866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt fputs(value, stdout); 1660a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann } else { 1661a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann /* there is at least one dangerous character in the 1662a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann value, which we have to quote. Write double quotes 1663a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann around the value and escape special characters with 1664a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann a backslash */ 166573866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" \""); 1666a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann 1667a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann for (p = strpbrk(value, escape_chars); p != NULL; 1668a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann p = strpbrk(value, escape_chars)) { 1669a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann if (p > value) 1670a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann fwrite(value, 1, p - value, stdout); 1671a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann putchar('\\'); 1672a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann putchar(*p); 1673a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann value = p + 1; 1674a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann } 1675a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann 1676a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann /* print the rest and finish the double quoted 1677a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann string */ 1678a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann fputs(value, stdout); 167973866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt putchar('\"'); 1680a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann } 1681a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann} 16820f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt 16830f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt/** 16840f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt * Check for option-intrapositional negation. 16850f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt * Do not use in new code. 16860f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt */ 16870f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardtint xtables_check_inverse(const char option[], int *invert, 1688bf97128c7262f17a02fec41cdae75b472ba77f88Jan Engelhardt int *my_optind, int argc, char **argv) 16890f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt{ 16902be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt if (option == NULL || strcmp(option, "!") != 0) 16912be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt return false; 16920f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt 16932be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt fprintf(stderr, "Using intrapositioned negation " 16942be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt "(`--option ! this`) is deprecated in favor of " 16952be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt "extrapositioned (`! --option this`).\n"); 16960f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt 16972be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt if (*invert) 16982be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 16992be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt "Multiple `!' flags not allowed"); 17002be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt *invert = true; 17012be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt if (my_optind != NULL) { 1702bf97128c7262f17a02fec41cdae75b472ba77f88Jan Engelhardt optarg = argv[*my_optind]; 17032be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt ++*my_optind; 17042be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt if (argc && *my_optind > argc) 17052be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 17062be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt "no argument following `!'"); 17070f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt } 17082be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt 17092be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt return true; 17100f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt} 17111de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt 17121de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardtconst struct xtables_pprot xtables_chain_protos[] = { 17131de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"tcp", IPPROTO_TCP}, 17141de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"sctp", IPPROTO_SCTP}, 17151de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"udp", IPPROTO_UDP}, 17161de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"udplite", IPPROTO_UDPLITE}, 17171de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"icmp", IPPROTO_ICMP}, 17181de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"icmpv6", IPPROTO_ICMPV6}, 17191de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"ipv6-icmp", IPPROTO_ICMPV6}, 17201de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"esp", IPPROTO_ESP}, 17211de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"ah", IPPROTO_AH}, 17221de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"ipv6-mh", IPPROTO_MH}, 17231de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"mh", IPPROTO_MH}, 17241de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"all", 0}, 17251de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {NULL}, 17261de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt}; 17271de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt 17287ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtuint16_t 17291de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardtxtables_parse_protocol(const char *s) 17301de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt{ 17311de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt unsigned int proto; 17321de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt 17331de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt if (!xtables_strtoui(s, NULL, &proto, 0, UINT8_MAX)) { 17341de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt struct protoent *pent; 17351de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt 17361de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt /* first deal with the special case of 'all' to prevent 17371de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt * people from being able to redefine 'all' in nsswitch 17381de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt * and/or provoke expensive [not working] ldap/nis/... 17391de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt * lookups */ 17401de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt if (!strcmp(s, "all")) 17411de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt return 0; 17421de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt 17431de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt if ((pent = getprotobyname(s))) 17441de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt proto = pent->p_proto; 17451de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt else { 17461de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt unsigned int i; 17471de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt for (i = 0; i < ARRAY_SIZE(xtables_chain_protos); ++i) { 1748e55cc4aaa6e35448c14370e5261c3387d26b257dPablo Neira Ayuso if (xtables_chain_protos[i].name == NULL) 1749e55cc4aaa6e35448c14370e5261c3387d26b257dPablo Neira Ayuso continue; 1750e55cc4aaa6e35448c14370e5261c3387d26b257dPablo Neira Ayuso 17511de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt if (strcmp(s, xtables_chain_protos[i].name) == 0) { 17521de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt proto = xtables_chain_protos[i].num; 17531de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt break; 17541de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt } 17551de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt } 17561de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt if (i == ARRAY_SIZE(xtables_chain_protos)) 17578b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 17581de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt "unknown protocol `%s' specified", 17591de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt s); 17601de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt } 17611de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt } 17621de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt 17631de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt return proto; 17641de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt} 1765