xtables.c revision cd9e7aa106e80c44bd526af74b616701b0772d05
15208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI/*
25208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI * (C) 2000-2006 by the netfilter coreteam <coreteam@netfilter.org>:
35208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *
45208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	This program is free software; you can redistribute it and/or modify
55208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	it under the terms of the GNU General Public License as published by
65208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	the Free Software Foundation; either version 2 of the License, or
75208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	(at your option) any later version.
85208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *
95208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	This program is distributed in the hope that it will be useful,
105208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	but WITHOUT ANY WARRANTY; without even the implied warranty of
115208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
125208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	GNU General Public License for more details.
135208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *
145208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	You should have received a copy of the GNU General Public License
155208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	along with this program; if not, write to the Free Software
165208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
175208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI */
185208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI
193dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI#include <errno.h>
200b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <fcntl.h>
2104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI#include <netdb.h>
22cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt#include <stdbool.h>
233dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI#include <stdio.h>
243dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI#include <stdlib.h>
250b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <string.h>
260b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <unistd.h>
270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#include <sys/socket.h>
280b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <sys/stat.h>
290b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <sys/types.h>
300b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <sys/wait.h>
313dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
325208806f2708f761e97e62550561e3164b541770Yasuyuki KOZAKAI#include <xtables.h>
333dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
345a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#ifndef NO_SHARED_LIBS
355a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#include <dlfcn.h>
365a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger#endif
375a26b5fd7bf11ca93d54fe7dc24b3423fb7d89b2Mike Frysinger
380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#define NPROTO	255
390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
400b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#ifndef PROC_SYS_MODPROBE
410b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe"
420b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#endif
430b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIchar *lib_dir;
450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
460b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI/* the path to command to load kernel module */
470b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAIconst char *modprobe = NULL;
480b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI/* Keeping track of external matches and targets: linked lists.  */
500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_match *xtables_matches;
510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_target *xtables_targets;
520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
533dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAIvoid *fw_calloc(size_t count, size_t size)
543dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI{
553dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	void *p;
563dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
573dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	if ((p = calloc(count, size)) == NULL) {
583dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI		perror("ip[6]tables: calloc failed");
593dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI		exit(1);
603dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	}
613dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
623dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	return p;
633dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI}
643dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
653dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAIvoid *fw_malloc(size_t size)
663dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI{
673dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	void *p;
683dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
693dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	if ((p = malloc(size)) == NULL) {
703dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI		perror("ip[6]tables: malloc failed");
713dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI		exit(1);
723dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	}
733dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
743dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	return p;
753dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI}
760b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
770b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAIstatic char *get_modprobe(void)
780b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI{
790b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	int procfile;
800b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	char *ret;
810b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
820b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#define PROCFILE_BUFSIZ	1024
830b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	procfile = open(PROC_SYS_MODPROBE, O_RDONLY);
840b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	if (procfile < 0)
850b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		return NULL;
860b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
870b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	ret = (char *) malloc(PROCFILE_BUFSIZ);
880b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	if (ret) {
890b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		memset(ret, 0, PROCFILE_BUFSIZ);
900b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		switch (read(procfile, ret, PROCFILE_BUFSIZ)) {
910b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		case -1: goto fail;
920b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		case PROCFILE_BUFSIZ: goto fail; /* Partial read.  Wierd */
930b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		}
940b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		if (ret[strlen(ret)-1]=='\n')
950b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			ret[strlen(ret)-1]=0;
960b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		close(procfile);
970b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		return ret;
980b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	}
990b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI fail:
1000b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	free(ret);
1010b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	close(procfile);
1020b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	return NULL;
1030b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI}
1040b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
1050b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAIint xtables_insmod(const char *modname, const char *modprobe, int quiet)
1060b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI{
1070b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	char *buf = NULL;
1080b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	char *argv[4];
1090b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	int status;
1100b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
1110b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	/* If they don't explicitly set it, read out of kernel */
1120b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	if (!modprobe) {
1130b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		buf = get_modprobe();
1140b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		if (!buf)
1150b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			return -1;
1160b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		modprobe = buf;
1170b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	}
1180b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
1190b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	switch (fork()) {
1200b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	case 0:
1210b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		argv[0] = (char *)modprobe;
1220b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		argv[1] = (char *)modname;
1230b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		if (quiet) {
1240b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[2] = "-q";
1250b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[3] = NULL;
1260b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		} else {
1270b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[2] = NULL;
1280b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[3] = NULL;
1290b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		}
1300b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		execv(argv[0], argv);
1310b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
1320b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		/* not usually reached */
1330b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		exit(1);
1340b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	case -1:
1350b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		return -1;
1360b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
1370b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	default: /* parent */
1380b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		wait(&status);
1390b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	}
1400b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
1410b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	free(buf);
1420b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
1430b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		return 0;
1440b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	return -1;
1450b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI}
1460b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
1470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIint load_xtables_ko(const char *modprobe, int quiet)
1480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
1490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	static int loaded = 0;
1500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	static int ret = -1;
1510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
1520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (!loaded) {
1530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		ret = xtables_insmod(afinfo.kmod, modprobe, quiet);
1540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		loaded = (ret == 0);
1550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
1560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
1570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return ret;
1580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
1590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
16004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAIint string_to_number_ll(const char *s, unsigned long long min,
16104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			unsigned long long max, unsigned long long *ret)
16204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{
16304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	unsigned long long number;
16404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	char *end;
16504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
16604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	/* Handle hex, octal, etc. */
16704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	errno = 0;
16804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	number = strtoull(s, &end, 0);
16904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	if (*end == '\0' && end != s) {
17004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		/* we parsed a number, let's see if we want this */
17104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		if (errno != ERANGE && min <= number && (!max || number <= max)) {
17204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			*ret = number;
17304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			return 0;
17404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		}
17504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	}
17604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	return -1;
17704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI}
17804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
17904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAIint string_to_number_l(const char *s, unsigned long min, unsigned long max,
18004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		       unsigned long *ret)
18104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{
18204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	int result;
18304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	unsigned long long number;
18404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
18504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	result = string_to_number_ll(s, min, max, &number);
18604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	*ret = (unsigned long)number;
18704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
18804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	return result;
18904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI}
19004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
19104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAIint string_to_number(const char *s, unsigned int min, unsigned int max,
19204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		unsigned int *ret)
19304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{
19404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	int result;
19504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	unsigned long number;
19604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
19704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	result = string_to_number_l(s, min, max, &number);
19804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	*ret = (unsigned int)number;
19904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
20004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	return result;
20104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI}
20204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
203cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt/*
204cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt * strtonum{,l} - string to number conversion
205cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt *
206cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt * If @end is NULL, we assume the caller does not want
207cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt * a case like "15a", so reject it.
208cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt */
209cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardtbool strtonuml(const char *s, char **end, unsigned long *value,
210cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt               unsigned long min, unsigned long max)
211cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt{
212cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	unsigned long v;
213cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	char *my_end;
214cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
215cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	errno = 0;
216cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	v = strtoul(s, &my_end, 0);
217cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
218cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	if (my_end == s)
219cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		return false;
220cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	if (end != NULL)
221cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		*end = my_end;
222cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
223cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	if (errno != ERANGE && min <= v && (max == 0 || v <= max)) {
224cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		if (value != NULL)
225cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt			*value = v;
226cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		if (end == NULL)
227cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt			return *my_end == '\0';
228cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		return true;
229cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	}
230cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
231cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	return false;
232cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt}
233cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
234cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardtbool strtonum(const char *s, char **end, unsigned int *value,
235cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt                  unsigned int min, unsigned int max)
236cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt{
237cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	unsigned long v;
238cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	bool ret;
239cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
240cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	ret = strtonuml(s, end, &v, min, max);
241cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	if (value != NULL)
242cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt		*value = v;
243cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt	return ret;
244cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt}
245cd9e7aa106e80c44bd526af74b616701b0772d05Jan Engelhardt
24604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAIint service_to_port(const char *name, const char *proto)
24704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{
24804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	struct servent *service;
24904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
25004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	if ((service = getservbyname(name, proto)) != NULL)
25104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		return ntohs((unsigned short) service->s_port);
25204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
25304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	return -1;
25404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI}
25504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
25604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAIu_int16_t parse_port(const char *port, const char *proto)
25704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{
25804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	unsigned int portnum;
25904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
26004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	if ((string_to_number(port, 0, 65535, &portnum)) != -1 ||
26104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	    (portnum = service_to_port(port, proto)) != -1)
26204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		return (u_int16_t)portnum;
26304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
26404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	exit_error(PARAMETER_PROBLEM,
26504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		   "invalid port/service `%s' specified", port);
26604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI}
26704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
26804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAIvoid parse_interface(const char *arg, char *vianame, unsigned char *mask)
26904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{
27004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	int vialen = strlen(arg);
27104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	unsigned int i;
27204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
27304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	memset(mask, 0, IFNAMSIZ);
27404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	memset(vianame, 0, IFNAMSIZ);
27504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
27604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	if (vialen + 1 > IFNAMSIZ)
27704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		exit_error(PARAMETER_PROBLEM,
27804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			   "interface name `%s' must be shorter than IFNAMSIZ"
27904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			   " (%i)", arg, IFNAMSIZ-1);
28004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
28104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	strcpy(vianame, arg);
28204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	if ((vialen == 0) || (vialen == 1 && vianame[0] == '+'))
28304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask, 0, IFNAMSIZ);
28404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	else if (vianame[vialen - 1] == '+') {
28504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask, 0xFF, vialen - 1);
28604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask + vialen - 1, 0, IFNAMSIZ - vialen + 1);
28704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		/* Don't remove `+' here! -HW */
28804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	} else {
28904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		/* Include nul-terminator in match */
29004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask, 0xFF, vialen + 1);
29104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask + vialen + 1, 0, IFNAMSIZ - vialen - 1);
29204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		for (i = 0; vianame[i]; i++) {
29304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			if (vianame[i] == ':' ||
29404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			    vianame[i] == '!' ||
29504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			    vianame[i] == '*') {
296aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann				fprintf(stderr,
297aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann					"Warning: weird character in interface"
298aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann					" `%s' (No aliases, :, ! or *).\n",
299aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann					vianame);
30004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI				break;
30104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			}
30204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		}
30304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	}
30404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI}
30504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
3060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_match *find_match(const char *name, enum xt_tryload tryload,
3070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				 struct xtables_rule_match **matches)
3080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
3090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xtables_match *ptr;
3100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	const char *icmp6 = "icmp6";
3110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* This is ugly as hell. Nonetheless, there is no way of changing
3130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	 * this without hurting backwards compatibility */
3140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if ( (strcmp(name,"icmpv6") == 0) ||
3150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	     (strcmp(name,"ipv6-icmp") == 0) ||
3160d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	     (strcmp(name,"icmp6") == 0) )
3170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		name = icmp6;
3180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	for (ptr = xtables_matches; ptr; ptr = ptr->next) {
3200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (strcmp(name, ptr->name) == 0) {
3210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			struct xtables_match *clone;
3220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* First match of this type: */
3240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			if (ptr->m == NULL)
3250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				break;
3260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* Second and subsequent clones */
3280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			clone = fw_malloc(sizeof(struct xtables_match));
3290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			memcpy(clone, ptr, sizeof(struct xtables_match));
3300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			clone->mflags = 0;
3310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* This is a clone: */
3320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			clone->next = clone;
3330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr = clone;
3350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			break;
3360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
3370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
3380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#ifndef NO_SHARED_LIBS
3400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (!ptr && tryload != DONT_LOAD && tryload != DURING_LOAD) {
3410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		char path[strlen(lib_dir) + sizeof("/.so")
3420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			  + strlen(afinfo.libprefix) + strlen(name)];
343170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI
344170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI		sprintf(path, "%s/libxt_%s.so", lib_dir, name);
345170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI		if (dlopen(path, RTLD_NOW) != NULL)
3460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* Found library.  If it didn't register itself,
3470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			   maybe they specified target as match. */
3480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr = find_match(name, DONT_LOAD, NULL);
3490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
350170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI		if (ptr == NULL) {
351170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI			sprintf(path, "%s/%s%s.so", lib_dir, afinfo.libprefix,
352170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI				name);
353170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI			if (dlopen(path, RTLD_NOW) != NULL)
354170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI				ptr = find_match(name, DONT_LOAD, NULL);
355170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI		}
356170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI
357170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI		if (ptr == NULL && tryload == LOAD_MUST_SUCCEED)
3580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			exit_error(PARAMETER_PROBLEM,
3590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				   "Couldn't load match `%s':%s\n",
3600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				   name, dlerror());
3610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
3620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#else
3630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr && !ptr->loaded) {
3640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (tryload != DONT_LOAD)
3650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr->loaded = 1;
3660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		else
3670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr = NULL;
3680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
3690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if(!ptr && (tryload == LOAD_MUST_SUCCEED)) {
3700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit_error(PARAMETER_PROBLEM,
3710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			   "Couldn't find match `%s'\n", name);
3720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
3730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#endif
3740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr && matches) {
3760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		struct xtables_rule_match **i;
3770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		struct xtables_rule_match *newentry;
3780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		newentry = fw_malloc(sizeof(struct xtables_rule_match));
3800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		for (i = matches; *i; i = &(*i)->next) {
3820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			if (strcmp(name, (*i)->match->name) == 0)
3830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				(*i)->completed = 1;
3840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
3850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		newentry->match = ptr;
3860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		newentry->completed = 0;
3870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		newentry->next = NULL;
3880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		*i = newentry;
3890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
3900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return ptr;
3920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
3930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_target *find_target(const char *name, enum xt_tryload tryload)
3960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
3970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xtables_target *ptr;
3980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* Standard target? */
4000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (strcmp(name, "") == 0
4010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_ACCEPT) == 0
4020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_DROP) == 0
4030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_QUEUE) == 0
4040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_RETURN) == 0)
4050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		name = "standard";
4060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
4070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	for (ptr = xtables_targets; ptr; ptr = ptr->next) {
4080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (strcmp(name, ptr->name) == 0)
4090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			break;
4100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
4110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
4120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#ifndef NO_SHARED_LIBS
4130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (!ptr && tryload != DONT_LOAD && tryload != DURING_LOAD) {
4140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		char path[strlen(lib_dir) + sizeof("/.so")
4150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			  + strlen(afinfo.libprefix) + strlen(name)];
416170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI
417170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI		sprintf(path, "%s/libxt_%s.so", lib_dir, name);
418170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI		if (dlopen(path, RTLD_NOW) != NULL)
4190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* Found library.  If it didn't register itself,
4200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			   maybe they specified match as a target. */
4210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr = find_target(name, DONT_LOAD);
422170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI
423170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI		if (ptr == NULL) {
424170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI			sprintf(path, "%s/%s%s.so", lib_dir, afinfo.libprefix,
425170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI				name);
426170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI			if (dlopen(path, RTLD_NOW) != NULL)
427170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI				ptr = find_target(name, DONT_LOAD);
428170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI		}
429170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI		if (ptr == NULL && tryload == LOAD_MUST_SUCCEED)
4300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			exit_error(PARAMETER_PROBLEM,
4310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				   "Couldn't load target `%s':%s\n",
4320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				   name, dlerror());
4330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
4340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#else
4350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr && !ptr->loaded) {
4360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (tryload != DONT_LOAD)
4370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr->loaded = 1;
4380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		else
4390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr = NULL;
4400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
4410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if(!ptr && (tryload == LOAD_MUST_SUCCEED)) {
4420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit_error(PARAMETER_PROBLEM,
4430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			   "Couldn't find target `%s'\n", name);
4440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
4450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#endif
4460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
4470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr)
4480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		ptr->used = 1;
4490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
4500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return ptr;
4510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
4520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
4530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstatic int compatible_revision(const char *name, u_int8_t revision, int opt)
4540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
4550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xt_get_revision rev;
4560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	socklen_t s = sizeof(rev);
4570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	int max_rev, sockfd;
4580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
4590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	sockfd = socket(afinfo.family, SOCK_RAW, IPPROTO_RAW);
4600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (sockfd < 0) {
461df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy		if (errno == EPERM) {
462df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy			/* revision 0 is always supported. */
463df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy			if (revision != 0)
464df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy				fprintf(stderr, "Could not determine whether "
465df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy						"revision %u is supported, "
466df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy						"assuming it is.\n",
467df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy					revision);
468df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy			return 1;
469df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy		}
4700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "Could not open socket to kernel: %s\n",
4710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			strerror(errno));
4720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
4730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
4740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
4750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	load_xtables_ko(modprobe, 1);
4760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
4770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	strcpy(rev.name, name);
4780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	rev.revision = revision;
4790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
4800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	max_rev = getsockopt(sockfd, afinfo.ipproto, opt, &rev, &s);
4810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (max_rev < 0) {
4820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Definitely don't support this? */
4830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (errno == ENOENT || errno == EPROTONOSUPPORT) {
4840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			close(sockfd);
4850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return 0;
4860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		} else if (errno == ENOPROTOOPT) {
4870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			close(sockfd);
4880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* Assume only revision 0 support (old kernel) */
4890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return (revision == 0);
4900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		} else {
4910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			fprintf(stderr, "getsockopt failed strangely: %s\n",
4920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				strerror(errno));
4930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			exit(1);
4940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
4950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
4960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	close(sockfd);
4970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return 1;
4980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
4990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstatic int compatible_match_revision(const char *name, u_int8_t revision)
5020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
5030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return compatible_revision(name, revision, afinfo.so_rev_match);
5040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
5050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstatic int compatible_target_revision(const char *name, u_int8_t revision)
5070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
5080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return compatible_revision(name, revision, afinfo.so_rev_target);
5090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
5100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIvoid xtables_register_match(struct xtables_match *me)
5120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
5130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xtables_match **i, *old;
5140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (strcmp(me->version, program_version) != 0) {
5160d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: match `%s' v%s (I'm v%s).\n",
5170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			program_name, me->name, me->version, program_version);
5180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
5190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
5200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* Revision field stole a char from name. */
5220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (strlen(me->name) >= XT_FUNCTION_MAXNAMELEN-1) {
5230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: target `%s' has invalid name\n",
5240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			program_name, me->name);
5250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
5260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
5270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->family >= NPROTO) {
5290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr,
5300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			"%s: BUG: match %s has invalid protocol family\n",
5310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			program_name, me->name);
5320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
5330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
5340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* ignore not interested match */
5360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->family != afinfo.family)
5370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		return;
5380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	old = find_match(me->name, DURING_LOAD, NULL);
5400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (old) {
5410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (old->revision == me->revision) {
5420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			fprintf(stderr,
5430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				"%s: match `%s' already registered.\n",
5440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				program_name, me->name);
5450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			exit(1);
5460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
5470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Now we have two (or more) options, check compatibility. */
5490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (compatible_match_revision(old->name, old->revision)
5500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		    && old->revision > me->revision)
5510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
5520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Replace if compatible. */
5540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (!compatible_match_revision(me->name, me->revision))
5550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
5560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Delete old one. */
5580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		for (i = &xtables_matches; *i!=old; i = &(*i)->next);
5590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		*i = old->next;
5600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
5610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->size != XT_ALIGN(me->size)) {
5630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: match `%s' has invalid size %u.\n",
5640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			program_name, me->name, (unsigned int)me->size);
5650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
5660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
5670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* Append to list. */
5690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	for (i = &xtables_matches; *i; i = &(*i)->next);
5700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->next = NULL;
5710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	*i = me;
5720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->m = NULL;
5740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->mflags = 0;
5750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
5760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIvoid xtables_register_target(struct xtables_target *me)
5780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
5790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xtables_target *old;
5800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (strcmp(me->version, program_version) != 0) {
5820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: target `%s' v%s (I'm v%s).\n",
5830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			program_name, me->name, me->version, program_version);
5840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
5850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
5860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* Revision field stole a char from name. */
5880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (strlen(me->name) >= XT_FUNCTION_MAXNAMELEN-1) {
5890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: target `%s' has invalid name\n",
5900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			program_name, me->name);
5910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
5920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
5930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->family >= NPROTO) {
5950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr,
5960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			"%s: BUG: target %s has invalid protocol family\n",
5970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			program_name, me->name);
5980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
5990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* ignore not interested target */
6020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->family != afinfo.family)
6030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		return;
6040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	old = find_target(me->name, DURING_LOAD);
6060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (old) {
6070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		struct xtables_target **i;
6080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (old->revision == me->revision) {
6100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			fprintf(stderr,
6110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				"%s: target `%s' already registered.\n",
6120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				program_name, me->name);
6130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			exit(1);
6140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
6150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6160d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Now we have two (or more) options, check compatibility. */
6170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (compatible_target_revision(old->name, old->revision)
6180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		    && old->revision > me->revision)
6190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
6200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Replace if compatible. */
6220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (!compatible_target_revision(me->name, me->revision))
6230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
6240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Delete old one. */
6260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		for (i = &xtables_targets; *i!=old; i = &(*i)->next);
6270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		*i = old->next;
6280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->size != XT_ALIGN(me->size)) {
6310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: target `%s' has invalid size %u.\n",
6320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			program_name, me->name, (unsigned int)me->size);
6330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
6340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
6350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
6360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* Prepend to list. */
6370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->next = xtables_targets;
6380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	xtables_targets = me;
6390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->t = NULL;
6400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->tflags = 0;
6410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
642