xtables.c revision e1639b0bc28420ca01d733749c8db16d5a3fbd0c
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> 52aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include "iptables/internal.h" 531e128bd804b676ee91beca48312de9b251845d09Jan Engelhardt#include "xshared.h" 545a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger 550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#define NPROTO 255 560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 570b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#ifndef PROC_SYS_MODPROBE 580b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe" 590b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#endif 600b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 618b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salimvoid basic_exit_err(enum xtables_exittype status, const char *msg, ...) __attribute__((noreturn, format(printf,2,3))); 628b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim 6340a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salimstruct xtables_globals *xt_params = NULL; 6440a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim 658b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salimvoid basic_exit_err(enum xtables_exittype status, const char *msg, ...) 6640a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim{ 6740a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim va_list args; 6840a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim 6940a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim va_start(args, msg); 7040a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim fprintf(stderr, "%s v%s: ", xt_params->program_name, xt_params->program_version); 7140a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim vfprintf(stderr, msg, args); 7240a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim va_end(args); 7340a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim fprintf(stderr, "\n"); 7440a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim exit(status); 7540a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim} 7640a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim 77600f38db82548a683775fd89b6e136673e924097Jan Engelhardtvoid xtables_free_opts(int unused) 7884c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim{ 79df288236cd254798be3759fef4cbc3e535f5a1c3Jan Engelhardt if (xt_params->opts != xt_params->orig_opts) { 8059e8114c6792242e80785f4461d5e663fb9a3d64Jan Engelhardt free(xt_params->opts); 81df288236cd254798be3759fef4cbc3e535f5a1c3Jan Engelhardt xt_params->opts = NULL; 82df288236cd254798be3759fef4cbc3e535f5a1c3Jan Engelhardt } 8384c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim} 8484c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim 85600f38db82548a683775fd89b6e136673e924097Jan Engelhardtstruct option *xtables_merge_options(struct option *orig_opts, 86600f38db82548a683775fd89b6e136673e924097Jan Engelhardt struct option *oldopts, 8770581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim const struct option *newopts, 8870581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim unsigned int *option_offset) 8970581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim{ 90600f38db82548a683775fd89b6e136673e924097Jan Engelhardt unsigned int num_oold = 0, num_old = 0, num_new = 0, i; 91600f38db82548a683775fd89b6e136673e924097Jan Engelhardt struct option *merge, *mp; 9270581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim 9370581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim if (newopts == NULL) 9470581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim return oldopts; 9570581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim 96600f38db82548a683775fd89b6e136673e924097Jan Engelhardt for (num_oold = 0; orig_opts[num_oold].name; num_oold++) ; 97600f38db82548a683775fd89b6e136673e924097Jan Engelhardt if (oldopts != NULL) 98600f38db82548a683775fd89b6e136673e924097Jan Engelhardt for (num_old = 0; oldopts[num_old].name; num_old++) ; 9970581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim for (num_new = 0; newopts[num_new].name; num_new++) ; 10070581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim 1011dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt /* 1021dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt * Since @oldopts also has @orig_opts already (and does so at the 1031dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt * start), skip these entries. 1041dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt */ 1051dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt oldopts += num_oold; 1061dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt num_old -= num_oold; 1071dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt 108600f38db82548a683775fd89b6e136673e924097Jan Engelhardt merge = malloc(sizeof(*mp) * (num_oold + num_old + num_new + 1)); 109600f38db82548a683775fd89b6e136673e924097Jan Engelhardt if (merge == NULL) 110600f38db82548a683775fd89b6e136673e924097Jan Engelhardt return NULL; 111600f38db82548a683775fd89b6e136673e924097Jan Engelhardt 112600f38db82548a683775fd89b6e136673e924097Jan Engelhardt /* Let the base options -[ADI...] have precedence over everything */ 113600f38db82548a683775fd89b6e136673e924097Jan Engelhardt memcpy(merge, orig_opts, sizeof(*mp) * num_oold); 114600f38db82548a683775fd89b6e136673e924097Jan Engelhardt mp = merge + num_oold; 115600f38db82548a683775fd89b6e136673e924097Jan Engelhardt 116600f38db82548a683775fd89b6e136673e924097Jan Engelhardt /* Second, the new options */ 1171e128bd804b676ee91beca48312de9b251845d09Jan Engelhardt xt_params->option_offset += XT_OPTION_OFFSET_SCALE; 11870581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim *option_offset = xt_params->option_offset; 119600f38db82548a683775fd89b6e136673e924097Jan Engelhardt memcpy(mp, newopts, sizeof(*mp) * num_new); 12070581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim 121600f38db82548a683775fd89b6e136673e924097Jan Engelhardt for (i = 0; i < num_new; ++i, ++mp) 122600f38db82548a683775fd89b6e136673e924097Jan Engelhardt mp->val += *option_offset; 123600f38db82548a683775fd89b6e136673e924097Jan Engelhardt 124600f38db82548a683775fd89b6e136673e924097Jan Engelhardt /* Third, the old options */ 125600f38db82548a683775fd89b6e136673e924097Jan Engelhardt memcpy(mp, oldopts, sizeof(*mp) * num_old); 126600f38db82548a683775fd89b6e136673e924097Jan Engelhardt mp += num_old; 127600f38db82548a683775fd89b6e136673e924097Jan Engelhardt xtables_free_opts(0); 12870581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim 129600f38db82548a683775fd89b6e136673e924097Jan Engelhardt /* Clear trailing entry */ 130600f38db82548a683775fd89b6e136673e924097Jan Engelhardt memset(mp, 0, sizeof(*mp)); 13170581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim return merge; 13270581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim} 13370581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim 13477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtstatic const struct xtables_afinfo afinfo_ipv4 = { 13577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .kmod = "ip_tables", 13677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .libprefix = "libipt_", 13777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .family = NFPROTO_IPV4, 13877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .ipproto = IPPROTO_IP, 13977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .so_rev_match = IPT_SO_GET_REVISION_MATCH, 14077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .so_rev_target = IPT_SO_GET_REVISION_TARGET, 14177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt}; 14277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt 14377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtstatic const struct xtables_afinfo afinfo_ipv6 = { 14477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .kmod = "ip6_tables", 14577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .libprefix = "libip6t_", 14677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .family = NFPROTO_IPV6, 14777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .ipproto = IPPROTO_IPV6, 14877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .so_rev_match = IP6T_SO_GET_REVISION_MATCH, 14977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .so_rev_target = IP6T_SO_GET_REVISION_TARGET, 15077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt}; 15177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt 152aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtconst struct xtables_afinfo *afinfo; 15377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt 15439bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt/* Search path for Xtables .so files */ 15539bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardtstatic const char *xtables_libdir; 1560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 1570b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI/* the path to command to load kernel module */ 158c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtconst char *xtables_modprobe_program; 1590b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 1600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI/* Keeping track of external matches and targets: linked lists. */ 1610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_match *xtables_matches; 1620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_target *xtables_targets; 1630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 16439bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardtvoid xtables_init(void) 16539bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt{ 16639bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt xtables_libdir = getenv("XTABLES_LIBDIR"); 16739bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt if (xtables_libdir != NULL) 16839bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt return; 16939bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt xtables_libdir = getenv("IPTABLES_LIB_DIR"); 17039bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt if (xtables_libdir != NULL) { 17139bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt fprintf(stderr, "IPTABLES_LIB_DIR is deprecated, " 17239bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt "use XTABLES_LIBDIR.\n"); 17339bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt return; 17439bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt } 175ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt /* 176ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt * Well yes, IP6TABLES_LIB_DIR is of lower priority over 177ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt * IPTABLES_LIB_DIR since this moved to libxtables; I think that is ok 178ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt * for these env vars are deprecated anyhow, and in light of the 179ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt * (shared) libxt_*.so files, makes less sense to have 180ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt * IPTABLES_LIB_DIR != IP6TABLES_LIB_DIR. 181ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt */ 182ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt xtables_libdir = getenv("IP6TABLES_LIB_DIR"); 183ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt if (xtables_libdir != NULL) { 184ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt fprintf(stderr, "IP6TABLES_LIB_DIR is deprecated, " 185ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt "use XTABLES_LIBDIR.\n"); 186ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt return; 187ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt } 18839bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt xtables_libdir = XTABLES_LIBDIR; 18939bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt} 19039bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt 19177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtvoid xtables_set_nfproto(uint8_t nfproto) 19277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt{ 19377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt switch (nfproto) { 19477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt case NFPROTO_IPV4: 19577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt afinfo = &afinfo_ipv4; 19677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt break; 19777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt case NFPROTO_IPV6: 19877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt afinfo = &afinfo_ipv6; 19977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt break; 20077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt default: 20177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt fprintf(stderr, "libxtables: unhandled NFPROTO in %s\n", 20277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt __func__); 20377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt } 20477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt} 20577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt 206630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt/** 2077e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * xtables_set_params - set the global parameters used by xtables 2087e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * @xtp: input xtables_globals structure 2097e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * 2107e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * The app is expected to pass a valid xtables_globals data-filled 2117e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * with proper values 2127e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * @xtp cannot be NULL 2137e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * 2147e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * Returns -1 on failure to set and 0 on success 2157e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim */ 2167e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salimint xtables_set_params(struct xtables_globals *xtp) 2177e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim{ 2187e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim if (!xtp) { 2197e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim fprintf(stderr, "%s: Illegal global params\n",__func__); 2207e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim return -1; 2217e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim } 2227e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim 2237e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim xt_params = xtp; 2247e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim 2257e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim if (!xt_params->exit_err) 2267e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim xt_params->exit_err = basic_exit_err; 2277e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim 2287e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim return 0; 2297e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim} 2307e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim 2317e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salimint xtables_init_all(struct xtables_globals *xtp, uint8_t nfproto) 2327e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim{ 2337e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim xtables_init(); 2347e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim xtables_set_nfproto(nfproto); 2357e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim return xtables_set_params(xtp); 2367e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim} 2377e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim 2387e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim/** 239630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt * xtables_*alloc - wrappers that exit on failure 240630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt */ 241630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardtvoid *xtables_calloc(size_t count, size_t size) 2423dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI{ 2433dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI void *p; 2443dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 2453dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI if ((p = calloc(count, size)) == NULL) { 2463dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI perror("ip[6]tables: calloc failed"); 2473dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI exit(1); 2483dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI } 2493dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 2503dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI return p; 2513dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI} 2523dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 253630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardtvoid *xtables_malloc(size_t size) 2543dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI{ 2553dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI void *p; 2563dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 2573dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI if ((p = malloc(size)) == NULL) { 2583dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI perror("ip[6]tables: malloc failed"); 2593dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI exit(1); 2603dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI } 2613dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 2623dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI return p; 2633dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI} 2640b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 265332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowvoid *xtables_realloc(void *ptr, size_t size) 266332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow{ 267332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow void *p; 268332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 269332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if ((p = realloc(ptr, size)) == NULL) { 270332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow perror("ip[6]tables: realloc failed"); 271332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow exit(1); 272332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 273332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 274332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow return p; 275332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow} 276332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 2770b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAIstatic char *get_modprobe(void) 2780b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI{ 2790b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI int procfile; 2800b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI char *ret; 2810b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 2820b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#define PROCFILE_BUFSIZ 1024 2830b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI procfile = open(PROC_SYS_MODPROBE, O_RDONLY); 2840b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (procfile < 0) 2850b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return NULL; 286a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski if (fcntl(procfile, F_SETFD, FD_CLOEXEC) == -1) { 287a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski fprintf(stderr, "Could not set close on exec: %s\n", 288a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski strerror(errno)); 289a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski exit(1); 290a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski } 2910b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 292371cea299f0b2eb100b9fc9fb99089640d2d606fJan Engelhardt ret = malloc(PROCFILE_BUFSIZ); 2930b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (ret) { 2940b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI memset(ret, 0, PROCFILE_BUFSIZ); 2950b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI switch (read(procfile, ret, PROCFILE_BUFSIZ)) { 2960b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI case -1: goto fail; 2970b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI case PROCFILE_BUFSIZ: goto fail; /* Partial read. Wierd */ 2980b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 2990b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (ret[strlen(ret)-1]=='\n') 3000b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI ret[strlen(ret)-1]=0; 3010b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI close(procfile); 3020b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return ret; 3030b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 3040b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI fail: 3050b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI free(ret); 3060b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI close(procfile); 3070b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return NULL; 3080b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI} 3090b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 310c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtint xtables_insmod(const char *modname, const char *modprobe, bool quiet) 3110b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI{ 3120b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI char *buf = NULL; 3130b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI char *argv[4]; 3140b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI int status; 3150b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 3160b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI /* If they don't explicitly set it, read out of kernel */ 3170b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (!modprobe) { 3180b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI buf = get_modprobe(); 3190b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (!buf) 3200b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return -1; 3210b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI modprobe = buf; 3220b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 3230b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 324c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt /* 325c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt * Need to flush the buffer, or the child may output it again 326c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt * when switching the program thru execv. 327c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt */ 328c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt fflush(stdout); 329c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt 33094aa2ea67d7b8a669e8541f094661a1dc89722a3Jan Engelhardt switch (vfork()) { 3310b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI case 0: 3320b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[0] = (char *)modprobe; 3330b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[1] = (char *)modname; 3340b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (quiet) { 3350b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[2] = "-q"; 3360b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[3] = NULL; 3370b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } else { 3380b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[2] = NULL; 3390b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[3] = NULL; 3400b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 3410b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI execv(argv[0], argv); 3420b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 3430b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI /* not usually reached */ 3440b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI exit(1); 3450b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI case -1: 3460b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return -1; 3470b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 3480b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI default: /* parent */ 3490b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI wait(&status); 3500b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 3510b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 3520b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI free(buf); 3530b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (WIFEXITED(status) && WEXITSTATUS(status) == 0) 3540b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return 0; 3550b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return -1; 3560b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI} 3570b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 358c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtint xtables_load_ko(const char *modprobe, bool quiet) 3590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 360c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardt static bool loaded = false; 3610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI static int ret = -1; 3620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (!loaded) { 36477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt ret = xtables_insmod(afinfo->kmod, modprobe, quiet); 3650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI loaded = (ret == 0); 3660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 3670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return ret; 3690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 3700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 3715f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt/** 3725f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * xtables_strtou{i,l} - string to number conversion 3735f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @s: input string 3745f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @end: like strtoul's "end" pointer 3755f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @value: pointer for result 3765f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @min: minimum accepted value 3775f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @max: maximum accepted value 3785f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * 3795f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * If @end is NULL, we assume the caller wants a "strict strtoul", and hence 3805f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * "15a" is rejected. 3815f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * In either case, the value obtained is compared for min-max compliance. 3825f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * Base is always 0, i.e. autodetect depending on @s. 383cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt * 3845f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * Returns true/false whether number was accepted. On failure, *value has 3855f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * undefined contents. 386cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt */ 3875f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardtbool xtables_strtoul(const char *s, char **end, unsigned long *value, 3885f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt unsigned long min, unsigned long max) 389cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt{ 390cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt unsigned long v; 391cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt char *my_end; 392cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 393cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt errno = 0; 394cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt v = strtoul(s, &my_end, 0); 395cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 396cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (my_end == s) 397cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return false; 398cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (end != NULL) 399cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt *end = my_end; 400cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 401cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (errno != ERANGE && min <= v && (max == 0 || v <= max)) { 402cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (value != NULL) 403cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt *value = v; 404cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (end == NULL) 405cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return *my_end == '\0'; 406cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return true; 407cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt } 408cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 409cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return false; 410cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt} 411cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 4125f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardtbool xtables_strtoui(const char *s, char **end, unsigned int *value, 4135f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt unsigned int min, unsigned int max) 414cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt{ 415cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt unsigned long v; 416cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt bool ret; 417cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 4185f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt ret = xtables_strtoul(s, end, &v, min, max); 419cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (value != NULL) 420cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt *value = v; 421cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return ret; 422cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt} 423cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 424aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardtint xtables_service_to_port(const char *name, const char *proto) 42504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{ 42604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI struct servent *service; 42704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 42804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI if ((service = getservbyname(name, proto)) != NULL) 42904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI return ntohs((unsigned short) service->s_port); 43004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 43104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI return -1; 43204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI} 43304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 4347ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtuint16_t xtables_parse_port(const char *port, const char *proto) 43504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{ 4367a236f4cc685a420c1a782a5db614a93baf37ccfJan Engelhardt unsigned int portnum; 43704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 4385f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt if (xtables_strtoui(port, NULL, &portnum, 0, UINT16_MAX) || 439aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardt (portnum = xtables_service_to_port(port, proto)) != (unsigned)-1) 440213e185afbb298e6708881e4c2adffdc47a8b6daJan Engelhardt return portnum; 44104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 4428b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 44304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI "invalid port/service `%s' specified", port); 44404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI} 44504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 446aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardtvoid xtables_parse_interface(const char *arg, char *vianame, 447aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardt unsigned char *mask) 44804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{ 449fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt unsigned int vialen = strlen(arg); 45004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI unsigned int i; 45104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 45204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask, 0, IFNAMSIZ); 45304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(vianame, 0, IFNAMSIZ); 45404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 45504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI if (vialen + 1 > IFNAMSIZ) 4568b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 45704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI "interface name `%s' must be shorter than IFNAMSIZ" 45804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI " (%i)", arg, IFNAMSIZ-1); 45904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 46004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI strcpy(vianame, arg); 461fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt if (vialen == 0) 46204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask, 0, IFNAMSIZ); 46304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI else if (vianame[vialen - 1] == '+') { 46404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask, 0xFF, vialen - 1); 46504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask + vialen - 1, 0, IFNAMSIZ - vialen + 1); 46604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI /* Don't remove `+' here! -HW */ 46704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } else { 46804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI /* Include nul-terminator in match */ 46904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask, 0xFF, vialen + 1); 47004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask + vialen + 1, 0, IFNAMSIZ - vialen - 1); 47104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI for (i = 0; vianame[i]; i++) { 472fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt if (vianame[i] == '/' || 473fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt vianame[i] == ' ') { 474aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann fprintf(stderr, 475aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann "Warning: weird character in interface" 476fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt " `%s' ('/' and ' ' are not allowed by the kernel).\n", 477aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann vianame); 47804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI break; 47904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } 48004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } 48104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } 48204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI} 48304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 484cb25af809a8734c4766b6bfa4cca99596cbf01dbJan Engelhardt#ifndef NO_SHARED_LIBS 485927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardtstatic void *load_extension(const char *search_path, const char *af_prefix, 48621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt const char *name, bool is_target) 48721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt{ 488927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt const char *all_prefixes[] = {"libxt_", af_prefix, NULL}; 489927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt const char **prefix; 49021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt const char *dir = search_path, *next; 49121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt void *ptr = NULL; 49221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt struct stat sb; 49321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt char path[256]; 49421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 49521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt do { 49621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt next = strchr(dir, ':'); 49721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt if (next == NULL) 49821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt next = dir + strlen(dir); 49921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 500927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt for (prefix = all_prefixes; *prefix != NULL; ++prefix) { 501927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt snprintf(path, sizeof(path), "%.*s/%s%s.so", 502927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt (unsigned int)(next - dir), dir, 503927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt *prefix, name); 504927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt 505927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt if (stat(path, &sb) != 0) { 506927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt if (errno == ENOENT) 507927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt continue; 508927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt fprintf(stderr, "%s: %s\n", path, 509927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt strerror(errno)); 510927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt return NULL; 511927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt } 512927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt if (dlopen(path, RTLD_NOW) == NULL) { 513927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt fprintf(stderr, "%s: %s\n", path, dlerror()); 514927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt break; 515927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt } 51621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 51721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt if (is_target) 5182338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt ptr = xtables_find_target(name, XTF_DONT_LOAD); 51921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt else 5202338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt ptr = xtables_find_match(name, 5212338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt XTF_DONT_LOAD, NULL); 52221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 523927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt if (ptr != NULL) 524927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt return ptr; 52521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 526927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt fprintf(stderr, "%s: no \"%s\" extension found for " 527927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt "this protocol\n", path, name); 528927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt errno = ENOENT; 529927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt return NULL; 530927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt } 53121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt dir = next + 1; 53221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt } while (*next != '\0'); 53321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 53421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt return NULL; 53521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt} 536cb25af809a8734c4766b6bfa4cca99596cbf01dbJan Engelhardt#endif 53721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 5382338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtstruct xtables_match * 5392338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtxtables_find_match(const char *name, enum xtables_tryload tryload, 5402338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt struct xtables_rule_match **matches) 5410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 5420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_match *ptr; 5430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI const char *icmp6 = "icmp6"; 5440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5450cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt if (strlen(name) >= XT_EXTENSION_MAXNAMELEN) 54621d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt xtables_error(PARAMETER_PROBLEM, 54721d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt "Invalid match name \"%s\" (%u chars max)", 5480cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt name, XT_EXTENSION_MAXNAMELEN - 1); 54921d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt 5500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* This is ugly as hell. Nonetheless, there is no way of changing 5510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI * this without hurting backwards compatibility */ 5520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if ( (strcmp(name,"icmpv6") == 0) || 5530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI (strcmp(name,"ipv6-icmp") == 0) || 5540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI (strcmp(name,"icmp6") == 0) ) 5550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI name = icmp6; 5560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (ptr = xtables_matches; ptr; ptr = ptr->next) { 5580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(name, ptr->name) == 0) { 5590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_match *clone; 5600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* First match of this type: */ 5620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr->m == NULL) 5630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI break; 5640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Second and subsequent clones */ 566630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt clone = xtables_malloc(sizeof(struct xtables_match)); 5670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI memcpy(clone, ptr, sizeof(struct xtables_match)); 5680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI clone->mflags = 0; 5690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* This is a clone: */ 5700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI clone->next = clone; 5710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr = clone; 5730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI break; 5740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#ifndef NO_SHARED_LIBS 5782338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) { 57977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt ptr = load_extension(xtables_libdir, afinfo->libprefix, 58039bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt name, false); 581170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI 5822338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) 5838b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 5840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "Couldn't load match `%s':%s\n", 585927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt name, strerror(errno)); 5860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#else 5880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr && !ptr->loaded) { 5892338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if (tryload != XTF_DONT_LOAD) 5900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr->loaded = 1; 5910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI else 5920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr = NULL; 5930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5942338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if(!ptr && (tryload == XTF_LOAD_MUST_SUCCEED)) { 5958b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 5960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "Couldn't find match `%s'\n", name); 5970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 5980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#endif 5990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr && matches) { 6010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_rule_match **i; 6020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_rule_match *newentry; 6030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 604630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt newentry = xtables_malloc(sizeof(struct xtables_rule_match)); 6050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (i = matches; *i; i = &(*i)->next) { 6070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(name, (*i)->match->name) == 0) 6082338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt (*i)->completed = true; 6090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI newentry->match = ptr; 6112338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt newentry->completed = false; 6120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI newentry->next = NULL; 6130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI *i = newentry; 6140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6160d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return ptr; 6170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 6180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6192338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtstruct xtables_target * 6202338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtxtables_find_target(const char *name, enum xtables_tryload tryload) 6210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 6220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_target *ptr; 6230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Standard target? */ 6250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(name, "") == 0 6260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI || strcmp(name, XTC_LABEL_ACCEPT) == 0 6270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI || strcmp(name, XTC_LABEL_DROP) == 0 6280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI || strcmp(name, XTC_LABEL_QUEUE) == 0 6290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI || strcmp(name, XTC_LABEL_RETURN) == 0) 6300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI name = "standard"; 6310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (ptr = xtables_targets; ptr; ptr = ptr->next) { 6330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(name, ptr->name) == 0) 6340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI break; 6350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#ifndef NO_SHARED_LIBS 6382338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) { 63977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt ptr = load_extension(xtables_libdir, afinfo->libprefix, 64039bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt name, true); 641170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI 6422338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) 6438b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 6440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "Couldn't load target `%s':%s\n", 645927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt name, strerror(errno)); 6460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#else 6480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr && !ptr->loaded) { 6492338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if (tryload != XTF_DONT_LOAD) 6500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr->loaded = 1; 6510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI else 6520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr = NULL; 6530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 654854d2d9bd7556cfd8a676b0bc18dc059a9a2dd25Peter Volkov if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) { 6558b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 6560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "Couldn't find target `%s'\n", name); 6570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#endif 6590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr) 6610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr->used = 1; 6620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return ptr; 6640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 6650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6667ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtstatic int compatible_revision(const char *name, uint8_t revision, int opt) 6670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 6680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xt_get_revision rev; 6690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI socklen_t s = sizeof(rev); 6700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI int max_rev, sockfd; 6710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 67277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt sockfd = socket(afinfo->family, SOCK_RAW, IPPROTO_RAW); 6730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (sockfd < 0) { 674df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy if (errno == EPERM) { 675df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy /* revision 0 is always supported. */ 676df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy if (revision != 0) 677e1639b0bc28420ca01d733749c8db16d5a3fbd0cJan Engelhardt fprintf(stderr, "%s: Could not determine whether " 678df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy "revision %u is supported, " 679df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy "assuming it is.\n", 680e1639b0bc28420ca01d733749c8db16d5a3fbd0cJan Engelhardt name, revision); 681df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy return 1; 682df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy } 6830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "Could not open socket to kernel: %s\n", 6840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI strerror(errno)); 6850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 6860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 688a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski if (fcntl(sockfd, F_SETFD, FD_CLOEXEC) == -1) { 689a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski fprintf(stderr, "Could not set close on exec: %s\n", 690a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski strerror(errno)); 691a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski exit(1); 692a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski } 693a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski 694c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardt xtables_load_ko(xtables_modprobe_program, true); 6950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI strcpy(rev.name, name); 6970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI rev.revision = revision; 6980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 69977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt max_rev = getsockopt(sockfd, afinfo->ipproto, opt, &rev, &s); 7000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (max_rev < 0) { 7010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Definitely don't support this? */ 7020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (errno == ENOENT || errno == EPROTONOSUPPORT) { 7030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI close(sockfd); 7040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return 0; 7050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } else if (errno == ENOPROTOOPT) { 7060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI close(sockfd); 7070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Assume only revision 0 support (old kernel) */ 7080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return (revision == 0); 7090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } else { 7100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "getsockopt failed strangely: %s\n", 7110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI strerror(errno)); 7120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 7130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 7140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 7150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI close(sockfd); 7160d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return 1; 7170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 7180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7207ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtstatic int compatible_match_revision(const char *name, uint8_t revision) 7210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 72277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt return compatible_revision(name, revision, afinfo->so_rev_match); 7230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 7240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7257ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtstatic int compatible_target_revision(const char *name, uint8_t revision) 7260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 72777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt return compatible_revision(name, revision, afinfo->so_rev_target); 7280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 7290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 730dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardtstatic void xtables_check_options(const char *name, const struct option *opt) 731dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt{ 732dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt for (; opt->name != NULL; ++opt) 733dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt if (opt->val < 0 || opt->val >= XT_OPTION_OFFSET_SCALE) { 734dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt fprintf(stderr, "%s: Extension %s uses invalid " 735dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt "option value %d\n",xt_params->program_name, 736dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt name, opt->val); 737dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt exit(1); 738dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt } 739dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt} 740dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt 7410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIvoid xtables_register_match(struct xtables_match *me) 7420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 7430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_match **i, *old; 7440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 745c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt if (me->version == NULL) { 746c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt fprintf(stderr, "%s: match %s<%u> is missing a version\n", 747c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt xt_params->program_name, me->name, me->revision); 748c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt exit(1); 749c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt } 750dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt if (strcmp(me->version, XTABLES_VERSION) != 0) { 751dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt fprintf(stderr, "%s: match \"%s\" has version \"%s\", " 752dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt "but \"%s\" is required.\n", 7535dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name, 754dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt me->version, XTABLES_VERSION); 7550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 7560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 7570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7580cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) { 759281439ba6b96b729ef1400a49ec53eda298bb9f8Li Yewang fprintf(stderr, "%s: match `%s' has invalid name\n", 7605dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name); 7610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 7620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 7630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (me->family >= NPROTO) { 7650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, 7660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "%s: BUG: match %s has invalid protocol family\n", 7675dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name); 7680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 7690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 7700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 771aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (me->x6_options != NULL) 772aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtables_option_metavalidate(me->name, me->x6_options); 773dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt if (me->extra_opts != NULL) 774dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt xtables_check_options(me->name, me->extra_opts); 775dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt 7760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* ignore not interested match */ 77777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt if (me->family != afinfo->family && me->family != AF_UNSPEC) 7780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 7790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7802338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt old = xtables_find_match(me->name, XTF_DURING_LOAD, NULL); 7810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (old) { 78223545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt if (old->revision == me->revision && 78323545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt old->family == me->family) { 7840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, 7850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "%s: match `%s' already registered.\n", 7865dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name); 7870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 7880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 7890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Now we have two (or more) options, check compatibility. */ 7910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (compatible_match_revision(old->name, old->revision) 7920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI && old->revision > me->revision) 7930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 7940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 79523545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt /* See if new match can be used. */ 7960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (!compatible_match_revision(me->name, me->revision)) 7970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 7980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 79923545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt /* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */ 80023545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt if (old->revision == me->revision && me->family == AF_UNSPEC) 80123545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt return; 80223545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt 8030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Delete old one. */ 8040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (i = &xtables_matches; *i!=old; i = &(*i)->next); 8050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI *i = old->next; 8060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 8070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (me->size != XT_ALIGN(me->size)) { 8090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "%s: match `%s' has invalid size %u.\n", 8105dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name, 8115dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim (unsigned int)me->size); 8120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 8130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 8140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Append to list. */ 8160d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (i = &xtables_matches; *i; i = &(*i)->next); 8170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->next = NULL; 8180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI *i = me; 8190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->m = NULL; 8210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->mflags = 0; 8220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 8230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8249a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardtvoid xtables_register_matches(struct xtables_match *match, unsigned int n) 8259a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt{ 8269a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt do { 8279a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt xtables_register_match(&match[--n]); 8289a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt } while (n > 0); 8299a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt} 8309a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt 8310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIvoid xtables_register_target(struct xtables_target *me) 8320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 8330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_target *old; 8340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 835c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt if (me->version == NULL) { 836c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt fprintf(stderr, "%s: target %s<%u> is missing a version\n", 837c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt xt_params->program_name, me->name, me->revision); 838c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt exit(1); 839c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt } 840dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt if (strcmp(me->version, XTABLES_VERSION) != 0) { 841dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt fprintf(stderr, "%s: target \"%s\" has version \"%s\", " 842dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt "but \"%s\" is required.\n", 8435dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name, 844dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt me->version, XTABLES_VERSION); 8450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 8460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 8470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8480cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) { 8490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "%s: target `%s' has invalid name\n", 8505dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name); 8510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 8520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 8530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (me->family >= NPROTO) { 8550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, 8560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "%s: BUG: target %s has invalid protocol family\n", 8575dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name); 8580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 8590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 8600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 861aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (me->x6_options != NULL) 862aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtables_option_metavalidate(me->name, me->x6_options); 863dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt if (me->extra_opts != NULL) 864dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt xtables_check_options(me->name, me->extra_opts); 865dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt 8660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* ignore not interested target */ 86777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt if (me->family != afinfo->family && me->family != AF_UNSPEC) 8680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 8690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8702338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt old = xtables_find_target(me->name, XTF_DURING_LOAD); 8710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (old) { 8720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_target **i; 8730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 87423545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt if (old->revision == me->revision && 87523545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt old->family == me->family) { 8760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, 8770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "%s: target `%s' already registered.\n", 8785dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name); 8790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 8800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 8810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Now we have two (or more) options, check compatibility. */ 8830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (compatible_target_revision(old->name, old->revision) 8840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI && old->revision > me->revision) 8850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 8860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 88723545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt /* See if new target can be used. */ 8880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (!compatible_target_revision(me->name, me->revision)) 8890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 8900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 89123545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt /* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */ 89223545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt if (old->revision == me->revision && me->family == AF_UNSPEC) 89323545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt return; 89423545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt 8950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Delete old one. */ 8960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (i = &xtables_targets; *i!=old; i = &(*i)->next); 8970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI *i = old->next; 8980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 8990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 9000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (me->size != XT_ALIGN(me->size)) { 9010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "%s: target `%s' has invalid size %u.\n", 9025dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name, 9035dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim (unsigned int)me->size); 9040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 9050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 9060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 9070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Prepend to list. */ 9080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->next = xtables_targets; 9090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI xtables_targets = me; 9100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->t = NULL; 9110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->tflags = 0; 9120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 913aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt 9149a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardtvoid xtables_register_targets(struct xtables_target *target, unsigned int n) 9159a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt{ 9169a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt do { 9179a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt xtables_register_target(&target[--n]); 9189a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt } while (n > 0); 9199a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt} 9209a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt 921a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt/** 922a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * xtables_param_act - act on condition 923a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @status: a constant from enum xtables_exittype 924a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * 925a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_ONLY_ONCE: print error message that option may only be used once. 926a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1: module name (e.g. "mark") 927a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2(...): option in conflict (e.g. "--mark") 928a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3(...): condition to match on (see extensions/ for examples) 929a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * 930a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_NO_INVERT: option does not support inversion 931a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1: module name 932a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2: option in conflict 933a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3: condition to match on 934a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * 935a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_BAD_VALUE: bad value for option 936a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1: module name 937a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2: option with which the problem occured (e.g. "--mark") 938a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3: string the user passed in (e.g. "99999999999999") 939a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * 940a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_ONE_ACTION: two mutually exclusive actions have been specified 941a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1: module name 942a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * 943a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * Displays an error message and exits the program. 944a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt */ 945a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardtvoid xtables_param_act(unsigned int status, const char *p1, ...) 946aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt{ 947aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt const char *p2, *p3; 948aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt va_list args; 949aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt bool b; 950aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt 951aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt va_start(args, p1); 952aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt 953aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt switch (status) { 954a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt case XTF_ONLY_ONCE: 955aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt p2 = va_arg(args, const char *); 956aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt b = va_arg(args, unsigned int); 957aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt if (!b) 958aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt return; 9598b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 960aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt "%s: \"%s\" option may only be specified once", 961aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt p1, p2); 962aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt break; 963a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt case XTF_NO_INVERT: 964aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt p2 = va_arg(args, const char *); 965aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt b = va_arg(args, unsigned int); 966aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt if (!b) 967aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt return; 9688b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 969aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt "%s: \"%s\" option cannot be inverted", p1, p2); 970aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt break; 971a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt case XTF_BAD_VALUE: 972aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt p2 = va_arg(args, const char *); 973aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt p3 = va_arg(args, const char *); 9748b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 975aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt "%s: Bad value for \"%s\" option: \"%s\"", 976aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt p1, p2, p3); 977aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt break; 978a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt case XTF_ONE_ACTION: 979aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt b = va_arg(args, unsigned int); 980aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt if (!b) 981aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt return; 9828b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 983aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt "%s: At most one action is possible", p1); 984aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt break; 985aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt default: 9868b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(status, p1, args); 987aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt break; 988aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt } 989aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt 990aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt va_end(args); 991aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt} 99208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 993e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ipaddr_to_numeric(const struct in_addr *addrp) 99408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 99508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt static char buf[20]; 99608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt const unsigned char *bytep = (const void *)&addrp->s_addr; 99708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 99808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt sprintf(buf, "%u.%u.%u.%u", bytep[0], bytep[1], bytep[2], bytep[3]); 99908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return buf; 100008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 100108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 100208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ipaddr_to_host(const struct in_addr *addr) 100308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 100408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt struct hostent *host; 100508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 100608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt host = gethostbyaddr(addr, sizeof(struct in_addr), AF_INET); 100708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if (host == NULL) 100808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return NULL; 100908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 101008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return host->h_name; 101108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 101208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 101308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ipaddr_to_network(const struct in_addr *addr) 101408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 101508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt struct netent *net; 101608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 101708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if ((net = getnetbyaddr(ntohl(addr->s_addr), AF_INET)) != NULL) 101808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return net->n_name; 101908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 102008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return NULL; 102108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 102208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 1023e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ipaddr_to_anyname(const struct in_addr *addr) 102408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 102508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt const char *name; 102608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 102708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if ((name = ipaddr_to_host(addr)) != NULL || 102808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt (name = ipaddr_to_network(addr)) != NULL) 102908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return name; 103008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 1031e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt return xtables_ipaddr_to_numeric(addr); 103208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 103308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 1034e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ipmask_to_numeric(const struct in_addr *mask) 103508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 103608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt static char buf[20]; 103708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt uint32_t maskaddr, bits; 103808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt int i; 103908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 104008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt maskaddr = ntohl(mask->s_addr); 104108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 104208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if (maskaddr == 0xFFFFFFFFL) 104308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt /* we don't want to see "/32" */ 104408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return ""; 104508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 104608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt i = 32; 104708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt bits = 0xFFFFFFFEL; 104808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt while (--i >= 0 && maskaddr != bits) 104908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt bits <<= 1; 105008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if (i >= 0) 105108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt sprintf(buf, "/%d", i); 105208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt else 105308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt /* mask was not a decent combination of 1's and 0's */ 1054e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt sprintf(buf, "/%s", xtables_ipaddr_to_numeric(mask)); 105508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 105608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return buf; 105708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 105808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 1059bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *__numeric_to_ipaddr(const char *dotted, bool is_mask) 1060bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1061bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt static struct in_addr addr; 1062bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned char *addrp; 1063bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned int onebyte; 1064bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt char buf[20], *p, *q; 1065bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt int i; 1066bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1067bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* copy dotted string, because we need to modify it */ 1068bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt strncpy(buf, dotted, sizeof(buf) - 1); 1069bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt buf[sizeof(buf) - 1] = '\0'; 1070bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = (void *)&addr.s_addr; 1071bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1072bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt p = buf; 1073bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (i = 0; i < 3; ++i) { 1074bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((q = strchr(p, '.')) == NULL) { 1075bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (is_mask) 1076bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1077bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1078bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* autocomplete, this is a network address */ 10795f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX)) 1080bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1081bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1082bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp[i] = onebyte; 1083bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt while (i < 3) 1084bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp[++i] = 0; 1085bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1086bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &addr; 1087bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1088bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1089bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *q = '\0'; 10905f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX)) 1091bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1092bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1093bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp[i] = onebyte; 1094bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt p = q + 1; 1095bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1096bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1097bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* we have checked 3 bytes, now we check the last one */ 10985f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX)) 1099bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1100bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1101bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp[3] = onebyte; 1102bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &addr; 1103bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1104bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 11051e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in_addr *xtables_numeric_to_ipaddr(const char *dotted) 1106bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1107bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return __numeric_to_ipaddr(dotted, false); 1108bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1109bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 11101e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in_addr *xtables_numeric_to_ipmask(const char *dotted) 1111bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1112bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return __numeric_to_ipaddr(dotted, true); 1113bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1114bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1115bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *network_to_ipaddr(const char *name) 1116bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1117bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt static struct in_addr addr; 1118bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct netent *net; 1119bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1120bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((net = getnetbyname(name)) != NULL) { 1121bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (net->n_addrtype != AF_INET) 1122bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1123bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addr.s_addr = htonl(net->n_net); 1124bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &addr; 1125bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1126bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1127bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1128bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1129bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1130bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *host_to_ipaddr(const char *name, unsigned int *naddr) 1131bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1132bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct hostent *host; 1133bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in_addr *addr; 1134bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned int i; 1135bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1136bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *naddr = 0; 1137bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((host = gethostbyname(name)) != NULL) { 1138bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (host->h_addrtype != AF_INET || 1139bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt host->h_length != sizeof(struct in_addr)) 1140bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1141bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1142bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt while (host->h_addr_list[*naddr] != NULL) 1143bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt ++*naddr; 114411e250ba02349cb1e34058673db3d0b54eb56c44Wes Campaigne addr = xtables_calloc(*naddr, sizeof(struct in_addr)); 1145bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (i = 0; i < *naddr; i++) 1146bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memcpy(&addr[i], host->h_addr_list[i], 1147bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt sizeof(struct in_addr)); 1148bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addr; 1149bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1150bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1151bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1152bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1153bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1154bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr * 1155bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtipparse_hostnetwork(const char *name, unsigned int *naddrs) 1156bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1157bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in_addr *addrptmp, *addrp; 1158bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 11591e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt if ((addrptmp = xtables_numeric_to_ipaddr(name)) != NULL || 1160bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt (addrptmp = network_to_ipaddr(name)) != NULL) { 1161630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt addrp = xtables_malloc(sizeof(struct in_addr)); 1162bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memcpy(addrp, addrptmp, sizeof(*addrp)); 1163bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *naddrs = 1; 1164bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addrp; 1165bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1166bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((addrptmp = host_to_ipaddr(name, naddrs)) != NULL) 1167bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addrptmp; 1168bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 11698b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name); 1170bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1171bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1172bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *parse_ipmask(const char *mask) 1173bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1174bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt static struct in_addr maskaddr; 1175bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in_addr *addrp; 1176bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned int bits; 1177bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1178bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (mask == NULL) { 1179bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* no mask at all defaults to 32 bits */ 1180bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt maskaddr.s_addr = 0xFFFFFFFF; 1181bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &maskaddr; 1182bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 11831e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt if ((addrp = xtables_numeric_to_ipmask(mask)) != NULL) 1184bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* dotted_to_addr already returns a network byte order addr */ 1185bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addrp; 11865f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt if (!xtables_strtoui(mask, NULL, &bits, 0, 32)) 11878b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 1188bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt "invalid mask `%s' specified", mask); 1189bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (bits != 0) { 1190bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt maskaddr.s_addr = htonl(0xFFFFFFFF << (32 - bits)); 1191bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &maskaddr; 1192bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1193bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1194bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt maskaddr.s_addr = 0U; 1195bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &maskaddr; 1196bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1197bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1198332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowvoid xtables_ipparse_multiple(const char *name, struct in_addr **addrpp, 1199332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow struct in_addr **maskpp, unsigned int *naddrs) 1200332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow{ 1201332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow struct in_addr *addrp; 1202332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow char buf[256], *p; 1203332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow unsigned int len, i, j, n, count = 1; 1204332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow const char *loop = name; 1205332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1206332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow while ((loop = strchr(loop, ',')) != NULL) { 1207332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow ++count; 1208332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow ++loop; /* skip ',' */ 1209332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1210332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1211332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *addrpp = xtables_malloc(sizeof(struct in_addr) * count); 1212332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *maskpp = xtables_malloc(sizeof(struct in_addr) * count); 1213332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1214332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow loop = name; 1215332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1216332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow for (i = 0; i < count; ++i) { 1217332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (loop == NULL) 1218332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow break; 1219332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (*loop == ',') 1220332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow ++loop; 1221332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (*loop == '\0') 1222332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow break; 1223332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow p = strchr(loop, ','); 1224332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (p != NULL) 1225332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow len = p - loop; 1226332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow else 1227332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow len = strlen(loop); 1228332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (len == 0 || sizeof(buf) - 1 < len) 1229332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow break; 1230332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1231332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow strncpy(buf, loop, len); 1232332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow buf[len] = '\0'; 1233332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow loop += len; 1234332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if ((p = strrchr(buf, '/')) != NULL) { 1235332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *p = '\0'; 1236332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow addrp = parse_ipmask(p + 1); 1237332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } else { 1238332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow addrp = parse_ipmask(NULL); 1239332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1240332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*maskpp + i, addrp, sizeof(*addrp)); 1241332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1242332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* if a null mask is given, the name is ignored, like in "any/0" */ 1243332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if ((*maskpp + i)->s_addr == 0) 1244332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* 1245332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow * A bit pointless to process multiple addresses 1246332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow * in this case... 1247332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow */ 1248332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow strcpy(buf, "0.0.0.0"); 1249332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1250332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow addrp = ipparse_hostnetwork(buf, &n); 1251332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (n > 1) { 1252332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow count += n - 1; 1253332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *addrpp = xtables_realloc(*addrpp, 1254332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(struct in_addr) * count); 1255332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *maskpp = xtables_realloc(*maskpp, 1256332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(struct in_addr) * count); 1257332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow for (j = 0; j < n; ++j) 1258332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* for each new addr */ 1259332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*addrpp + i + j, addrp + j, 1260332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(*addrp)); 1261332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow for (j = 1; j < n; ++j) 1262332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* for each new mask */ 1263332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*maskpp + i + j, *maskpp + i, 1264332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(*addrp)); 1265332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow i += n - 1; 1266332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } else { 1267332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*addrpp + i, addrp, sizeof(*addrp)); 1268332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1269332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* free what ipparse_hostnetwork had allocated: */ 1270332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow free(addrp); 1271332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1272332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *naddrs = count; 12734b110b426df7bf486a3e7884c56ebb3487023601Jan Engelhardt for (i = 0; i < count; ++i) 1274332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow (*addrpp+i)->s_addr &= (*maskpp+i)->s_addr; 1275332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow} 1276332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1277332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1278a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt/** 1279a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * xtables_ipparse_any - transform arbitrary name to in_addr 1280a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * 1281a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * Possible inputs (pseudo regex): 1282a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * m{^($hostname|$networkname|$ipaddr)(/$mask)?} 1283a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * "1.2.3.4/5", "1.2.3.4", "hostname", "networkname" 1284a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt */ 1285a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_ipparse_any(const char *name, struct in_addr **addrpp, 1286a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt struct in_addr *maskp, unsigned int *naddrs) 1287bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1288bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned int i, j, k, n; 1289bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in_addr *addrp; 1290bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt char buf[256], *p; 1291bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1292bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt strncpy(buf, name, sizeof(buf) - 1); 1293bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt buf[sizeof(buf) - 1] = '\0'; 1294bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((p = strrchr(buf, '/')) != NULL) { 1295bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *p = '\0'; 1296bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = parse_ipmask(p + 1); 1297bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } else { 1298bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = parse_ipmask(NULL); 1299bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1300bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memcpy(maskp, addrp, sizeof(*maskp)); 1301bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1302bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* if a null mask is given, the name is ignored, like in "any/0" */ 1303bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (maskp->s_addr == 0U) 1304bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt strcpy(buf, "0.0.0.0"); 1305bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1306bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = *addrpp = ipparse_hostnetwork(buf, naddrs); 1307bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt n = *naddrs; 1308bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (i = 0, j = 0; i < n; ++i) { 1309bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp[j++].s_addr &= maskp->s_addr; 1310bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (k = 0; k < j - 1; ++k) 1311bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (addrp[k].s_addr == addrp[j-1].s_addr) { 1312adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne /* 1313adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne * Nuke the dup by copying an address from the 1314adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne * tail here, and check the current position 1315adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne * again (--j). 1316adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne */ 1317adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne memcpy(&addrp[--j], &addrp[--*naddrs], 1318adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne sizeof(struct in_addr)); 1319bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt break; 1320bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1321bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1322bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1323bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1324e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6addr_to_numeric(const struct in6_addr *addrp) 132508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 132608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt /* 0000:0000:0000:0000:0000:000.000.000.000 132708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt * 0000:0000:0000:0000:0000:0000:0000:0000 */ 132808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt static char buf[50+1]; 132908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return inet_ntop(AF_INET6, addrp, buf, sizeof(buf)); 133008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 133108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 133208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ip6addr_to_host(const struct in6_addr *addr) 133308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 133408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt static char hostname[NI_MAXHOST]; 133508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt struct sockaddr_in6 saddr; 133608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt int err; 133708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 133808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt memset(&saddr, 0, sizeof(struct sockaddr_in6)); 133908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt memcpy(&saddr.sin6_addr, addr, sizeof(*addr)); 134008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt saddr.sin6_family = AF_INET6; 134108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 134208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt err = getnameinfo((const void *)&saddr, sizeof(struct sockaddr_in6), 134308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt hostname, sizeof(hostname) - 1, NULL, 0, 0); 134408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if (err != 0) { 134508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#ifdef DEBUG 134608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt fprintf(stderr,"IP2Name: %s\n",gai_strerror(err)); 134708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#endif 134808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return NULL; 134908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt } 135008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 135108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#ifdef DEBUG 135208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt fprintf (stderr, "\naddr2host: %s\n", hostname); 135308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#endif 135408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return hostname; 135508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 135608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 1357e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6addr_to_anyname(const struct in6_addr *addr) 135808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 135908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt const char *name; 136008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 136108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if ((name = ip6addr_to_host(addr)) != NULL) 136208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return name; 136308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 1364e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt return xtables_ip6addr_to_numeric(addr); 136508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 136608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 136708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic int ip6addr_prefix_length(const struct in6_addr *k) 136808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 136908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt unsigned int bits = 0; 137008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt uint32_t a, b, c, d; 137108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 137248607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt a = ntohl(k->s6_addr32[0]); 137348607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt b = ntohl(k->s6_addr32[1]); 137448607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt c = ntohl(k->s6_addr32[2]); 137548607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt d = ntohl(k->s6_addr32[3]); 137608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt while (a & 0x80000000U) { 137708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt ++bits; 137808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt a <<= 1; 137908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt a |= (b >> 31) & 1; 138008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt b <<= 1; 138108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt b |= (c >> 31) & 1; 138208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt c <<= 1; 138308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt c |= (d >> 31) & 1; 138408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt d <<= 1; 138508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt } 138608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if (a != 0 || b != 0 || c != 0 || d != 0) 138708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return -1; 138808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return bits; 138908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 139008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 1391e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6mask_to_numeric(const struct in6_addr *addrp) 139208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 139308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt static char buf[50+2]; 139408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt int l = ip6addr_prefix_length(addrp); 139508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 139608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if (l == -1) { 139708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt strcpy(buf, "/"); 1398e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt strcat(buf, xtables_ip6addr_to_numeric(addrp)); 139908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return buf; 140008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt } 140108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt sprintf(buf, "/%d", l); 140208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return buf; 140308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 1404bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 14051e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in6_addr *xtables_numeric_to_ip6addr(const char *num) 1406bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1407bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt static struct in6_addr ap; 1408bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt int err; 1409bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1410bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((err = inet_pton(AF_INET6, num, &ap)) == 1) 1411bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return ≈ 1412bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG 1413bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt fprintf(stderr, "\nnumeric2addr: %d\n", err); 1414bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif 1415bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1416bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1417bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1418bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr * 1419bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardthost_to_ip6addr(const char *name, unsigned int *naddr) 1420bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 14212ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne struct in6_addr *addr; 1422bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct addrinfo hints; 14232ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne struct addrinfo *res, *p; 1424bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt int err; 14252ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne unsigned int i; 1426bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1427bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memset(&hints, 0, sizeof(hints)); 1428bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt hints.ai_flags = AI_CANONNAME; 1429bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt hints.ai_family = AF_INET6; 1430bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt hints.ai_socktype = SOCK_RAW; 1431bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1432bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *naddr = 0; 1433bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((err = getaddrinfo(name, NULL, &hints, &res)) != 0) { 1434bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG 1435bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt fprintf(stderr,"Name2IP: %s\n",gai_strerror(err)); 1436bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif 1437bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1438bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } else { 14392ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne /* Find length of address chain */ 14402ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne for (p = res; p != NULL; p = p->ai_next) 14412ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne ++*naddr; 1442bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG 1443bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt fprintf(stderr, "resolved: len=%d %s ", res->ai_addrlen, 144430290aea009cf3fd76f27336fb4370be3467c4daPatrick McHardy xtables_ip6addr_to_numeric(&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr)); 1445bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif 14462ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne /* Copy each element of the address chain */ 14472ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne addr = xtables_calloc(*naddr, sizeof(struct in6_addr)); 14482ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne for (i = 0, p = res; p != NULL; p = p->ai_next) 14492ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne memcpy(&addr[i++], 14502ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne &((const struct sockaddr_in6 *)p->ai_addr)->sin6_addr, 14512ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne sizeof(struct in6_addr)); 1452bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt freeaddrinfo(res); 1453bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addr; 1454bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1455bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1456bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1457bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1458bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1459bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *network_to_ip6addr(const char *name) 1460bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1461bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* abort();*/ 1462bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* TODO: not implemented yet, but the exception breaks the 1463bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt * name resolvation */ 1464bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1465bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1466bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1467bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr * 1468bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtip6parse_hostnetwork(const char *name, unsigned int *naddrs) 1469bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1470bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in6_addr *addrp, *addrptmp; 1471bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 14721e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt if ((addrptmp = xtables_numeric_to_ip6addr(name)) != NULL || 1473bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt (addrptmp = network_to_ip6addr(name)) != NULL) { 1474630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt addrp = xtables_malloc(sizeof(struct in6_addr)); 1475bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memcpy(addrp, addrptmp, sizeof(*addrp)); 1476bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *naddrs = 1; 1477bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addrp; 1478bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1479bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((addrp = host_to_ip6addr(name, naddrs)) != NULL) 1480bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addrp; 1481bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 14828b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name); 1483bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1484bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1485bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *parse_ip6mask(char *mask) 1486bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1487bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt static struct in6_addr maskaddr; 1488bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in6_addr *addrp; 1489bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned int bits; 1490bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1491bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (mask == NULL) { 1492bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* no mask at all defaults to 128 bits */ 1493bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memset(&maskaddr, 0xff, sizeof maskaddr); 1494bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &maskaddr; 1495bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 14961e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt if ((addrp = xtables_numeric_to_ip6addr(mask)) != NULL) 1497bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addrp; 14985f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt if (!xtables_strtoui(mask, NULL, &bits, 0, 128)) 14998b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 1500bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt "invalid mask `%s' specified", mask); 1501bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (bits != 0) { 1502bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt char *p = (void *)&maskaddr; 1503bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memset(p, 0xff, bits / 8); 1504bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memset(p + (bits / 8) + 1, 0, (128 - bits) / 8); 1505bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt p[bits/8] = 0xff << (8 - (bits & 7)); 1506bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &maskaddr; 1507bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1508bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1509bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memset(&maskaddr, 0, sizeof(maskaddr)); 1510bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &maskaddr; 1511bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1512bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1513332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowvoid 1514332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowxtables_ip6parse_multiple(const char *name, struct in6_addr **addrpp, 1515332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow struct in6_addr **maskpp, unsigned int *naddrs) 1516332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow{ 151758df90174164fd673e8c4103f7ce0c4e55ef1aecOlaf Rempel static const struct in6_addr zero_addr; 1518332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow struct in6_addr *addrp; 1519332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow char buf[256], *p; 1520332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow unsigned int len, i, j, n, count = 1; 1521332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow const char *loop = name; 1522332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1523332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow while ((loop = strchr(loop, ',')) != NULL) { 1524332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow ++count; 1525332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow ++loop; /* skip ',' */ 1526332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1527332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1528332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *addrpp = xtables_malloc(sizeof(struct in6_addr) * count); 1529332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *maskpp = xtables_malloc(sizeof(struct in6_addr) * count); 1530332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1531332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow loop = name; 1532332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1533332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow for (i = 0; i < count /*NB: count can grow*/; ++i) { 1534332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (loop == NULL) 1535332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow break; 1536332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (*loop == ',') 1537332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow ++loop; 1538332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (*loop == '\0') 1539332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow break; 1540332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow p = strchr(loop, ','); 1541332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (p != NULL) 1542332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow len = p - loop; 1543332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow else 1544332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow len = strlen(loop); 1545332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (len == 0 || sizeof(buf) - 1 < len) 1546332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow break; 1547332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1548332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow strncpy(buf, loop, len); 1549332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow buf[len] = '\0'; 1550332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow loop += len; 1551332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if ((p = strrchr(buf, '/')) != NULL) { 1552332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *p = '\0'; 1553332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow addrp = parse_ip6mask(p + 1); 1554332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } else { 1555332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow addrp = parse_ip6mask(NULL); 1556332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1557332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*maskpp + i, addrp, sizeof(*addrp)); 1558332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1559332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* if a null mask is given, the name is ignored, like in "any/0" */ 156058df90174164fd673e8c4103f7ce0c4e55ef1aecOlaf Rempel if (memcmp(*maskpp + i, &zero_addr, sizeof(zero_addr)) == 0) 1561332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow strcpy(buf, "::"); 1562332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1563332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow addrp = ip6parse_hostnetwork(buf, &n); 1564332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (n > 1) { 1565332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow count += n - 1; 1566332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *addrpp = xtables_realloc(*addrpp, 1567332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(struct in6_addr) * count); 1568332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *maskpp = xtables_realloc(*maskpp, 1569332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(struct in6_addr) * count); 1570332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow for (j = 0; j < n; ++j) 1571332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* for each new addr */ 1572332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*addrpp + i + j, addrp + j, 1573332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(*addrp)); 1574332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow for (j = 1; j < n; ++j) 1575332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* for each new mask */ 1576332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*maskpp + i + j, *maskpp + i, 1577332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(*addrp)); 1578332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow i += n - 1; 1579332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } else { 1580332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*addrpp + i, addrp, sizeof(*addrp)); 1581332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1582332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* free what ip6parse_hostnetwork had allocated: */ 1583332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow free(addrp); 1584332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1585332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *naddrs = count; 15864b110b426df7bf486a3e7884c56ebb3487023601Jan Engelhardt for (i = 0; i < count; ++i) 1587332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow for (j = 0; j < 4; ++j) 1588332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow (*addrpp+i)->s6_addr32[j] &= (*maskpp+i)->s6_addr32[j]; 1589332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow} 1590332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1591a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_ip6parse_any(const char *name, struct in6_addr **addrpp, 1592a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt struct in6_addr *maskp, unsigned int *naddrs) 1593bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 15949c0fa7d8c84dc2478bd36d31b328b697fbe4d0afJan Engelhardt static const struct in6_addr zero_addr; 1595bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in6_addr *addrp; 1596bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned int i, j, k, n; 1597bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt char buf[256], *p; 1598bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1599bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt strncpy(buf, name, sizeof(buf) - 1); 1600bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt buf[sizeof(buf)-1] = '\0'; 1601bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((p = strrchr(buf, '/')) != NULL) { 1602bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *p = '\0'; 1603bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = parse_ip6mask(p + 1); 1604bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } else { 1605bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = parse_ip6mask(NULL); 1606bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1607bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memcpy(maskp, addrp, sizeof(*maskp)); 1608bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1609bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* if a null mask is given, the name is ignored, like in "any/0" */ 16109c0fa7d8c84dc2478bd36d31b328b697fbe4d0afJan Engelhardt if (memcmp(maskp, &zero_addr, sizeof(zero_addr)) == 0) 1611bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt strcpy(buf, "::"); 1612bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1613bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = *addrpp = ip6parse_hostnetwork(buf, naddrs); 1614bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt n = *naddrs; 1615bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (i = 0, j = 0; i < n; ++i) { 1616bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (k = 0; k < 4; ++k) 16175a2208c3e62a150e6f6297abbfa63056ab4a8066Yasuyuki Kozakai addrp[j].s6_addr32[k] &= maskp->s6_addr32[k]; 1618bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt ++j; 1619bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (k = 0; k < j - 1; ++k) 1620bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (IN6_ARE_ADDR_EQUAL(&addrp[k], &addrp[j - 1])) { 1621adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne /* 1622adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne * Nuke the dup by copying an address from the 1623adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne * tail here, and check the current position 1624adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne * again (--j). 1625adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne */ 1626adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne memcpy(&addrp[--j], &addrp[--*naddrs], 1627adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne sizeof(struct in_addr)); 1628bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt break; 1629bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1630bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1631bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1632a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann 1633a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_save_string(const char *value) 1634a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann{ 1635a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann static const char no_quote_chars[] = "_-0123456789" 1636a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann "abcdefghijklmnopqrstuvwxyz" 1637a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 1638a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann static const char escape_chars[] = "\"\\'"; 1639a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann size_t length; 1640a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann const char *p; 1641a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann 164287dc7c4c842deb1e2e3d38089ffcad9f238d98deMax Kellerman length = strspn(value, no_quote_chars); 1643a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann if (length > 0 && value[length] == 0) { 1644a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann /* no quoting required */ 1645a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann putchar(' '); 164673866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt fputs(value, stdout); 1647a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann } else { 1648a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann /* there is at least one dangerous character in the 1649a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann value, which we have to quote. Write double quotes 1650a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann around the value and escape special characters with 1651a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann a backslash */ 165273866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" \""); 1653a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann 1654a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann for (p = strpbrk(value, escape_chars); p != NULL; 1655a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann p = strpbrk(value, escape_chars)) { 1656a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann if (p > value) 1657a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann fwrite(value, 1, p - value, stdout); 1658a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann putchar('\\'); 1659a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann putchar(*p); 1660a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann value = p + 1; 1661a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann } 1662a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann 1663a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann /* print the rest and finish the double quoted 1664a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann string */ 1665a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann fputs(value, stdout); 166673866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt putchar('\"'); 1667a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann } 1668a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann} 16690f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt 16700f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt/** 16710f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt * Check for option-intrapositional negation. 16720f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt * Do not use in new code. 16730f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt */ 16740f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardtint xtables_check_inverse(const char option[], int *invert, 1675bf97128c7262f17a02fec41cdae75b472ba77f88Jan Engelhardt int *my_optind, int argc, char **argv) 16760f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt{ 16772be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt if (option == NULL || strcmp(option, "!") != 0) 16782be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt return false; 16790f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt 16802be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt fprintf(stderr, "Using intrapositioned negation " 16812be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt "(`--option ! this`) is deprecated in favor of " 16822be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt "extrapositioned (`! --option this`).\n"); 16830f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt 16842be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt if (*invert) 16852be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 16862be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt "Multiple `!' flags not allowed"); 16872be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt *invert = true; 16882be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt if (my_optind != NULL) { 1689bf97128c7262f17a02fec41cdae75b472ba77f88Jan Engelhardt optarg = argv[*my_optind]; 16902be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt ++*my_optind; 16912be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt if (argc && *my_optind > argc) 16922be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 16932be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt "no argument following `!'"); 16940f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt } 16952be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt 16962be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt return true; 16970f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt} 16981de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt 16991de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardtconst struct xtables_pprot xtables_chain_protos[] = { 17001de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"tcp", IPPROTO_TCP}, 17011de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"sctp", IPPROTO_SCTP}, 17021de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"udp", IPPROTO_UDP}, 17031de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"udplite", IPPROTO_UDPLITE}, 17041de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"icmp", IPPROTO_ICMP}, 17051de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"icmpv6", IPPROTO_ICMPV6}, 17061de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"ipv6-icmp", IPPROTO_ICMPV6}, 17071de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"esp", IPPROTO_ESP}, 17081de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"ah", IPPROTO_AH}, 17091de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"ipv6-mh", IPPROTO_MH}, 17101de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"mh", IPPROTO_MH}, 17111de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"all", 0}, 17121de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {NULL}, 17131de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt}; 17141de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt 17157ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtuint16_t 17161de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardtxtables_parse_protocol(const char *s) 17171de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt{ 17181de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt unsigned int proto; 17191de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt 17201de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt if (!xtables_strtoui(s, NULL, &proto, 0, UINT8_MAX)) { 17211de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt struct protoent *pent; 17221de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt 17231de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt /* first deal with the special case of 'all' to prevent 17241de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt * people from being able to redefine 'all' in nsswitch 17251de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt * and/or provoke expensive [not working] ldap/nis/... 17261de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt * lookups */ 17271de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt if (!strcmp(s, "all")) 17281de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt return 0; 17291de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt 17301de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt if ((pent = getprotobyname(s))) 17311de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt proto = pent->p_proto; 17321de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt else { 17331de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt unsigned int i; 17341de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt for (i = 0; i < ARRAY_SIZE(xtables_chain_protos); ++i) { 1735e55cc4aaa6e35448c14370e5261c3387d26b257dPablo Neira Ayuso if (xtables_chain_protos[i].name == NULL) 1736e55cc4aaa6e35448c14370e5261c3387d26b257dPablo Neira Ayuso continue; 1737e55cc4aaa6e35448c14370e5261c3387d26b257dPablo Neira Ayuso 17381de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt if (strcmp(s, xtables_chain_protos[i].name) == 0) { 17391de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt proto = xtables_chain_protos[i].num; 17401de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt break; 17411de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt } 17421de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt } 17431de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt if (i == ARRAY_SIZE(xtables_chain_protos)) 17448b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 17451de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt "unknown protocol `%s' specified", 17461de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt s); 17471de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt } 17481de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt } 17491de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt 17501de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt return proto; 17511de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt} 1752