xtables.c revision b32b361a725c8fe3a3aa494e6cdec09a80785aac
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> 30b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski#include <sys/statfs.h> 310b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <sys/types.h> 320b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <sys/wait.h> 3308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#include <arpa/inet.h> 34b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski#include <linux/magic.h> /* for PROC_SUPER_MAGIC */ 353dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 365208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI#include <xtables.h> 374e41854423b529d3107c23b85434d50a75d08057Jan Engelhardt#include <limits.h> /* INT_MAX in ip_tables.h/ip6_tables.h */ 3877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt#include <linux/netfilter_ipv4/ip_tables.h> 3977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt#include <linux/netfilter_ipv6/ip6_tables.h> 40ef18e8147903885708d1c264904129af4fb636d6Jan Engelhardt#include <libiptc/libxtc.h> 413dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 425a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#ifndef NO_SHARED_LIBS 435a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#include <dlfcn.h> 445a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#endif 45c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#ifndef IPT_SO_GET_REVISION_MATCH /* Old kernel source. */ 46c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt# define IPT_SO_GET_REVISION_MATCH (IPT_BASE_CTL + 2) 47c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt# define IPT_SO_GET_REVISION_TARGET (IPT_BASE_CTL + 3) 48c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#endif 49c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#ifndef IP6T_SO_GET_REVISION_MATCH /* Old kernel source. */ 50c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt# define IP6T_SO_GET_REVISION_MATCH 68 51c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt# define IP6T_SO_GET_REVISION_TARGET 69 52c31870f9bebb3d4d082016fcfaf8c2177ae32eb2Jan Engelhardt#endif 5370581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim#include <getopt.h> 54aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt#include "iptables/internal.h" 551e128bd804b676ee91beca48312de9b251845d09Jan Engelhardt#include "xshared.h" 565a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger 570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#define NPROTO 255 580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 590b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#ifndef PROC_SYS_MODPROBE 600b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe" 610b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#endif 620b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 6337911de507d0597980ad218a044a482501a21b01Maciej Zenczykowski/* we need this for ip6?tables-restore. ip6?tables-restore.c sets line to the 6437911de507d0597980ad218a044a482501a21b01Maciej Zenczykowski * current line of the input file, in order to give a more precise error 6537911de507d0597980ad218a044a482501a21b01Maciej Zenczykowski * message. ip6?tables itself doesn't need this, so it is initialized to the 6637911de507d0597980ad218a044a482501a21b01Maciej Zenczykowski * magic number of -1 */ 6737911de507d0597980ad218a044a482501a21b01Maciej Zenczykowskiint line = -1; 6837911de507d0597980ad218a044a482501a21b01Maciej Zenczykowski 698b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salimvoid basic_exit_err(enum xtables_exittype status, const char *msg, ...) __attribute__((noreturn, format(printf,2,3))); 708b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim 7140a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salimstruct xtables_globals *xt_params = NULL; 7240a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim 738b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salimvoid basic_exit_err(enum xtables_exittype status, const char *msg, ...) 7440a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim{ 7540a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim va_list args; 7640a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim 7740a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim va_start(args, msg); 7840a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim fprintf(stderr, "%s v%s: ", xt_params->program_name, xt_params->program_version); 7940a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim vfprintf(stderr, msg, args); 8040a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim va_end(args); 8140a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim fprintf(stderr, "\n"); 8240a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim exit(status); 8340a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim} 8440a8343d3ad0cdbc3a7e69c8d970ad75807c29edJamal Hadi Salim 85600f38db82548a683775fd89b6e136673e924097Jan Engelhardtvoid xtables_free_opts(int unused) 8684c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim{ 87df288236cd254798be3759fef4cbc3e535f5a1c3Jan Engelhardt if (xt_params->opts != xt_params->orig_opts) { 8859e8114c6792242e80785f4461d5e663fb9a3d64Jan Engelhardt free(xt_params->opts); 89df288236cd254798be3759fef4cbc3e535f5a1c3Jan Engelhardt xt_params->opts = NULL; 90df288236cd254798be3759fef4cbc3e535f5a1c3Jan Engelhardt } 9184c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim} 9284c3055bf08d0a8fe5db6e5f3f96dd826a290147Jamal Hadi Salim 93600f38db82548a683775fd89b6e136673e924097Jan Engelhardtstruct option *xtables_merge_options(struct option *orig_opts, 94600f38db82548a683775fd89b6e136673e924097Jan Engelhardt struct option *oldopts, 9570581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim const struct option *newopts, 9670581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim unsigned int *option_offset) 9770581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim{ 98600f38db82548a683775fd89b6e136673e924097Jan Engelhardt unsigned int num_oold = 0, num_old = 0, num_new = 0, i; 99600f38db82548a683775fd89b6e136673e924097Jan Engelhardt struct option *merge, *mp; 10070581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim 10170581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim if (newopts == NULL) 10270581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim return oldopts; 10370581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim 104600f38db82548a683775fd89b6e136673e924097Jan Engelhardt for (num_oold = 0; orig_opts[num_oold].name; num_oold++) ; 105600f38db82548a683775fd89b6e136673e924097Jan Engelhardt if (oldopts != NULL) 106600f38db82548a683775fd89b6e136673e924097Jan Engelhardt for (num_old = 0; oldopts[num_old].name; num_old++) ; 10770581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim for (num_new = 0; newopts[num_new].name; num_new++) ; 10870581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim 1091dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt /* 1101dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt * Since @oldopts also has @orig_opts already (and does so at the 1111dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt * start), skip these entries. 1121dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt */ 1131dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt oldopts += num_oold; 1141dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt num_old -= num_oold; 1151dc27393b7ba401e6228a5ee2472a6eb72836c43Jan Engelhardt 116600f38db82548a683775fd89b6e136673e924097Jan Engelhardt merge = malloc(sizeof(*mp) * (num_oold + num_old + num_new + 1)); 117600f38db82548a683775fd89b6e136673e924097Jan Engelhardt if (merge == NULL) 118600f38db82548a683775fd89b6e136673e924097Jan Engelhardt return NULL; 119600f38db82548a683775fd89b6e136673e924097Jan Engelhardt 120600f38db82548a683775fd89b6e136673e924097Jan Engelhardt /* Let the base options -[ADI...] have precedence over everything */ 121600f38db82548a683775fd89b6e136673e924097Jan Engelhardt memcpy(merge, orig_opts, sizeof(*mp) * num_oold); 122600f38db82548a683775fd89b6e136673e924097Jan Engelhardt mp = merge + num_oold; 123600f38db82548a683775fd89b6e136673e924097Jan Engelhardt 124600f38db82548a683775fd89b6e136673e924097Jan Engelhardt /* Second, the new options */ 1251e128bd804b676ee91beca48312de9b251845d09Jan Engelhardt xt_params->option_offset += XT_OPTION_OFFSET_SCALE; 12670581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim *option_offset = xt_params->option_offset; 127600f38db82548a683775fd89b6e136673e924097Jan Engelhardt memcpy(mp, newopts, sizeof(*mp) * num_new); 12870581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim 129600f38db82548a683775fd89b6e136673e924097Jan Engelhardt for (i = 0; i < num_new; ++i, ++mp) 130600f38db82548a683775fd89b6e136673e924097Jan Engelhardt mp->val += *option_offset; 131600f38db82548a683775fd89b6e136673e924097Jan Engelhardt 132600f38db82548a683775fd89b6e136673e924097Jan Engelhardt /* Third, the old options */ 133600f38db82548a683775fd89b6e136673e924097Jan Engelhardt memcpy(mp, oldopts, sizeof(*mp) * num_old); 134600f38db82548a683775fd89b6e136673e924097Jan Engelhardt mp += num_old; 135600f38db82548a683775fd89b6e136673e924097Jan Engelhardt xtables_free_opts(0); 13670581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim 137600f38db82548a683775fd89b6e136673e924097Jan Engelhardt /* Clear trailing entry */ 138600f38db82548a683775fd89b6e136673e924097Jan Engelhardt memset(mp, 0, sizeof(*mp)); 13970581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim return merge; 14070581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim} 14170581922f873a88306dd5b1cb83c5081ee239eb8Jamal Hadi Salim 14277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtstatic const struct xtables_afinfo afinfo_ipv4 = { 14377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .kmod = "ip_tables", 144b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski .proc_exists = "/proc/net/ip_tables_names", 14577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .libprefix = "libipt_", 14677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .family = NFPROTO_IPV4, 14777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .ipproto = IPPROTO_IP, 14877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .so_rev_match = IPT_SO_GET_REVISION_MATCH, 14977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .so_rev_target = IPT_SO_GET_REVISION_TARGET, 15077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt}; 15177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt 15277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtstatic const struct xtables_afinfo afinfo_ipv6 = { 15377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .kmod = "ip6_tables", 154b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski .proc_exists = "/proc/net/ip6_tables_names", 15577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .libprefix = "libip6t_", 15677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .family = NFPROTO_IPV6, 15777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .ipproto = IPPROTO_IPV6, 15877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .so_rev_match = IP6T_SO_GET_REVISION_MATCH, 15977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt .so_rev_target = IP6T_SO_GET_REVISION_TARGET, 16077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt}; 16177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt 162aa37acc1423126f555135935c687eb91995b9440Jan Engelhardtconst struct xtables_afinfo *afinfo; 16377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt 16439bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt/* Search path for Xtables .so files */ 16539bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardtstatic const char *xtables_libdir; 1660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 1670b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI/* the path to command to load kernel module */ 168c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtconst char *xtables_modprobe_program; 1690b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 1702c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski/* Keep track of matches/targets pending full registration: linked lists. */ 1712c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowskistruct xtables_match *xtables_pending_matches; 1722c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowskistruct xtables_target *xtables_pending_targets; 1732c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski 1742c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski/* Keep track of fully registered external matches/targets: linked lists. */ 1750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_match *xtables_matches; 1760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_target *xtables_targets; 1770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 1782c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski/* Fully register a match/target which was previously partially registered. */ 1792c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowskistatic void xtables_fully_register_pending_match(struct xtables_match *me); 1802c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowskistatic void xtables_fully_register_pending_target(struct xtables_target *me); 1812c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski 18239bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardtvoid xtables_init(void) 18339bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt{ 18439bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt xtables_libdir = getenv("XTABLES_LIBDIR"); 18539bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt if (xtables_libdir != NULL) 18639bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt return; 18739bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt xtables_libdir = getenv("IPTABLES_LIB_DIR"); 18839bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt if (xtables_libdir != NULL) { 18939bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt fprintf(stderr, "IPTABLES_LIB_DIR is deprecated, " 19039bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt "use XTABLES_LIBDIR.\n"); 19139bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt return; 19239bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt } 193ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt /* 194ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt * Well yes, IP6TABLES_LIB_DIR is of lower priority over 195ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt * IPTABLES_LIB_DIR since this moved to libxtables; I think that is ok 196ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt * for these env vars are deprecated anyhow, and in light of the 197ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt * (shared) libxt_*.so files, makes less sense to have 198ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt * IPTABLES_LIB_DIR != IP6TABLES_LIB_DIR. 199ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt */ 200ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt xtables_libdir = getenv("IP6TABLES_LIB_DIR"); 201ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt if (xtables_libdir != NULL) { 202ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt fprintf(stderr, "IP6TABLES_LIB_DIR is deprecated, " 203ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt "use XTABLES_LIBDIR.\n"); 204ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt return; 205ec934198bd6ee2f21171dba440ca96334b0d874bJan Engelhardt } 20639bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt xtables_libdir = XTABLES_LIBDIR; 20739bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt} 20839bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt 20977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardtvoid xtables_set_nfproto(uint8_t nfproto) 21077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt{ 21177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt switch (nfproto) { 21277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt case NFPROTO_IPV4: 21377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt afinfo = &afinfo_ipv4; 21477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt break; 21577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt case NFPROTO_IPV6: 21677f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt afinfo = &afinfo_ipv6; 21777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt break; 21877f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt default: 21977f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt fprintf(stderr, "libxtables: unhandled NFPROTO in %s\n", 22077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt __func__); 22177f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt } 22277f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt} 22377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt 224630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt/** 2257e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * xtables_set_params - set the global parameters used by xtables 2267e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * @xtp: input xtables_globals structure 2277e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * 2287e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * The app is expected to pass a valid xtables_globals data-filled 2297e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * with proper values 2307e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * @xtp cannot be NULL 2317e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * 2327e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim * Returns -1 on failure to set and 0 on success 2337e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim */ 2347e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salimint xtables_set_params(struct xtables_globals *xtp) 2357e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim{ 2367e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim if (!xtp) { 2377e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim fprintf(stderr, "%s: Illegal global params\n",__func__); 2387e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim return -1; 2397e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim } 2407e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim 2417e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim xt_params = xtp; 2427e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim 2437e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim if (!xt_params->exit_err) 2447e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim xt_params->exit_err = basic_exit_err; 2457e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim 2467e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim return 0; 2477e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim} 2487e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim 2497e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salimint xtables_init_all(struct xtables_globals *xtp, uint8_t nfproto) 2507e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim{ 2517e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim xtables_init(); 2527e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim xtables_set_nfproto(nfproto); 2537e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim return xtables_set_params(xtp); 2547e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim} 2557e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim 2567e4db2f50133007f549f222468bde4f3adcf41acJamal Hadi Salim/** 257630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt * xtables_*alloc - wrappers that exit on failure 258630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt */ 259630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardtvoid *xtables_calloc(size_t count, size_t size) 2603dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI{ 2613dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI void *p; 2623dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 2633dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI if ((p = calloc(count, size)) == NULL) { 2643dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI perror("ip[6]tables: calloc failed"); 2653dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI exit(1); 2663dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI } 2673dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 2683dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI return p; 2693dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI} 2703dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 271630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardtvoid *xtables_malloc(size_t size) 2723dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI{ 2733dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI void *p; 2743dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 2753dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI if ((p = malloc(size)) == NULL) { 2763dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI perror("ip[6]tables: malloc failed"); 2773dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI exit(1); 2783dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI } 2793dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI 2803dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI return p; 2813dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI} 2820b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 283332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowvoid *xtables_realloc(void *ptr, size_t size) 284332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow{ 285332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow void *p; 286332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 287332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if ((p = realloc(ptr, size)) == NULL) { 288332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow perror("ip[6]tables: realloc failed"); 289332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow exit(1); 290332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 291332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 292332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow return p; 293332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow} 294332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 2950b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAIstatic char *get_modprobe(void) 2960b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI{ 2970b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI int procfile; 2980b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI char *ret; 2990b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 3000b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#define PROCFILE_BUFSIZ 1024 3010b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI procfile = open(PROC_SYS_MODPROBE, O_RDONLY); 3020b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (procfile < 0) 3030b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return NULL; 304a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski if (fcntl(procfile, F_SETFD, FD_CLOEXEC) == -1) { 305a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski fprintf(stderr, "Could not set close on exec: %s\n", 306a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski strerror(errno)); 307a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski exit(1); 308a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski } 3090b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 310371cea299f0b2eb100b9fc9fb99089640d2d606fJan Engelhardt ret = malloc(PROCFILE_BUFSIZ); 3110b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (ret) { 3120b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI memset(ret, 0, PROCFILE_BUFSIZ); 3130b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI switch (read(procfile, ret, PROCFILE_BUFSIZ)) { 3140b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI case -1: goto fail; 3150b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI case PROCFILE_BUFSIZ: goto fail; /* Partial read. Wierd */ 3160b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 3170b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (ret[strlen(ret)-1]=='\n') 3180b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI ret[strlen(ret)-1]=0; 3190b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI close(procfile); 3200b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return ret; 3210b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 3220b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI fail: 3230b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI free(ret); 3240b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI close(procfile); 3250b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return NULL; 3260b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI} 3270b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 328c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtint xtables_insmod(const char *modname, const char *modprobe, bool quiet) 3290b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI{ 3300b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI char *buf = NULL; 3310b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI char *argv[4]; 3320b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI int status; 3330b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 3340b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI /* If they don't explicitly set it, read out of kernel */ 3350b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (!modprobe) { 3360b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI buf = get_modprobe(); 3370b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (!buf) 3380b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return -1; 3390b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI modprobe = buf; 3400b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 3410b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 342c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt /* 343c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt * Need to flush the buffer, or the child may output it again 344c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt * when switching the program thru execv. 345c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt */ 346c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt fflush(stdout); 347c19f880d8aac7c0372381e29d7cea09accd0db26Jan Engelhardt 34894aa2ea67d7b8a669e8541f094661a1dc89722a3Jan Engelhardt switch (vfork()) { 3490b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI case 0: 3500b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[0] = (char *)modprobe; 3510b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[1] = (char *)modname; 3520b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (quiet) { 3530b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[2] = "-q"; 3540b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[3] = NULL; 3550b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } else { 3560b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[2] = NULL; 3570b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI argv[3] = NULL; 3580b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 3590b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI execv(argv[0], argv); 3600b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 3610b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI /* not usually reached */ 3620b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI exit(1); 3630b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI case -1: 3640b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return -1; 3650b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 3660b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI default: /* parent */ 3670b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI wait(&status); 3680b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI } 3690b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 3700b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI free(buf); 3710b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI if (WIFEXITED(status) && WEXITSTATUS(status) == 0) 3720b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return 0; 3730b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI return -1; 3740b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI} 3750b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI 376b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski/* return true if a given file exists within procfs */ 377b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowskistatic bool proc_file_exists(const char *filename) 378b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski{ 379b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski struct stat s; 380b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski struct statfs f; 381b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski 382b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski if (lstat(filename, &s)) 383b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski return false; 384b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski if (!S_ISREG(s.st_mode)) 385b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski return false; 386b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski if (statfs(filename, &f)) 387b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski return false; 388b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski if (f.f_type != PROC_SUPER_MAGIC) 389b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski return false; 390b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski return true; 391b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski} 392b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski 393c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardtint xtables_load_ko(const char *modprobe, bool quiet) 3940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 395c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardt static bool loaded = false; 396b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski int ret; 3970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 398b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski if (loaded) 399b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski return 0; 400b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski 401b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski if (proc_file_exists(afinfo->proc_exists)) { 402b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski loaded = true; 403b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski return 0; 404b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski }; 405b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski 406b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski ret = xtables_insmod(afinfo->kmod, modprobe, quiet); 407b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski if (ret == 0) 408b32b361a725c8fe3a3aa494e6cdec09a80785aacMaciej Zenczykowski loaded = true; 4090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return ret; 4110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 4120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 4135f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt/** 4145f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * xtables_strtou{i,l} - string to number conversion 4155f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @s: input string 4165f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @end: like strtoul's "end" pointer 4175f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @value: pointer for result 4185f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @min: minimum accepted value 4195f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * @max: maximum accepted value 4205f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * 4215f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * If @end is NULL, we assume the caller wants a "strict strtoul", and hence 4225f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * "15a" is rejected. 4235f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * In either case, the value obtained is compared for min-max compliance. 4245f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * Base is always 0, i.e. autodetect depending on @s. 425cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt * 4265f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * Returns true/false whether number was accepted. On failure, *value has 4275f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt * undefined contents. 428cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt */ 4295f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardtbool xtables_strtoul(const char *s, char **end, unsigned long *value, 4305f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt unsigned long min, unsigned long max) 431cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt{ 432cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt unsigned long v; 433cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt char *my_end; 434cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 435cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt errno = 0; 436cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt v = strtoul(s, &my_end, 0); 437cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 438cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (my_end == s) 439cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return false; 440cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (end != NULL) 441cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt *end = my_end; 442cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 443cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (errno != ERANGE && min <= v && (max == 0 || v <= max)) { 444cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (value != NULL) 445cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt *value = v; 446cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (end == NULL) 447cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return *my_end == '\0'; 448cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return true; 449cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt } 450cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 451cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return false; 452cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt} 453cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 4545f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardtbool xtables_strtoui(const char *s, char **end, unsigned int *value, 4555f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt unsigned int min, unsigned int max) 456cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt{ 457cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt unsigned long v; 458cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt bool ret; 459cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 4605f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt ret = xtables_strtoul(s, end, &v, min, max); 461cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt if (value != NULL) 462cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt *value = v; 463cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt return ret; 464cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt} 465cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt 466aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardtint xtables_service_to_port(const char *name, const char *proto) 46704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{ 46804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI struct servent *service; 46904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 47004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI if ((service = getservbyname(name, proto)) != NULL) 47104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI return ntohs((unsigned short) service->s_port); 47204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 47304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI return -1; 47404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI} 47504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 4767ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtuint16_t xtables_parse_port(const char *port, const char *proto) 47704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{ 4787a236f4cc685a420c1a782a5db614a93baf37ccfJan Engelhardt unsigned int portnum; 47904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 4805f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt if (xtables_strtoui(port, NULL, &portnum, 0, UINT16_MAX) || 481aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardt (portnum = xtables_service_to_port(port, proto)) != (unsigned)-1) 482213e185afbb298e6708881e4c2adffdc47a8b6daJan Engelhardt return portnum; 48304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 4848b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 48504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI "invalid port/service `%s' specified", port); 48604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI} 48704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 488aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardtvoid xtables_parse_interface(const char *arg, char *vianame, 489aae6be9edc99e58164a3592c510fe5488141c698Jan Engelhardt unsigned char *mask) 49004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{ 491fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt unsigned int vialen = strlen(arg); 49204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI unsigned int i; 49304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 49404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask, 0, IFNAMSIZ); 49504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(vianame, 0, IFNAMSIZ); 49604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 49704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI if (vialen + 1 > IFNAMSIZ) 4988b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 49904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI "interface name `%s' must be shorter than IFNAMSIZ" 50004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI " (%i)", arg, IFNAMSIZ-1); 50104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 50204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI strcpy(vianame, arg); 503fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt if (vialen == 0) 50404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask, 0, IFNAMSIZ); 50504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI else if (vianame[vialen - 1] == '+') { 50604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask, 0xFF, vialen - 1); 50704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask + vialen - 1, 0, IFNAMSIZ - vialen + 1); 50804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI /* Don't remove `+' here! -HW */ 50904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } else { 51004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI /* Include nul-terminator in match */ 51104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask, 0xFF, vialen + 1); 51204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI memset(mask + vialen + 1, 0, IFNAMSIZ - vialen - 1); 51304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI for (i = 0; vianame[i]; i++) { 514fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt if (vianame[i] == '/' || 515fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt vianame[i] == ' ') { 516aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann fprintf(stderr, 517aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann "Warning: weird character in interface" 518fcf5723f415c81fcb2c93094cdcc39b35a316ff2Jan Engelhardt " `%s' ('/' and ' ' are not allowed by the kernel).\n", 519aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann vianame); 52004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI break; 52104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } 52204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } 52304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI } 52404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI} 52504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI 526cb25af809a8734c4766b6bfa4cca99596cbf01dbJan Engelhardt#ifndef NO_SHARED_LIBS 527927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardtstatic void *load_extension(const char *search_path, const char *af_prefix, 52821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt const char *name, bool is_target) 52921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt{ 530927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt const char *all_prefixes[] = {"libxt_", af_prefix, NULL}; 531927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt const char **prefix; 53221b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt const char *dir = search_path, *next; 53321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt void *ptr = NULL; 53421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt struct stat sb; 53521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt char path[256]; 53621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 53721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt do { 53821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt next = strchr(dir, ':'); 53921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt if (next == NULL) 54021b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt next = dir + strlen(dir); 54121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 542927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt for (prefix = all_prefixes; *prefix != NULL; ++prefix) { 543927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt snprintf(path, sizeof(path), "%.*s/%s%s.so", 544927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt (unsigned int)(next - dir), dir, 545927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt *prefix, name); 546927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt 547927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt if (stat(path, &sb) != 0) { 548927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt if (errno == ENOENT) 549927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt continue; 550927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt fprintf(stderr, "%s: %s\n", path, 551927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt strerror(errno)); 552927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt return NULL; 553927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt } 554927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt if (dlopen(path, RTLD_NOW) == NULL) { 555927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt fprintf(stderr, "%s: %s\n", path, dlerror()); 556927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt break; 557927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt } 55821b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 55921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt if (is_target) 5602338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt ptr = xtables_find_target(name, XTF_DONT_LOAD); 56121b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt else 5622338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt ptr = xtables_find_match(name, 5632338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt XTF_DONT_LOAD, NULL); 56421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 565927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt if (ptr != NULL) 566927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt return ptr; 56721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 568927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt fprintf(stderr, "%s: no \"%s\" extension found for " 569927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt "this protocol\n", path, name); 570927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt errno = ENOENT; 571927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt return NULL; 572927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt } 57321b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt dir = next + 1; 57421b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt } while (*next != '\0'); 57521b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 57621b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt return NULL; 57721b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt} 578cb25af809a8734c4766b6bfa4cca99596cbf01dbJan Engelhardt#endif 57921b41eea4724c57d2b6e5998cf38255046e43ad3Jan Engelhardt 5802338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtstruct xtables_match * 5812338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtxtables_find_match(const char *name, enum xtables_tryload tryload, 5822338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt struct xtables_rule_match **matches) 5830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 5842c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski struct xtables_match **dptr; 5850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_match *ptr; 5860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI const char *icmp6 = "icmp6"; 5870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 5880cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt if (strlen(name) >= XT_EXTENSION_MAXNAMELEN) 58921d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt xtables_error(PARAMETER_PROBLEM, 59021d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt "Invalid match name \"%s\" (%u chars max)", 5910cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt name, XT_EXTENSION_MAXNAMELEN - 1); 59221d1283750d9c4df7ca80165d2b9dc0b9bd214ebJan Engelhardt 5930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* This is ugly as hell. Nonetheless, there is no way of changing 5940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI * this without hurting backwards compatibility */ 5950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if ( (strcmp(name,"icmpv6") == 0) || 5960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI (strcmp(name,"ipv6-icmp") == 0) || 5970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI (strcmp(name,"icmp6") == 0) ) 5980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI name = icmp6; 5990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6002c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski /* Trigger delayed initialization */ 6012c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski for (dptr = &xtables_pending_matches; *dptr; ) { 6022c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski if (strcmp(name, (*dptr)->name) == 0) { 6032c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski ptr = *dptr; 6042c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski *dptr = (*dptr)->next; 6052c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski ptr->next = NULL; 6062c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski xtables_fully_register_pending_match(ptr); 6072c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski } else { 6082c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski dptr = &((*dptr)->next); 6092c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski } 6102c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski } 6112c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski 6120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (ptr = xtables_matches; ptr; ptr = ptr->next) { 6130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(name, ptr->name) == 0) { 6140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_match *clone; 6150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6160d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* First match of this type: */ 6170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr->m == NULL) 6180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI break; 6190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Second and subsequent clones */ 621630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt clone = xtables_malloc(sizeof(struct xtables_match)); 6220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI memcpy(clone, ptr, sizeof(struct xtables_match)); 6230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI clone->mflags = 0; 6240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* This is a clone: */ 6250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI clone->next = clone; 6260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr = clone; 6280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI break; 6290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#ifndef NO_SHARED_LIBS 6332338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) { 63477f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt ptr = load_extension(xtables_libdir, afinfo->libprefix, 63539bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt name, false); 636170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI 6372338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) 6388b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 6390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "Couldn't load match `%s':%s\n", 640927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt name, strerror(errno)); 6410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#else 6430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr && !ptr->loaded) { 6442338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if (tryload != XTF_DONT_LOAD) 6450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr->loaded = 1; 6460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI else 6470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr = NULL; 6480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6492338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if(!ptr && (tryload == XTF_LOAD_MUST_SUCCEED)) { 6508b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 6510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "Couldn't find match `%s'\n", name); 6520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#endif 6540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr && matches) { 6560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_rule_match **i; 6570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_rule_match *newentry; 6580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 659630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt newentry = xtables_malloc(sizeof(struct xtables_rule_match)); 6600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (i = matches; *i; i = &(*i)->next) { 6620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(name, (*i)->match->name) == 0) 6632338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt (*i)->completed = true; 6640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI newentry->match = ptr; 6662338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt newentry->completed = false; 6670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI newentry->next = NULL; 6680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI *i = newentry; 6690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 6700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return ptr; 6720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 6730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6742338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtstruct xtables_target * 6752338efd8f799d8373dc196c797bda9690283b698Jan Engelhardtxtables_find_target(const char *name, enum xtables_tryload tryload) 6760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 6772c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski struct xtables_target **dptr; 6780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_target *ptr; 6790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Standard target? */ 6810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(name, "") == 0 6820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI || strcmp(name, XTC_LABEL_ACCEPT) == 0 6830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI || strcmp(name, XTC_LABEL_DROP) == 0 6840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI || strcmp(name, XTC_LABEL_QUEUE) == 0 6850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI || strcmp(name, XTC_LABEL_RETURN) == 0) 6860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI name = "standard"; 6870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 6882c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski /* Trigger delayed initialization */ 6892c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski for (dptr = &xtables_pending_targets; *dptr; ) { 6902c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski if (strcmp(name, (*dptr)->name) == 0) { 6912c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski ptr = *dptr; 6922c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski *dptr = (*dptr)->next; 6932c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski ptr->next = NULL; 6942c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski xtables_fully_register_pending_target(ptr); 6952c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski } else { 6962c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski dptr = &((*dptr)->next); 6972c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski } 6982c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski } 6992c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski 7000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (ptr = xtables_targets; ptr; ptr = ptr->next) { 7010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (strcmp(name, ptr->name) == 0) 7020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI break; 7030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 7040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#ifndef NO_SHARED_LIBS 7062338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) { 70777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt ptr = load_extension(xtables_libdir, afinfo->libprefix, 70839bf9c8214d3073a496a8a1eff91046a8d6fbbdfJan Engelhardt name, true); 709170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI 7102338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) 7118b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 7120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "Couldn't load target `%s':%s\n", 713927385017047dce3f01c0aee73ab2989b108bbf0Jan Engelhardt name, strerror(errno)); 7140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 7150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#else 7160d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr && !ptr->loaded) { 7172338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt if (tryload != XTF_DONT_LOAD) 7180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr->loaded = 1; 7190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI else 7200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr = NULL; 7210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 722854d2d9bd7556cfd8a676b0bc18dc059a9a2dd25Peter Volkov if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) { 7238b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 7240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "Couldn't find target `%s'\n", name); 7250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 7260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#endif 7270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (ptr) 7290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI ptr->used = 1; 7300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return ptr; 7320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 7330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7347ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtstatic int compatible_revision(const char *name, uint8_t revision, int opt) 7350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 7360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xt_get_revision rev; 7370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI socklen_t s = sizeof(rev); 7380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI int max_rev, sockfd; 7390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 74077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt sockfd = socket(afinfo->family, SOCK_RAW, IPPROTO_RAW); 7410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (sockfd < 0) { 742df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy if (errno == EPERM) { 743df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy /* revision 0 is always supported. */ 744df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy if (revision != 0) 745df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy fprintf(stderr, "Could not determine whether " 746df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy "revision %u is supported, " 747df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy "assuming it is.\n", 748df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy revision); 749df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy return 1; 750df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy } 7510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "Could not open socket to kernel: %s\n", 7520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI strerror(errno)); 7530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 7540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 7550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 756a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski if (fcntl(sockfd, F_SETFD, FD_CLOEXEC) == -1) { 757a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski fprintf(stderr, "Could not set close on exec: %s\n", 758a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski strerror(errno)); 759a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski exit(1); 760a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski } 761a239728ec064666025de2723997d87b176d57fd6Maciej Zenczykowski 762c021c3ce7b1583eb5dd71b10ac3d8ab3cd36beaaJan Engelhardt xtables_load_ko(xtables_modprobe_program, true); 7630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI strcpy(rev.name, name); 7650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI rev.revision = revision; 7660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 76777f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt max_rev = getsockopt(sockfd, afinfo->ipproto, opt, &rev, &s); 7680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (max_rev < 0) { 7690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Definitely don't support this? */ 7700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (errno == ENOENT || errno == EPROTONOSUPPORT) { 7710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI close(sockfd); 7720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return 0; 7730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } else if (errno == ENOPROTOOPT) { 7740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI close(sockfd); 7750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Assume only revision 0 support (old kernel) */ 7760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return (revision == 0); 7770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } else { 7780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "getsockopt failed strangely: %s\n", 7790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI strerror(errno)); 7800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 7810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 7820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 7830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI close(sockfd); 7840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return 1; 7850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 7860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7887ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtstatic int compatible_match_revision(const char *name, uint8_t revision) 7890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 79077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt return compatible_revision(name, revision, afinfo->so_rev_match); 7910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 7920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 7937ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtstatic int compatible_target_revision(const char *name, uint8_t revision) 7940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 79577f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt return compatible_revision(name, revision, afinfo->so_rev_target); 7960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 7970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 798dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardtstatic void xtables_check_options(const char *name, const struct option *opt) 799dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt{ 800dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt for (; opt->name != NULL; ++opt) 801dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt if (opt->val < 0 || opt->val >= XT_OPTION_OFFSET_SCALE) { 802dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt fprintf(stderr, "%s: Extension %s uses invalid " 803dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt "option value %d\n",xt_params->program_name, 804dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt name, opt->val); 805dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt exit(1); 806dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt } 807dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt} 808dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt 8090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIvoid xtables_register_match(struct xtables_match *me) 8100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 811c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt if (me->version == NULL) { 812c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt fprintf(stderr, "%s: match %s<%u> is missing a version\n", 813c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt xt_params->program_name, me->name, me->revision); 814c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt exit(1); 815c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt } 816dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt if (strcmp(me->version, XTABLES_VERSION) != 0) { 817dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt fprintf(stderr, "%s: match \"%s\" has version \"%s\", " 818dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt "but \"%s\" is required.\n", 8195dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name, 820dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt me->version, XTABLES_VERSION); 8210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 8220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 8230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8240cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) { 825281439ba6b96b729ef1400a49ec53eda298bb9f8Li Yewang fprintf(stderr, "%s: match `%s' has invalid name\n", 8265dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name); 8270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 8280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 8290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (me->family >= NPROTO) { 8310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, 8320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "%s: BUG: match %s has invalid protocol family\n", 8335dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name); 8340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 8350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 8360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 837aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (me->x6_options != NULL) 838aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtables_option_metavalidate(me->name, me->x6_options); 839dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt if (me->extra_opts != NULL) 840dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt xtables_check_options(me->name, me->extra_opts); 841dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt 8420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* ignore not interested match */ 84377f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt if (me->family != afinfo->family && me->family != AF_UNSPEC) 8440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 8450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8462c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski /* place on linked list of matches pending full registration */ 8472c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski me->next = xtables_pending_matches; 8482c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski xtables_pending_matches = me; 8492c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski} 8502c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski 8512c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowskistatic void xtables_fully_register_pending_match(struct xtables_match *me) 8522c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski{ 8532c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski struct xtables_match **i, *old; 8542c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski 8552338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt old = xtables_find_match(me->name, XTF_DURING_LOAD, NULL); 8560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (old) { 85723545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt if (old->revision == me->revision && 85823545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt old->family == me->family) { 8590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, 8600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "%s: match `%s' already registered.\n", 8615dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name); 8620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 8630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 8640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Now we have two (or more) options, check compatibility. */ 8660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (compatible_match_revision(old->name, old->revision) 8670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI && old->revision > me->revision) 8680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 8690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 87023545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt /* See if new match can be used. */ 8710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (!compatible_match_revision(me->name, me->revision)) 8720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 8730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 87423545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt /* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */ 87523545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt if (old->revision == me->revision && me->family == AF_UNSPEC) 87623545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt return; 87723545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt 8780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Delete old one. */ 8790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (i = &xtables_matches; *i!=old; i = &(*i)->next); 8800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI *i = old->next; 8810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 8820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (me->size != XT_ALIGN(me->size)) { 8840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "%s: match `%s' has invalid size %u.\n", 8855dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name, 8865dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim (unsigned int)me->size); 8870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 8880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 8890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Append to list. */ 8910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (i = &xtables_matches; *i; i = &(*i)->next); 8920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->next = NULL; 8930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI *i = me; 8940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->m = NULL; 8960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->mflags = 0; 8970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 8980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 8999a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardtvoid xtables_register_matches(struct xtables_match *match, unsigned int n) 9009a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt{ 9019a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt do { 9029a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt xtables_register_match(&match[--n]); 9039a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt } while (n > 0); 9049a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt} 9059a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt 9060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIvoid xtables_register_target(struct xtables_target *me) 9070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{ 908c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt if (me->version == NULL) { 909c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt fprintf(stderr, "%s: target %s<%u> is missing a version\n", 910c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt xt_params->program_name, me->name, me->revision); 911c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt exit(1); 912c284de545d03aad9a04a4e17cfb55d911a96810cJan Engelhardt } 913dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt if (strcmp(me->version, XTABLES_VERSION) != 0) { 914dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt fprintf(stderr, "%s: target \"%s\" has version \"%s\", " 915dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt "but \"%s\" is required.\n", 9165dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name, 917dacafa55379fd98212031d8c559096c91d7ce93bJan Engelhardt me->version, XTABLES_VERSION); 9180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 9190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 9200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 9210cb675b8f18c4b074d4c69461638820708e98100Jan Engelhardt if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) { 9220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "%s: target `%s' has invalid name\n", 9235dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name); 9240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 9250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 9260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 9270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (me->family >= NPROTO) { 9280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, 9290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "%s: BUG: target %s has invalid protocol family\n", 9305dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name); 9310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 9320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 9330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 934aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt if (me->x6_options != NULL) 935aa37acc1423126f555135935c687eb91995b9440Jan Engelhardt xtables_option_metavalidate(me->name, me->x6_options); 936dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt if (me->extra_opts != NULL) 937dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt xtables_check_options(me->name, me->extra_opts); 938dfbedfedf610210c4ee3f00e9c4f9ea24c4ffe23Jan Engelhardt 9390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* ignore not interested target */ 94077f48c2f1ef21fa43aa68c25a1457db319ca2526Jan Engelhardt if (me->family != afinfo->family && me->family != AF_UNSPEC) 9410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 9420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 9432c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski /* place on linked list of targets pending full registration */ 9442c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski me->next = xtables_pending_targets; 9452c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski xtables_pending_targets = me; 9462c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski} 9472c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski 9482c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowskistatic void xtables_fully_register_pending_target(struct xtables_target *me) 9492c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski{ 9502c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski struct xtables_target *old; 9512c6ac071a9c660b61a76565d1024d372deac8a98Maciej Zenczykowski 9522338efd8f799d8373dc196c797bda9690283b698Jan Engelhardt old = xtables_find_target(me->name, XTF_DURING_LOAD); 9530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (old) { 9540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI struct xtables_target **i; 9550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 95623545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt if (old->revision == me->revision && 95723545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt old->family == me->family) { 9580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, 9590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI "%s: target `%s' already registered.\n", 9605dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name); 9610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 9620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 9630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 9640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Now we have two (or more) options, check compatibility. */ 9650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (compatible_target_revision(old->name, old->revision) 9660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI && old->revision > me->revision) 9670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 9680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 96923545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt /* See if new target can be used. */ 9700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (!compatible_target_revision(me->name, me->revision)) 9710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI return; 9720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 97323545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt /* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */ 97423545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt if (old->revision == me->revision && me->family == AF_UNSPEC) 97523545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt return; 97623545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt 9770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Delete old one. */ 9780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI for (i = &xtables_targets; *i!=old; i = &(*i)->next); 9790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI *i = old->next; 9800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 9810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 9820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI if (me->size != XT_ALIGN(me->size)) { 9830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI fprintf(stderr, "%s: target `%s' has invalid size %u.\n", 9845dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim xt_params->program_name, me->name, 9855dd19de34380c91ad07bbe79a34726e59891cf54Jamal Hadi Salim (unsigned int)me->size); 9860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI exit(1); 9870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI } 9880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI 9890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI /* Prepend to list. */ 9900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->next = xtables_targets; 9910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI xtables_targets = me; 9920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->t = NULL; 9930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI me->tflags = 0; 9940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI} 995aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt 9969a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardtvoid xtables_register_targets(struct xtables_target *target, unsigned int n) 9979a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt{ 9989a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt do { 9999a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt xtables_register_target(&target[--n]); 10009a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt } while (n > 0); 10019a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt} 10029a8fc4f89ef120d7beda3724994a1544346b947dJan Engelhardt 1003a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt/** 1004a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * xtables_param_act - act on condition 1005a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @status: a constant from enum xtables_exittype 1006a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * 1007a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_ONLY_ONCE: print error message that option may only be used once. 1008a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1: module name (e.g. "mark") 1009a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2(...): option in conflict (e.g. "--mark") 1010a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3(...): condition to match on (see extensions/ for examples) 1011a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * 1012a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_NO_INVERT: option does not support inversion 1013a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1: module name 1014a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2: option in conflict 1015a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3: condition to match on 1016a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * 1017a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_BAD_VALUE: bad value for option 1018a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1: module name 1019a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p2: option with which the problem occured (e.g. "--mark") 1020a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p3: string the user passed in (e.g. "99999999999999") 1021a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * 1022a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * %XTF_ONE_ACTION: two mutually exclusive actions have been specified 1023a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * @p1: module name 1024a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * 1025a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt * Displays an error message and exits the program. 1026a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt */ 1027a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardtvoid xtables_param_act(unsigned int status, const char *p1, ...) 1028aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt{ 1029aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt const char *p2, *p3; 1030aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt va_list args; 1031aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt bool b; 1032aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt 1033aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt va_start(args, p1); 1034aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt 1035aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt switch (status) { 1036a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt case XTF_ONLY_ONCE: 1037aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt p2 = va_arg(args, const char *); 1038aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt b = va_arg(args, unsigned int); 1039aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt if (!b) 1040aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt return; 10418b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 1042aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt "%s: \"%s\" option may only be specified once", 1043aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt p1, p2); 1044aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt break; 1045a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt case XTF_NO_INVERT: 1046aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt p2 = va_arg(args, const char *); 1047aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt b = va_arg(args, unsigned int); 1048aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt if (!b) 1049aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt return; 10508b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 1051aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt "%s: \"%s\" option cannot be inverted", p1, p2); 1052aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt break; 1053a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt case XTF_BAD_VALUE: 1054aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt p2 = va_arg(args, const char *); 1055aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt p3 = va_arg(args, const char *); 10568b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 1057aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt "%s: Bad value for \"%s\" option: \"%s\"", 1058aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt p1, p2, p3); 1059aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt break; 1060a41545ca7cde43e0ba53260ba74bd9bf74025a68Jan Engelhardt case XTF_ONE_ACTION: 1061aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt b = va_arg(args, unsigned int); 1062aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt if (!b) 1063aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt return; 10648b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 1065aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt "%s: At most one action is possible", p1); 1066aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt break; 1067aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt default: 10688b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(status, p1, args); 1069aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt break; 1070aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt } 1071aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt 1072aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt va_end(args); 1073aafd269675fc45bac6340027c866ea6073643c3bJan Engelhardt} 107408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 1075e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ipaddr_to_numeric(const struct in_addr *addrp) 107608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 107708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt static char buf[20]; 107808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt const unsigned char *bytep = (const void *)&addrp->s_addr; 107908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 108008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt sprintf(buf, "%u.%u.%u.%u", bytep[0], bytep[1], bytep[2], bytep[3]); 108108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return buf; 108208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 108308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 108408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ipaddr_to_host(const struct in_addr *addr) 108508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 108608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt struct hostent *host; 108708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 108808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt host = gethostbyaddr(addr, sizeof(struct in_addr), AF_INET); 108908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if (host == NULL) 109008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return NULL; 109108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 109208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return host->h_name; 109308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 109408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 109508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ipaddr_to_network(const struct in_addr *addr) 109608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 109708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt struct netent *net; 109808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 109908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if ((net = getnetbyaddr(ntohl(addr->s_addr), AF_INET)) != NULL) 110008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return net->n_name; 110108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 110208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return NULL; 110308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 110408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 1105e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ipaddr_to_anyname(const struct in_addr *addr) 110608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 110708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt const char *name; 110808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 110908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if ((name = ipaddr_to_host(addr)) != NULL || 111008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt (name = ipaddr_to_network(addr)) != NULL) 111108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return name; 111208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 1113e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt return xtables_ipaddr_to_numeric(addr); 111408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 111508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 1116e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ipmask_to_numeric(const struct in_addr *mask) 111708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 111808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt static char buf[20]; 111908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt uint32_t maskaddr, bits; 112008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt int i; 112108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 112208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt maskaddr = ntohl(mask->s_addr); 112308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 112408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if (maskaddr == 0xFFFFFFFFL) 112508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt /* we don't want to see "/32" */ 112608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return ""; 112708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 112808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt i = 32; 112908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt bits = 0xFFFFFFFEL; 113008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt while (--i >= 0 && maskaddr != bits) 113108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt bits <<= 1; 113208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if (i >= 0) 113308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt sprintf(buf, "/%d", i); 113408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt else 113508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt /* mask was not a decent combination of 1's and 0's */ 1136e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt sprintf(buf, "/%s", xtables_ipaddr_to_numeric(mask)); 113708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 113808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return buf; 113908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 114008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 1141bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *__numeric_to_ipaddr(const char *dotted, bool is_mask) 1142bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1143bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt static struct in_addr addr; 1144bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned char *addrp; 1145bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned int onebyte; 1146bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt char buf[20], *p, *q; 1147bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt int i; 1148bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1149bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* copy dotted string, because we need to modify it */ 1150bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt strncpy(buf, dotted, sizeof(buf) - 1); 1151bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt buf[sizeof(buf) - 1] = '\0'; 1152bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = (void *)&addr.s_addr; 1153bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1154bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt p = buf; 1155bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (i = 0; i < 3; ++i) { 1156bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((q = strchr(p, '.')) == NULL) { 1157bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (is_mask) 1158bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1159bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1160bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* autocomplete, this is a network address */ 11615f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX)) 1162bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1163bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1164bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp[i] = onebyte; 1165bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt while (i < 3) 1166bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp[++i] = 0; 1167bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1168bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &addr; 1169bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1170bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1171bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *q = '\0'; 11725f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX)) 1173bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1174bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1175bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp[i] = onebyte; 1176bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt p = q + 1; 1177bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1178bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1179bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* we have checked 3 bytes, now we check the last one */ 11805f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX)) 1181bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1182bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1183bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp[3] = onebyte; 1184bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &addr; 1185bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1186bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 11871e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in_addr *xtables_numeric_to_ipaddr(const char *dotted) 1188bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1189bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return __numeric_to_ipaddr(dotted, false); 1190bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1191bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 11921e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in_addr *xtables_numeric_to_ipmask(const char *dotted) 1193bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1194bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return __numeric_to_ipaddr(dotted, true); 1195bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1196bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1197bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *network_to_ipaddr(const char *name) 1198bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1199bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt static struct in_addr addr; 1200bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct netent *net; 1201bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1202bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((net = getnetbyname(name)) != NULL) { 1203bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (net->n_addrtype != AF_INET) 1204bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1205bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addr.s_addr = htonl(net->n_net); 1206bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &addr; 1207bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1208bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1209bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1210bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1211bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1212bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *host_to_ipaddr(const char *name, unsigned int *naddr) 1213bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1214bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct hostent *host; 1215bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in_addr *addr; 1216bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned int i; 1217bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1218bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *naddr = 0; 1219bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((host = gethostbyname(name)) != NULL) { 1220bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (host->h_addrtype != AF_INET || 1221bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt host->h_length != sizeof(struct in_addr)) 1222bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1223bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1224bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt while (host->h_addr_list[*naddr] != NULL) 1225bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt ++*naddr; 122611e250ba02349cb1e34058673db3d0b54eb56c44Wes Campaigne addr = xtables_calloc(*naddr, sizeof(struct in_addr)); 1227bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (i = 0; i < *naddr; i++) 1228bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memcpy(&addr[i], host->h_addr_list[i], 1229bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt sizeof(struct in_addr)); 1230bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addr; 1231bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1232bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1233bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1234bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1235bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1236bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr * 1237bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtipparse_hostnetwork(const char *name, unsigned int *naddrs) 1238bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1239bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in_addr *addrptmp, *addrp; 1240bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 12411e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt if ((addrptmp = xtables_numeric_to_ipaddr(name)) != NULL || 1242bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt (addrptmp = network_to_ipaddr(name)) != NULL) { 1243630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt addrp = xtables_malloc(sizeof(struct in_addr)); 1244bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memcpy(addrp, addrptmp, sizeof(*addrp)); 1245bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *naddrs = 1; 1246bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addrp; 1247bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1248bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((addrptmp = host_to_ipaddr(name, naddrs)) != NULL) 1249bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addrptmp; 1250bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 12518b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name); 1252bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1253bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1254bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in_addr *parse_ipmask(const char *mask) 1255bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1256bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt static struct in_addr maskaddr; 1257bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in_addr *addrp; 1258bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned int bits; 1259bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1260bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (mask == NULL) { 1261bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* no mask at all defaults to 32 bits */ 1262bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt maskaddr.s_addr = 0xFFFFFFFF; 1263bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &maskaddr; 1264bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 12651e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt if ((addrp = xtables_numeric_to_ipmask(mask)) != NULL) 1266bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* dotted_to_addr already returns a network byte order addr */ 1267bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addrp; 12685f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt if (!xtables_strtoui(mask, NULL, &bits, 0, 32)) 12698b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 1270bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt "invalid mask `%s' specified", mask); 1271bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (bits != 0) { 1272bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt maskaddr.s_addr = htonl(0xFFFFFFFF << (32 - bits)); 1273bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &maskaddr; 1274bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1275bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1276bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt maskaddr.s_addr = 0U; 1277bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &maskaddr; 1278bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1279bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1280332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowvoid xtables_ipparse_multiple(const char *name, struct in_addr **addrpp, 1281332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow struct in_addr **maskpp, unsigned int *naddrs) 1282332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow{ 1283332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow struct in_addr *addrp; 1284332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow char buf[256], *p; 1285332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow unsigned int len, i, j, n, count = 1; 1286332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow const char *loop = name; 1287332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1288332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow while ((loop = strchr(loop, ',')) != NULL) { 1289332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow ++count; 1290332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow ++loop; /* skip ',' */ 1291332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1292332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1293332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *addrpp = xtables_malloc(sizeof(struct in_addr) * count); 1294332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *maskpp = xtables_malloc(sizeof(struct in_addr) * count); 1295332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1296332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow loop = name; 1297332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1298332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow for (i = 0; i < count; ++i) { 1299332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (loop == NULL) 1300332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow break; 1301332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (*loop == ',') 1302332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow ++loop; 1303332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (*loop == '\0') 1304332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow break; 1305332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow p = strchr(loop, ','); 1306332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (p != NULL) 1307332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow len = p - loop; 1308332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow else 1309332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow len = strlen(loop); 1310332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (len == 0 || sizeof(buf) - 1 < len) 1311332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow break; 1312332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1313332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow strncpy(buf, loop, len); 1314332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow buf[len] = '\0'; 1315332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow loop += len; 1316332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if ((p = strrchr(buf, '/')) != NULL) { 1317332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *p = '\0'; 1318332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow addrp = parse_ipmask(p + 1); 1319332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } else { 1320332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow addrp = parse_ipmask(NULL); 1321332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1322332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*maskpp + i, addrp, sizeof(*addrp)); 1323332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1324332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* if a null mask is given, the name is ignored, like in "any/0" */ 1325332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if ((*maskpp + i)->s_addr == 0) 1326332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* 1327332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow * A bit pointless to process multiple addresses 1328332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow * in this case... 1329332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow */ 1330332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow strcpy(buf, "0.0.0.0"); 1331332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1332332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow addrp = ipparse_hostnetwork(buf, &n); 1333332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (n > 1) { 1334332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow count += n - 1; 1335332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *addrpp = xtables_realloc(*addrpp, 1336332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(struct in_addr) * count); 1337332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *maskpp = xtables_realloc(*maskpp, 1338332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(struct in_addr) * count); 1339332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow for (j = 0; j < n; ++j) 1340332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* for each new addr */ 1341332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*addrpp + i + j, addrp + j, 1342332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(*addrp)); 1343332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow for (j = 1; j < n; ++j) 1344332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* for each new mask */ 1345332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*maskpp + i + j, *maskpp + i, 1346332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(*addrp)); 1347332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow i += n - 1; 1348332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } else { 1349332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*addrpp + i, addrp, sizeof(*addrp)); 1350332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1351332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* free what ipparse_hostnetwork had allocated: */ 1352332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow free(addrp); 1353332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1354332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *naddrs = count; 13554b110b426df7bf486a3e7884c56ebb3487023601Jan Engelhardt for (i = 0; i < count; ++i) 1356332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow (*addrpp+i)->s_addr &= (*maskpp+i)->s_addr; 1357332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow} 1358332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1359332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1360a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt/** 1361a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * xtables_ipparse_any - transform arbitrary name to in_addr 1362a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * 1363a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * Possible inputs (pseudo regex): 1364a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * m{^($hostname|$networkname|$ipaddr)(/$mask)?} 1365a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt * "1.2.3.4/5", "1.2.3.4", "hostname", "networkname" 1366a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt */ 1367a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_ipparse_any(const char *name, struct in_addr **addrpp, 1368a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt struct in_addr *maskp, unsigned int *naddrs) 1369bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1370bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned int i, j, k, n; 1371bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in_addr *addrp; 1372bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt char buf[256], *p; 1373bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1374bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt strncpy(buf, name, sizeof(buf) - 1); 1375bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt buf[sizeof(buf) - 1] = '\0'; 1376bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((p = strrchr(buf, '/')) != NULL) { 1377bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *p = '\0'; 1378bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = parse_ipmask(p + 1); 1379bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } else { 1380bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = parse_ipmask(NULL); 1381bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1382bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memcpy(maskp, addrp, sizeof(*maskp)); 1383bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1384bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* if a null mask is given, the name is ignored, like in "any/0" */ 1385bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (maskp->s_addr == 0U) 1386bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt strcpy(buf, "0.0.0.0"); 1387bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1388bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = *addrpp = ipparse_hostnetwork(buf, naddrs); 1389bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt n = *naddrs; 1390bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (i = 0, j = 0; i < n; ++i) { 1391bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp[j++].s_addr &= maskp->s_addr; 1392bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (k = 0; k < j - 1; ++k) 1393bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (addrp[k].s_addr == addrp[j-1].s_addr) { 1394adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne /* 1395adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne * Nuke the dup by copying an address from the 1396adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne * tail here, and check the current position 1397adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne * again (--j). 1398adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne */ 1399adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne memcpy(&addrp[--j], &addrp[--*naddrs], 1400adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne sizeof(struct in_addr)); 1401bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt break; 1402bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1403bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1404bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1405bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1406e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6addr_to_numeric(const struct in6_addr *addrp) 140708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 1408cf3e52d00b7d3fedf98ef7710c337c441270d936Maciej Zenczykowski /* 0000:0000:0000:0000:0000:0000:000.000.000.000 140908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt * 0000:0000:0000:0000:0000:0000:0000:0000 */ 141008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt static char buf[50+1]; 141108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return inet_ntop(AF_INET6, addrp, buf, sizeof(buf)); 141208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 141308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 141408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic const char *ip6addr_to_host(const struct in6_addr *addr) 141508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 141608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt static char hostname[NI_MAXHOST]; 141708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt struct sockaddr_in6 saddr; 141808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt int err; 141908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 142008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt memset(&saddr, 0, sizeof(struct sockaddr_in6)); 142108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt memcpy(&saddr.sin6_addr, addr, sizeof(*addr)); 142208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt saddr.sin6_family = AF_INET6; 142308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 142408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt err = getnameinfo((const void *)&saddr, sizeof(struct sockaddr_in6), 142508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt hostname, sizeof(hostname) - 1, NULL, 0, 0); 142608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if (err != 0) { 142708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#ifdef DEBUG 142808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt fprintf(stderr,"IP2Name: %s\n",gai_strerror(err)); 142908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#endif 143008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return NULL; 143108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt } 143208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 143308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#ifdef DEBUG 143408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt fprintf (stderr, "\naddr2host: %s\n", hostname); 143508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt#endif 143608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return hostname; 143708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 143808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 1439e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6addr_to_anyname(const struct in6_addr *addr) 144008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 144108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt const char *name; 144208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 144308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if ((name = ip6addr_to_host(addr)) != NULL) 144408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return name; 144508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 1446e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt return xtables_ip6addr_to_numeric(addr); 144708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 144808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 144908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardtstatic int ip6addr_prefix_length(const struct in6_addr *k) 145008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 145108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt unsigned int bits = 0; 145208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt uint32_t a, b, c, d; 145308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 145448607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt a = ntohl(k->s6_addr32[0]); 145548607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt b = ntohl(k->s6_addr32[1]); 145648607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt c = ntohl(k->s6_addr32[2]); 145748607816796124ce2177ee22645d3fd8180f1e98Jan Engelhardt d = ntohl(k->s6_addr32[3]); 145808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt while (a & 0x80000000U) { 145908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt ++bits; 146008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt a <<= 1; 146108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt a |= (b >> 31) & 1; 146208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt b <<= 1; 146308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt b |= (c >> 31) & 1; 146408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt c <<= 1; 146508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt c |= (d >> 31) & 1; 146608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt d <<= 1; 146708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt } 146808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if (a != 0 || b != 0 || c != 0 || d != 0) 146908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return -1; 147008b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return bits; 147108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 147208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 1473e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardtconst char *xtables_ip6mask_to_numeric(const struct in6_addr *addrp) 147408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt{ 147508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt static char buf[50+2]; 147608b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt int l = ip6addr_prefix_length(addrp); 147708b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt 147808b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt if (l == -1) { 147908b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt strcpy(buf, "/"); 1480e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7Jan Engelhardt strcat(buf, xtables_ip6addr_to_numeric(addrp)); 148108b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return buf; 148208b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt } 148308b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt sprintf(buf, "/%d", l); 148408b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt return buf; 148508b1616e068166e016b3ee7110db10ae5d853422Jan Engelhardt} 1486bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 14871e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardtstruct in6_addr *xtables_numeric_to_ip6addr(const char *num) 1488bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1489bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt static struct in6_addr ap; 1490bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt int err; 1491bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1492bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((err = inet_pton(AF_INET6, num, &ap)) == 1) 1493bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return ≈ 1494bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG 1495bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt fprintf(stderr, "\nnumeric2addr: %d\n", err); 1496bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif 1497bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1498bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1499bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1500bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr * 1501bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardthost_to_ip6addr(const char *name, unsigned int *naddr) 1502bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 15032ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne struct in6_addr *addr; 1504bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct addrinfo hints; 15052ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne struct addrinfo *res, *p; 1506bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt int err; 15072ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne unsigned int i; 1508bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1509bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memset(&hints, 0, sizeof(hints)); 1510bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt hints.ai_flags = AI_CANONNAME; 1511bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt hints.ai_family = AF_INET6; 1512bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt hints.ai_socktype = SOCK_RAW; 1513bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1514bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *naddr = 0; 1515bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((err = getaddrinfo(name, NULL, &hints, &res)) != 0) { 1516bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG 1517bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt fprintf(stderr,"Name2IP: %s\n",gai_strerror(err)); 1518bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif 1519bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1520bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } else { 15212ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne /* Find length of address chain */ 15222ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne for (p = res; p != NULL; p = p->ai_next) 15232ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne ++*naddr; 1524bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#ifdef DEBUG 1525bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt fprintf(stderr, "resolved: len=%d %s ", res->ai_addrlen, 152630290aea009cf3fd76f27336fb4370be3467c4daPatrick McHardy xtables_ip6addr_to_numeric(&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr)); 1527bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt#endif 15282ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne /* Copy each element of the address chain */ 15292ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne addr = xtables_calloc(*naddr, sizeof(struct in6_addr)); 15302ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne for (i = 0, p = res; p != NULL; p = p->ai_next) 15312ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne memcpy(&addr[i++], 15322ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne &((const struct sockaddr_in6 *)p->ai_addr)->sin6_addr, 15332ad8dc895ec28a173c629c695c2e11c41b625b6eWes Campaigne sizeof(struct in6_addr)); 1534bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt freeaddrinfo(res); 1535bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addr; 1536bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1537bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1538bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1539bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1540bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1541bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *network_to_ip6addr(const char *name) 1542bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1543bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* abort();*/ 1544bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* TODO: not implemented yet, but the exception breaks the 1545bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt * name resolvation */ 1546bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return NULL; 1547bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1548bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1549bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr * 1550bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtip6parse_hostnetwork(const char *name, unsigned int *naddrs) 1551bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1552bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in6_addr *addrp, *addrptmp; 1553bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 15541e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt if ((addrptmp = xtables_numeric_to_ip6addr(name)) != NULL || 1555bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt (addrptmp = network_to_ip6addr(name)) != NULL) { 1556630ef48037f3602333addfdb53789c9c6a4bb4c8Jan Engelhardt addrp = xtables_malloc(sizeof(struct in6_addr)); 1557bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memcpy(addrp, addrptmp, sizeof(*addrp)); 1558bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *naddrs = 1; 1559bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addrp; 1560bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1561bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((addrp = host_to_ip6addr(name, naddrs)) != NULL) 1562bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addrp; 1563bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 15648b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name); 1565bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1566bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1567bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardtstatic struct in6_addr *parse_ip6mask(char *mask) 1568bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 1569bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt static struct in6_addr maskaddr; 1570bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in6_addr *addrp; 1571bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned int bits; 1572bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1573bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (mask == NULL) { 1574bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* no mask at all defaults to 128 bits */ 1575bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memset(&maskaddr, 0xff, sizeof maskaddr); 1576bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &maskaddr; 1577bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 15781e01b0b82f70b0b11dcfbced485dbe7aeac4fb8cJan Engelhardt if ((addrp = xtables_numeric_to_ip6addr(mask)) != NULL) 1579bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return addrp; 15805f2922cfc0bbfbeb878f5c12e9fb3eb602ae5507Jan Engelhardt if (!xtables_strtoui(mask, NULL, &bits, 0, 128)) 15818b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 1582bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt "invalid mask `%s' specified", mask); 1583bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (bits != 0) { 1584bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt char *p = (void *)&maskaddr; 1585bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memset(p, 0xff, bits / 8); 1586bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memset(p + (bits / 8) + 1, 0, (128 - bits) / 8); 1587bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt p[bits/8] = 0xff << (8 - (bits & 7)); 1588bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &maskaddr; 1589bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1590bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1591bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memset(&maskaddr, 0, sizeof(maskaddr)); 1592bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt return &maskaddr; 1593bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1594bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1595332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowvoid 1596332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzowxtables_ip6parse_multiple(const char *name, struct in6_addr **addrpp, 1597332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow struct in6_addr **maskpp, unsigned int *naddrs) 1598332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow{ 159958df90174164fd673e8c4103f7ce0c4e55ef1aecOlaf Rempel static const struct in6_addr zero_addr; 1600332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow struct in6_addr *addrp; 1601332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow char buf[256], *p; 1602332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow unsigned int len, i, j, n, count = 1; 1603332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow const char *loop = name; 1604332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1605332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow while ((loop = strchr(loop, ',')) != NULL) { 1606332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow ++count; 1607332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow ++loop; /* skip ',' */ 1608332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1609332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1610332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *addrpp = xtables_malloc(sizeof(struct in6_addr) * count); 1611332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *maskpp = xtables_malloc(sizeof(struct in6_addr) * count); 1612332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1613332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow loop = name; 1614332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1615332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow for (i = 0; i < count /*NB: count can grow*/; ++i) { 1616332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (loop == NULL) 1617332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow break; 1618332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (*loop == ',') 1619332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow ++loop; 1620332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (*loop == '\0') 1621332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow break; 1622332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow p = strchr(loop, ','); 1623332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (p != NULL) 1624332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow len = p - loop; 1625332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow else 1626332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow len = strlen(loop); 1627332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (len == 0 || sizeof(buf) - 1 < len) 1628332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow break; 1629332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1630332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow strncpy(buf, loop, len); 1631332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow buf[len] = '\0'; 1632332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow loop += len; 1633332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if ((p = strrchr(buf, '/')) != NULL) { 1634332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *p = '\0'; 1635332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow addrp = parse_ip6mask(p + 1); 1636332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } else { 1637332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow addrp = parse_ip6mask(NULL); 1638332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1639332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*maskpp + i, addrp, sizeof(*addrp)); 1640332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1641332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* if a null mask is given, the name is ignored, like in "any/0" */ 164258df90174164fd673e8c4103f7ce0c4e55ef1aecOlaf Rempel if (memcmp(*maskpp + i, &zero_addr, sizeof(zero_addr)) == 0) 1643332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow strcpy(buf, "::"); 1644332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1645332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow addrp = ip6parse_hostnetwork(buf, &n); 1646332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow if (n > 1) { 1647332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow count += n - 1; 1648332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *addrpp = xtables_realloc(*addrpp, 1649332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(struct in6_addr) * count); 1650332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *maskpp = xtables_realloc(*maskpp, 1651332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(struct in6_addr) * count); 1652332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow for (j = 0; j < n; ++j) 1653332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* for each new addr */ 1654332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*addrpp + i + j, addrp + j, 1655332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(*addrp)); 1656332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow for (j = 1; j < n; ++j) 1657332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* for each new mask */ 1658332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*maskpp + i + j, *maskpp + i, 1659332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow sizeof(*addrp)); 1660332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow i += n - 1; 1661332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } else { 1662332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow memcpy(*addrpp + i, addrp, sizeof(*addrp)); 1663332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1664332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow /* free what ip6parse_hostnetwork had allocated: */ 1665332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow free(addrp); 1666332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow } 1667332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow *naddrs = count; 16684b110b426df7bf486a3e7884c56ebb3487023601Jan Engelhardt for (i = 0; i < count; ++i) 1669332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow for (j = 0; j < 4; ++j) 1670332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow (*addrpp+i)->s6_addr32[j] &= (*maskpp+i)->s6_addr32[j]; 1671332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow} 1672332e4acc574e3a348fe611d55bf642de0d50fbdaMichael Granzow 1673a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_ip6parse_any(const char *name, struct in6_addr **addrpp, 1674a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardt struct in6_addr *maskp, unsigned int *naddrs) 1675bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt{ 16769c0fa7d8c84dc2478bd36d31b328b697fbe4d0afJan Engelhardt static const struct in6_addr zero_addr; 1677bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt struct in6_addr *addrp; 1678bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt unsigned int i, j, k, n; 1679bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt char buf[256], *p; 1680bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1681bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt strncpy(buf, name, sizeof(buf) - 1); 1682bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt buf[sizeof(buf)-1] = '\0'; 1683bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if ((p = strrchr(buf, '/')) != NULL) { 1684bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt *p = '\0'; 1685bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = parse_ip6mask(p + 1); 1686bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } else { 1687bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = parse_ip6mask(NULL); 1688bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1689bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt memcpy(maskp, addrp, sizeof(*maskp)); 1690bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1691bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt /* if a null mask is given, the name is ignored, like in "any/0" */ 16929c0fa7d8c84dc2478bd36d31b328b697fbe4d0afJan Engelhardt if (memcmp(maskp, &zero_addr, sizeof(zero_addr)) == 0) 1693bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt strcpy(buf, "::"); 1694bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt 1695bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt addrp = *addrpp = ip6parse_hostnetwork(buf, naddrs); 1696bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt n = *naddrs; 1697bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (i = 0, j = 0; i < n; ++i) { 1698bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (k = 0; k < 4; ++k) 16995a2208c3e62a150e6f6297abbfa63056ab4a8066Yasuyuki Kozakai addrp[j].s6_addr32[k] &= maskp->s6_addr32[k]; 1700bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt ++j; 1701bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt for (k = 0; k < j - 1; ++k) 1702bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt if (IN6_ARE_ADDR_EQUAL(&addrp[k], &addrp[j - 1])) { 1703adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne /* 1704adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne * Nuke the dup by copying an address from the 1705adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne * tail here, and check the current position 1706adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne * again (--j). 1707adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne */ 1708adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne memcpy(&addrp[--j], &addrp[--*naddrs], 1709adcb28101d53c2a7f372de256b1af50804fee899Wes Campaigne sizeof(struct in_addr)); 1710bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt break; 1711bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1712bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt } 1713bd9438420d92c41a5cf20a53b7a18d3ddea4216dJan Engelhardt} 1714a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann 1715a0baae85f8159f03d52535934aa9b3a375e0f1f3Jan Engelhardtvoid xtables_save_string(const char *value) 1716a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann{ 1717a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann static const char no_quote_chars[] = "_-0123456789" 1718a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann "abcdefghijklmnopqrstuvwxyz" 1719a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 1720a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann static const char escape_chars[] = "\"\\'"; 1721a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann size_t length; 1722a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann const char *p; 1723a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann 172487dc7c4c842deb1e2e3d38089ffcad9f238d98deMax Kellerman length = strspn(value, no_quote_chars); 1725a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann if (length > 0 && value[length] == 0) { 1726a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann /* no quoting required */ 1727a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann putchar(' '); 172873866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt fputs(value, stdout); 1729a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann } else { 1730a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann /* there is at least one dangerous character in the 1731a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann value, which we have to quote. Write double quotes 1732a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann around the value and escape special characters with 1733a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann a backslash */ 173473866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" \""); 1735a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann 1736a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann for (p = strpbrk(value, escape_chars); p != NULL; 1737a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann p = strpbrk(value, escape_chars)) { 1738a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann if (p > value) 1739a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann fwrite(value, 1, p - value, stdout); 1740a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann putchar('\\'); 1741a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann putchar(*p); 1742a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann value = p + 1; 1743a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann } 1744a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann 1745a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann /* print the rest and finish the double quoted 1746a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann string */ 1747a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann fputs(value, stdout); 174873866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt putchar('\"'); 1749a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann } 1750a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann} 17510f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt 17520f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt/** 17530f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt * Check for option-intrapositional negation. 17540f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt * Do not use in new code. 17550f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt */ 17560f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardtint xtables_check_inverse(const char option[], int *invert, 1757bf97128c7262f17a02fec41cdae75b472ba77f88Jan Engelhardt int *my_optind, int argc, char **argv) 17580f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt{ 17592be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt if (option == NULL || strcmp(option, "!") != 0) 17602be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt return false; 17610f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt 17622be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt fprintf(stderr, "Using intrapositioned negation " 17632be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt "(`--option ! this`) is deprecated in favor of " 17642be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt "extrapositioned (`! --option this`).\n"); 17650f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt 17662be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt if (*invert) 17672be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 17682be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt "Multiple `!' flags not allowed"); 17692be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt *invert = true; 17702be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt if (my_optind != NULL) { 1771bf97128c7262f17a02fec41cdae75b472ba77f88Jan Engelhardt optarg = argv[*my_optind]; 17722be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt ++*my_optind; 17732be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt if (argc && *my_optind > argc) 17742be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt xt_params->exit_err(PARAMETER_PROBLEM, 17752be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt "no argument following `!'"); 17760f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt } 17772be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt 17782be22fb36dd1268baecb42ddf35b7a40a6de21d7Jan Engelhardt return true; 17790f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt} 17801de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt 17811de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardtconst struct xtables_pprot xtables_chain_protos[] = { 17821de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"tcp", IPPROTO_TCP}, 17831de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"sctp", IPPROTO_SCTP}, 17841de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"udp", IPPROTO_UDP}, 17851de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"udplite", IPPROTO_UDPLITE}, 17861de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"icmp", IPPROTO_ICMP}, 17871de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"icmpv6", IPPROTO_ICMPV6}, 17881de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"ipv6-icmp", IPPROTO_ICMPV6}, 17891de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"esp", IPPROTO_ESP}, 17901de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"ah", IPPROTO_AH}, 17911de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"ipv6-mh", IPPROTO_MH}, 17921de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"mh", IPPROTO_MH}, 17931de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {"all", 0}, 17941de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt {NULL}, 17951de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt}; 17961de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt 17977ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtuint16_t 17981de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardtxtables_parse_protocol(const char *s) 17991de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt{ 18001de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt unsigned int proto; 18011de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt 18021de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt if (!xtables_strtoui(s, NULL, &proto, 0, UINT8_MAX)) { 18031de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt struct protoent *pent; 18041de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt 18051de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt /* first deal with the special case of 'all' to prevent 18061de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt * people from being able to redefine 'all' in nsswitch 18071de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt * and/or provoke expensive [not working] ldap/nis/... 18081de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt * lookups */ 18091de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt if (!strcmp(s, "all")) 18101de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt return 0; 18111de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt 18121de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt if ((pent = getprotobyname(s))) 18131de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt proto = pent->p_proto; 18141de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt else { 18151de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt unsigned int i; 18161de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt for (i = 0; i < ARRAY_SIZE(xtables_chain_protos); ++i) { 1817e55cc4aaa6e35448c14370e5261c3387d26b257dPablo Neira Ayuso if (xtables_chain_protos[i].name == NULL) 1818e55cc4aaa6e35448c14370e5261c3387d26b257dPablo Neira Ayuso continue; 1819e55cc4aaa6e35448c14370e5261c3387d26b257dPablo Neira Ayuso 18201de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt if (strcmp(s, xtables_chain_protos[i].name) == 0) { 18211de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt proto = xtables_chain_protos[i].num; 18221de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt break; 18231de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt } 18241de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt } 18251de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt if (i == ARRAY_SIZE(xtables_chain_protos)) 18268b7baebc93989106fd5d26b262d0ce191f8ef7c0Jamal Hadi Salim xt_params->exit_err(PARAMETER_PROBLEM, 18271de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt "unknown protocol `%s' specified", 18281de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt s); 18291de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt } 18301de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt } 18311de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt 18321de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt return proto; 18331de7edffc9085c0f41c261dca995e28ae4126c29Jan Engelhardt} 1834