1449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt#include <getopt.h> 29cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek#include <libgen.h> 3f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt#include <netdb.h> 4acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt#include <stdbool.h> 5f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt#include <stdint.h> 6f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt#include <stdio.h> 79cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek#include <stdlib.h> 89cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek#include <string.h> 993587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester#include <sys/socket.h> 1093587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester#include <sys/un.h> 1193587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester#include <unistd.h> 12f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt#include <xtables.h> 13f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt#include "xshared.h" 14f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt 1593587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester#define XT_SOCKET_NAME "xtables" 1693587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester#define XT_SOCKET_LEN 8 1793587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester 18f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt/* 19f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt * Print out any special helps. A user might like to be able to add a --help 20f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt * to the commandline, and see expected results. So we call help for all 21f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt * specified matches and targets. 22f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt */ 23f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardtvoid print_extension_helps(const struct xtables_target *t, 24f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt const struct xtables_rule_match *m) 25f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt{ 26f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt for (; t != NULL; t = t->next) { 27f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt if (t->used) { 28f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt printf("\n"); 29f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt if (t->help == NULL) 30f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt printf("%s does not take any options\n", 31f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt t->name); 32f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt else 33f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt t->help(); 34f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt } 35f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt } 36f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt for (; m != NULL; m = m->next) { 37f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt printf("\n"); 38f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt if (m->match->help == NULL) 39f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt printf("%s does not take any options\n", 40f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt m->match->name); 41f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt else 42f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt m->match->help(); 43f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt } 44f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt} 45f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt 46f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardtconst char * 47f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardtproto_to_name(uint8_t proto, int nolookup) 48f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt{ 49f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt unsigned int i; 50f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt 51f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt if (proto && !nolookup) { 52f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt struct protoent *pent = getprotobynumber(proto); 53f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt if (pent) 54f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt return pent->p_name; 55f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt } 56f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt 57f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt for (i = 0; xtables_chain_protos[i].name != NULL; ++i) 58f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt if (xtables_chain_protos[i].num == proto) 59f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt return xtables_chain_protos[i].name; 60f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt 61f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt return NULL; 62f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt} 63f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt 64acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardtstatic struct xtables_match * 65f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardtfind_proto(const char *pname, enum xtables_tryload tryload, 66f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt int nolookup, struct xtables_rule_match **matches) 67f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt{ 68f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt unsigned int proto; 69f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt 70f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt if (xtables_strtoui(pname, NULL, &proto, 0, UINT8_MAX)) { 71f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt const char *protoname = proto_to_name(proto, nolookup); 72f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt 73f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt if (protoname) 74f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt return xtables_find_match(protoname, tryload, matches); 75f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt } else 76f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt return xtables_find_match(pname, tryload, matches); 77f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt 78f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt return NULL; 79f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt} 80acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt 81acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt/* 82acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * Some explanations (after four different bugs in 3 different releases): If 83acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * we encounter a parameter, that has not been parsed yet, it's not an option 84acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * of an explicitly loaded match or a target. However, we support implicit 85acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * loading of the protocol match extension. '-p tcp' means 'l4 proto 6' and at 86acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * the same time 'load tcp protocol match on demand if we specify --dport'. 87acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * 88acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * To make this work, we need to make sure: 89acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * - the parameter has not been parsed by a match (m above) 90acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * - a protocol has been specified 91acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * - the protocol extension has not been loaded yet, or is loaded and unused 92acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * [think of ip6tables-restore!] 93acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * - the protocol extension can be successively loaded 94acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt */ 95acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardtstatic bool should_load_proto(struct iptables_command_state *cs) 96acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt{ 97acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt if (cs->protocol == NULL) 98acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt return false; 99acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt if (find_proto(cs->protocol, XTF_DONT_LOAD, 100ee52e00adfb10250e1828b94e43d9482bb201827Jan Engelhardt cs->options & OPT_NUMERIC, NULL) == NULL) 101acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt return true; 1027c816547270050ccc29fb07c9e62c230e015c8e3Changli Gao return !cs->proto_used; 103acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt} 104acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt 105acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardtstruct xtables_match *load_proto(struct iptables_command_state *cs) 106acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt{ 107acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt if (!should_load_proto(cs)) 108acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt return NULL; 109acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt return find_proto(cs->protocol, XTF_TRY_LOAD, 110acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt cs->options & OPT_NUMERIC, &cs->matches); 111acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt} 1129cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek 113780607f8b040a47cd2d4775376e2d30f567dc049Jan Engelhardtint command_default(struct iptables_command_state *cs, 114780607f8b040a47cd2d4775376e2d30f567dc049Jan Engelhardt struct xtables_globals *gl) 115449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt{ 116449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt struct xtables_rule_match *matchp; 117449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt struct xtables_match *m; 118449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt 119449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt if (cs->target != NULL && 120449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt (cs->target->parse != NULL || cs->target->x6_parse != NULL) && 121449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt cs->c >= cs->target->option_offset && 122449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt cs->c < cs->target->option_offset + XT_OPTION_OFFSET_SCALE) { 123449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt xtables_option_tpcall(cs->c, cs->argv, cs->invert, 124449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt cs->target, &cs->fw); 125780607f8b040a47cd2d4775376e2d30f567dc049Jan Engelhardt return 0; 126449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt } 127449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt 128449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt for (matchp = cs->matches; matchp; matchp = matchp->next) { 129449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt m = matchp->match; 130449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt 131449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt if (matchp->completed || 132449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt (m->x6_parse == NULL && m->parse == NULL)) 133449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt continue; 134449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt if (cs->c < matchp->match->option_offset || 135449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt cs->c >= matchp->match->option_offset + XT_OPTION_OFFSET_SCALE) 136449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt continue; 137449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt xtables_option_mpcall(cs->c, cs->argv, cs->invert, m, &cs->fw); 138780607f8b040a47cd2d4775376e2d30f567dc049Jan Engelhardt return 0; 139449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt } 140449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt 141449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt /* Try loading protocol */ 142449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt m = load_proto(cs); 143449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt if (m != NULL) { 144449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt size_t size; 145449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt 146449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt cs->proto_used = 1; 147449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt 14814da56743c6cdf25da35b7b5ca7a5d201771990dJan Engelhardt size = XT_ALIGN(sizeof(struct xt_entry_match)) + m->size; 149449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt 150449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt m->m = xtables_calloc(1, size); 151449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt m->m->u.match_size = size; 152449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt strcpy(m->m->u.user.name, m->name); 153449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt m->m->u.user.revision = m->revision; 15414190986f87301b18bcc473c842bd82d778d87a2Jan Engelhardt xs_init_match(m); 155449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt 156449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt if (m->x6_options != NULL) 157449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt gl->opts = xtables_options_xfrm(gl->orig_opts, 158449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt gl->opts, 159449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt m->x6_options, 160449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt &m->option_offset); 161449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt else 162449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt gl->opts = xtables_merge_options(gl->orig_opts, 163449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt gl->opts, 164449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt m->extra_opts, 165449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt &m->option_offset); 166449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt if (gl->opts == NULL) 167449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt xtables_error(OTHER_PROBLEM, "can't alloc memory!"); 168449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt optind--; 169780607f8b040a47cd2d4775376e2d30f567dc049Jan Engelhardt /* Indicate to rerun getopt *immediately* */ 170780607f8b040a47cd2d4775376e2d30f567dc049Jan Engelhardt return 1; 171449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt } 172449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt 173449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt if (cs->c == ':') 174449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt xtables_error(PARAMETER_PROBLEM, "option \"%s\" " 175449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt "requires an argument", cs->argv[optind-1]); 176449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt if (cs->c == '?') 177449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt xtables_error(PARAMETER_PROBLEM, "unknown option " 178449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt "\"%s\"", cs->argv[optind-1]); 179449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt xtables_error(PARAMETER_PROBLEM, "Unknown arg \"%s\"", optarg); 180780607f8b040a47cd2d4775376e2d30f567dc049Jan Engelhardt return 0; 181449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt} 182449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt 1839cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanekstatic mainfunc_t subcmd_get(const char *cmd, const struct subcommand *cb) 1849cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek{ 1859cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek for (; cb->name != NULL; ++cb) 1869cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek if (strcmp(cb->name, cmd) == 0) 1879cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek return cb->main; 1889cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek return NULL; 1899cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek} 1909cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek 1919cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanekint subcmd_main(int argc, char **argv, const struct subcommand *cb) 1929cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek{ 1939cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek const char *cmd = basename(*argv); 1949cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek mainfunc_t f = subcmd_get(cmd, cb); 1959cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek 1969cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek if (f == NULL && argc > 1) { 1979cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek /* 1989cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek * Unable to find a main method for our command name? 1999cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek * Let's try again with the first argument! 2009cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek */ 2019cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek ++argv; 2029cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek --argc; 2039cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek f = subcmd_get(*argv, cb); 2049cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek } 2059cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek 2069cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek /* now we should have a valid function pointer */ 2079cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek if (f != NULL) 2089cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek return f(argc, argv); 2099cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek 2109cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek fprintf(stderr, "ERROR: No valid subcommand given.\nValid subcommands:\n"); 2119cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek for (; cb->name != NULL; ++cb) 2129cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek fprintf(stderr, " * %s\n", cb->name); 2139cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek exit(EXIT_FAILURE); 2149cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek} 21514190986f87301b18bcc473c842bd82d778d87a2Jan Engelhardt 21614190986f87301b18bcc473c842bd82d778d87a2Jan Engelhardtvoid xs_init_target(struct xtables_target *target) 21714190986f87301b18bcc473c842bd82d778d87a2Jan Engelhardt{ 2182dba676b68ef842025f3afecba26cb0b2ae4c09bJan Engelhardt if (target->udata_size != 0) { 2192dba676b68ef842025f3afecba26cb0b2ae4c09bJan Engelhardt free(target->udata); 2202dba676b68ef842025f3afecba26cb0b2ae4c09bJan Engelhardt target->udata = calloc(1, target->udata_size); 2212dba676b68ef842025f3afecba26cb0b2ae4c09bJan Engelhardt if (target->udata == NULL) 2222dba676b68ef842025f3afecba26cb0b2ae4c09bJan Engelhardt xtables_error(RESOURCE_PROBLEM, "malloc"); 2232dba676b68ef842025f3afecba26cb0b2ae4c09bJan Engelhardt } 22414190986f87301b18bcc473c842bd82d778d87a2Jan Engelhardt if (target->init != NULL) 22514190986f87301b18bcc473c842bd82d778d87a2Jan Engelhardt target->init(target->t); 22614190986f87301b18bcc473c842bd82d778d87a2Jan Engelhardt} 22714190986f87301b18bcc473c842bd82d778d87a2Jan Engelhardt 22814190986f87301b18bcc473c842bd82d778d87a2Jan Engelhardtvoid xs_init_match(struct xtables_match *match) 22914190986f87301b18bcc473c842bd82d778d87a2Jan Engelhardt{ 2302dba676b68ef842025f3afecba26cb0b2ae4c09bJan Engelhardt if (match->udata_size != 0) { 2312dba676b68ef842025f3afecba26cb0b2ae4c09bJan Engelhardt /* 2322dba676b68ef842025f3afecba26cb0b2ae4c09bJan Engelhardt * As soon as a subsequent instance of the same match 2332dba676b68ef842025f3afecba26cb0b2ae4c09bJan Engelhardt * is used, e.g. "-m time -m time", the first instance 2342dba676b68ef842025f3afecba26cb0b2ae4c09bJan Engelhardt * is no longer reachable anyway, so we can free udata. 2352dba676b68ef842025f3afecba26cb0b2ae4c09bJan Engelhardt * Same goes for target. 2362dba676b68ef842025f3afecba26cb0b2ae4c09bJan Engelhardt */ 2372dba676b68ef842025f3afecba26cb0b2ae4c09bJan Engelhardt free(match->udata); 2382dba676b68ef842025f3afecba26cb0b2ae4c09bJan Engelhardt match->udata = calloc(1, match->udata_size); 2392dba676b68ef842025f3afecba26cb0b2ae4c09bJan Engelhardt if (match->udata == NULL) 2402dba676b68ef842025f3afecba26cb0b2ae4c09bJan Engelhardt xtables_error(RESOURCE_PROBLEM, "malloc"); 2412dba676b68ef842025f3afecba26cb0b2ae4c09bJan Engelhardt } 24214190986f87301b18bcc473c842bd82d778d87a2Jan Engelhardt if (match->init != NULL) 24314190986f87301b18bcc473c842bd82d778d87a2Jan Engelhardt match->init(match->m); 24414190986f87301b18bcc473c842bd82d778d87a2Jan Engelhardt} 24593587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester 24693587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oesterbool xtables_lock(bool wait) 24793587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester{ 24893587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester int i = 0, ret, xt_socket; 24993587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester struct sockaddr_un xt_addr; 25093587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester 25193587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester memset(&xt_addr, 0, sizeof(xt_addr)); 25293587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester xt_addr.sun_family = AF_UNIX; 25393587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester strcpy(xt_addr.sun_path+1, XT_SOCKET_NAME); 25493587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester xt_socket = socket(AF_UNIX, SOCK_STREAM, 0); 25593587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester /* If we can't even create a socket, fall back to prior (lockless) behavior */ 25693587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester if (xt_socket < 0) 25793587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester return true; 25893587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester 25993587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester while (1) { 26093587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester ret = bind(xt_socket, (struct sockaddr*)&xt_addr, 26193587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester offsetof(struct sockaddr_un, sun_path)+XT_SOCKET_LEN); 26293587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester if (ret == 0) 26393587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester return true; 26493587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester else if (wait == false) 26593587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester return false; 26693587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester if (++i % 2 == 0) 26793587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester fprintf(stderr, "Another app is currently holding the xtables lock; " 26893587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester "waiting for it to exit...\n"); 26993587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester sleep(1); 27093587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester } 27193587a04d0f2511e108bbc4d87a8b9d28a5c5dd8Phil Oester} 272