xtables.c revision df1ef3862761e534c6cec6bd9370285cb5909dd0
136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/* 236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines * (C) 2000-2006 by the netfilter coreteam <coreteam@netfilter.org>: 336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines * 436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines * This program is free software; you can redistribute it and/or modify 536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines * it under the terms of the GNU General Public License as published by 636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines * the Free Software Foundation; either version 2 of the License, or 736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines * (at your option) any later version. 836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines * 936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines * This program is distributed in the hope that it will be useful, 1036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines * but WITHOUT ANY WARRANTY; without even the implied warranty of 1136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines * GNU General Public License for more details. 1336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines * 1436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines * You should have received a copy of the GNU General Public License 1536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines * along with this program; if not, write to the Free Software 1636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 1736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines */ 1836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 1936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include <dlfcn.h> 2036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include <errno.h> 2136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include <fcntl.h> 2236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include <netdb.h> 2336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include <stdio.h> 2436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include <stdlib.h> 2536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include <string.h> 2636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include <unistd.h> 2736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include <sys/socket.h> 2836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include <sys/stat.h> 2936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include <sys/types.h> 3036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include <sys/wait.h> 3136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 3236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include <xtables.h> 3336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 3436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#define NPROTO 255 3536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 3636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#ifndef PROC_SYS_MODPROBE 3736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe" 3836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#endif 3936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 4036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hineschar *lib_dir; 4136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 4236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/* the path to command to load kernel module */ 4336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesconst char *modprobe = NULL; 4436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 4536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/* Keeping track of external matches and targets: linked lists. */ 4636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstruct xtables_match *xtables_matches; 4736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstruct xtables_target *xtables_targets; 4836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 4936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid *fw_calloc(size_t count, size_t size) 5036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ 5136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void *p; 5236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 5336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if ((p = calloc(count, size)) == NULL) { 5436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines perror("ip[6]tables: calloc failed"); 5536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines exit(1); 5636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 5736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 5836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return p; 5936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 6036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 6136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid *fw_malloc(size_t size) 6236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ 6336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void *p; 6436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 6536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if ((p = malloc(size)) == NULL) { 6636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines perror("ip[6]tables: malloc failed"); 6736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines exit(1); 6836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 6936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 7036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return p; 7136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 7236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 7336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic char *get_modprobe(void) 7436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ 7536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines int procfile; 7636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines char *ret; 7736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 7836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#define PROCFILE_BUFSIZ 1024 7936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines procfile = open(PROC_SYS_MODPROBE, O_RDONLY); 8036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (procfile < 0) 8136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return NULL; 8236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 8336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ret = (char *) malloc(PROCFILE_BUFSIZ); 8436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (ret) { 8536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines memset(ret, 0, PROCFILE_BUFSIZ); 8636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines switch (read(procfile, ret, PROCFILE_BUFSIZ)) { 8736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case -1: goto fail; 8836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case PROCFILE_BUFSIZ: goto fail; /* Partial read. Wierd */ 8936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 9036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (ret[strlen(ret)-1]=='\n') 9136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ret[strlen(ret)-1]=0; 9236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines close(procfile); 9336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return ret; 9436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 9536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines fail: 9636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines free(ret); 9736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines close(procfile); 9836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return NULL; 9936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 10036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 10136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesint xtables_insmod(const char *modname, const char *modprobe, int quiet) 10236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ 10336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines char *buf = NULL; 10436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines char *argv[4]; 10536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines int status; 10636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 10736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /* If they don't explicitly set it, read out of kernel */ 10836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (!modprobe) { 10936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines buf = get_modprobe(); 11036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (!buf) 11136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return -1; 11236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines modprobe = buf; 11336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 11436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 11536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines switch (fork()) { 11636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case 0: 11736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines argv[0] = (char *)modprobe; 11836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines argv[1] = (char *)modname; 11936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (quiet) { 12036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines argv[2] = "-q"; 12136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines argv[3] = NULL; 12236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } else { 12336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines argv[2] = NULL; 12436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines argv[3] = NULL; 12536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 12636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines execv(argv[0], argv); 12736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 12836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /* not usually reached */ 12936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines exit(1); 13036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case -1: 13136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return -1; 13236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 13336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines default: /* parent */ 13436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines wait(&status); 13536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 13636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 13736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines free(buf); 13836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (WIFEXITED(status) && WEXITSTATUS(status) == 0) 13936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return 0; 14036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return -1; 14136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 14236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 14336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesint load_xtables_ko(const char *modprobe, int quiet) 14436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ 14536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines static int loaded = 0; 14636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines static int ret = -1; 14736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 14836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (!loaded) { 14936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ret = xtables_insmod(afinfo.kmod, modprobe, quiet); 15036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines loaded = (ret == 0); 15136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 15236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 15336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return ret; 15436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 15536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 15636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesint string_to_number_ll(const char *s, unsigned long long min, 15736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned long long max, unsigned long long *ret) 15836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ 15936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned long long number; 16036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines char *end; 16136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 16236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /* Handle hex, octal, etc. */ 16336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines errno = 0; 16436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines number = strtoull(s, &end, 0); 16536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (*end == '\0' && end != s) { 16636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /* we parsed a number, let's see if we want this */ 16736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (errno != ERANGE && min <= number && (!max || number <= max)) { 16836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines *ret = number; 16936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return 0; 17036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 17136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 17236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return -1; 17336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 17436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 17536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesint string_to_number_l(const char *s, unsigned long min, unsigned long max, 17636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned long *ret) 17736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ 17836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines int result; 17936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned long long number; 18036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 18136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines result = string_to_number_ll(s, min, max, &number); 18236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines *ret = (unsigned long)number; 18336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 18436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return result; 18536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 18636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 18736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesint string_to_number(const char *s, unsigned int min, unsigned int max, 18836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned int *ret) 18936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ 19036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines int result; 19136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned long number; 19236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 19336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines result = string_to_number_l(s, min, max, &number); 19436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines *ret = (unsigned int)number; 19536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 19636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return result; 19736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 19836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 19936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesint service_to_port(const char *name, const char *proto) 20036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ 20136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines struct servent *service; 20236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 20336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if ((service = getservbyname(name, proto)) != NULL) 20436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return ntohs((unsigned short) service->s_port); 20536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 20636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return -1; 20736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 20836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 20936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesu_int16_t parse_port(const char *port, const char *proto) 21036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ 21136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned int portnum; 21236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 21336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if ((string_to_number(port, 0, 65535, &portnum)) != -1 || 21436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines (portnum = service_to_port(port, proto)) != -1) 21536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return (u_int16_t)portnum; 21636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 21736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines exit_error(PARAMETER_PROBLEM, 21836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines "invalid port/service `%s' specified", port); 21936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 22036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 22136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid parse_interface(const char *arg, char *vianame, unsigned char *mask) 22236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ 22336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines int vialen = strlen(arg); 22436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned int i; 22536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 22636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines memset(mask, 0, IFNAMSIZ); 22736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines memset(vianame, 0, IFNAMSIZ); 22836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 22936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (vialen + 1 > IFNAMSIZ) 23036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines exit_error(PARAMETER_PROBLEM, 23136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines "interface name `%s' must be shorter than IFNAMSIZ" 23236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines " (%i)", arg, IFNAMSIZ-1); 23336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 23436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines strcpy(vianame, arg); 23536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if ((vialen == 0) || (vialen == 1 && vianame[0] == '+')) 23636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines memset(mask, 0, IFNAMSIZ); 23736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines else if (vianame[vialen - 1] == '+') { 23836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines memset(mask, 0xFF, vialen - 1); 23936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines memset(mask + vialen - 1, 0, IFNAMSIZ - vialen + 1); 24036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /* Don't remove `+' here! -HW */ 24136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } else { 24236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /* Include nul-terminator in match */ 24336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines memset(mask, 0xFF, vialen + 1); 24436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines memset(mask + vialen + 1, 0, IFNAMSIZ - vialen - 1); 24536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (i = 0; vianame[i]; i++) { 24636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (vianame[i] == ':' || 24736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines vianame[i] == '!' || 24836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines vianame[i] == '*') { 24936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines fprintf(stderr, 25036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines "Warning: weird character in interface" 25136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines " `%s' (No aliases, :, ! or *).\n", 25236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines vianame); 25336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines break; 25436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 25536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 25636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 25736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 25836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 25936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstruct xtables_match *find_match(const char *name, enum xt_tryload tryload, 26036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines struct xtables_rule_match **matches) 26136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ 26236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines struct xtables_match *ptr; 26336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const char *icmp6 = "icmp6"; 26436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 26536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /* This is ugly as hell. Nonetheless, there is no way of changing 26636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines * this without hurting backwards compatibility */ 26736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if ( (strcmp(name,"icmpv6") == 0) || 26836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines (strcmp(name,"ipv6-icmp") == 0) || 26936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines (strcmp(name,"icmp6") == 0) ) 27036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines name = icmp6; 27136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 27236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (ptr = xtables_matches; ptr; ptr = ptr->next) { 27336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (strcmp(name, ptr->name) == 0) { 27436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines struct xtables_match *clone; 27536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 27636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /* First match of this type: */ 27736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (ptr->m == NULL) 27836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines break; 27936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 28036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /* Second and subsequent clones */ 28136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines clone = fw_malloc(sizeof(struct xtables_match)); 28236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines memcpy(clone, ptr, sizeof(struct xtables_match)); 28336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines clone->mflags = 0; 28436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /* This is a clone: */ 28536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines clone->next = clone; 28636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 28736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ptr = clone; 28836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines break; 28936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 29036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 29136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 29236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#ifndef NO_SHARED_LIBS 29336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (!ptr && tryload != DONT_LOAD && tryload != DURING_LOAD) { 29436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines char path[strlen(lib_dir) + sizeof("/.so") 29536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines + strlen(afinfo.libprefix) + strlen(name)]; 29636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 29736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines sprintf(path, "%s/libxt_%s.so", lib_dir, name); 29836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (dlopen(path, RTLD_NOW) != NULL) 29936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /* Found library. If it didn't register itself, 30036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines maybe they specified target as match. */ 30136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ptr = find_match(name, DONT_LOAD, NULL); 30236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 30336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (ptr == NULL) { 30436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines sprintf(path, "%s/%s%s.so", lib_dir, afinfo.libprefix, 30536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines name); 30636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (dlopen(path, RTLD_NOW) != NULL) 30736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ptr = find_match(name, DONT_LOAD, NULL); 30836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 30936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 31036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (ptr == NULL && tryload == LOAD_MUST_SUCCEED) 31136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines exit_error(PARAMETER_PROBLEM, 31236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines "Couldn't load match `%s':%s\n", 31336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines name, dlerror()); 31436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 31536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#else 31636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (ptr && !ptr->loaded) { 31736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (tryload != DONT_LOAD) 31836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ptr->loaded = 1; 31936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines else 32036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ptr = NULL; 32136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 32236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if(!ptr && (tryload == LOAD_MUST_SUCCEED)) { 32336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines exit_error(PARAMETER_PROBLEM, 32436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines "Couldn't find match `%s'\n", name); 32536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 32636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#endif 32736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 32836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (ptr && matches) { 32936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines struct xtables_rule_match **i; 33036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines struct xtables_rule_match *newentry; 33136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 33236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines newentry = fw_malloc(sizeof(struct xtables_rule_match)); 33336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 33436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (i = matches; *i; i = &(*i)->next) { 33536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (strcmp(name, (*i)->match->name) == 0) 33636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines (*i)->completed = 1; 33736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 33836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines newentry->match = ptr; 33936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines newentry->completed = 0; 34036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines newentry->next = NULL; 34136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines *i = newentry; 34236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 34336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 34436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return ptr; 34536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 34636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 34736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 34836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstruct xtables_target *find_target(const char *name, enum xt_tryload tryload) 34936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ 35036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines struct xtables_target *ptr; 35136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 35236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /* Standard target? */ 35336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (strcmp(name, "") == 0 35436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines || strcmp(name, XTC_LABEL_ACCEPT) == 0 35536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines || strcmp(name, XTC_LABEL_DROP) == 0 35636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines || strcmp(name, XTC_LABEL_QUEUE) == 0 35736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines || strcmp(name, XTC_LABEL_RETURN) == 0) 35836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines name = "standard"; 35936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 36036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (ptr = xtables_targets; ptr; ptr = ptr->next) { 36136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (strcmp(name, ptr->name) == 0) 36236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines break; 36336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 36436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 36536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#ifndef NO_SHARED_LIBS 36636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (!ptr && tryload != DONT_LOAD && tryload != DURING_LOAD) { 36736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines char path[strlen(lib_dir) + sizeof("/.so") 36836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines + strlen(afinfo.libprefix) + strlen(name)]; 36936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 37036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines sprintf(path, "%s/libxt_%s.so", lib_dir, name); 37136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (dlopen(path, RTLD_NOW) != NULL) 37236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /* Found library. If it didn't register itself, 37336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines maybe they specified match as a target. */ 37436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ptr = find_target(name, DONT_LOAD); 37536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 37636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (ptr == NULL) { 37736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines sprintf(path, "%s/%s%s.so", lib_dir, afinfo.libprefix, 37836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines name); 37936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (dlopen(path, RTLD_NOW) != NULL) 38036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ptr = find_target(name, DONT_LOAD); 38136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 38236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (ptr == NULL && tryload == LOAD_MUST_SUCCEED) 38336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines exit_error(PARAMETER_PROBLEM, 38436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines "Couldn't load target `%s':%s\n", 38536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines name, dlerror()); 38636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 38736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#else 38836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (ptr && !ptr->loaded) { 38936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (tryload != DONT_LOAD) 39036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ptr->loaded = 1; 39136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines else 39236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ptr = NULL; 39336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 39436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if(!ptr && (tryload == LOAD_MUST_SUCCEED)) { 39536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines exit_error(PARAMETER_PROBLEM, 39636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines "Couldn't find target `%s'\n", name); 39736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 39836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#endif 39936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 40036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (ptr) 40136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ptr->used = 1; 40236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 40336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return ptr; 40436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 40536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 40636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic int compatible_revision(const char *name, u_int8_t revision, int opt) 40736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ 40836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines struct xt_get_revision rev; 40936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines socklen_t s = sizeof(rev); 41036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines int max_rev, sockfd; 41136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 41236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines sockfd = socket(afinfo.family, SOCK_RAW, IPPROTO_RAW); 41336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (sockfd < 0) { 41436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (errno == EPERM) { 41536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /* revision 0 is always supported. */ 41636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (revision != 0) 41736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines fprintf(stderr, "Could not determine whether " 41836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines "revision %u is supported, " 41936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines "assuming it is.\n", 42036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines revision); 42136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return 1; 42236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 42336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines fprintf(stderr, "Could not open socket to kernel: %s\n", 42436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines strerror(errno)); 42536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines exit(1); 42636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 42736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 42836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines load_xtables_ko(modprobe, 1); 42936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 43036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines strcpy(rev.name, name); 43136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines rev.revision = revision; 43236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 43336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines max_rev = getsockopt(sockfd, afinfo.ipproto, opt, &rev, &s); 43436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (max_rev < 0) { 43536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /* Definitely don't support this? */ 43636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (errno == ENOENT || errno == EPROTONOSUPPORT) { 43736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines close(sockfd); 43836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return 0; 43936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } else if (errno == ENOPROTOOPT) { 44036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines close(sockfd); 44136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /* Assume only revision 0 support (old kernel) */ 44236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return (revision == 0); 44336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } else { 44436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines fprintf(stderr, "getsockopt failed strangely: %s\n", 44536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines strerror(errno)); 44636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines exit(1); 44736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 44836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 44936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines close(sockfd); 45036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return 1; 45136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 45236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 45336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 45436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic int compatible_match_revision(const char *name, u_int8_t revision) 45536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ 45636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return compatible_revision(name, revision, afinfo.so_rev_match); 45736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 45836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 45936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic int compatible_target_revision(const char *name, u_int8_t revision) 46036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ 46136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return compatible_revision(name, revision, afinfo.so_rev_target); 46236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 46336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 46436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid xtables_register_match(struct xtables_match *me) 46536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ 46636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines struct xtables_match **i, *old; 46736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 46836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (strcmp(me->version, program_version) != 0) { 46936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines fprintf(stderr, "%s: match `%s' v%s (I'm v%s).\n", 47036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines program_name, me->name, me->version, program_version); 47136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines exit(1); 47236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 47336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 47436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /* Revision field stole a char from name. */ 47536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (strlen(me->name) >= XT_FUNCTION_MAXNAMELEN-1) { 47636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines fprintf(stderr, "%s: target `%s' has invalid name\n", 47736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines program_name, me->name); 47836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines exit(1); 47936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 48036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 48136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (me->family >= NPROTO) { 48236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines fprintf(stderr, 48336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines "%s: BUG: match %s has invalid protocol family\n", 48436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines program_name, me->name); 48536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines exit(1); 48636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 48736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 48836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /* ignore not interested match */ 48936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (me->family != afinfo.family) 49036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 49136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 49236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines old = find_match(me->name, DURING_LOAD, NULL); 49336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (old) { 49436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (old->revision == me->revision) { 49536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines fprintf(stderr, 49636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines "%s: match `%s' already registered.\n", 49736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines program_name, me->name); 49836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines exit(1); 49936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 50036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 50136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /* Now we have two (or more) options, check compatibility. */ 50236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (compatible_match_revision(old->name, old->revision) 50336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines && old->revision > me->revision) 50436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 50536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 50636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /* Replace if compatible. */ 50736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (!compatible_match_revision(me->name, me->revision)) 50836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 50936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 51036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /* Delete old one. */ 51136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (i = &xtables_matches; *i!=old; i = &(*i)->next); 51236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines *i = old->next; 51336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 51436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 51536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (me->size != XT_ALIGN(me->size)) { 51636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines fprintf(stderr, "%s: match `%s' has invalid size %u.\n", 51736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines program_name, me->name, (unsigned int)me->size); 51836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines exit(1); 51936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 52036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 52136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /* Append to list. */ 52236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (i = &xtables_matches; *i; i = &(*i)->next); 52336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines me->next = NULL; 52436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines *i = me; 52536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 52636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines me->m = NULL; 52736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines me->mflags = 0; 52836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 52936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 53036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid xtables_register_target(struct xtables_target *me) 53136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ 53236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines struct xtables_target *old; 53336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 53436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (strcmp(me->version, program_version) != 0) { 53536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines fprintf(stderr, "%s: target `%s' v%s (I'm v%s).\n", 53636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines program_name, me->name, me->version, program_version); 53736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines exit(1); 53836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 53936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 54036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /* Revision field stole a char from name. */ 54136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (strlen(me->name) >= XT_FUNCTION_MAXNAMELEN-1) { 54236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines fprintf(stderr, "%s: target `%s' has invalid name\n", 54336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines program_name, me->name); 54436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines exit(1); 54536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 54636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 54736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (me->family >= NPROTO) { 54836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines fprintf(stderr, 54936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines "%s: BUG: target %s has invalid protocol family\n", 55036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines program_name, me->name); 55136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines exit(1); 55236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 55336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 55436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /* ignore not interested target */ 55536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (me->family != afinfo.family) 55636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 55736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 55836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines old = find_target(me->name, DURING_LOAD); 55936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (old) { 56036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines struct xtables_target **i; 56136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 56236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (old->revision == me->revision) { 56336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines fprintf(stderr, 56436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines "%s: target `%s' already registered.\n", 56536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines program_name, me->name); 56636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines exit(1); 56736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 56836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 56936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /* Now we have two (or more) options, check compatibility. */ 57036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (compatible_target_revision(old->name, old->revision) 57136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines && old->revision > me->revision) 57236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 57336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 57436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /* Replace if compatible. */ 57536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (!compatible_target_revision(me->name, me->revision)) 57636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 57736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 57836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /* Delete old one. */ 57936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (i = &xtables_targets; *i!=old; i = &(*i)->next); 58036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines *i = old->next; 58136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 58236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 58336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (me->size != XT_ALIGN(me->size)) { 58436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines fprintf(stderr, "%s: target `%s' has invalid size %u.\n", 58536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines program_name, me->name, (unsigned int)me->size); 58636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines exit(1); 58736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 58836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 58936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /* Prepend to list. */ 59036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines me->next = xtables_targets; 59136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines xtables_targets = me; 59236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines me->t = NULL; 59336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines me->tflags = 0; 59436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 59536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines