xshared.c revision 780607f8b040a47cd2d4775376e2d30f567dc049
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> 9f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt#include <xtables.h> 10f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt#include "xshared.h" 11f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt 12f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt/* 13f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt * Print out any special helps. A user might like to be able to add a --help 14f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt * to the commandline, and see expected results. So we call help for all 15f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt * specified matches and targets. 16f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt */ 17f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardtvoid print_extension_helps(const struct xtables_target *t, 18f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt const struct xtables_rule_match *m) 19f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt{ 20f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt for (; t != NULL; t = t->next) { 21f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt if (t->used) { 22f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt printf("\n"); 23f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt if (t->help == NULL) 24f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt printf("%s does not take any options\n", 25f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt t->name); 26f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt else 27f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt t->help(); 28f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt } 29f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt } 30f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt for (; m != NULL; m = m->next) { 31f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt printf("\n"); 32f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt if (m->match->help == NULL) 33f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt printf("%s does not take any options\n", 34f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt m->match->name); 35f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt else 36f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt m->match->help(); 37f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt } 38f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt} 39f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt 40f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardtconst char * 41f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardtproto_to_name(uint8_t proto, int nolookup) 42f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt{ 43f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt unsigned int i; 44f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt 45f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt if (proto && !nolookup) { 46f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt struct protoent *pent = getprotobynumber(proto); 47f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt if (pent) 48f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt return pent->p_name; 49f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt } 50f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt 51f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt for (i = 0; xtables_chain_protos[i].name != NULL; ++i) 52f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt if (xtables_chain_protos[i].num == proto) 53f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt return xtables_chain_protos[i].name; 54f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt 55f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt return NULL; 56f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt} 57f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt 58acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardtstatic struct xtables_match * 59f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardtfind_proto(const char *pname, enum xtables_tryload tryload, 60f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt int nolookup, struct xtables_rule_match **matches) 61f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt{ 62f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt unsigned int proto; 63f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt 64f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt if (xtables_strtoui(pname, NULL, &proto, 0, UINT8_MAX)) { 65f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt const char *protoname = proto_to_name(proto, nolookup); 66f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt 67f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt if (protoname) 68f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt return xtables_find_match(protoname, tryload, matches); 69f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt } else 70f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt return xtables_find_match(pname, tryload, matches); 71f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt 72f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt return NULL; 73f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt} 74acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt 75acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt/* 76acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * Some explanations (after four different bugs in 3 different releases): If 77acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * we encounter a parameter, that has not been parsed yet, it's not an option 78acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * of an explicitly loaded match or a target. However, we support implicit 79acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * loading of the protocol match extension. '-p tcp' means 'l4 proto 6' and at 80acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * the same time 'load tcp protocol match on demand if we specify --dport'. 81acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * 82acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * To make this work, we need to make sure: 83acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * - the parameter has not been parsed by a match (m above) 84acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * - a protocol has been specified 85acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * - the protocol extension has not been loaded yet, or is loaded and unused 86acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * [think of ip6tables-restore!] 87acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * - the protocol extension can be successively loaded 88acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt */ 89acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardtstatic bool should_load_proto(struct iptables_command_state *cs) 90acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt{ 91acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt if (cs->protocol == NULL) 92acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt return false; 93acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt if (find_proto(cs->protocol, XTF_DONT_LOAD, 94ee52e00adfb10250e1828b94e43d9482bb201827Jan Engelhardt cs->options & OPT_NUMERIC, NULL) == NULL) 95acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt return true; 967c816547270050ccc29fb07c9e62c230e015c8e3Changli Gao return !cs->proto_used; 97acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt} 98acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt 99acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardtstruct xtables_match *load_proto(struct iptables_command_state *cs) 100acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt{ 101acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt if (!should_load_proto(cs)) 102acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt return NULL; 103acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt return find_proto(cs->protocol, XTF_TRY_LOAD, 104acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt cs->options & OPT_NUMERIC, &cs->matches); 105acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt} 1069cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek 107780607f8b040a47cd2d4775376e2d30f567dc049Jan Engelhardtint command_default(struct iptables_command_state *cs, 108780607f8b040a47cd2d4775376e2d30f567dc049Jan Engelhardt struct xtables_globals *gl) 109449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt{ 110449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt struct xtables_rule_match *matchp; 111449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt struct xtables_match *m; 112449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt 113449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt if (cs->target != NULL && 114449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt (cs->target->parse != NULL || cs->target->x6_parse != NULL) && 115449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt cs->c >= cs->target->option_offset && 116449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt cs->c < cs->target->option_offset + XT_OPTION_OFFSET_SCALE) { 117449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt xtables_option_tpcall(cs->c, cs->argv, cs->invert, 118449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt cs->target, &cs->fw); 119780607f8b040a47cd2d4775376e2d30f567dc049Jan Engelhardt return 0; 120449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt } 121449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt 122449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt for (matchp = cs->matches; matchp; matchp = matchp->next) { 123449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt m = matchp->match; 124449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt 125449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt if (matchp->completed || 126449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt (m->x6_parse == NULL && m->parse == NULL)) 127449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt continue; 128449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt if (cs->c < matchp->match->option_offset || 129449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt cs->c >= matchp->match->option_offset + XT_OPTION_OFFSET_SCALE) 130449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt continue; 131449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt xtables_option_mpcall(cs->c, cs->argv, cs->invert, m, &cs->fw); 132780607f8b040a47cd2d4775376e2d30f567dc049Jan Engelhardt return 0; 133449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt } 134449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt 135449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt /* Try loading protocol */ 136449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt m = load_proto(cs); 137449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt if (m != NULL) { 138449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt size_t size; 139449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt 140449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt cs->proto_used = 1; 141449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt 142449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt size = XT_ALIGN(sizeof(struct ip6t_entry_match)) + m->size; 143449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt 144449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt m->m = xtables_calloc(1, size); 145449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt m->m->u.match_size = size; 146449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt strcpy(m->m->u.user.name, m->name); 147449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt m->m->u.user.revision = m->revision; 148449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt if (m->init != NULL) 149449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt m->init(m->m); 150449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt 151449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt if (m->x6_options != NULL) 152449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt gl->opts = xtables_options_xfrm(gl->orig_opts, 153449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt gl->opts, 154449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt m->x6_options, 155449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt &m->option_offset); 156449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt else 157449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt gl->opts = xtables_merge_options(gl->orig_opts, 158449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt gl->opts, 159449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt m->extra_opts, 160449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt &m->option_offset); 161449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt if (gl->opts == NULL) 162449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt xtables_error(OTHER_PROBLEM, "can't alloc memory!"); 163449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt optind--; 164780607f8b040a47cd2d4775376e2d30f567dc049Jan Engelhardt /* Indicate to rerun getopt *immediately* */ 165780607f8b040a47cd2d4775376e2d30f567dc049Jan Engelhardt return 1; 166449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt } 167449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt 168449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt if (cs->c == ':') 169449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt xtables_error(PARAMETER_PROBLEM, "option \"%s\" " 170449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt "requires an argument", cs->argv[optind-1]); 171449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt if (cs->c == '?') 172449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt xtables_error(PARAMETER_PROBLEM, "unknown option " 173449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt "\"%s\"", cs->argv[optind-1]); 174449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt xtables_error(PARAMETER_PROBLEM, "Unknown arg \"%s\"", optarg); 175780607f8b040a47cd2d4775376e2d30f567dc049Jan Engelhardt return 0; 176449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt} 177449cdd6bcc8d1867bbd26ecbcae9832ab01eb04aJan Engelhardt 1789cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanekstatic mainfunc_t subcmd_get(const char *cmd, const struct subcommand *cb) 1799cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek{ 1809cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek for (; cb->name != NULL; ++cb) 1819cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek if (strcmp(cb->name, cmd) == 0) 1829cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek return cb->main; 1839cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek return NULL; 1849cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek} 1859cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek 1869cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanekint subcmd_main(int argc, char **argv, const struct subcommand *cb) 1879cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek{ 1889cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek const char *cmd = basename(*argv); 1899cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek mainfunc_t f = subcmd_get(cmd, cb); 1909cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek 1919cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek if (f == NULL && argc > 1) { 1929cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek /* 1939cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek * Unable to find a main method for our command name? 1949cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek * Let's try again with the first argument! 1959cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek */ 1969cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek ++argv; 1979cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek --argc; 1989cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek f = subcmd_get(*argv, cb); 1999cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek } 2009cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek 2019cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek /* now we should have a valid function pointer */ 2029cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek if (f != NULL) 2039cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek return f(argc, argv); 2049cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek 2059cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek fprintf(stderr, "ERROR: No valid subcommand given.\nValid subcommands:\n"); 2069cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek for (; cb->name != NULL; ++cb) 2079cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek fprintf(stderr, " * %s\n", cb->name); 2089cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek exit(EXIT_FAILURE); 2099cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek} 210