iptables-xml.c revision 9ee386a1b6d7704b259460152c959ab0e79e02aa
18d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez/* Code to convert iptables-save format to xml format, 28d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez * (C) 2006 Ufo Mechanic <azez@ufomechanic.net> 38d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez * based on iptables-restor (C) 2000-2002 by Harald Welte <laforge@gnumonks.org> 48d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez * based on previous code from Rusty Russell <rusty@linuxcare.com.au> 58d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez * 68d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez * This code is distributed under the terms of GNU GPL v2 78d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez * 88d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez * $Id: iptables-xml.c,v 1.4 2006/11/09 12:02:17 azez Exp $ 98d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez */ 108d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 118d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez#include <getopt.h> 128d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez#include <sys/errno.h> 138d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez#include <string.h> 148d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez#include <stdio.h> 158d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez#include <stdlib.h> 168d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez#include <stdarg.h> 178d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez#include "iptables.h" 188d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez#include "libiptc/libiptc.h" 198d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 208d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez#ifdef DEBUG 218d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez#define DEBUGP(x, args...) fprintf(stderr, x, ## args) 228d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez#else 238d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez#define DEBUGP(x, args...) 248d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez#endif 258d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 268d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez/* no need to link with iptables.o */ 278d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezconst char *program_name; 288d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezconst char *program_version; 298d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 30e78c69c8146c5dcd096ba13ac03d7a7bb90e3ea7Lutz Jaenicke#ifndef IPTABLES_MULTI 31e78c69c8146c5dcd096ba13ac03d7a7bb90e3ea7Lutz Jaenickeint line = 0; 32d884051d7dfa51ebe1a37e343af516b1bba6943dJan Engelhardtvoid exit_error(enum exittype status, const char *msg, ...) 338d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez{ 348d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez va_list args; 358d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 368d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez va_start(args, msg); 378d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez fprintf(stderr, "%s v%s: ", program_name, program_version); 388d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez vfprintf(stderr, msg, args); 398d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez va_end(args); 408d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez fprintf(stderr, "\n"); 418d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez /* On error paths, make sure that we don't leak memory */ 428d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez exit(status); 438d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez} 44e78c69c8146c5dcd096ba13ac03d7a7bb90e3ea7Lutz Jaenicke#endif 458d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 468d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezstatic void print_usage(const char *name, const char *version) 478d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez __attribute__ ((noreturn)); 488d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 498d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezstatic int verbose = 0; 508d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez/* Whether to combine actions of sequential rules with identical conditions */ 518d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezstatic int combine = 0; 528d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez/* Keeping track of external matches and targets. */ 538d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezstatic struct option options[] = { 548d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez {"verbose", 0, 0, 'v'}, 558d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez {"combine", 0, 0, 'c'}, 568d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez {"help", 0, 0, 'h'}, 579ee386a1b6d7704b259460152c959ab0e79e02aaMax Kellermann { .name = NULL } 588d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez}; 598d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 608d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezstatic void 618d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezprint_usage(const char *name, const char *version) 628d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez{ 638d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez fprintf(stderr, "Usage: %s [-c] [-v] [-h]\n" 648d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez " [--combine ]\n" 658d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez " [ --verbose ]\n" " [ --help ]\n", name); 668d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 678d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez exit(1); 688d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez} 698d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 70e78c69c8146c5dcd096ba13ac03d7a7bb90e3ea7Lutz Jaenickestatic int 718d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezparse_counters(char *string, struct ipt_counters *ctr) 728d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez{ 73b73691f9e67149deefbc2d2115d66dfc62264333Patrick McHardy u_int64_t *pcnt, *bcnt; 74b73691f9e67149deefbc2d2115d66dfc62264333Patrick McHardy 75b73691f9e67149deefbc2d2115d66dfc62264333Patrick McHardy if (string != NULL) { 76b73691f9e67149deefbc2d2115d66dfc62264333Patrick McHardy pcnt = &ctr->pcnt; 77b73691f9e67149deefbc2d2115d66dfc62264333Patrick McHardy bcnt = &ctr->bcnt; 788d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez return (sscanf 798d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez (string, "[%llu:%llu]", 80b73691f9e67149deefbc2d2115d66dfc62264333Patrick McHardy (unsigned long long *)pcnt, 81b73691f9e67149deefbc2d2115d66dfc62264333Patrick McHardy (unsigned long long *)bcnt) == 2); 82b73691f9e67149deefbc2d2115d66dfc62264333Patrick McHardy } else 838d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez return (0 == 2); 848d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez} 858d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 868d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez/* global new argv and argc */ 878d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezstatic char *newargv[255]; 889ee386a1b6d7704b259460152c959ab0e79e02aaMax Kellermannstatic unsigned newargc = 0; 898d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 908d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezstatic char *oldargv[255]; 919ee386a1b6d7704b259460152c959ab0e79e02aaMax Kellermannstatic unsigned oldargc = 0; 928d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 938d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez/* arg meta data, were they quoted, frinstance */ 948d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezstatic int newargvattr[255]; 958d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 968d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez#define IPT_CHAIN_MAXNAMELEN IPT_TABLE_MAXNAMELEN 978d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezchar closeActionTag[IPT_TABLE_MAXNAMELEN + 1]; 988d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezchar closeRuleTag[IPT_TABLE_MAXNAMELEN + 1]; 998d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezchar curTable[IPT_TABLE_MAXNAMELEN + 1]; 1008d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezchar curChain[IPT_CHAIN_MAXNAMELEN + 1]; 1018d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 1028d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azeztypedef struct chain 1038d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez{ 1048d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez char *chain; 1058d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez char *policy; 1068d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez struct ipt_counters count; 1078d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez int created; 1088d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez} chain; 1098d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 1108d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez#define maxChains 10240 /* max chains per table */ 1118d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezstatic chain chains[maxChains]; 1128d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezstatic int nextChain = 0; 1138d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 1148d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez/* funCtion adding one argument to newargv, updating newargc 1158d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez * returns true if argument added, false otherwise */ 1168d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezstatic int 1178d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezadd_argv(char *what, int quoted) 1188d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez{ 1198d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez DEBUGP("add_argv: %d %s\n", newargc, what); 1208d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (what && ((newargc + 1) < sizeof(newargv) / sizeof(char *))) { 1218d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez newargv[newargc] = strdup(what); 1228d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez newargvattr[newargc] = quoted; 1238d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez newargc++; 1248d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez return 1; 1258d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } else 1268d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez return 0; 1278d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez} 1288d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 1298d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezstatic void 1308d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezfree_argv(void) 1318d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez{ 1329ee386a1b6d7704b259460152c959ab0e79e02aaMax Kellermann unsigned i; 1338d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 1348d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez for (i = 0; i < newargc; i++) { 1358d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez free(newargv[i]); 1368d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez newargv[i] = NULL; 1378d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 1388d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez newargc = 0; 1398d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 1408d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez for (i = 0; i < oldargc; i++) { 1418d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez free(oldargv[i]); 1428d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez oldargv[i] = NULL; 1438d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 1448d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez oldargc = 0; 1458d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez} 1468d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 1478d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez/* save parsed rule for comparison with next rule 1488d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez to perform action agregation on duplicate conditions */ 1498d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezstatic void 1508d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezsave_argv(void) 1518d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez{ 1529ee386a1b6d7704b259460152c959ab0e79e02aaMax Kellermann unsigned i; 1538d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 1548d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez for (i = 0; i < oldargc; i++) 1558d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez free(oldargv[i]); 1568d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez oldargc = newargc; 1578d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez newargc = 0; 1588d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez for (i = 0; i < oldargc; i++) { 1598d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez oldargv[i] = newargv[i]; 1608d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez newargv[i] = NULL; 1618d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 1628d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez} 1638d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 1648d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez/* like puts but with xml encoding */ 1658d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezstatic void 1668d3eccb19a9c6fc006193d633b985205e350b9c5Amin AzezxmlEncode(char *text) 1678d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez{ 1688d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez while (text && *text) { 1698d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if ((unsigned char) (*text) >= 127) 1708d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf("&#%d;", (unsigned char) (*text)); 1718d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez else if (*text == '&') 1728d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf("&"); 1738d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez else if (*text == '<') 1748d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf("<"); 1758d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez else if (*text == '>') 1768d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf(">"); 1778d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez else if (*text == '"') 1788d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf("""); 1798d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez else 1808d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez putchar(*text); 1818d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez text++; 1828d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 1838d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez} 1848d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 1858d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez/* Output text as a comment, avoiding a double hyphen */ 1868d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezstatic void 1878d3eccb19a9c6fc006193d633b985205e350b9c5Amin AzezxmlCommentEscape(char *comment) 1888d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez{ 1898d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez int h_count = 0; 1908d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 1918d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez while (comment && *comment) { 1928d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (*comment == '-') { 1938d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez h_count++; 1948d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (h_count >= 2) { 1958d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez h_count = 0; 1968d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez putchar(' '); 1978d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 1988d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez putchar('*'); 1998d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 2008d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez /* strip trailing newline */ 2018d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (*comment == '\n' && *(comment + 1) == 0); 2028d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez else 2038d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez putchar(*comment); 2048d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez comment++; 2058d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 2068d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez} 2078d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 2088d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezstatic void 2098d3eccb19a9c6fc006193d633b985205e350b9c5Amin AzezxmlComment(char *comment) 2108d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez{ 2118d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf("<!-- "); 2128d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez xmlCommentEscape(comment); 2138d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf(" -->\n"); 2148d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez} 2158d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 2168d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezstatic void 2178d3eccb19a9c6fc006193d633b985205e350b9c5Amin AzezxmlAttrS(char *name, char *value) 2188d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez{ 2198d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf("%s=\"", name); 2208d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez xmlEncode(value); 2218d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf("\" "); 2228d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez} 2238d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 2248d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezstatic void 2258d3eccb19a9c6fc006193d633b985205e350b9c5Amin AzezxmlAttrI(char *name, long long int num) 2268d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez{ 2278d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf("%s=\"%lld\" ", name, num); 2288d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez} 2298d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 2308d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezstatic void 2319ee386a1b6d7704b259460152c959ab0e79e02aaMax KellermanncloseChain(void) 2328d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez{ 2338d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (curChain[0] == 0) 2348d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez return; 2358d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 2368d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (closeActionTag[0]) 2378d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf("%s\n", closeActionTag); 2388d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez closeActionTag[0] = 0; 2398d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (closeRuleTag[0]) 2408d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf("%s\n", closeRuleTag); 2418d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez closeRuleTag[0] = 0; 2428d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (curChain[0]) 2438d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf(" </chain>\n"); 2448d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez curChain[0] = 0; 2458d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez //lastRule[0]=0; 2468d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez} 2478d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 2488d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezstatic void 2498d3eccb19a9c6fc006193d633b985205e350b9c5Amin AzezopenChain(char *chain, char *policy, struct ipt_counters *ctr, char close) 2508d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez{ 2518d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez closeChain(); 2528d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 2538d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez strncpy(curChain, chain, IPT_CHAIN_MAXNAMELEN); 2548d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez curChain[IPT_CHAIN_MAXNAMELEN] = '\0'; 2558d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 2568d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf(" <chain "); 2578d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez xmlAttrS("name", curChain); 2588d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (strcmp(policy, "-") != 0) 2598d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez xmlAttrS("policy", policy); 2608d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez xmlAttrI("packet-count", (unsigned long long) ctr->pcnt); 2618d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez xmlAttrI("byte-count", (unsigned long long) ctr->bcnt); 2628d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (close) { 2638d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf("%c", close); 2648d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez curChain[0] = 0; 2658d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 2668d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf(">\n"); 2678d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez} 2688d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 2698d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezstatic int 2708d3eccb19a9c6fc006193d633b985205e350b9c5Amin AzezexistsChain(char *chain) 2718d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez{ 2728d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez /* open a saved chain */ 2738d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez int c = 0; 2748d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 2758d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (0 == strcmp(curChain, chain)) 2768d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez return 1; 2778d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez for (c = 0; c < nextChain; c++) 2788d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (chains[c].chain && strcmp(chains[c].chain, chain) == 0) 2798d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez return 1; 2808d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez return 0; 2818d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez} 2828d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 2838d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezstatic void 2848d3eccb19a9c6fc006193d633b985205e350b9c5Amin AzezneedChain(char *chain) 2858d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez{ 2868d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez /* open a saved chain */ 2878d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez int c = 0; 2888d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 2898d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (0 == strcmp(curChain, chain)) 2908d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez return; 2918d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 2928d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez for (c = 0; c < nextChain; c++) 2938d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (chains[c].chain && strcmp(chains[c].chain, chain) == 0) { 2948d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez openChain(chains[c].chain, chains[c].policy, 2958d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez &(chains[c].count), '\0'); 2968d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez /* And, mark it as done so we don't create 2978d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez an empty chain at table-end time */ 2988d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez chains[c].created = 1; 2998d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 3008d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez} 3018d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 3028d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezstatic void 3038d3eccb19a9c6fc006193d633b985205e350b9c5Amin AzezsaveChain(char *chain, char *policy, struct ipt_counters *ctr) 3048d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez{ 3058d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (nextChain >= maxChains) { 3068d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez exit_error(PARAMETER_PROBLEM, 3078d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez "%s: line %u chain name invalid\n", 3088d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez program_name, line); 3098d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez exit(1); 3108d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez }; 3118d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez chains[nextChain].chain = strdup(chain); 3128d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez chains[nextChain].policy = strdup(policy); 3138d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez chains[nextChain].count = *ctr; 3148d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez chains[nextChain].created = 0; 3158d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez nextChain++; 3168d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez} 3178d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 3188d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezstatic void 3199ee386a1b6d7704b259460152c959ab0e79e02aaMax KellermannfinishChains(void) 3208d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez{ 3218d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez int c; 3228d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 3238d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez for (c = 0; c < nextChain; c++) 3248d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (!chains[c].created) { 3258d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez openChain(chains[c].chain, chains[c].policy, 3268d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez &(chains[c].count), '/'); 3278d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez free(chains[c].chain); 3288d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez free(chains[c].policy); 3298d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 3308d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez nextChain = 0; 3318d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez} 3328d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 3338d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezstatic void 3349ee386a1b6d7704b259460152c959ab0e79e02aaMax KellermanncloseTable(void) 3358d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez{ 3368d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez closeChain(); 3378d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez finishChains(); 3388d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (curTable[0]) 3398d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf(" </table>\n"); 3408d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez curTable[0] = 0; 3418d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez} 3428d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 3438d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezstatic void 3448d3eccb19a9c6fc006193d633b985205e350b9c5Amin AzezopenTable(char *table) 3458d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez{ 3468d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez closeTable(); 3478d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 3488d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez strncpy(curTable, table, IPT_TABLE_MAXNAMELEN); 3498d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez curTable[IPT_TABLE_MAXNAMELEN] = '\0'; 3508d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 3518d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf(" <table "); 3528d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez xmlAttrS("name", curTable); 3538d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf(">\n"); 3548d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez} 3558d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 3568d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez// is char* -j --jump -g or --goto 3578d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezstatic int 3588d3eccb19a9c6fc006193d633b985205e350b9c5Amin AzezisTarget(char *arg) 3598d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez{ 3608d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez return ((arg) 3618d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez && (strcmp((arg), "-j") == 0 || strcmp((arg), "--jump") == 0 3628d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez || strcmp((arg), "-g") == 0 3638d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez || strcmp((arg), "--goto") == 0)); 3648d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez} 3658d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 3668e52815a55692d657aeca7f8ecf656cd65dcfce0Sam Liddicott// is it a terminating target like -j ACCEPT, etc 3678e52815a55692d657aeca7f8ecf656cd65dcfce0Sam Liddicott// (or I guess -j SNAT in nat table, but we don't check for that yet 3688e52815a55692d657aeca7f8ecf656cd65dcfce0Sam Liddicottstatic int 3698e52815a55692d657aeca7f8ecf656cd65dcfce0Sam LiddicottisTerminatingTarget(char *arg) 3708e52815a55692d657aeca7f8ecf656cd65dcfce0Sam Liddicott{ 3718e52815a55692d657aeca7f8ecf656cd65dcfce0Sam Liddicott return ((arg) 3728e52815a55692d657aeca7f8ecf656cd65dcfce0Sam Liddicott && (strcmp((arg), "ACCEPT") == 0 3738e52815a55692d657aeca7f8ecf656cd65dcfce0Sam Liddicott || strcmp((arg), "DROP") == 0 3748e52815a55692d657aeca7f8ecf656cd65dcfce0Sam Liddicott || strcmp((arg), "QUEUE") == 0 3758e52815a55692d657aeca7f8ecf656cd65dcfce0Sam Liddicott || strcmp((arg), "RETURN") == 0)); 3768e52815a55692d657aeca7f8ecf656cd65dcfce0Sam Liddicott} 3778e52815a55692d657aeca7f8ecf656cd65dcfce0Sam Liddicott 3788d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez// part=-1 means do conditions, part=1 means do rules, part=0 means do both 3798d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezstatic void 3808d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezdo_rule_part(char *leveltag1, char *leveltag2, int part, int argc, 3818d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez char *argv[], int argvattr[]) 3828d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez{ 3838d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez int arg = 1; // ignore leading -A 3848d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez char invert_next = 0; 3858d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez char *thisChain = NULL; 3868d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez char *spacer = ""; // space when needed to assemble arguments 3878d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez char *level1 = NULL; 3888d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez char *level2 = NULL; 3898d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez char *leveli1 = " "; 3908d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez char *leveli2 = " "; 3918d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 3928d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez#define CLOSE_LEVEL(LEVEL) \ 3938d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez do { \ 3948d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (level ## LEVEL) printf("</%s>\n", \ 3958d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez (leveltag ## LEVEL)?(leveltag ## LEVEL):(level ## LEVEL)); \ 3968d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez level ## LEVEL=NULL;\ 3978d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } while(0) 3988d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 3998d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez#define OPEN_LEVEL(LEVEL,TAG) \ 4008d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez do {\ 4018d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez level ## LEVEL=TAG;\ 4028d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (leveltag ## LEVEL) {\ 4038d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf("%s<%s ", (leveli ## LEVEL), \ 4048d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez (leveltag ## LEVEL));\ 4058d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez xmlAttrS("type", (TAG)); \ 4068d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } else printf("%s<%s ", (leveli ## LEVEL), (level ## LEVEL)); \ 4078d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } while(0) 4088d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 4098d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez thisChain = argv[arg++]; 4108d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 4118d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (part == 1) { /* skip */ 4128d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez /* use argvattr to tell which arguments were quoted 4138d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez to avoid comparing quoted arguments, like comments, to -j, */ 4148d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez while (arg < argc && (argvattr[arg] || !isTarget(argv[arg]))) 4158d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez arg++; 4168d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 4178d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 4188d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez /* Before we start, if the first arg is -[^-] and not -m or -j or -g 4198d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez then start a dummy <match> tag for old style built-in matches. 4208d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez We would do this in any case, but no need if it would be empty */ 4218d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (arg < argc && argv[arg][0] == '-' && !isTarget(argv[arg]) 4228d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez && strcmp(argv[arg], "-m") != 0) { 4238d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez OPEN_LEVEL(1, "match"); 4248d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf(">\n"); 4258d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 4268d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez while (arg < argc) { 4278d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez // If ! is followed by -* then apply to that else output as data 4288d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez // Stop, if we need to 4298d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (part == -1 && !argvattr[arg] && (isTarget(argv[arg]))) { 4308d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez break; 4318d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } else if (!argvattr[arg] && strcmp(argv[arg], "!") == 0) { 4328d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if ((arg + 1) < argc && argv[arg + 1][0] == '-') 4338d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez invert_next = '!'; 4348d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez else 4358d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf("%s%s", spacer, argv[arg]); 4368d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez spacer = " "; 4378d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } else if (!argvattr[arg] && isTarget(argv[arg]) 4388d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez && existsChain(argv[arg + 1]) 4398d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez && (2 + arg >= argc)) { 4408d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (!((1 + arg) < argc)) 4418d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez // no args to -j, -m or -g, ignore & finish loop 4428d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez break; 4438d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez CLOSE_LEVEL(2); 4448d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (level1) 4458d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf("%s", leveli1); 4468d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez CLOSE_LEVEL(1); 4478d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez spacer = ""; 4488d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez invert_next = 0; 4498d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (strcmp(argv[arg], "-g") == 0 4508d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez || strcmp(argv[arg], "--goto") == 0) { 4518d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez /* goto user chain */ 4528d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez OPEN_LEVEL(1, "goto"); 4538d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf(">\n"); 4548d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez arg++; 4558d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez OPEN_LEVEL(2, argv[arg]); 4568d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf("/>\n"); 4578d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez level2 = NULL; 4588d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } else { 4598d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez /* call user chain */ 4608d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez OPEN_LEVEL(1, "call"); 4618d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf(">\n"); 4628d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez arg++; 4638d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez OPEN_LEVEL(2, argv[arg]); 4648d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf("/>\n"); 4658d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez level2 = NULL; 4668d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 4678d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } else if (!argvattr[arg] 4688d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez && (isTarget(argv[arg]) 4698d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez || strcmp(argv[arg], "-m") == 0 4708d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez || strcmp(argv[arg], "--module") == 0)) { 4718d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (!((1 + arg) < argc)) 4728d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez // no args to -j, -m or -g, ignore & finish loop 4738d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez break; 4748d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez CLOSE_LEVEL(2); 4758d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (level1) 4768d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf("%s", leveli1); 4778d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez CLOSE_LEVEL(1); 4788d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez spacer = ""; 4798d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez invert_next = 0; 4808d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez arg++; 4818d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez OPEN_LEVEL(1, (argv[arg])); 4828d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez // Optimize case, can we close this tag already? 4838d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if ((arg + 1) >= argc || (!argvattr[arg + 1] 4848d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez && (isTarget(argv[arg + 1]) 4858d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez || strcmp(argv[arg + 1], 4868d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez "-m") == 0 4878d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez || strcmp(argv[arg + 1], 4888d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez "--module") == 4898d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 0))) { 4908d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf(" />\n"); 4918d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez level1 = NULL; 4928d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } else { 4938d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf(">\n"); 4948d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 4958d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } else if (!argvattr[arg] && argv[arg][0] == '-') { 4968d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez char *tag; 4978d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez CLOSE_LEVEL(2); 4988d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez // Skip past any - 4998d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez tag = argv[arg]; 5008d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez while (*tag == '-' && *tag) 5018d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez tag++; 5028d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 5038d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez spacer = ""; 5048d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez OPEN_LEVEL(2, tag); 5058d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (invert_next) 5068d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf(" invert=\"1\""); 5078d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez invert_next = 0; 5088d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 5098d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez // Optimize case, can we close this tag already? 5108d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (!((arg + 1) < argc) 5118d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez || (argv[arg + 1][0] == '-' /* NOT QUOTED */ )) { 5128d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf(" />\n"); 5138d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez level2 = NULL; 5148d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } else { 5158d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf(">"); 5168d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 5178d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } else { // regular data 5188d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez char *spaces = strchr(argv[arg], ' '); 5198d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf("%s", spacer); 5208d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (spaces || argvattr[arg]) 5218d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf("""); 5228d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez // if argv[arg] contains a space, enclose in quotes 5238d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez xmlEncode(argv[arg]); 5248d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (spaces || argvattr[arg]) 5258d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf("""); 5268d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez spacer = " "; 5278d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 5288d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez arg++; 5298d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 5308d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez CLOSE_LEVEL(2); 5318d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (level1) 5328d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf("%s", leveli1); 5338d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez CLOSE_LEVEL(1); 5348d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 5358d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez return; 5368d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez} 5378d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 5388d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezstatic int 5399ee386a1b6d7704b259460152c959ab0e79e02aaMax KellermanncompareRules(void) 5408d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez{ 5418d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez /* compare arguments up to -j or -g for match. 5428d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez NOTE: We don't want to combine actions if there were no criteria 5438d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez in each rule, or rules didn't have an action 5448d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez NOTE: Depends on arguments being in some kind of "normal" order which 5458d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez is the case when processing the ACTUAL output of actual iptables-save 5468d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez rather than a file merely in a compatable format */ 5478d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 5489ee386a1b6d7704b259460152c959ab0e79e02aaMax Kellermann unsigned old = 0; 5499ee386a1b6d7704b259460152c959ab0e79e02aaMax Kellermann unsigned new = 0; 5508d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 5518d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez int compare = 0; 5528d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 5538d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez while (new < newargc && old < oldargc) { 5548d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (isTarget(oldargv[old]) && isTarget(newargv[new])) { 5558e52815a55692d657aeca7f8ecf656cd65dcfce0Sam Liddicott /* if oldarg was a terminating action then it makes no sense 5568e52815a55692d657aeca7f8ecf656cd65dcfce0Sam Liddicott * to combine further actions into the same xml */ 5578e52815a55692d657aeca7f8ecf656cd65dcfce0Sam Liddicott if (((strcmp((oldargv[old]), "-j") == 0 5588e52815a55692d657aeca7f8ecf656cd65dcfce0Sam Liddicott || strcmp((oldargv[old]), "--jump") == 0) 5598e52815a55692d657aeca7f8ecf656cd65dcfce0Sam Liddicott && old+1 < oldargc 5608e52815a55692d657aeca7f8ecf656cd65dcfce0Sam Liddicott && isTerminatingTarget(oldargv[old+1]) ) 5618e52815a55692d657aeca7f8ecf656cd65dcfce0Sam Liddicott || strcmp((oldargv[old]), "-g") == 0 5628e52815a55692d657aeca7f8ecf656cd65dcfce0Sam Liddicott || strcmp((oldargv[old]), "--goto") == 0 ) { 5638e52815a55692d657aeca7f8ecf656cd65dcfce0Sam Liddicott /* Previous rule had terminating action */ 5648e52815a55692d657aeca7f8ecf656cd65dcfce0Sam Liddicott compare = 0; 5658e52815a55692d657aeca7f8ecf656cd65dcfce0Sam Liddicott } else { 5668e52815a55692d657aeca7f8ecf656cd65dcfce0Sam Liddicott compare = 1; 5678e52815a55692d657aeca7f8ecf656cd65dcfce0Sam Liddicott } 5688d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez break; 5698d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 5708d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez // break when old!=new 5718d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (strcmp(oldargv[old], newargv[new]) != 0) { 5728d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez compare = 0; 5738d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez break; 5748d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 5758d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 5768d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez old++; 5778d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez new++; 5788d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 5798d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez // We won't match unless both rules had a target. 5808d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez // This means we don't combine target-less rules, which is good 5818d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 5828d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez return compare == 1; 5838d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez} 5848d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 5858d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez/* has a nice parsed rule starting with -A */ 5868d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezstatic void 5878d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezdo_rule(char *pcnt, char *bcnt, int argc, char *argv[], int argvattr[]) 5888d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez{ 5898d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez /* are these conditions the same as the previous rule? 5908d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez * If so, skip arg straight to -j or -g */ 5918d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (combine && argc > 2 && !isTarget(argv[2]) && compareRules()) { 5928d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez xmlComment("Combine action from next rule"); 5938d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } else { 5948d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 5958d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (closeActionTag[0]) { 5968d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf("%s\n", closeActionTag); 5978d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez closeActionTag[0] = 0; 5988d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 5998d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (closeRuleTag[0]) { 6008d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf("%s\n", closeRuleTag); 6018d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez closeRuleTag[0] = 0; 6028d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 6038d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 6048d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf(" <rule "); 6058d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez //xmlAttrS("table",curTable); // not needed in full mode 6068d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez //xmlAttrS("chain",argv[1]); // not needed in full mode 6078d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (pcnt) 6088d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez xmlAttrS("packet-count", pcnt); 6098d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (bcnt) 6108d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez xmlAttrS("byte-count", bcnt); 6118d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf(">\n"); 6128d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 6138d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez strncpy(closeRuleTag, " </rule>\n", IPT_TABLE_MAXNAMELEN); 6148d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez closeRuleTag[IPT_TABLE_MAXNAMELEN] = '\0'; 6158d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 6168d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez /* no point in writing out condition if there isn't one */ 6178d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (argc >= 3 && !isTarget(argv[2])) { 6188d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf(" <conditions>\n"); 6198d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez do_rule_part(NULL, NULL, -1, argc, argv, argvattr); 6208d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf(" </conditions>\n"); 6218d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 6228d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 6238d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez /* Write out the action */ 6248d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez //do_rule_part("action","arg",1,argc,argv,argvattr); 6258d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (!closeActionTag[0]) { 6268d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf(" <actions>\n"); 6278d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez strncpy(closeActionTag, " </actions>\n", 6288d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez IPT_TABLE_MAXNAMELEN); 6298d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez closeActionTag[IPT_TABLE_MAXNAMELEN] = '\0'; 6308d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 6318d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez do_rule_part(NULL, NULL, 1, argc, argv, argvattr); 6328d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez} 6338d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 6348d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 6358d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez#ifdef IPTABLES_MULTI 6368d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezint 637e78c69c8146c5dcd096ba13ac03d7a7bb90e3ea7Lutz Jaenickeiptables_xml_main(int argc, char *argv[]) 6388d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez#else 6398d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezint 6408d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azezmain(int argc, char *argv[]) 6418d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez#endif 6428d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez{ 6438d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez char buffer[10240]; 6448d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez int c; 6458d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez FILE *in; 6468d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 6478d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez program_name = "iptables-xml"; 6488d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez program_version = IPTABLES_VERSION; 6498d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez line = 0; 6508d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 6518d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez while ((c = getopt_long(argc, argv, "cvh", options, NULL)) != -1) { 6528d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez switch (c) { 6538d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez case 'c': 6548d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez combine = 1; 6558d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez break; 6568d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez case 'v': 6578d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf("xptables-xml\n"); 6588d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez verbose = 1; 6598d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez break; 6608d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez case 'h': 6618d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez print_usage("iptables-xml", IPTABLES_VERSION); 6628d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez break; 6638d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 6648d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 6658d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 6668d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (optind == argc - 1) { 6678d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez in = fopen(argv[optind], "r"); 6688d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (!in) { 6698d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez fprintf(stderr, "Can't open %s: %s", argv[optind], 6708d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez strerror(errno)); 6718d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez exit(1); 6728d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 6738d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } else if (optind < argc) { 6748d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez fprintf(stderr, "Unknown arguments found on commandline"); 6758d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez exit(1); 6768d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } else 6778d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez in = stdin; 6788d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 6798d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf("<iptables-rules version=\"1.0\">\n"); 6808d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 6818d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez /* Grab standard input. */ 6828d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez while (fgets(buffer, sizeof(buffer), in)) { 6838d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez int ret = 0; 6848d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 6858d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez line++; 6868d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 6878d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (buffer[0] == '\n') 6888d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez continue; 6898d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez else if (buffer[0] == '#') { 6908d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez xmlComment(buffer); 6918d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez continue; 6928d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 6938d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 6948d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (verbose) { 6958d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf("<!-- line %d ", line); 6968d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez xmlCommentEscape(buffer); 6978d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf(" -->\n"); 6988d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 6998d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 7008d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if ((strcmp(buffer, "COMMIT\n") == 0) && (curTable[0])) { 7018d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez DEBUGP("Calling commit\n"); 7028d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez closeTable(); 7038d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez ret = 1; 7048d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } else if ((buffer[0] == '*')) { 7058d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez /* New table */ 7068d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez char *table; 7078d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 7088d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez table = strtok(buffer + 1, " \t\n"); 7098d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez DEBUGP("line %u, table '%s'\n", line, table); 7108d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (!table) { 7118d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez exit_error(PARAMETER_PROBLEM, 7128d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez "%s: line %u table name invalid\n", 7138d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez program_name, line); 7148d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez exit(1); 7158d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 7168d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez openTable(table); 7178d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 7188d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez ret = 1; 7198d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } else if ((buffer[0] == ':') && (curTable[0])) { 7208d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez /* New chain. */ 7218d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez char *policy, *chain; 7228d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez struct ipt_counters count; 7238d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez char *ctrs; 7248d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 7258d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez chain = strtok(buffer + 1, " \t\n"); 7268d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez DEBUGP("line %u, chain '%s'\n", line, chain); 7278d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (!chain) { 7288d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez exit_error(PARAMETER_PROBLEM, 7298d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez "%s: line %u chain name invalid\n", 7308d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez program_name, line); 7318d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez exit(1); 7328d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 7338d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 7348d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez DEBUGP("Creating new chain '%s'\n", chain); 7358d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 7368d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez policy = strtok(NULL, " \t\n"); 7378d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez DEBUGP("line %u, policy '%s'\n", line, policy); 7388d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (!policy) { 7398d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez exit_error(PARAMETER_PROBLEM, 7408d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez "%s: line %u policy invalid\n", 7418d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez program_name, line); 7428d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez exit(1); 7438d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 7448d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 7458d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez ctrs = strtok(NULL, " \t\n"); 7468d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez parse_counters(ctrs, &count); 7478d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez saveChain(chain, policy, &count); 7488d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 7498d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez ret = 1; 7508d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } else if (curTable[0]) { 7519ee386a1b6d7704b259460152c959ab0e79e02aaMax Kellermann unsigned a; 7528d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez char *ptr = buffer; 7538d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez char *pcnt = NULL; 7548d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez char *bcnt = NULL; 7558d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez char *parsestart; 7568d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez char *chain = NULL; 7578d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 7588d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez /* the parser */ 7598d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez char *param_start, *curchar; 7608d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez int quote_open, quoted; 7618d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 7628d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez /* reset the newargv */ 7638d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez newargc = 0; 7648d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 7658d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (buffer[0] == '[') { 7668d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez /* we have counters in our input */ 7678d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez ptr = strchr(buffer, ']'); 7688d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (!ptr) 7698d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez exit_error(PARAMETER_PROBLEM, 7708d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez "Bad line %u: need ]\n", 7718d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez line); 7728d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 7738d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez pcnt = strtok(buffer + 1, ":"); 7748d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (!pcnt) 7758d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez exit_error(PARAMETER_PROBLEM, 7768d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez "Bad line %u: need :\n", 7778d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez line); 7788d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 7798d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez bcnt = strtok(NULL, "]"); 7808d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (!bcnt) 7818d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez exit_error(PARAMETER_PROBLEM, 7828d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez "Bad line %u: need ]\n", 7838d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez line); 7848d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 7858d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez /* start command parsing after counter */ 7868d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez parsestart = ptr + 1; 7878d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } else { 7888d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez /* start command parsing at start of line */ 7898d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez parsestart = buffer; 7908d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 7918d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 7928d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 7938d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez /* This is a 'real' parser crafted in artist mode 7948d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez * not hacker mode. If the author can live with that 7958d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez * then so can everyone else */ 7968d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 7978d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez quote_open = 0; 7988d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez /* We need to know which args were quoted so we 7998d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez can preserve quote */ 8008d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez quoted = 0; 8018d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez param_start = parsestart; 8028d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 8038d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez for (curchar = parsestart; *curchar; curchar++) { 8048d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (*curchar == '"') { 8058d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez /* quote_open cannot be true if there 8068d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez * was no previous character. Thus, 8078d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez * curchar-1 has to be within bounds */ 8088d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (quote_open && 8098d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez *(curchar - 1) != '\\') { 8108d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez quote_open = 0; 8118d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez *curchar = ' '; 8128d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } else { 8138d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez quote_open = 1; 8148d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez quoted = 1; 8158d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez param_start++; 8168d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 8178d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 8188d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (*curchar == ' ' 8198d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez || *curchar == '\t' || *curchar == '\n') { 8208d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez char param_buffer[1024]; 8218d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez int param_len = curchar - param_start; 8228d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 8238d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (quote_open) 8248d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez continue; 8258d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 8268d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (!param_len) { 8278d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez /* two spaces? */ 8288d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez param_start++; 8298d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez continue; 8308d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 8318d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 8328d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez /* end of one parameter */ 8338d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez strncpy(param_buffer, param_start, 8348d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez param_len); 8358d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez *(param_buffer + param_len) = '\0'; 8368d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 8378d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez /* check if table name specified */ 8388d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (!strncmp(param_buffer, "-t", 3) 8398d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez || !strncmp(param_buffer, 8408d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez "--table", 8)) { 8418d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez exit_error(PARAMETER_PROBLEM, 8428d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez "Line %u seems to have a " 8438d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez "-t table option.\n", 8448d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez line); 8458d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez exit(1); 8468d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 8478d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 8488d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez add_argv(param_buffer, quoted); 8498d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (newargc >= 2 8508d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez && 0 == 8518d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez strcmp(newargv[newargc - 2], "-A")) 8528d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez chain = newargv[newargc - 1]; 8538d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez quoted = 0; 8548d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez param_start += param_len + 1; 8558d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } else { 8568d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez /* regular character, skip */ 8578d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 8588d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 8598d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 8608d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez DEBUGP("calling do_command(%u, argv, &%s, handle):\n", 8618d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez newargc, curTable); 8628d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 8638d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez for (a = 0; a < newargc; a++) 8648d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez DEBUGP("argv[%u]: %s\n", a, newargv[a]); 8658d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 8668d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez needChain(chain);// Should we explicitly look for -A 8678d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez do_rule(pcnt, bcnt, newargc, newargv, newargvattr); 8688d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 8698d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez save_argv(); 8708d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez ret = 1; 8718d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 8728d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (!ret) { 8738d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez fprintf(stderr, "%s: line %u failed\n", 8748d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez program_name, line); 8758d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez exit(1); 8768d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 8778d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 8788d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez if (curTable[0]) { 8798d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez fprintf(stderr, "%s: COMMIT expected at line %u\n", 8808d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez program_name, line + 1); 8818d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez exit(1); 8828d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez } 8838d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 8848d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez printf("</iptables-rules>\n"); 8858d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez free_argv(); 8868d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez 8878d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez return 0; 8888d3eccb19a9c6fc006193d633b985205e350b9c5Amin Azez} 889