xtables.c revision df1ef3862761e534c6cec6bd9370285cb5909dd0
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
190b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <dlfcn.h>
203dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI#include <errno.h>
210b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#include <fcntl.h>
2204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI#include <netdb.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
340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#define NPROTO	255
350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
360b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#ifndef PROC_SYS_MODPROBE
370b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe"
380b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#endif
390b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIchar *lib_dir;
410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
420b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI/* the path to command to load kernel module */
430b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAIconst char *modprobe = NULL;
440b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI/* Keeping track of external matches and targets: linked lists.  */
460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_match *xtables_matches;
470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_target *xtables_targets;
480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
493dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAIvoid *fw_calloc(size_t count, size_t size)
503dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI{
513dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	void *p;
523dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
533dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	if ((p = calloc(count, size)) == NULL) {
543dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI		perror("ip[6]tables: calloc failed");
553dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI		exit(1);
563dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	}
573dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
583dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	return p;
593dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI}
603dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
613dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAIvoid *fw_malloc(size_t size)
623dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI{
633dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	void *p;
643dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
653dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	if ((p = malloc(size)) == NULL) {
663dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI		perror("ip[6]tables: malloc failed");
673dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI		exit(1);
683dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	}
693dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI
703dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI	return p;
713dfa4488b032fc32aaf2470f48ac1fc3a534794fYasuyuki KOZAKAI}
720b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
730b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAIstatic char *get_modprobe(void)
740b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI{
750b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	int procfile;
760b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	char *ret;
770b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
780b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI#define PROCFILE_BUFSIZ	1024
790b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	procfile = open(PROC_SYS_MODPROBE, O_RDONLY);
800b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	if (procfile < 0)
810b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		return NULL;
820b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
830b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	ret = (char *) malloc(PROCFILE_BUFSIZ);
840b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	if (ret) {
850b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		memset(ret, 0, PROCFILE_BUFSIZ);
860b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		switch (read(procfile, ret, PROCFILE_BUFSIZ)) {
870b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		case -1: goto fail;
880b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		case PROCFILE_BUFSIZ: goto fail; /* Partial read.  Wierd */
890b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		}
900b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		if (ret[strlen(ret)-1]=='\n')
910b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			ret[strlen(ret)-1]=0;
920b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		close(procfile);
930b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		return ret;
940b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	}
950b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI fail:
960b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	free(ret);
970b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	close(procfile);
980b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	return NULL;
990b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI}
1000b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
1010b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAIint xtables_insmod(const char *modname, const char *modprobe, int quiet)
1020b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI{
1030b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	char *buf = NULL;
1040b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	char *argv[4];
1050b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	int status;
1060b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
1070b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	/* If they don't explicitly set it, read out of kernel */
1080b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	if (!modprobe) {
1090b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		buf = get_modprobe();
1100b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		if (!buf)
1110b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			return -1;
1120b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		modprobe = buf;
1130b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	}
1140b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
1150b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	switch (fork()) {
1160b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	case 0:
1170b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		argv[0] = (char *)modprobe;
1180b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		argv[1] = (char *)modname;
1190b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		if (quiet) {
1200b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[2] = "-q";
1210b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[3] = NULL;
1220b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		} else {
1230b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[2] = NULL;
1240b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI			argv[3] = NULL;
1250b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		}
1260b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		execv(argv[0], argv);
1270b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
1280b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		/* not usually reached */
1290b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		exit(1);
1300b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	case -1:
1310b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		return -1;
1320b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
1330b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	default: /* parent */
1340b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		wait(&status);
1350b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	}
1360b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
1370b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	free(buf);
1380b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
1390b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI		return 0;
1400b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI	return -1;
1410b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI}
1420b82e8e81e887843011c8771f70d2302901f7e5eYasuyuki KOZAKAI
1430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIint load_xtables_ko(const char *modprobe, int quiet)
1440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
1450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	static int loaded = 0;
1460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	static int ret = -1;
1470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
1480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (!loaded) {
1490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		ret = xtables_insmod(afinfo.kmod, modprobe, quiet);
1500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		loaded = (ret == 0);
1510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
1520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
1530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return ret;
1540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
1550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
15604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAIint string_to_number_ll(const char *s, unsigned long long min,
15704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			unsigned long long max, unsigned long long *ret)
15804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{
15904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	unsigned long long number;
16004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	char *end;
16104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
16204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	/* Handle hex, octal, etc. */
16304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	errno = 0;
16404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	number = strtoull(s, &end, 0);
16504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	if (*end == '\0' && end != s) {
16604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		/* we parsed a number, let's see if we want this */
16704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		if (errno != ERANGE && min <= number && (!max || number <= max)) {
16804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			*ret = number;
16904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			return 0;
17004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		}
17104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	}
17204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	return -1;
17304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI}
17404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
17504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAIint string_to_number_l(const char *s, unsigned long min, unsigned long max,
17604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		       unsigned long *ret)
17704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{
17804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	int result;
17904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	unsigned long long number;
18004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
18104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	result = string_to_number_ll(s, min, max, &number);
18204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	*ret = (unsigned long)number;
18304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
18404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	return result;
18504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI}
18604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
18704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAIint string_to_number(const char *s, unsigned int min, unsigned int max,
18804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		unsigned int *ret)
18904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{
19004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	int result;
19104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	unsigned long number;
19204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
19304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	result = string_to_number_l(s, min, max, &number);
19404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	*ret = (unsigned int)number;
19504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
19604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	return result;
19704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI}
19804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
19904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAIint service_to_port(const char *name, const char *proto)
20004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{
20104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	struct servent *service;
20204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
20304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	if ((service = getservbyname(name, proto)) != NULL)
20404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		return ntohs((unsigned short) service->s_port);
20504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
20604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	return -1;
20704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI}
20804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
20904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAIu_int16_t parse_port(const char *port, const char *proto)
21004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{
21104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	unsigned int portnum;
21204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
21304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	if ((string_to_number(port, 0, 65535, &portnum)) != -1 ||
21404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	    (portnum = service_to_port(port, proto)) != -1)
21504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		return (u_int16_t)portnum;
21604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
21704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	exit_error(PARAMETER_PROBLEM,
21804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		   "invalid port/service `%s' specified", port);
21904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI}
22004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
22104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAIvoid parse_interface(const char *arg, char *vianame, unsigned char *mask)
22204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI{
22304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	int vialen = strlen(arg);
22404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	unsigned int i;
22504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
22604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	memset(mask, 0, IFNAMSIZ);
22704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	memset(vianame, 0, IFNAMSIZ);
22804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
22904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	if (vialen + 1 > IFNAMSIZ)
23004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		exit_error(PARAMETER_PROBLEM,
23104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			   "interface name `%s' must be shorter than IFNAMSIZ"
23204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			   " (%i)", arg, IFNAMSIZ-1);
23304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
23404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	strcpy(vianame, arg);
23504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	if ((vialen == 0) || (vialen == 1 && vianame[0] == '+'))
23604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask, 0, IFNAMSIZ);
23704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	else if (vianame[vialen - 1] == '+') {
23804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask, 0xFF, vialen - 1);
23904f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask + vialen - 1, 0, IFNAMSIZ - vialen + 1);
24004f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		/* Don't remove `+' here! -HW */
24104f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	} else {
24204f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		/* Include nul-terminator in match */
24304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask, 0xFF, vialen + 1);
24404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		memset(mask + vialen + 1, 0, IFNAMSIZ - vialen - 1);
24504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		for (i = 0; vianame[i]; i++) {
24604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			if (vianame[i] == ':' ||
24704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			    vianame[i] == '!' ||
24804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			    vianame[i] == '*') {
249aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann				fprintf(stderr,
250aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann					"Warning: weird character in interface"
251aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann					" `%s' (No aliases, :, ! or *).\n",
252aae4f82eb83d923f59a328d6e13396f424be28f9Max Kellermann					vianame);
25304f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI				break;
25404f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI			}
25504f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI		}
25604f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI	}
25704f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI}
25804f8c54dc52e19096d31d94593bd1040716afe4dYasuyuki KOZAKAI
2590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_match *find_match(const char *name, enum xt_tryload tryload,
2600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				 struct xtables_rule_match **matches)
2610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
2620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xtables_match *ptr;
2630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	const char *icmp6 = "icmp6";
2640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
2650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* This is ugly as hell. Nonetheless, there is no way of changing
2660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	 * this without hurting backwards compatibility */
2670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if ( (strcmp(name,"icmpv6") == 0) ||
2680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	     (strcmp(name,"ipv6-icmp") == 0) ||
2690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	     (strcmp(name,"icmp6") == 0) )
2700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		name = icmp6;
2710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
2720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	for (ptr = xtables_matches; ptr; ptr = ptr->next) {
2730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (strcmp(name, ptr->name) == 0) {
2740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			struct xtables_match *clone;
2750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
2760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* First match of this type: */
2770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			if (ptr->m == NULL)
2780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				break;
2790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
2800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* Second and subsequent clones */
2810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			clone = fw_malloc(sizeof(struct xtables_match));
2820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			memcpy(clone, ptr, sizeof(struct xtables_match));
2830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			clone->mflags = 0;
2840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* This is a clone: */
2850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			clone->next = clone;
2860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
2870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr = clone;
2880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			break;
2890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
2900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
2910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
2920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#ifndef NO_SHARED_LIBS
2930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (!ptr && tryload != DONT_LOAD && tryload != DURING_LOAD) {
2940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		char path[strlen(lib_dir) + sizeof("/.so")
2950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			  + strlen(afinfo.libprefix) + strlen(name)];
296170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI
297170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI		sprintf(path, "%s/libxt_%s.so", lib_dir, name);
298170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI		if (dlopen(path, RTLD_NOW) != NULL)
2990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* Found library.  If it didn't register itself,
3000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			   maybe they specified target as match. */
3010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr = find_match(name, DONT_LOAD, NULL);
3020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
303170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI		if (ptr == NULL) {
304170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI			sprintf(path, "%s/%s%s.so", lib_dir, afinfo.libprefix,
305170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI				name);
306170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI			if (dlopen(path, RTLD_NOW) != NULL)
307170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI				ptr = find_match(name, DONT_LOAD, NULL);
308170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI		}
309170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI
310170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI		if (ptr == NULL && tryload == LOAD_MUST_SUCCEED)
3110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			exit_error(PARAMETER_PROBLEM,
3120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				   "Couldn't load match `%s':%s\n",
3130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				   name, dlerror());
3140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
3150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#else
3160d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr && !ptr->loaded) {
3170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (tryload != DONT_LOAD)
3180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr->loaded = 1;
3190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		else
3200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr = NULL;
3210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
3220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if(!ptr && (tryload == LOAD_MUST_SUCCEED)) {
3230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit_error(PARAMETER_PROBLEM,
3240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			   "Couldn't find match `%s'\n", name);
3250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
3260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#endif
3270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr && matches) {
3290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		struct xtables_rule_match **i;
3300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		struct xtables_rule_match *newentry;
3310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		newentry = fw_malloc(sizeof(struct xtables_rule_match));
3330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		for (i = matches; *i; i = &(*i)->next) {
3350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			if (strcmp(name, (*i)->match->name) == 0)
3360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				(*i)->completed = 1;
3370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
3380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		newentry->match = ptr;
3390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		newentry->completed = 0;
3400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		newentry->next = NULL;
3410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		*i = newentry;
3420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
3430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return ptr;
3450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
3460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstruct xtables_target *find_target(const char *name, enum xt_tryload tryload)
3490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
3500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xtables_target *ptr;
3510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* Standard target? */
3530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (strcmp(name, "") == 0
3540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_ACCEPT) == 0
3550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_DROP) == 0
3560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_QUEUE) == 0
3570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	    || strcmp(name, XTC_LABEL_RETURN) == 0)
3580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		name = "standard";
3590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	for (ptr = xtables_targets; ptr; ptr = ptr->next) {
3610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (strcmp(name, ptr->name) == 0)
3620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			break;
3630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
3640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
3650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#ifndef NO_SHARED_LIBS
3660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (!ptr && tryload != DONT_LOAD && tryload != DURING_LOAD) {
3670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		char path[strlen(lib_dir) + sizeof("/.so")
3680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			  + strlen(afinfo.libprefix) + strlen(name)];
369170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI
370170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI		sprintf(path, "%s/libxt_%s.so", lib_dir, name);
371170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI		if (dlopen(path, RTLD_NOW) != NULL)
3720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* Found library.  If it didn't register itself,
3730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			   maybe they specified match as a target. */
3740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr = find_target(name, DONT_LOAD);
375170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI
376170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI		if (ptr == NULL) {
377170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI			sprintf(path, "%s/%s%s.so", lib_dir, afinfo.libprefix,
378170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI				name);
379170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI			if (dlopen(path, RTLD_NOW) != NULL)
380170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI				ptr = find_target(name, DONT_LOAD);
381170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI		}
382170af8c566faa9605c1ead558792a031f1d0d48dYasuyuki KOZAKAI		if (ptr == NULL && tryload == LOAD_MUST_SUCCEED)
3830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			exit_error(PARAMETER_PROBLEM,
3840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				   "Couldn't load target `%s':%s\n",
3850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				   name, dlerror());
3860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
3870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#else
3880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr && !ptr->loaded) {
3890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (tryload != DONT_LOAD)
3900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr->loaded = 1;
3910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		else
3920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			ptr = NULL;
3930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
3940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if(!ptr && (tryload == LOAD_MUST_SUCCEED)) {
3950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit_error(PARAMETER_PROBLEM,
3960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			   "Couldn't find target `%s'\n", name);
3970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
3980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI#endif
3990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
4000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (ptr)
4010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		ptr->used = 1;
4020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
4030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return ptr;
4040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
4050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
4060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstatic int compatible_revision(const char *name, u_int8_t revision, int opt)
4070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
4080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xt_get_revision rev;
4090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	socklen_t s = sizeof(rev);
4100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	int max_rev, sockfd;
4110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
4120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	sockfd = socket(afinfo.family, SOCK_RAW, IPPROTO_RAW);
4130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (sockfd < 0) {
414df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy		if (errno == EPERM) {
415df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy			/* revision 0 is always supported. */
416df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy			if (revision != 0)
417df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy				fprintf(stderr, "Could not determine whether "
418df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy						"revision %u is supported, "
419df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy						"assuming it is.\n",
420df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy					revision);
421df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy			return 1;
422df1ef3862761e534c6cec6bd9370285cb5909dd0Patrick McHardy		}
4230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "Could not open socket to kernel: %s\n",
4240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			strerror(errno));
4250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
4260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
4270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
4280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	load_xtables_ko(modprobe, 1);
4290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
4300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	strcpy(rev.name, name);
4310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	rev.revision = revision;
4320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
4330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	max_rev = getsockopt(sockfd, afinfo.ipproto, opt, &rev, &s);
4340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (max_rev < 0) {
4350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Definitely don't support this? */
4360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (errno == ENOENT || errno == EPROTONOSUPPORT) {
4370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			close(sockfd);
4380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return 0;
4390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		} else if (errno == ENOPROTOOPT) {
4400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			close(sockfd);
4410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			/* Assume only revision 0 support (old kernel) */
4420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return (revision == 0);
4430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		} else {
4440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			fprintf(stderr, "getsockopt failed strangely: %s\n",
4450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				strerror(errno));
4460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			exit(1);
4470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
4480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
4490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	close(sockfd);
4500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return 1;
4510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
4520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
4530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
4540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstatic int compatible_match_revision(const char *name, u_int8_t revision)
4550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
4560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return compatible_revision(name, revision, afinfo.so_rev_match);
4570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
4580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
4590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIstatic int compatible_target_revision(const char *name, u_int8_t revision)
4600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
4610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	return compatible_revision(name, revision, afinfo.so_rev_target);
4620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
4630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
4640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIvoid xtables_register_match(struct xtables_match *me)
4650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
4660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xtables_match **i, *old;
4670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
4680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (strcmp(me->version, program_version) != 0) {
4690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: match `%s' v%s (I'm v%s).\n",
4700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			program_name, me->name, me->version, program_version);
4710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
4720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
4730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
4740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* Revision field stole a char from name. */
4750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (strlen(me->name) >= XT_FUNCTION_MAXNAMELEN-1) {
4760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: target `%s' has invalid name\n",
4770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			program_name, me->name);
4780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
4790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
4800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
4810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->family >= NPROTO) {
4820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr,
4830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			"%s: BUG: match %s has invalid protocol family\n",
4840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			program_name, me->name);
4850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
4860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
4870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
4880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* ignore not interested match */
4890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->family != afinfo.family)
4900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		return;
4910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
4920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	old = find_match(me->name, DURING_LOAD, NULL);
4930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (old) {
4940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (old->revision == me->revision) {
4950d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			fprintf(stderr,
4960d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				"%s: match `%s' already registered.\n",
4970d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				program_name, me->name);
4980d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			exit(1);
4990d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
5000d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5010d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Now we have two (or more) options, check compatibility. */
5020d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (compatible_match_revision(old->name, old->revision)
5030d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		    && old->revision > me->revision)
5040d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
5050d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5060d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Replace if compatible. */
5070d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (!compatible_match_revision(me->name, me->revision))
5080d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
5090d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5100d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Delete old one. */
5110d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		for (i = &xtables_matches; *i!=old; i = &(*i)->next);
5120d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		*i = old->next;
5130d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
5140d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5150d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->size != XT_ALIGN(me->size)) {
5160d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: match `%s' has invalid size %u.\n",
5170d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			program_name, me->name, (unsigned int)me->size);
5180d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
5190d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
5200d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5210d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* Append to list. */
5220d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	for (i = &xtables_matches; *i; i = &(*i)->next);
5230d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->next = NULL;
5240d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	*i = me;
5250d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5260d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->m = NULL;
5270d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->mflags = 0;
5280d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
5290d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5300d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAIvoid xtables_register_target(struct xtables_target *me)
5310d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI{
5320d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	struct xtables_target *old;
5330d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5340d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (strcmp(me->version, program_version) != 0) {
5350d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: target `%s' v%s (I'm v%s).\n",
5360d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			program_name, me->name, me->version, program_version);
5370d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
5380d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
5390d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5400d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* Revision field stole a char from name. */
5410d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (strlen(me->name) >= XT_FUNCTION_MAXNAMELEN-1) {
5420d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: target `%s' has invalid name\n",
5430d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			program_name, me->name);
5440d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
5450d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
5460d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5470d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->family >= NPROTO) {
5480d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr,
5490d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			"%s: BUG: target %s has invalid protocol family\n",
5500d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			program_name, me->name);
5510d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
5520d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
5530d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5540d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* ignore not interested target */
5550d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->family != afinfo.family)
5560d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		return;
5570d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5580d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	old = find_target(me->name, DURING_LOAD);
5590d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (old) {
5600d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		struct xtables_target **i;
5610d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5620d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (old->revision == me->revision) {
5630d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			fprintf(stderr,
5640d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				"%s: target `%s' already registered.\n",
5650d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI				program_name, me->name);
5660d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			exit(1);
5670d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		}
5680d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5690d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Now we have two (or more) options, check compatibility. */
5700d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (compatible_target_revision(old->name, old->revision)
5710d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		    && old->revision > me->revision)
5720d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
5730d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5740d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Replace if compatible. */
5750d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		if (!compatible_target_revision(me->name, me->revision))
5760d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			return;
5770d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5780d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		/* Delete old one. */
5790d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		for (i = &xtables_targets; *i!=old; i = &(*i)->next);
5800d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		*i = old->next;
5810d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
5820d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5830d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	if (me->size != XT_ALIGN(me->size)) {
5840d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		fprintf(stderr, "%s: target `%s' has invalid size %u.\n",
5850d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI			program_name, me->name, (unsigned int)me->size);
5860d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI		exit(1);
5870d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	}
5880d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI
5890d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	/* Prepend to list. */
5900d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->next = xtables_targets;
5910d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	xtables_targets = me;
5920d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->t = NULL;
5930d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI	me->tflags = 0;
5940d502bcdbc97ed359e84f6a21dfa0049b3b60a6cYasuyuki KOZAKAI}
595