xtables.c revision 5dd19de34380c91ad07bbe79a34726e59891cf54
1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* 2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * (C) 2000-2006 by the netfilter coreteam <coreteam@netfilter.org>: 3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * This program is free software; you can redistribute it and/or modify 5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * it under the terms of the GNU General Public License as published by 6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the Free Software Foundation; either version 2 of the License, or 7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * (at your option) any later version. 8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * This program is distributed in the hope that it will be useful, 10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * but WITHOUT ANY WARRANTY; without even the implied warranty of 11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * GNU General Public License for more details. 13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * You should have received a copy of the GNU General Public License 15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * along with this program; if not, write to the Free Software 16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <errno.h> 20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <fcntl.h> 21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <netdb.h> 22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <stdarg.h> 23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <stdbool.h> 24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <stdio.h> 25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <stdlib.h> 26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <string.h> 27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <unistd.h> 28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <sys/socket.h> 29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <sys/stat.h> 30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <sys/types.h> 31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <sys/wait.h> 32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <arpa/inet.h> 33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <xtables.h> 35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <linux/netfilter_ipv4/ip_tables.h> 36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <linux/netfilter_ipv6/ip6_tables.h> 37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <libiptc/libxtc.h> 38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifndef NO_SHARED_LIBS 40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <dlfcn.h> 41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif 42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifndef IPT_SO_GET_REVISION_MATCH /* Old kernel source. */ 43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# define IPT_SO_GET_REVISION_MATCH (IPT_BASE_CTL + 2) 44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# define IPT_SO_GET_REVISION_TARGET (IPT_BASE_CTL + 3) 45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif 46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifndef IP6T_SO_GET_REVISION_MATCH /* Old kernel source. */ 47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# define IP6T_SO_GET_REVISION_MATCH 68 48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# define IP6T_SO_GET_REVISION_TARGET 69 49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif 50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <getopt.h> 51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define NPROTO 255 54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifndef PROC_SYS_MODPROBE 56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe" 57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif 58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid basic_exit_err(enum xtables_exittype status, const char *msg, ...) __attribute__((noreturn, format(printf,2,3))); 60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct xtables_globals *xt_params = NULL; 62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid basic_exit_err(enum xtables_exittype status, const char *msg, ...) 64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org va_list args; 66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org va_start(args, msg); 68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fprintf(stderr, "%s v%s: ", xt_params->program_name, xt_params->program_version); 69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org vfprintf(stderr, msg, args); 70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org va_end(args); 71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fprintf(stderr, "\n"); 72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org exit(status); 73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid xtables_free_opts(int reset_offset) 77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (xt_params->opts != xt_params->orig_opts) { 79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org free(xt_params->opts); 80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->opts = xt_params->orig_opts; 81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (reset_offset) 82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->option_offset = 0; 83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct option *xtables_merge_options(struct option *oldopts, 87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const struct option *newopts, 88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned int *option_offset) 89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned int num_old, num_new, i; 91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct option *merge; 92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (newopts == NULL) 94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return oldopts; 95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (num_old = 0; oldopts[num_old].name; num_old++) ; 97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (num_new = 0; newopts[num_new].name; num_new++) ; 98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->option_offset += OPTION_OFFSET; 100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *option_offset = xt_params->option_offset; 101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org merge = malloc(sizeof(struct option) * (num_new + num_old + 1)); 103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (merge == NULL) 104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org memcpy(merge, oldopts, num_old * sizeof(struct option)); 106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xtables_free_opts(0); /* Release any old options merged */ 107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (i = 0; i < num_new; i++) { 108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org merge[num_old + i] = newopts[i]; 109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org merge[num_old + i].val += *option_offset; 110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org memset(merge + num_old + num_new, 0, sizeof(struct option)); 112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return merge; 114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid xtables_set_revision(char *name, u_int8_t revision) 117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Old kernel sources don't have ".revision" field, 119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * but we stole a byte from name. */ 120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org name[XT_FUNCTION_MAXNAMELEN - 2] = '\0'; 121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org name[XT_FUNCTION_MAXNAMELEN - 1] = revision; 122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * xtables_afinfo - protocol family dependent information 126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @kmod: kernel module basename (e.g. "ip_tables") 127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @libprefix: prefix of .so library name (e.g. "libipt_") 128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @family: nfproto family 129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @ipproto: used by setsockopt (e.g. IPPROTO_IP) 130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @so_rev_match: optname to check revision support of match 131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @so_rev_target: optname to check revision support of target 132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct xtables_afinfo { 134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *kmod; 135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *libprefix; 136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uint8_t family; 137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uint8_t ipproto; 138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int so_rev_match; 139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int so_rev_target; 140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}; 141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic const struct xtables_afinfo afinfo_ipv4 = { 143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org .kmod = "ip_tables", 144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org .libprefix = "libipt_", 145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org .family = NFPROTO_IPV4, 146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org .ipproto = IPPROTO_IP, 147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org .so_rev_match = IPT_SO_GET_REVISION_MATCH, 148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org .so_rev_target = IPT_SO_GET_REVISION_TARGET, 149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}; 150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic const struct xtables_afinfo afinfo_ipv6 = { 152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org .kmod = "ip6_tables", 153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org .libprefix = "libip6t_", 154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org .family = NFPROTO_IPV6, 155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org .ipproto = IPPROTO_IPV6, 156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org .so_rev_match = IP6T_SO_GET_REVISION_MATCH, 157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org .so_rev_target = IP6T_SO_GET_REVISION_TARGET, 158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}; 159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic const struct xtables_afinfo *afinfo; 161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* Search path for Xtables .so files */ 163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic const char *xtables_libdir; 164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* the path to command to load kernel module */ 166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgconst char *xtables_modprobe_program; 167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* Keeping track of external matches and targets: linked lists. */ 169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct xtables_match *xtables_matches; 170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct xtables_target *xtables_targets; 171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid xtables_init(void) 173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xtables_libdir = getenv("XTABLES_LIBDIR"); 175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (xtables_libdir != NULL) 176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xtables_libdir = getenv("IPTABLES_LIB_DIR"); 178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (xtables_libdir != NULL) { 179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fprintf(stderr, "IPTABLES_LIB_DIR is deprecated, " 180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "use XTABLES_LIBDIR.\n"); 181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* 184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Well yes, IP6TABLES_LIB_DIR is of lower priority over 185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * IPTABLES_LIB_DIR since this moved to libxtables; I think that is ok 186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * for these env vars are deprecated anyhow, and in light of the 187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * (shared) libxt_*.so files, makes less sense to have 188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * IPTABLES_LIB_DIR != IP6TABLES_LIB_DIR. 189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xtables_libdir = getenv("IP6TABLES_LIB_DIR"); 191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (xtables_libdir != NULL) { 192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fprintf(stderr, "IP6TABLES_LIB_DIR is deprecated, " 193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "use XTABLES_LIBDIR.\n"); 194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xtables_libdir = XTABLES_LIBDIR; 197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid xtables_set_nfproto(uint8_t nfproto) 200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org switch (nfproto) { 202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case NFPROTO_IPV4: 203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org afinfo = &afinfo_ipv4; 204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case NFPROTO_IPV6: 206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org afinfo = &afinfo_ipv6; 207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org default: 209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fprintf(stderr, "libxtables: unhandled NFPROTO in %s\n", 210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org __func__); 211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * xtables_set_params - set the global parameters used by xtables 216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @xtp: input xtables_globals structure 217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The app is expected to pass a valid xtables_globals data-filled 219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * with proper values 220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @xtp cannot be NULL 221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Returns -1 on failure to set and 0 on success 223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint xtables_set_params(struct xtables_globals *xtp) 225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!xtp) { 227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fprintf(stderr, "%s: Illegal global params\n",__func__); 228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return -1; 229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params = xtp; 232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!xt_params->exit_err) 234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->exit_err = basic_exit_err; 235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return 0; 237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint xtables_init_all(struct xtables_globals *xtp, uint8_t nfproto) 240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xtables_init(); 242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xtables_set_nfproto(nfproto); 243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return xtables_set_params(xtp); 244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * xtables_*alloc - wrappers that exit on failure 248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid *xtables_calloc(size_t count, size_t size) 250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org void *p; 252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((p = calloc(count, size)) == NULL) { 254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org perror("ip[6]tables: calloc failed"); 255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org exit(1); 256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return p; 259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid *xtables_malloc(size_t size) 262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org void *p; 264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((p = malloc(size)) == NULL) { 266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org perror("ip[6]tables: malloc failed"); 267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org exit(1); 268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return p; 271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic char *get_modprobe(void) 274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int procfile; 276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org char *ret; 277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define PROCFILE_BUFSIZ 1024 279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org procfile = open(PROC_SYS_MODPROBE, O_RDONLY); 280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (procfile < 0) 281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ret = (char *) malloc(PROCFILE_BUFSIZ); 284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (ret) { 285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org memset(ret, 0, PROCFILE_BUFSIZ); 286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org switch (read(procfile, ret, PROCFILE_BUFSIZ)) { 287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case -1: goto fail; 288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case PROCFILE_BUFSIZ: goto fail; /* Partial read. Wierd */ 289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (ret[strlen(ret)-1]=='\n') 291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ret[strlen(ret)-1]=0; 292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org close(procfile); 293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return ret; 294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fail: 296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org free(ret); 297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org close(procfile); 298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint xtables_insmod(const char *modname, const char *modprobe, bool quiet) 302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org char *buf = NULL; 304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org char *argv[4]; 305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int status; 306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* If they don't explicitly set it, read out of kernel */ 308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!modprobe) { 309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org buf = get_modprobe(); 310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!buf) 311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return -1; 312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org modprobe = buf; 313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* 316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Need to flush the buffer, or the child may output it again 317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * when switching the program thru execv. 318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fflush(stdout); 320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org switch (fork()) { 322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case 0: 323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org argv[0] = (char *)modprobe; 324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org argv[1] = (char *)modname; 325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (quiet) { 326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org argv[2] = "-q"; 327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org argv[3] = NULL; 328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org argv[2] = NULL; 330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org argv[3] = NULL; 331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org execv(argv[0], argv); 333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* not usually reached */ 335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org exit(1); 336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case -1: 337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return -1; 338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org default: /* parent */ 340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org wait(&status); 341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org free(buf); 344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (WIFEXITED(status) && WEXITSTATUS(status) == 0) 345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return 0; 346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return -1; 347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint xtables_load_ko(const char *modprobe, bool quiet) 350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org static bool loaded = false; 352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org static int ret = -1; 353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!loaded) { 355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ret = xtables_insmod(afinfo->kmod, modprobe, quiet); 356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org loaded = (ret == 0); 357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return ret; 360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * xtables_strtou{i,l} - string to number conversion 364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @s: input string 365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @end: like strtoul's "end" pointer 366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @value: pointer for result 367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @min: minimum accepted value 368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @max: maximum accepted value 369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * If @end is NULL, we assume the caller wants a "strict strtoul", and hence 371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * "15a" is rejected. 372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * In either case, the value obtained is compared for min-max compliance. 373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Base is always 0, i.e. autodetect depending on @s. 374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Returns true/false whether number was accepted. On failure, *value has 376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * undefined contents. 377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool xtables_strtoul(const char *s, char **end, unsigned long *value, 379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned long min, unsigned long max) 380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned long v; 382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org char *my_end; 383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org errno = 0; 385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org v = strtoul(s, &my_end, 0); 386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 387f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (my_end == s) 388f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 389f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (end != NULL) 390f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *end = my_end; 391f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 392f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (errno != ERANGE && min <= v && (max == 0 || v <= max)) { 393f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (value != NULL) 394f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *value = v; 395f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (end == NULL) 396f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return *my_end == '\0'; 397f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 398f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 399f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 400f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 401f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 402f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 403f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool xtables_strtoui(const char *s, char **end, unsigned int *value, 404f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned int min, unsigned int max) 405f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 406f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned long v; 407f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool ret; 408f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 409f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ret = xtables_strtoul(s, end, &v, min, max); 410f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (value != NULL) 411f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *value = v; 412f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return ret; 413f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 414f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 415f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint xtables_service_to_port(const char *name, const char *proto) 416f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 417f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct servent *service; 418f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 419f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((service = getservbyname(name, proto)) != NULL) 420f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return ntohs((unsigned short) service->s_port); 421f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 422f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return -1; 423f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 424f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 425f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgu_int16_t xtables_parse_port(const char *port, const char *proto) 426f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 427f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned int portnum; 428f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 429f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (xtables_strtoui(port, NULL, &portnum, 0, UINT16_MAX) || 430f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (portnum = xtables_service_to_port(port, proto)) != (unsigned)-1) 431f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return portnum; 432f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 433f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->exit_err(PARAMETER_PROBLEM, 434f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "invalid port/service `%s' specified", port); 435f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 436f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 437f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid xtables_parse_interface(const char *arg, char *vianame, 438f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned char *mask) 439f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 440f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int vialen = strlen(arg); 441f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned int i; 442f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 443f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org memset(mask, 0, IFNAMSIZ); 444f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org memset(vianame, 0, IFNAMSIZ); 445f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 446f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (vialen + 1 > IFNAMSIZ) 447f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->exit_err(PARAMETER_PROBLEM, 448f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "interface name `%s' must be shorter than IFNAMSIZ" 449f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org " (%i)", arg, IFNAMSIZ-1); 450f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 451f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org strcpy(vianame, arg); 452f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((vialen == 0) || (vialen == 1 && vianame[0] == '+')) 453f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org memset(mask, 0, IFNAMSIZ); 454f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org else if (vianame[vialen - 1] == '+') { 455f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org memset(mask, 0xFF, vialen - 1); 456f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org memset(mask + vialen - 1, 0, IFNAMSIZ - vialen + 1); 457f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Don't remove `+' here! -HW */ 458f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 459f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Include nul-terminator in match */ 460f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org memset(mask, 0xFF, vialen + 1); 461f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org memset(mask + vialen + 1, 0, IFNAMSIZ - vialen - 1); 462f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (i = 0; vianame[i]; i++) { 463f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (vianame[i] == ':' || 464f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org vianame[i] == '!' || 465f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org vianame[i] == '*') { 466f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fprintf(stderr, 467f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "Warning: weird character in interface" 468f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org " `%s' (No aliases, :, ! or *).\n", 469f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org vianame); 470f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 471f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 472f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 473f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 474f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 475f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 476f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifndef NO_SHARED_LIBS 477f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void *load_extension(const char *search_path, const char *prefix, 478f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *name, bool is_target) 479f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 480f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *dir = search_path, *next; 481f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org void *ptr = NULL; 482f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct stat sb; 483f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org char path[256]; 484f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 485f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org do { 486f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org next = strchr(dir, ':'); 487f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (next == NULL) 488f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org next = dir + strlen(dir); 489f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org snprintf(path, sizeof(path), "%.*s/libxt_%s.so", 490f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (unsigned int)(next - dir), dir, name); 491f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 492f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (dlopen(path, RTLD_NOW) != NULL) { 493f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Found library. If it didn't register itself, 494f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org maybe they specified target as match. */ 495f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (is_target) 496f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ptr = xtables_find_target(name, XTF_DONT_LOAD); 497f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org else 498f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ptr = xtables_find_match(name, 499f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org XTF_DONT_LOAD, NULL); 500f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else if (stat(path, &sb) == 0) { 501f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fprintf(stderr, "%s: %s\n", path, dlerror()); 502f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 503f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 504f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (ptr != NULL) 505f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return ptr; 506f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 507f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org snprintf(path, sizeof(path), "%.*s/%s%s.so", 508f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (unsigned int)(next - dir), dir, prefix, name); 509f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (dlopen(path, RTLD_NOW) != NULL) { 510f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (is_target) 511f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ptr = xtables_find_target(name, XTF_DONT_LOAD); 512f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org else 513f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ptr = xtables_find_match(name, 514f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org XTF_DONT_LOAD, NULL); 515f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else if (stat(path, &sb) == 0) { 516f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fprintf(stderr, "%s: %s\n", path, dlerror()); 517f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 518f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 519f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (ptr != NULL) 520f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return ptr; 521f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 522f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org dir = next + 1; 523f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } while (*next != '\0'); 524f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 525f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 526f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 527f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif 528f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 529f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct xtables_match * 530f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgxtables_find_match(const char *name, enum xtables_tryload tryload, 531f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct xtables_rule_match **matches) 532f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 533f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct xtables_match *ptr; 534f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *icmp6 = "icmp6"; 535f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 536f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* This is ugly as hell. Nonetheless, there is no way of changing 537f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * this without hurting backwards compatibility */ 538f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ( (strcmp(name,"icmpv6") == 0) || 539f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (strcmp(name,"ipv6-icmp") == 0) || 540f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (strcmp(name,"icmp6") == 0) ) 541f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org name = icmp6; 542f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 543f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (ptr = xtables_matches; ptr; ptr = ptr->next) { 544f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (strcmp(name, ptr->name) == 0) { 545f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct xtables_match *clone; 546f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 547f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* First match of this type: */ 548f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (ptr->m == NULL) 549f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 550f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 551f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Second and subsequent clones */ 552f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org clone = xtables_malloc(sizeof(struct xtables_match)); 553f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org memcpy(clone, ptr, sizeof(struct xtables_match)); 554f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org clone->mflags = 0; 555f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* This is a clone: */ 556f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org clone->next = clone; 557f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 558f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ptr = clone; 559f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 560f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 561f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 562f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 563f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifndef NO_SHARED_LIBS 564f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) { 565f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ptr = load_extension(xtables_libdir, afinfo->libprefix, 566f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org name, false); 567f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 568f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) 569f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->exit_err(PARAMETER_PROBLEM, 570f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "Couldn't load match `%s':%s\n", 571f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org name, dlerror()); 572f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 573f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else 574f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (ptr && !ptr->loaded) { 575f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (tryload != XTF_DONT_LOAD) 576f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ptr->loaded = 1; 577f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org else 578f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ptr = NULL; 579f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 580f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if(!ptr && (tryload == XTF_LOAD_MUST_SUCCEED)) { 581f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->exit_err(PARAMETER_PROBLEM, 582f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "Couldn't find match `%s'\n", name); 583f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 584f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif 585f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 586f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (ptr && matches) { 587f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct xtables_rule_match **i; 588f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct xtables_rule_match *newentry; 589f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 590f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org newentry = xtables_malloc(sizeof(struct xtables_rule_match)); 591f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 592f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (i = matches; *i; i = &(*i)->next) { 593f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (strcmp(name, (*i)->match->name) == 0) 594f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (*i)->completed = true; 595f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 596f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org newentry->match = ptr; 597f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org newentry->completed = false; 598f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org newentry->next = NULL; 599f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *i = newentry; 600f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 601f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 602f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return ptr; 603f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 604f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 605f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct xtables_target * 606f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgxtables_find_target(const char *name, enum xtables_tryload tryload) 607f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 608f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct xtables_target *ptr; 609f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 610f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Standard target? */ 611f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (strcmp(name, "") == 0 612f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org || strcmp(name, XTC_LABEL_ACCEPT) == 0 613f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org || strcmp(name, XTC_LABEL_DROP) == 0 614f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org || strcmp(name, XTC_LABEL_QUEUE) == 0 615f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org || strcmp(name, XTC_LABEL_RETURN) == 0) 616f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org name = "standard"; 617f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 618f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (ptr = xtables_targets; ptr; ptr = ptr->next) { 619f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (strcmp(name, ptr->name) == 0) 620f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 621f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 622f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 623f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifndef NO_SHARED_LIBS 624f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) { 625f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ptr = load_extension(xtables_libdir, afinfo->libprefix, 626f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org name, true); 627f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 628f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) 629f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->exit_err(PARAMETER_PROBLEM, 630f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "Couldn't load target `%s':%s\n", 631f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org name, dlerror()); 632f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 633f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else 634f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (ptr && !ptr->loaded) { 635f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (tryload != XTF_DONT_LOAD) 636f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ptr->loaded = 1; 637f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org else 638f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ptr = NULL; 639f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 640f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if(!ptr && (tryload == LOAD_MUST_SUCCEED)) { 641f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->exit_err(PARAMETER_PROBLEM, 642f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "Couldn't find target `%s'\n", name); 643f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 644f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif 645f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 646f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (ptr) 647f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ptr->used = 1; 648f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 649f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return ptr; 650f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 651f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 652f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic int compatible_revision(const char *name, u_int8_t revision, int opt) 653f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 654f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct xt_get_revision rev; 655f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org socklen_t s = sizeof(rev); 656f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int max_rev, sockfd; 657f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 658f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org sockfd = socket(afinfo->family, SOCK_RAW, IPPROTO_RAW); 659f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (sockfd < 0) { 660f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (errno == EPERM) { 661f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* revision 0 is always supported. */ 662f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (revision != 0) 663f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fprintf(stderr, "Could not determine whether " 664f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "revision %u is supported, " 665f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "assuming it is.\n", 666f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org revision); 667f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return 1; 668f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 669f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fprintf(stderr, "Could not open socket to kernel: %s\n", 670f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org strerror(errno)); 671f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org exit(1); 672f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 673f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 674f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xtables_load_ko(xtables_modprobe_program, true); 675f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 676f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org strcpy(rev.name, name); 677f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org rev.revision = revision; 678f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 679f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org max_rev = getsockopt(sockfd, afinfo->ipproto, opt, &rev, &s); 680f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (max_rev < 0) { 681f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Definitely don't support this? */ 682f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (errno == ENOENT || errno == EPROTONOSUPPORT) { 683f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org close(sockfd); 684f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return 0; 685f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else if (errno == ENOPROTOOPT) { 686f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org close(sockfd); 687f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Assume only revision 0 support (old kernel) */ 688f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return (revision == 0); 689f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 690f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fprintf(stderr, "getsockopt failed strangely: %s\n", 691f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org strerror(errno)); 692f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org exit(1); 693f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 694f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 695f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org close(sockfd); 696f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return 1; 697f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 698f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 699f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 700f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic int compatible_match_revision(const char *name, u_int8_t revision) 701f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 702f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return compatible_revision(name, revision, afinfo->so_rev_match); 703f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 704f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 705f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic int compatible_target_revision(const char *name, u_int8_t revision) 706f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 707f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return compatible_revision(name, revision, afinfo->so_rev_target); 708f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 709f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 710f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid xtables_register_match(struct xtables_match *me) 711f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 712f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct xtables_match **i, *old; 713f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 714f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (strcmp(me->version, XTABLES_VERSION) != 0) { 715f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fprintf(stderr, "%s: match \"%s\" has version \"%s\", " 716f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "but \"%s\" is required.\n", 717f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->program_name, me->name, 718f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org me->version, XTABLES_VERSION); 719f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org exit(1); 720f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 721f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 722f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Revision field stole a char from name. */ 723f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (strlen(me->name) >= XT_FUNCTION_MAXNAMELEN-1) { 724f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fprintf(stderr, "%s: target `%s' has invalid name\n", 725f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->program_name, me->name); 726f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org exit(1); 727f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 728f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 729f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (me->family >= NPROTO) { 730f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fprintf(stderr, 731f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "%s: BUG: match %s has invalid protocol family\n", 732f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->program_name, me->name); 733f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org exit(1); 734f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 735f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 736f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* ignore not interested match */ 737f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (me->family != afinfo->family && me->family != AF_UNSPEC) 738f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 739f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 740f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org old = xtables_find_match(me->name, XTF_DURING_LOAD, NULL); 741f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (old) { 742f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (old->revision == me->revision && 743f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org old->family == me->family) { 744f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fprintf(stderr, 745f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "%s: match `%s' already registered.\n", 746f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->program_name, me->name); 747f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org exit(1); 748f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 749f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 750f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Now we have two (or more) options, check compatibility. */ 751f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (compatible_match_revision(old->name, old->revision) 752f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org && old->revision > me->revision) 753f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 754f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 755f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* See if new match can be used. */ 756f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!compatible_match_revision(me->name, me->revision)) 757f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 758f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 759f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */ 760f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (old->revision == me->revision && me->family == AF_UNSPEC) 761f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 762f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 763f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Delete old one. */ 764f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (i = &xtables_matches; *i!=old; i = &(*i)->next); 765f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *i = old->next; 766f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 767f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 768f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (me->size != XT_ALIGN(me->size)) { 769f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fprintf(stderr, "%s: match `%s' has invalid size %u.\n", 770f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->program_name, me->name, 771f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (unsigned int)me->size); 772f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org exit(1); 773f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 774f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 775f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Append to list. */ 776f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (i = &xtables_matches; *i; i = &(*i)->next); 777f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org me->next = NULL; 778f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *i = me; 779f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 780f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org me->m = NULL; 781f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org me->mflags = 0; 782f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 783f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 784f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid xtables_register_target(struct xtables_target *me) 785f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 786f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct xtables_target *old; 787f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 788f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (strcmp(me->version, XTABLES_VERSION) != 0) { 789f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fprintf(stderr, "%s: target \"%s\" has version \"%s\", " 790f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "but \"%s\" is required.\n", 791f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->program_name, me->name, 792f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org me->version, XTABLES_VERSION); 793f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org exit(1); 794f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 795f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 796f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Revision field stole a char from name. */ 797f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (strlen(me->name) >= XT_FUNCTION_MAXNAMELEN-1) { 798f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fprintf(stderr, "%s: target `%s' has invalid name\n", 799f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->program_name, me->name); 800f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org exit(1); 801f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 802f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 803f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (me->family >= NPROTO) { 804f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fprintf(stderr, 805f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "%s: BUG: target %s has invalid protocol family\n", 806f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->program_name, me->name); 807f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org exit(1); 808f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 809f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 810f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* ignore not interested target */ 811f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (me->family != afinfo->family && me->family != AF_UNSPEC) 812f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 813f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 814f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org old = xtables_find_target(me->name, XTF_DURING_LOAD); 815f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (old) { 816f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct xtables_target **i; 817f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 818f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (old->revision == me->revision && 819f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org old->family == me->family) { 820f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fprintf(stderr, 821f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "%s: target `%s' already registered.\n", 822f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->program_name, me->name); 823f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org exit(1); 824f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 825f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 826f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Now we have two (or more) options, check compatibility. */ 827f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (compatible_target_revision(old->name, old->revision) 828f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org && old->revision > me->revision) 829f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 830f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 831f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* See if new target can be used. */ 832f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!compatible_target_revision(me->name, me->revision)) 833f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 834f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 835f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */ 836f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (old->revision == me->revision && me->family == AF_UNSPEC) 837f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 838f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 839f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Delete old one. */ 840f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (i = &xtables_targets; *i!=old; i = &(*i)->next); 841f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *i = old->next; 842f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 843f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 844f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (me->size != XT_ALIGN(me->size)) { 845f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fprintf(stderr, "%s: target `%s' has invalid size %u.\n", 846f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->program_name, me->name, 847f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (unsigned int)me->size); 848f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org exit(1); 849f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 850f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 851f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Prepend to list. */ 852f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org me->next = xtables_targets; 853f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xtables_targets = me; 854f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org me->t = NULL; 855f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org me->tflags = 0; 856f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 857f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 858f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 859f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * xtables_param_act - act on condition 860f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @status: a constant from enum xtables_exittype 861f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 862f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * %XTF_ONLY_ONCE: print error message that option may only be used once. 863f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @p1: module name (e.g. "mark") 864f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @p2(...): option in conflict (e.g. "--mark") 865f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @p3(...): condition to match on (see extensions/ for examples) 866f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 867f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * %XTF_NO_INVERT: option does not support inversion 868f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @p1: module name 869f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @p2: option in conflict 870f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @p3: condition to match on 871f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 872f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * %XTF_BAD_VALUE: bad value for option 873f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @p1: module name 874f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @p2: option with which the problem occured (e.g. "--mark") 875f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @p3: string the user passed in (e.g. "99999999999999") 876f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 877f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * %XTF_ONE_ACTION: two mutually exclusive actions have been specified 878f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * @p1: module name 879f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 880f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Displays an error message and exits the program. 881f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 882f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid xtables_param_act(unsigned int status, const char *p1, ...) 883f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 884f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *p2, *p3; 885f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org va_list args; 886f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool b; 887f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 888f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org va_start(args, p1); 889f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 890f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org switch (status) { 891f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case XTF_ONLY_ONCE: 892f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org p2 = va_arg(args, const char *); 893f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org b = va_arg(args, unsigned int); 894f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!b) 895f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 896f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->exit_err(PARAMETER_PROBLEM, 897f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "%s: \"%s\" option may only be specified once", 898f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org p1, p2); 899f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 900f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case XTF_NO_INVERT: 901f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org p2 = va_arg(args, const char *); 902f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org b = va_arg(args, unsigned int); 903f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!b) 904f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 905f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->exit_err(PARAMETER_PROBLEM, 906f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "%s: \"%s\" option cannot be inverted", p1, p2); 907f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 908f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case XTF_BAD_VALUE: 909f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org p2 = va_arg(args, const char *); 910f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org p3 = va_arg(args, const char *); 911f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->exit_err(PARAMETER_PROBLEM, 912f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "%s: Bad value for \"%s\" option: \"%s\"", 913f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org p1, p2, p3); 914f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 915f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case XTF_ONE_ACTION: 916f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org b = va_arg(args, unsigned int); 917f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!b) 918f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 919f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->exit_err(PARAMETER_PROBLEM, 920f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "%s: At most one action is possible", p1); 921f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 922f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org default: 923f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->exit_err(status, p1, args); 924f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 925f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 926f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 927f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org va_end(args); 928f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 929f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 930f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgconst char *xtables_ipaddr_to_numeric(const struct in_addr *addrp) 931f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 932f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org static char buf[20]; 933f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const unsigned char *bytep = (const void *)&addrp->s_addr; 934f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 935f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org sprintf(buf, "%u.%u.%u.%u", bytep[0], bytep[1], bytep[2], bytep[3]); 936f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return buf; 937f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 938f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 939f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic const char *ipaddr_to_host(const struct in_addr *addr) 940f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 941f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct hostent *host; 942f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 943f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org host = gethostbyaddr(addr, sizeof(struct in_addr), AF_INET); 944f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (host == NULL) 945f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 946f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 947f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return host->h_name; 948f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 949f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 950f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic const char *ipaddr_to_network(const struct in_addr *addr) 951f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 952f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct netent *net; 953f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 954f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((net = getnetbyaddr(ntohl(addr->s_addr), AF_INET)) != NULL) 955f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return net->n_name; 956f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 957f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 958f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 959f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 960f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgconst char *xtables_ipaddr_to_anyname(const struct in_addr *addr) 961f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 962f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *name; 963f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 964f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((name = ipaddr_to_host(addr)) != NULL || 965f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (name = ipaddr_to_network(addr)) != NULL) 966f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return name; 967f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 968f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return xtables_ipaddr_to_numeric(addr); 969f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 970f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 971f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgconst char *xtables_ipmask_to_numeric(const struct in_addr *mask) 972f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 973f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org static char buf[20]; 974f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uint32_t maskaddr, bits; 975f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int i; 976f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 977f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org maskaddr = ntohl(mask->s_addr); 978f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 979f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (maskaddr == 0xFFFFFFFFL) 980f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* we don't want to see "/32" */ 981f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return ""; 982f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 983f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org i = 32; 984f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bits = 0xFFFFFFFEL; 985f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org while (--i >= 0 && maskaddr != bits) 986f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bits <<= 1; 987f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (i >= 0) 988f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org sprintf(buf, "/%d", i); 989f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org else 990f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* mask was not a decent combination of 1's and 0's */ 991f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org sprintf(buf, "/%s", xtables_ipaddr_to_numeric(mask)); 992f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 993f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return buf; 994f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 995f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 996f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic struct in_addr *__numeric_to_ipaddr(const char *dotted, bool is_mask) 997f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 998f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org static struct in_addr addr; 999f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned char *addrp; 1000f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned int onebyte; 1001f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org char buf[20], *p, *q; 1002f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int i; 1003f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1004f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* copy dotted string, because we need to modify it */ 1005f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org strncpy(buf, dotted, sizeof(buf) - 1); 1006f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org buf[sizeof(buf) - 1] = '\0'; 1007f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org addrp = (void *)&addr.s_addr; 1008f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1009f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org p = buf; 1010f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (i = 0; i < 3; ++i) { 1011f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((q = strchr(p, '.')) == NULL) { 1012f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (is_mask) 1013f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 1014f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1015f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* autocomplete, this is a network address */ 1016f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX)) 1017f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 1018f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1019f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org addrp[i] = onebyte; 1020f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org while (i < 3) 1021f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org addrp[++i] = 0; 1022f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1023f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return &addr; 1024f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1025f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1026f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *q = '\0'; 1027f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX)) 1028f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 1029f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1030f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org addrp[i] = onebyte; 1031f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org p = q + 1; 1032f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1033f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1034f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* we have checked 3 bytes, now we check the last one */ 1035f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX)) 1036f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 1037f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1038f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org addrp[3] = onebyte; 1039f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return &addr; 1040f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1041f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1042f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct in_addr *xtables_numeric_to_ipaddr(const char *dotted) 1043f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1044f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return __numeric_to_ipaddr(dotted, false); 1045f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1046f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1047f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct in_addr *xtables_numeric_to_ipmask(const char *dotted) 1048f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1049f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return __numeric_to_ipaddr(dotted, true); 1050f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1051f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1052f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic struct in_addr *network_to_ipaddr(const char *name) 1053f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1054f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org static struct in_addr addr; 1055f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct netent *net; 1056f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1057f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((net = getnetbyname(name)) != NULL) { 1058f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (net->n_addrtype != AF_INET) 1059f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 1060f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org addr.s_addr = htonl(net->n_net); 1061f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return &addr; 1062f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1063f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1064f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 1065f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1066f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1067f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic struct in_addr *host_to_ipaddr(const char *name, unsigned int *naddr) 1068f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1069f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct hostent *host; 1070f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct in_addr *addr; 1071f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned int i; 1072f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1073f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *naddr = 0; 1074f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((host = gethostbyname(name)) != NULL) { 1075f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (host->h_addrtype != AF_INET || 1076f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org host->h_length != sizeof(struct in_addr)) 1077f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 1078f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1079f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org while (host->h_addr_list[*naddr] != NULL) 1080f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ++*naddr; 1081f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org addr = xtables_calloc(*naddr, sizeof(struct in_addr) * *naddr); 1082f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (i = 0; i < *naddr; i++) 1083f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org memcpy(&addr[i], host->h_addr_list[i], 1084f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org sizeof(struct in_addr)); 1085f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return addr; 1086f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1087f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1088f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 1089f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1090f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1091f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic struct in_addr * 1092f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgipparse_hostnetwork(const char *name, unsigned int *naddrs) 1093f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1094f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct in_addr *addrptmp, *addrp; 1095f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1096f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((addrptmp = xtables_numeric_to_ipaddr(name)) != NULL || 1097f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (addrptmp = network_to_ipaddr(name)) != NULL) { 1098f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org addrp = xtables_malloc(sizeof(struct in_addr)); 1099f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org memcpy(addrp, addrptmp, sizeof(*addrp)); 1100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *naddrs = 1; 1101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return addrp; 1102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((addrptmp = host_to_ipaddr(name, naddrs)) != NULL) 1104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return addrptmp; 1105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name); 1107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic struct in_addr *parse_ipmask(const char *mask) 1110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org static struct in_addr maskaddr; 1112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct in_addr *addrp; 1113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned int bits; 1114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (mask == NULL) { 1116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* no mask at all defaults to 32 bits */ 1117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org maskaddr.s_addr = 0xFFFFFFFF; 1118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return &maskaddr; 1119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((addrp = xtables_numeric_to_ipmask(mask)) != NULL) 1121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* dotted_to_addr already returns a network byte order addr */ 1122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return addrp; 1123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!xtables_strtoui(mask, NULL, &bits, 0, 32)) 1124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->exit_err(PARAMETER_PROBLEM, 1125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "invalid mask `%s' specified", mask); 1126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (bits != 0) { 1127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org maskaddr.s_addr = htonl(0xFFFFFFFF << (32 - bits)); 1128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return &maskaddr; 1129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org maskaddr.s_addr = 0U; 1132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return &maskaddr; 1133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 1136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * xtables_ipparse_any - transform arbitrary name to in_addr 1137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Possible inputs (pseudo regex): 1139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * m{^($hostname|$networkname|$ipaddr)(/$mask)?} 1140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * "1.2.3.4/5", "1.2.3.4", "hostname", "networkname" 1141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid xtables_ipparse_any(const char *name, struct in_addr **addrpp, 1143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct in_addr *maskp, unsigned int *naddrs) 1144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned int i, j, k, n; 1146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct in_addr *addrp; 1147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org char buf[256], *p; 1148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org strncpy(buf, name, sizeof(buf) - 1); 1150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org buf[sizeof(buf) - 1] = '\0'; 1151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((p = strrchr(buf, '/')) != NULL) { 1152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *p = '\0'; 1153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org addrp = parse_ipmask(p + 1); 1154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 1155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org addrp = parse_ipmask(NULL); 1156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org memcpy(maskp, addrp, sizeof(*maskp)); 1158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* if a null mask is given, the name is ignored, like in "any/0" */ 1160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (maskp->s_addr == 0U) 1161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org strcpy(buf, "0.0.0.0"); 1162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org addrp = *addrpp = ipparse_hostnetwork(buf, naddrs); 1164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org n = *naddrs; 1165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (i = 0, j = 0; i < n; ++i) { 1166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org addrp[j++].s_addr &= maskp->s_addr; 1167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (k = 0; k < j - 1; ++k) 1168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (addrp[k].s_addr == addrp[j-1].s_addr) { 1169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org --*naddrs; 1170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org --j; 1171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 1172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgconst char *xtables_ip6addr_to_numeric(const struct in6_addr *addrp) 1177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* 0000:0000:0000:0000:0000:000.000.000.000 1179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 0000:0000:0000:0000:0000:0000:0000:0000 */ 1180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org static char buf[50+1]; 1181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return inet_ntop(AF_INET6, addrp, buf, sizeof(buf)); 1182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic const char *ip6addr_to_host(const struct in6_addr *addr) 1185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org static char hostname[NI_MAXHOST]; 1187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct sockaddr_in6 saddr; 1188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int err; 1189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org memset(&saddr, 0, sizeof(struct sockaddr_in6)); 1191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org memcpy(&saddr.sin6_addr, addr, sizeof(*addr)); 1192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org saddr.sin6_family = AF_INET6; 1193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org err = getnameinfo((const void *)&saddr, sizeof(struct sockaddr_in6), 1195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org hostname, sizeof(hostname) - 1, NULL, 0, 0); 1196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (err != 0) { 1197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifdef DEBUG 1198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fprintf(stderr,"IP2Name: %s\n",gai_strerror(err)); 1199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif 1200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 1201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifdef DEBUG 1204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fprintf (stderr, "\naddr2host: %s\n", hostname); 1205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif 1206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return hostname; 1207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgconst char *xtables_ip6addr_to_anyname(const struct in6_addr *addr) 1210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *name; 1212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((name = ip6addr_to_host(addr)) != NULL) 1214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return name; 1215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return xtables_ip6addr_to_numeric(addr); 1217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic int ip6addr_prefix_length(const struct in6_addr *k) 1220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned int bits = 0; 1222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uint32_t a, b, c, d; 1223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org a = ntohl(k->s6_addr32[0]); 1225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org b = ntohl(k->s6_addr32[1]); 1226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org c = ntohl(k->s6_addr32[2]); 1227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org d = ntohl(k->s6_addr32[3]); 1228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org while (a & 0x80000000U) { 1229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ++bits; 1230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org a <<= 1; 1231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org a |= (b >> 31) & 1; 1232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org b <<= 1; 1233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org b |= (c >> 31) & 1; 1234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org c <<= 1; 1235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org c |= (d >> 31) & 1; 1236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org d <<= 1; 1237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (a != 0 || b != 0 || c != 0 || d != 0) 1239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return -1; 1240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return bits; 1241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgconst char *xtables_ip6mask_to_numeric(const struct in6_addr *addrp) 1244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org static char buf[50+2]; 1246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int l = ip6addr_prefix_length(addrp); 1247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (l == -1) { 1249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org strcpy(buf, "/"); 1250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org strcat(buf, xtables_ip6addr_to_numeric(addrp)); 1251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return buf; 1252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org sprintf(buf, "/%d", l); 1254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return buf; 1255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct in6_addr *xtables_numeric_to_ip6addr(const char *num) 1258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org static struct in6_addr ap; 1260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int err; 1261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((err = inet_pton(AF_INET6, num, &ap)) == 1) 1263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return ≈ 1264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifdef DEBUG 1265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fprintf(stderr, "\nnumeric2addr: %d\n", err); 1266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif 1267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 1268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic struct in6_addr * 1271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orghost_to_ip6addr(const char *name, unsigned int *naddr) 1272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org static struct in6_addr *addr; 1274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct addrinfo hints; 1275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct addrinfo *res; 1276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int err; 1277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org memset(&hints, 0, sizeof(hints)); 1279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org hints.ai_flags = AI_CANONNAME; 1280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org hints.ai_family = AF_INET6; 1281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org hints.ai_socktype = SOCK_RAW; 1282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org hints.ai_protocol = IPPROTO_IPV6; 1283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org hints.ai_next = NULL; 1284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *naddr = 0; 1286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((err = getaddrinfo(name, NULL, &hints, &res)) != 0) { 1287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifdef DEBUG 1288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fprintf(stderr,"Name2IP: %s\n",gai_strerror(err)); 1289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif 1290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 1291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 1292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (res->ai_family != AF_INET6 || 1293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org res->ai_addrlen != sizeof(struct sockaddr_in6)) 1294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 1295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifdef DEBUG 1297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fprintf(stderr, "resolved: len=%d %s ", res->ai_addrlen, 1298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ip6addr_to_numeric(&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr)); 1299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif 1300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Get the first element of the address-chain */ 1301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org addr = xtables_malloc(sizeof(struct in6_addr)); 1302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org memcpy(addr, &((const struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 1303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org sizeof(struct in6_addr)); 1304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org freeaddrinfo(res); 1305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *naddr = 1; 1306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return addr; 1307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 1310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic struct in6_addr *network_to_ip6addr(const char *name) 1313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* abort();*/ 1315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* TODO: not implemented yet, but the exception breaks the 1316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * name resolvation */ 1317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 1318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic struct in6_addr * 1321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgip6parse_hostnetwork(const char *name, unsigned int *naddrs) 1322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct in6_addr *addrp, *addrptmp; 1324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((addrptmp = xtables_numeric_to_ip6addr(name)) != NULL || 1326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (addrptmp = network_to_ip6addr(name)) != NULL) { 1327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org addrp = xtables_malloc(sizeof(struct in6_addr)); 1328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org memcpy(addrp, addrptmp, sizeof(*addrp)); 1329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *naddrs = 1; 1330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return addrp; 1331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((addrp = host_to_ip6addr(name, naddrs)) != NULL) 1333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return addrp; 1334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name); 1336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic struct in6_addr *parse_ip6mask(char *mask) 1339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org static struct in6_addr maskaddr; 1341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct in6_addr *addrp; 1342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned int bits; 1343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (mask == NULL) { 1345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* no mask at all defaults to 128 bits */ 1346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org memset(&maskaddr, 0xff, sizeof maskaddr); 1347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return &maskaddr; 1348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((addrp = xtables_numeric_to_ip6addr(mask)) != NULL) 1350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return addrp; 1351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!xtables_strtoui(mask, NULL, &bits, 0, 128)) 1352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->exit_err(PARAMETER_PROBLEM, 1353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "invalid mask `%s' specified", mask); 1354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (bits != 0) { 1355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org char *p = (void *)&maskaddr; 1356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org memset(p, 0xff, bits / 8); 1357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org memset(p + (bits / 8) + 1, 0, (128 - bits) / 8); 1358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org p[bits/8] = 0xff << (8 - (bits & 7)); 1359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return &maskaddr; 1360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org memset(&maskaddr, 0, sizeof(maskaddr)); 1363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return &maskaddr; 1364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid xtables_ip6parse_any(const char *name, struct in6_addr **addrpp, 1367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct in6_addr *maskp, unsigned int *naddrs) 1368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct in6_addr *addrp; 1370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned int i, j, k, n; 1371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org char buf[256], *p; 1372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org strncpy(buf, name, sizeof(buf) - 1); 1374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org buf[sizeof(buf)-1] = '\0'; 1375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((p = strrchr(buf, '/')) != NULL) { 1376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *p = '\0'; 1377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org addrp = parse_ip6mask(p + 1); 1378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 1379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org addrp = parse_ip6mask(NULL); 1380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org memcpy(maskp, addrp, sizeof(*maskp)); 1382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* if a null mask is given, the name is ignored, like in "any/0" */ 1384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (memcmp(maskp, &in6addr_any, sizeof(in6addr_any)) == 0) 1385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org strcpy(buf, "::"); 1386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1387f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org addrp = *addrpp = ip6parse_hostnetwork(buf, naddrs); 1388f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org n = *naddrs; 1389f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (i = 0, j = 0; i < n; ++i) { 1390f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (k = 0; k < 4; ++k) 1391f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org addrp[j].s6_addr32[k] &= maskp->s6_addr32[k]; 1392f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ++j; 1393f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (k = 0; k < j - 1; ++k) 1394f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (IN6_ARE_ADDR_EQUAL(&addrp[k], &addrp[j - 1])) { 1395f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org --*naddrs; 1396f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org --j; 1397f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 1398f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1399f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1400f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1401f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1402f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid xtables_save_string(const char *value) 1403f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1404f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org static const char no_quote_chars[] = "_-0123456789" 1405f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "abcdefghijklmnopqrstuvwxyz" 1406f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 1407f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org static const char escape_chars[] = "\"\\'"; 1408f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org size_t length; 1409f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *p; 1410f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1411f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org length = strcspn(value, no_quote_chars); 1412f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (length > 0 && value[length] == 0) { 1413f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* no quoting required */ 1414f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fputs(value, stdout); 1415f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org putchar(' '); 1416f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 1417f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* there is at least one dangerous character in the 1418f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org value, which we have to quote. Write double quotes 1419f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org around the value and escape special characters with 1420f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org a backslash */ 1421f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org putchar('"'); 1422f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1423f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (p = strpbrk(value, escape_chars); p != NULL; 1424f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org p = strpbrk(value, escape_chars)) { 1425f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (p > value) 1426f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fwrite(value, 1, p - value, stdout); 1427f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org putchar('\\'); 1428f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org putchar(*p); 1429f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org value = p + 1; 1430f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1431f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1432f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* print the rest and finish the double quoted 1433f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org string */ 1434f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fputs(value, stdout); 1435f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org printf("\" "); 1436f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1437f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1438f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1439f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 1440f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Check for option-intrapositional negation. 1441f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Do not use in new code. 1442f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 1443f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint xtables_check_inverse(const char option[], int *invert, 1444f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int *my_optind, int argc) 1445f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1446f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (option && strcmp(option, "!") == 0) { 1447f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org fprintf(stderr, "Using intrapositioned negation " 1448f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "(`--option ! this`) is deprecated in favor of " 1449f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "extrapositioned (`! --option this`).\n"); 1450f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1451f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (*invert) 1452f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->exit_err(PARAMETER_PROBLEM, 1453f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "Multiple `!' flags not allowed"); 1454f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *invert = true; 1455f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (my_optind != NULL) { 1456f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ++*my_optind; 1457f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (argc && *my_optind > argc) 1458f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->exit_err(PARAMETER_PROBLEM, 1459f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "no argument following `!'"); 1460f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1461f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1462f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 1463f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1464f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 1465f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1466f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1467f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgconst struct xtables_pprot xtables_chain_protos[] = { 1468f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org {"tcp", IPPROTO_TCP}, 1469f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org {"sctp", IPPROTO_SCTP}, 1470f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org {"udp", IPPROTO_UDP}, 1471f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org {"udplite", IPPROTO_UDPLITE}, 1472f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org {"icmp", IPPROTO_ICMP}, 1473f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org {"icmpv6", IPPROTO_ICMPV6}, 1474f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org {"ipv6-icmp", IPPROTO_ICMPV6}, 1475f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org {"esp", IPPROTO_ESP}, 1476f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org {"ah", IPPROTO_AH}, 1477f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org {"ipv6-mh", IPPROTO_MH}, 1478f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org {"mh", IPPROTO_MH}, 1479f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org {"all", 0}, 1480f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org {NULL}, 1481f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}; 1482f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1483f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgu_int16_t 1484f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgxtables_parse_protocol(const char *s) 1485f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 1486f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned int proto; 1487f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1488f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!xtables_strtoui(s, NULL, &proto, 0, UINT8_MAX)) { 1489f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct protoent *pent; 1490f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1491f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* first deal with the special case of 'all' to prevent 1492f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * people from being able to redefine 'all' in nsswitch 1493f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * and/or provoke expensive [not working] ldap/nis/... 1494f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * lookups */ 1495f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!strcmp(s, "all")) 1496f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return 0; 1497f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1498f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((pent = getprotobyname(s))) 1499f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org proto = pent->p_proto; 1500f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org else { 1501f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned int i; 1502f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (i = 0; i < ARRAY_SIZE(xtables_chain_protos); ++i) { 1503f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (strcmp(s, xtables_chain_protos[i].name) == 0) { 1504f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org proto = xtables_chain_protos[i].num; 1505f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 1506f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1507f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1508f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (i == ARRAY_SIZE(xtables_chain_protos)) 1509f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org xt_params->exit_err(PARAMETER_PROBLEM, 1510f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "unknown protocol `%s' specified", 1511f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org s); 1512f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1513f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 1514f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 1515f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return proto; 1516f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 1517f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org