Blame iptables/iptables-xml.c

Packit 7b22a4
/* Code to convert iptables-save format to xml format,
Packit 7b22a4
 * (C) 2006 Ufo Mechanic <azez@ufomechanic.net>
Packit 7b22a4
 * based on iptables-restore (C) 2000-2002 by Harald Welte <laforge@gnumonks.org>
Packit 7b22a4
 * based on previous code from Rusty Russell <rusty@linuxcare.com.au>
Packit 7b22a4
 *
Packit 7b22a4
 * This code is distributed under the terms of GNU GPL v2
Packit 7b22a4
 */
Packit 7b22a4
#include "config.h"
Packit 7b22a4
#include <getopt.h>
Packit 7b22a4
#include <errno.h>
Packit 7b22a4
#include <string.h>
Packit 7b22a4
#include <stdio.h>
Packit 7b22a4
#include <stdlib.h>
Packit 7b22a4
#include <stdarg.h>
Packit 7b22a4
#include "iptables.h"
Packit 7b22a4
#include "libiptc/libiptc.h"
Packit 7b22a4
#include "xtables-multi.h"
Packit 7b22a4
#include <xtables.h>
Packit 7b22a4
#include "xshared.h"
Packit 7b22a4
Packit 7b22a4
struct xtables_globals iptables_xml_globals = {
Packit 7b22a4
	.option_offset = 0,
Packit 7b22a4
	.program_version = PACKAGE_VERSION,
Packit 7b22a4
	.program_name = "iptables-xml",
Packit 7b22a4
};
Packit 7b22a4
#define prog_name iptables_xml_globals.program_name
Packit 7b22a4
#define prog_vers iptables_xml_globals.program_version
Packit 7b22a4
Packit 7b22a4
static void print_usage(const char *name, const char *version)
Packit 7b22a4
	    __attribute__ ((noreturn));
Packit 7b22a4
Packit 7b22a4
static int verbose;
Packit 7b22a4
/* Whether to combine actions of sequential rules with identical conditions */
Packit 7b22a4
static int combine;
Packit 7b22a4
/* Keeping track of external matches and targets.  */
Packit 7b22a4
static const struct option options[] = {
Packit 7b22a4
	{"verbose", 0, NULL, 'v'},
Packit 7b22a4
	{"combine", 0, NULL, 'c'},
Packit 7b22a4
	{"help", 0, NULL, 'h'},
Packit 7b22a4
	{ .name = NULL }
Packit 7b22a4
};
Packit 7b22a4
Packit 7b22a4
static void
Packit 7b22a4
print_usage(const char *name, const char *version)
Packit 7b22a4
{
Packit 7b22a4
	fprintf(stderr, "Usage: %s [-c] [-v] [-h]\n"
Packit 7b22a4
		"          [--combine ]\n"
Packit 7b22a4
		"	   [ --verbose ]\n" "	   [ --help ]\n", name);
Packit 7b22a4
Packit 7b22a4
	exit(1);
Packit 7b22a4
}
Packit 7b22a4
Packit 7b22a4
#define XT_CHAIN_MAXNAMELEN XT_TABLE_MAXNAMELEN
Packit 7b22a4
static char closeActionTag[XT_TABLE_MAXNAMELEN + 1];
Packit 7b22a4
static char closeRuleTag[XT_TABLE_MAXNAMELEN + 1];
Packit 7b22a4
static char curTable[XT_TABLE_MAXNAMELEN + 1];
Packit 7b22a4
static char curChain[XT_CHAIN_MAXNAMELEN + 1];
Packit 7b22a4
Packit 7b22a4
struct chain {
Packit 7b22a4
	char *chain;
Packit 7b22a4
	char *policy;
Packit 7b22a4
	struct xt_counters count;
Packit 7b22a4
	int created;
Packit 7b22a4
};
Packit 7b22a4
Packit 7b22a4
#define maxChains 10240		/* max chains per table */
Packit 7b22a4
static struct chain chains[maxChains];
Packit 7b22a4
static int nextChain;
Packit 7b22a4
Packit 7b22a4
/* like puts but with xml encoding */
Packit 7b22a4
static void
Packit 7b22a4
xmlEncode(char *text)
Packit 7b22a4
{
Packit 7b22a4
	while (text && *text) {
Packit 7b22a4
		if ((unsigned char) (*text) >= 127)
Packit 7b22a4
			printf("&#%d;", (unsigned char) (*text));
Packit 7b22a4
		else if (*text == '&')
Packit 7b22a4
			printf("&");
Packit 7b22a4
		else if (*text == '<')
Packit 7b22a4
			printf("<");
Packit 7b22a4
		else if (*text == '>')
Packit 7b22a4
			printf(">");
Packit 7b22a4
		else if (*text == '"')
Packit 7b22a4
			printf(""");
Packit 7b22a4
		else
Packit 7b22a4
			putchar(*text);
Packit 7b22a4
		text++;
Packit 7b22a4
	}
Packit 7b22a4
}
Packit 7b22a4
Packit 7b22a4
/* Output text as a comment, avoiding a double hyphen */
Packit 7b22a4
static void
Packit 7b22a4
xmlCommentEscape(char *comment)
Packit 7b22a4
{
Packit 7b22a4
	int h_count = 0;
Packit 7b22a4
Packit 7b22a4
	while (comment && *comment) {
Packit 7b22a4
		if (*comment == '-') {
Packit 7b22a4
			h_count++;
Packit 7b22a4
			if (h_count >= 2) {
Packit 7b22a4
				h_count = 0;
Packit 7b22a4
				putchar(' ');
Packit 7b22a4
			}
Packit 7b22a4
			putchar('*');
Packit 7b22a4
		}
Packit 7b22a4
		/* strip trailing newline */
Packit 7b22a4
		if (*comment == '\n' && *(comment + 1) == 0);
Packit 7b22a4
		else
Packit 7b22a4
			putchar(*comment);
Packit 7b22a4
		comment++;
Packit 7b22a4
	}
Packit 7b22a4
}
Packit 7b22a4
Packit 7b22a4
static void
Packit 7b22a4
xmlComment(char *comment)
Packit 7b22a4
{
Packit 7b22a4
	printf("
Packit 7b22a4
	xmlCommentEscape(comment);
Packit 7b22a4
	printf(" -->\n");
Packit 7b22a4
}
Packit 7b22a4
Packit 7b22a4
static void
Packit 7b22a4
xmlAttrS(char *name, char *value)
Packit 7b22a4
{
Packit 7b22a4
	printf("%s=\"", name);
Packit 7b22a4
	xmlEncode(value);
Packit 7b22a4
	printf("\" ");
Packit 7b22a4
}
Packit 7b22a4
Packit 7b22a4
static void
Packit 7b22a4
xmlAttrI(char *name, long long int num)
Packit 7b22a4
{
Packit 7b22a4
	printf("%s=\"%lld\" ", name, num);
Packit 7b22a4
}
Packit 7b22a4
Packit 7b22a4
static void
Packit 7b22a4
closeChain(void)
Packit 7b22a4
{
Packit 7b22a4
	if (curChain[0] == 0)
Packit 7b22a4
		return;
Packit 7b22a4
Packit 7b22a4
	if (closeActionTag[0])
Packit 7b22a4
		printf("%s\n", closeActionTag);
Packit 7b22a4
	closeActionTag[0] = 0;
Packit 7b22a4
	if (closeRuleTag[0])
Packit 7b22a4
		printf("%s\n", closeRuleTag);
Packit 7b22a4
	closeRuleTag[0] = 0;
Packit 7b22a4
	if (curChain[0])
Packit 7b22a4
		printf("    </chain>\n");
Packit 7b22a4
	curChain[0] = 0;
Packit 7b22a4
	//lastRule[0]=0;
Packit 7b22a4
}
Packit 7b22a4
Packit 7b22a4
static void
Packit 7b22a4
openChain(char *chain, char *policy, struct xt_counters *ctr, char close)
Packit 7b22a4
{
Packit 7b22a4
	closeChain();
Packit 7b22a4
Packit 7b22a4
	strncpy(curChain, chain, XT_CHAIN_MAXNAMELEN);
Packit 7b22a4
	curChain[XT_CHAIN_MAXNAMELEN] = '\0';
Packit 7b22a4
Packit 7b22a4
	printf("    
Packit 7b22a4
	xmlAttrS("name", curChain);
Packit 7b22a4
	if (strcmp(policy, "-") != 0)
Packit 7b22a4
		xmlAttrS("policy", policy);
Packit 7b22a4
	xmlAttrI("packet-count", (unsigned long long) ctr->pcnt);
Packit 7b22a4
	xmlAttrI("byte-count", (unsigned long long) ctr->bcnt);
Packit 7b22a4
	if (close) {
Packit 7b22a4
		printf("%c", close);
Packit 7b22a4
		curChain[0] = 0;
Packit 7b22a4
	}
Packit 7b22a4
	printf(">\n");
Packit 7b22a4
}
Packit 7b22a4
Packit 7b22a4
static int
Packit 7b22a4
existsChain(char *chain)
Packit 7b22a4
{
Packit 7b22a4
	/* open a saved chain */
Packit 7b22a4
	int c = 0;
Packit 7b22a4
Packit 7b22a4
	if (0 == strcmp(curChain, chain))
Packit 7b22a4
		return 1;
Packit 7b22a4
	for (c = 0; c < nextChain; c++)
Packit 7b22a4
		if (chains[c].chain && strcmp(chains[c].chain, chain) == 0)
Packit 7b22a4
			return 1;
Packit 7b22a4
	return 0;
Packit 7b22a4
}
Packit 7b22a4
Packit 7b22a4
static void
Packit 7b22a4
needChain(char *chain)
Packit 7b22a4
{
Packit 7b22a4
	/* open a saved chain */
Packit 7b22a4
	int c = 0;
Packit 7b22a4
Packit 7b22a4
	if (0 == strcmp(curChain, chain))
Packit 7b22a4
		return;
Packit 7b22a4
Packit 7b22a4
	for (c = 0; c < nextChain; c++)
Packit 7b22a4
		if (chains[c].chain && strcmp(chains[c].chain, chain) == 0) {
Packit 7b22a4
			openChain(chains[c].chain, chains[c].policy,
Packit 7b22a4
				  &(chains[c].count), '\0');
Packit 7b22a4
			/* And, mark it as done so we don't create 
Packit 7b22a4
			   an empty chain at table-end time */
Packit 7b22a4
			chains[c].created = 1;
Packit 7b22a4
		}
Packit 7b22a4
}
Packit 7b22a4
Packit 7b22a4
static void
Packit 7b22a4
saveChain(char *chain, char *policy, struct xt_counters *ctr)
Packit 7b22a4
{
Packit 7b22a4
	if (nextChain >= maxChains)
Packit 7b22a4
		xtables_error(PARAMETER_PROBLEM,
Packit 7b22a4
			   "%s: line %u chain name invalid\n",
Packit 7b22a4
			   prog_name, line);
Packit 7b22a4
Packit 7b22a4
	chains[nextChain].chain = strdup(chain);
Packit 7b22a4
	chains[nextChain].policy = strdup(policy);
Packit 7b22a4
	chains[nextChain].count = *ctr;
Packit 7b22a4
	chains[nextChain].created = 0;
Packit 7b22a4
	nextChain++;
Packit 7b22a4
}
Packit 7b22a4
Packit 7b22a4
static void
Packit 7b22a4
finishChains(void)
Packit 7b22a4
{
Packit 7b22a4
	int c;
Packit 7b22a4
Packit 7b22a4
	for (c = 0; c < nextChain; c++)
Packit 7b22a4
		if (!chains[c].created) {
Packit 7b22a4
			openChain(chains[c].chain, chains[c].policy,
Packit 7b22a4
				  &(chains[c].count), '/');
Packit 7b22a4
			free(chains[c].chain);
Packit 7b22a4
			free(chains[c].policy);
Packit 7b22a4
		}
Packit 7b22a4
	nextChain = 0;
Packit 7b22a4
}
Packit 7b22a4
Packit 7b22a4
static void
Packit 7b22a4
closeTable(void)
Packit 7b22a4
{
Packit 7b22a4
	closeChain();
Packit 7b22a4
	finishChains();
Packit 7b22a4
	if (curTable[0])
Packit 7b22a4
		printf("  \n");
Packit 7b22a4
	curTable[0] = 0;
Packit 7b22a4
}
Packit 7b22a4
Packit 7b22a4
static void
Packit 7b22a4
openTable(char *table)
Packit 7b22a4
{
Packit 7b22a4
	closeTable();
Packit 7b22a4
Packit 7b22a4
	strncpy(curTable, table, XT_TABLE_MAXNAMELEN);
Packit 7b22a4
	curTable[XT_TABLE_MAXNAMELEN] = '\0';
Packit 7b22a4
Packit 7b22a4
	printf("  
Packit 7b22a4
	xmlAttrS("name", curTable);
Packit 7b22a4
	printf(">\n");
Packit 7b22a4
}
Packit 7b22a4
Packit 7b22a4
// is char* -j --jump -g or --goto
Packit 7b22a4
static int
Packit 7b22a4
isTarget(char *arg)
Packit 7b22a4
{
Packit 7b22a4
	return ((arg)
Packit 7b22a4
		&& (strcmp((arg), "-j") == 0 || strcmp((arg), "--jump") == 0
Packit 7b22a4
		    || strcmp((arg), "-g") == 0
Packit 7b22a4
		    || strcmp((arg), "--goto") == 0));
Packit 7b22a4
}
Packit 7b22a4
Packit 7b22a4
// is it a terminating target like -j ACCEPT, etc
Packit 7b22a4
// (or I guess -j SNAT in nat table, but we don't check for that yet
Packit 7b22a4
static int
Packit 7b22a4
isTerminatingTarget(char *arg)
Packit 7b22a4
{
Packit 7b22a4
	return ((arg)
Packit 7b22a4
		&& (strcmp((arg), "ACCEPT") == 0
Packit 7b22a4
		    || strcmp((arg), "DROP") == 0
Packit 7b22a4
		    || strcmp((arg), "QUEUE") == 0
Packit 7b22a4
		    || strcmp((arg), "RETURN") == 0));
Packit 7b22a4
}
Packit 7b22a4
Packit 7b22a4
// part=-1 means do conditions, part=1 means do rules, part=0 means do both
Packit 7b22a4
static void
Packit 7b22a4
do_rule_part(char *leveltag1, char *leveltag2, int part, int argc,
Packit 7b22a4
	     char *argv[], int argvattr[])
Packit 7b22a4
{
Packit 7b22a4
	int i;
Packit 7b22a4
	int arg = 2;		// ignore leading -A <chain>
Packit 7b22a4
	char invert_next = 0;
Packit 7b22a4
	char *spacer = "";	// space when needed to assemble arguments
Packit 7b22a4
	char *level1 = NULL;
Packit 7b22a4
	char *level2 = NULL;
Packit 7b22a4
	char *leveli1 = "        ";
Packit 7b22a4
	char *leveli2 = "          ";
Packit 7b22a4
Packit 7b22a4
#define CLOSE_LEVEL(LEVEL) \
Packit 7b22a4
	do { \
Packit 7b22a4
		if (level ## LEVEL) printf("</%s>\n", \
Packit 7b22a4
		(leveltag ## LEVEL)?(leveltag ## LEVEL):(level ## LEVEL)); \
Packit 7b22a4
		level ## LEVEL=NULL;\
Packit 7b22a4
	} while(0)
Packit 7b22a4
Packit 7b22a4
#define OPEN_LEVEL(LEVEL,TAG) \
Packit 7b22a4
	do {\
Packit 7b22a4
		level ## LEVEL=TAG;\
Packit 7b22a4
		if (leveltag ## LEVEL) {\
Packit 7b22a4
			printf("%s<%s ", (leveli ## LEVEL), \
Packit 7b22a4
				(leveltag ## LEVEL));\
Packit 7b22a4
			xmlAttrS("type", (TAG)); \
Packit 7b22a4
		} else printf("%s<%s ", (leveli ## LEVEL), (level ## LEVEL)); \
Packit 7b22a4
	} while(0)
Packit 7b22a4
Packit 7b22a4
	if (part == 1) {	/* skip */
Packit 7b22a4
		/* use argvattr to tell which arguments were quoted 
Packit 7b22a4
		   to avoid comparing quoted arguments, like comments, to -j, */
Packit 7b22a4
		while (arg < argc && (argvattr[arg] || !isTarget(argv[arg])))
Packit 7b22a4
			arg++;
Packit 7b22a4
	}
Packit 7b22a4
Packit 7b22a4
	/* Before we start, if the first arg is -[^-] and not -m or -j or -g
Packit 7b22a4
	 * then start a dummy <match> tag for old style built-in matches.
Packit 7b22a4
	 * We would do this in any case, but no need if it would be empty.
Packit 7b22a4
	 * In the case of negation, we need to look at arg+1
Packit 7b22a4
	 */
Packit 7b22a4
	if (arg < argc && strcmp(argv[arg], "!") == 0)
Packit 7b22a4
		i = arg + 1;
Packit 7b22a4
	else
Packit 7b22a4
		i = arg;
Packit 7b22a4
	if (i < argc && argv[i][0] == '-' && !isTarget(argv[i])
Packit 7b22a4
	    && strcmp(argv[i], "-m") != 0) {
Packit 7b22a4
		OPEN_LEVEL(1, "match");
Packit 7b22a4
		printf(">\n");
Packit 7b22a4
	}
Packit 7b22a4
	while (arg < argc) {
Packit 7b22a4
		// If ! is followed by -* then apply to that else output as data
Packit 7b22a4
		// Stop, if we need to
Packit 7b22a4
		if (part == -1 && !argvattr[arg] && (isTarget(argv[arg]))) {
Packit 7b22a4
			break;
Packit 7b22a4
		} else if (!argvattr[arg] && strcmp(argv[arg], "!") == 0) {
Packit 7b22a4
			if ((arg + 1) < argc && argv[arg + 1][0] == '-')
Packit 7b22a4
				invert_next = '!';
Packit 7b22a4
			else
Packit 7b22a4
				printf("%s%s", spacer, argv[arg]);
Packit 7b22a4
			spacer = " ";
Packit 7b22a4
		} else if (!argvattr[arg] && isTarget(argv[arg]) &&
Packit 7b22a4
			   (arg + 1 < argc) &&
Packit 7b22a4
			   existsChain(argv[arg + 1])) {
Packit 7b22a4
			CLOSE_LEVEL(2);
Packit 7b22a4
			if (level1)
Packit 7b22a4
				printf("%s", leveli1);
Packit 7b22a4
			CLOSE_LEVEL(1);
Packit 7b22a4
			spacer = "";
Packit 7b22a4
			invert_next = 0;
Packit 7b22a4
			if (strcmp(argv[arg], "-g") == 0
Packit 7b22a4
			    || strcmp(argv[arg], "--goto") == 0) {
Packit 7b22a4
				/* goto user chain */
Packit 7b22a4
				OPEN_LEVEL(1, "goto");
Packit 7b22a4
				printf(">\n");
Packit 7b22a4
				arg++;
Packit 7b22a4
				OPEN_LEVEL(2, argv[arg]);
Packit 7b22a4
				printf("/>\n");
Packit 7b22a4
				level2 = NULL;
Packit 7b22a4
			} else {
Packit 7b22a4
				/* call user chain */
Packit 7b22a4
				OPEN_LEVEL(1, "call");
Packit 7b22a4
				printf(">\n");
Packit 7b22a4
				arg++;
Packit 7b22a4
				OPEN_LEVEL(2, argv[arg]);
Packit 7b22a4
				printf("/>\n");
Packit 7b22a4
				level2 = NULL;
Packit 7b22a4
			}
Packit 7b22a4
		} else if (!argvattr[arg]
Packit 7b22a4
			   && (isTarget(argv[arg])
Packit 7b22a4
			       || strcmp(argv[arg], "-m") == 0
Packit 7b22a4
			       || strcmp(argv[arg], "--module") == 0)) {
Packit 7b22a4
			if (!((1 + arg) < argc))
Packit 7b22a4
				// no args to -j, -m or -g, ignore & finish loop
Packit 7b22a4
				break;
Packit 7b22a4
			CLOSE_LEVEL(2);
Packit 7b22a4
			if (level1)
Packit 7b22a4
				printf("%s", leveli1);
Packit 7b22a4
			CLOSE_LEVEL(1);
Packit 7b22a4
			spacer = "";
Packit 7b22a4
			invert_next = 0;
Packit 7b22a4
			arg++;
Packit 7b22a4
			OPEN_LEVEL(1, (argv[arg]));
Packit 7b22a4
			// Optimize case, can we close this tag already?
Packit 7b22a4
			if ((arg + 1) >= argc || (!argvattr[arg + 1]
Packit 7b22a4
						  && (isTarget(argv[arg + 1])
Packit 7b22a4
						      || strcmp(argv[arg + 1],
Packit 7b22a4
								"-m") == 0
Packit 7b22a4
						      || strcmp(argv[arg + 1],
Packit 7b22a4
								"--module") ==
Packit 7b22a4
						      0))) {
Packit 7b22a4
				printf(" />\n");
Packit 7b22a4
				level1 = NULL;
Packit 7b22a4
			} else {
Packit 7b22a4
				printf(">\n");
Packit 7b22a4
			}
Packit 7b22a4
		} else if (!argvattr[arg] && argv[arg][0] == '-') {
Packit 7b22a4
			char *tag;
Packit 7b22a4
			CLOSE_LEVEL(2);
Packit 7b22a4
			// Skip past any -
Packit 7b22a4
			tag = argv[arg];
Packit 7b22a4
			while (*tag == '-' && *tag)
Packit 7b22a4
				tag++;
Packit 7b22a4
Packit 7b22a4
			spacer = "";
Packit 7b22a4
			OPEN_LEVEL(2, tag);
Packit 7b22a4
			if (invert_next)
Packit 7b22a4
				printf(" invert=\"1\"");
Packit 7b22a4
			invert_next = 0;
Packit 7b22a4
Packit 7b22a4
			// Optimize case, can we close this tag already?
Packit 7b22a4
			if (!((arg + 1) < argc)
Packit 7b22a4
			    || (argv[arg + 1][0] == '-' /* NOT QUOTED */ )) {
Packit 7b22a4
				printf(" />\n");
Packit 7b22a4
				level2 = NULL;
Packit 7b22a4
			} else {
Packit 7b22a4
				printf(">");
Packit 7b22a4
			}
Packit 7b22a4
		} else {	// regular data
Packit 7b22a4
			char *spaces = strchr(argv[arg], ' ');
Packit 7b22a4
			printf("%s", spacer);
Packit 7b22a4
			if (spaces || argvattr[arg])
Packit 7b22a4
				printf(""");
Packit 7b22a4
			// if argv[arg] contains a space, enclose in quotes
Packit 7b22a4
			xmlEncode(argv[arg]);
Packit 7b22a4
			if (spaces || argvattr[arg])
Packit 7b22a4
				printf(""");
Packit 7b22a4
			spacer = " ";
Packit 7b22a4
		}
Packit 7b22a4
		arg++;
Packit 7b22a4
	}
Packit 7b22a4
	CLOSE_LEVEL(2);
Packit 7b22a4
	if (level1)
Packit 7b22a4
		printf("%s", leveli1);
Packit 7b22a4
	CLOSE_LEVEL(1);
Packit 7b22a4
}
Packit 7b22a4
Packit 7b22a4
static int
Packit 7b22a4
compareRules(int newargc, char *newargv[], int oldargc, char *oldargv[])
Packit 7b22a4
{
Packit 7b22a4
	/* Compare arguments up to -j or -g for match.
Packit 7b22a4
	 * NOTE: We don't want to combine actions if there were no criteria
Packit 7b22a4
	 * in each rule, or rules didn't have an action.
Packit 7b22a4
	 * NOTE: Depends on arguments being in some kind of "normal" order which
Packit 7b22a4
	 * is the case when processing the ACTUAL output of actual iptables-save
Packit 7b22a4
	 * rather than a file merely in a compatible format.
Packit 7b22a4
	 */
Packit 7b22a4
Packit 7b22a4
	unsigned int old = 0;
Packit 7b22a4
	unsigned int new = 0;
Packit 7b22a4
Packit 7b22a4
	int compare = 0;
Packit 7b22a4
Packit 7b22a4
	while (new < newargc && old < oldargc) {
Packit 7b22a4
		if (isTarget(oldargv[old]) && isTarget(newargv[new])) {
Packit 7b22a4
			/* if oldarg was a terminating action then it makes no sense
Packit 7b22a4
			 * to combine further actions into the same xml */
Packit 7b22a4
			if (((strcmp((oldargv[old]), "-j") == 0 
Packit 7b22a4
					|| strcmp((oldargv[old]), "--jump") == 0) 
Packit 7b22a4
				&& old+1 < oldargc
Packit 7b22a4
				&& isTerminatingTarget(oldargv[old+1]) )
Packit 7b22a4
			    || strcmp((oldargv[old]), "-g") == 0 
Packit 7b22a4
			    || strcmp((oldargv[old]), "--goto") == 0 ) {
Packit 7b22a4
				/* Previous rule had terminating action */	
Packit 7b22a4
				compare = 0;
Packit 7b22a4
			} else {
Packit 7b22a4
				compare = 1;
Packit 7b22a4
			}
Packit 7b22a4
			break;
Packit 7b22a4
		}
Packit 7b22a4
		// break when old!=new
Packit 7b22a4
		if (strcmp(oldargv[old], newargv[new]) != 0) {
Packit 7b22a4
			compare = 0;
Packit 7b22a4
			break;
Packit 7b22a4
		}
Packit 7b22a4
Packit 7b22a4
		old++;
Packit 7b22a4
		new++;
Packit 7b22a4
	}
Packit 7b22a4
	// We won't match unless both rules had a target. 
Packit 7b22a4
	// This means we don't combine target-less rules, which is good
Packit 7b22a4
Packit 7b22a4
	return compare == 1;
Packit 7b22a4
}
Packit 7b22a4
Packit 7b22a4
/* has a nice parsed rule starting with -A */
Packit 7b22a4
static void
Packit 7b22a4
do_rule(char *pcnt, char *bcnt, int argc, char *argv[], int argvattr[],
Packit 7b22a4
	int oldargc, char *oldargv[])
Packit 7b22a4
{
Packit 7b22a4
	/* are these conditions the same as the previous rule?
Packit 7b22a4
	 * If so, skip arg straight to -j or -g */
Packit 7b22a4
	if (combine && argc > 2 && !isTarget(argv[2]) &&
Packit 7b22a4
	    compareRules(argc, argv, oldargc, oldargv)) {
Packit 7b22a4
		xmlComment("Combine action from next rule");
Packit 7b22a4
	} else {
Packit 7b22a4
Packit 7b22a4
		if (closeActionTag[0]) {
Packit 7b22a4
			printf("%s\n", closeActionTag);
Packit 7b22a4
			closeActionTag[0] = 0;
Packit 7b22a4
		}
Packit 7b22a4
		if (closeRuleTag[0]) {
Packit 7b22a4
			printf("%s\n", closeRuleTag);
Packit 7b22a4
			closeRuleTag[0] = 0;
Packit 7b22a4
		}
Packit 7b22a4
Packit 7b22a4
		printf("      
Packit 7b22a4
		//xmlAttrS("table",curTable); // not needed in full mode 
Packit 7b22a4
		//xmlAttrS("chain",argv[1]); // not needed in full mode 
Packit 7b22a4
		if (pcnt)
Packit 7b22a4
			xmlAttrS("packet-count", pcnt);
Packit 7b22a4
		if (bcnt)
Packit 7b22a4
			xmlAttrS("byte-count", bcnt);
Packit 7b22a4
		printf(">\n");
Packit 7b22a4
Packit 7b22a4
		strncpy(closeRuleTag, "      </rule>\n", XT_TABLE_MAXNAMELEN);
Packit 7b22a4
		closeRuleTag[XT_TABLE_MAXNAMELEN] = '\0';
Packit 7b22a4
Packit 7b22a4
		/* no point in writing out condition if there isn't one */
Packit 7b22a4
		if (argc >= 3 && !isTarget(argv[2])) {
Packit 7b22a4
			printf("       <conditions>\n");
Packit 7b22a4
			do_rule_part(NULL, NULL, -1, argc, argv, argvattr);
Packit 7b22a4
			printf("       </conditions>\n");
Packit 7b22a4
		}
Packit 7b22a4
	}
Packit 7b22a4
	/* Write out the action */
Packit 7b22a4
	//do_rule_part("action","arg",1,argc,argv,argvattr);
Packit 7b22a4
	if (!closeActionTag[0]) {
Packit 7b22a4
		printf("       <actions>\n");
Packit 7b22a4
		strncpy(closeActionTag, "       </actions>\n",
Packit 7b22a4
			XT_TABLE_MAXNAMELEN);
Packit 7b22a4
		closeActionTag[XT_TABLE_MAXNAMELEN] = '\0';
Packit 7b22a4
	}
Packit 7b22a4
	do_rule_part(NULL, NULL, 1, argc, argv, argvattr);
Packit 7b22a4
}
Packit 7b22a4
Packit 7b22a4
int
Packit 7b22a4
iptables_xml_main(int argc, char *argv[])
Packit 7b22a4
{
Packit 7b22a4
	struct argv_store last_rule = {}, cur_rule = {};
Packit 7b22a4
	char buffer[10240];
Packit 7b22a4
	int c;
Packit 7b22a4
	FILE *in;
Packit 7b22a4
Packit 7b22a4
	line = 0;
Packit 7b22a4
Packit 7b22a4
	xtables_set_params(&iptables_xml_globals);
Packit 7b22a4
	while ((c = getopt_long(argc, argv, "cvh", options, NULL)) != -1) {
Packit 7b22a4
		switch (c) {
Packit 7b22a4
		case 'c':
Packit 7b22a4
			combine = 1;
Packit 7b22a4
			break;
Packit 7b22a4
		case 'v':
Packit 7b22a4
			printf("xptables-xml\n");
Packit 7b22a4
			verbose = 1;
Packit 7b22a4
			break;
Packit 7b22a4
		case 'h':
Packit 7b22a4
			print_usage("iptables-xml", PACKAGE_VERSION);
Packit 7b22a4
			break;
Packit 7b22a4
		}
Packit 7b22a4
	}
Packit 7b22a4
Packit 7b22a4
	if (optind == argc - 1) {
Packit 7b22a4
		in = fopen(argv[optind], "re");
Packit 7b22a4
		if (!in) {
Packit 7b22a4
			fprintf(stderr, "Can't open %s: %s", argv[optind],
Packit 7b22a4
				strerror(errno));
Packit 7b22a4
			exit(1);
Packit 7b22a4
		}
Packit 7b22a4
	} else if (optind < argc) {
Packit 7b22a4
		fprintf(stderr, "Unknown arguments found on commandline");
Packit 7b22a4
		exit(1);
Packit 7b22a4
	} else
Packit 7b22a4
		in = stdin;
Packit 7b22a4
Packit 7b22a4
	printf("<iptables-rules version=\"1.0\">\n");
Packit 7b22a4
Packit 7b22a4
	/* Grab standard input. */
Packit 7b22a4
	while (fgets(buffer, sizeof(buffer), in)) {
Packit 7b22a4
		int ret = 0;
Packit 7b22a4
Packit 7b22a4
		line++;
Packit 7b22a4
Packit 7b22a4
		if (buffer[0] == '\n')
Packit 7b22a4
			continue;
Packit 7b22a4
		else if (buffer[0] == '#') {
Packit 7b22a4
			xmlComment(buffer);
Packit 7b22a4
			continue;
Packit 7b22a4
		}
Packit 7b22a4
Packit 7b22a4
		if (verbose) {
Packit 7b22a4
			printf("
Packit 7b22a4
			xmlCommentEscape(buffer);
Packit 7b22a4
			printf(" -->\n");
Packit 7b22a4
		}
Packit 7b22a4
Packit 7b22a4
		if ((strcmp(buffer, "COMMIT\n") == 0) && (curTable[0])) {
Packit 7b22a4
			DEBUGP("Calling commit\n");
Packit 7b22a4
			closeTable();
Packit 7b22a4
			ret = 1;
Packit 7b22a4
		} else if ((buffer[0] == '*')) {
Packit 7b22a4
			/* New table */
Packit 7b22a4
			char *table;
Packit 7b22a4
Packit 7b22a4
			table = strtok(buffer + 1, " \t\n");
Packit 7b22a4
			DEBUGP("line %u, table '%s'\n", line, table);
Packit 7b22a4
			if (!table)
Packit 7b22a4
				xtables_error(PARAMETER_PROBLEM,
Packit 7b22a4
					   "%s: line %u table name invalid\n",
Packit 7b22a4
					   prog_name, line);
Packit 7b22a4
Packit 7b22a4
			openTable(table);
Packit 7b22a4
Packit 7b22a4
			ret = 1;
Packit 7b22a4
		} else if ((buffer[0] == ':') && (curTable[0])) {
Packit 7b22a4
			/* New chain. */
Packit 7b22a4
			char *policy, *chain;
Packit 7b22a4
			struct xt_counters count;
Packit 7b22a4
			char *ctrs;
Packit 7b22a4
Packit 7b22a4
			chain = strtok(buffer + 1, " \t\n");
Packit 7b22a4
			DEBUGP("line %u, chain '%s'\n", line, chain);
Packit 7b22a4
			if (!chain)
Packit 7b22a4
				xtables_error(PARAMETER_PROBLEM,
Packit 7b22a4
					   "%s: line %u chain name invalid\n",
Packit 7b22a4
					   prog_name, line);
Packit 7b22a4
Packit 7b22a4
			DEBUGP("Creating new chain '%s'\n", chain);
Packit 7b22a4
Packit 7b22a4
			policy = strtok(NULL, " \t\n");
Packit 7b22a4
			DEBUGP("line %u, policy '%s'\n", line, policy);
Packit 7b22a4
			if (!policy)
Packit 7b22a4
				xtables_error(PARAMETER_PROBLEM,
Packit 7b22a4
					   "%s: line %u policy invalid\n",
Packit 7b22a4
					   prog_name, line);
Packit 7b22a4
Packit 7b22a4
			ctrs = strtok(NULL, " \t\n");
Packit 7b22a4
			parse_counters(ctrs, &count);
Packit 7b22a4
			saveChain(chain, policy, &count);
Packit 7b22a4
Packit 7b22a4
			ret = 1;
Packit 7b22a4
		} else if (curTable[0]) {
Packit 7b22a4
			unsigned int a;
Packit 7b22a4
			char *pcnt = NULL;
Packit 7b22a4
			char *bcnt = NULL;
Packit 7b22a4
			char *parsestart = buffer;
Packit 7b22a4
			char *chain = NULL;
Packit 7b22a4
Packit 7b22a4
			tokenize_rule_counters(&parsestart, &pcnt, &bcnt, line);
Packit 7b22a4
			add_param_to_argv(&cur_rule, parsestart, line);
Packit 7b22a4
Packit 7b22a4
			DEBUGP("calling do_command4(%u, argv, &%s, handle):\n",
Packit 7b22a4
			       cur_rule.argc, curTable);
Packit 7b22a4
			debug_print_argv(&cur_rule);
Packit 7b22a4
Packit 7b22a4
			for (a = 1; a < cur_rule.argc; a++) {
Packit 7b22a4
				if (strcmp(cur_rule.argv[a - 1], "-A"))
Packit 7b22a4
					continue;
Packit 7b22a4
				chain = cur_rule.argv[a];
Packit 7b22a4
				break;
Packit 7b22a4
			}
Packit 7b22a4
			if (!chain) {
Packit 7b22a4
				fprintf(stderr, "%s: line %u failed - no chain found\n",
Packit 7b22a4
					prog_name, line);
Packit 7b22a4
				exit(1);
Packit 7b22a4
			}
Packit 7b22a4
			needChain(chain);// Should we explicitly look for -A
Packit 7b22a4
			do_rule(pcnt, bcnt, cur_rule.argc, cur_rule.argv,
Packit 7b22a4
				cur_rule.argvattr, last_rule.argc, last_rule.argv);
Packit 7b22a4
Packit 7b22a4
			save_argv(&last_rule, &cur_rule);
Packit 7b22a4
			ret = 1;
Packit 7b22a4
		}
Packit 7b22a4
		if (!ret) {
Packit 7b22a4
			fprintf(stderr, "%s: line %u failed\n",
Packit 7b22a4
				prog_name, line);
Packit 7b22a4
			exit(1);
Packit 7b22a4
		}
Packit 7b22a4
	}
Packit 7b22a4
	if (curTable[0]) {
Packit 7b22a4
		fprintf(stderr, "%s: COMMIT expected at line %u\n",
Packit 7b22a4
			prog_name, line + 1);
Packit 7b22a4
		exit(1);
Packit 7b22a4
	}
Packit 7b22a4
Packit 7b22a4
	fclose(in);
Packit 7b22a4
	printf("</iptables-rules>\n");
Packit 7b22a4
	free_argv(&last_rule);
Packit 7b22a4
Packit 7b22a4
	return 0;
Packit 7b22a4
}