xshared.c revision 9cc4f24e72f87ca191c2e723e7cd293f6477481c
19cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek#include <libgen.h> 2f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt#include <netdb.h> 3acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt#include <stdbool.h> 4f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt#include <stdint.h> 5f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt#include <stdio.h> 69cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek#include <stdlib.h> 79cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek#include <string.h> 8f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt#include <xtables.h> 9f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt#include "xshared.h" 10f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt 11f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt/* 12f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt * Print out any special helps. A user might like to be able to add a --help 13f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt * to the commandline, and see expected results. So we call help for all 14f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt * specified matches and targets. 15f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt */ 16f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardtvoid print_extension_helps(const struct xtables_target *t, 17f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt const struct xtables_rule_match *m) 18f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt{ 19f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt for (; t != NULL; t = t->next) { 20f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt if (t->used) { 21f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt printf("\n"); 22f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt if (t->help == NULL) 23f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt printf("%s does not take any options\n", 24f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt t->name); 25f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt else 26f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt t->help(); 27f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt } 28f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt } 29f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt for (; m != NULL; m = m->next) { 30f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt printf("\n"); 31f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt if (m->match->help == NULL) 32f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt printf("%s does not take any options\n", 33f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt m->match->name); 34f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt else 35f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt m->match->help(); 36f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt } 37f89c1716a7743ca6e2e6164d3b64c15b2e285e1eJan Engelhardt} 38f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt 39f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardtconst char * 40f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardtproto_to_name(uint8_t proto, int nolookup) 41f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt{ 42f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt unsigned int i; 43f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt 44f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt if (proto && !nolookup) { 45f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt struct protoent *pent = getprotobynumber(proto); 46f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt if (pent) 47f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt return pent->p_name; 48f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt } 49f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt 50f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt for (i = 0; xtables_chain_protos[i].name != NULL; ++i) 51f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt if (xtables_chain_protos[i].num == proto) 52f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt return xtables_chain_protos[i].name; 53f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt 54f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt return NULL; 55f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt} 56f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt 57acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardtstatic struct xtables_match * 58f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardtfind_proto(const char *pname, enum xtables_tryload tryload, 59f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt int nolookup, struct xtables_rule_match **matches) 60f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt{ 61f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt unsigned int proto; 62f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt 63f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt if (xtables_strtoui(pname, NULL, &proto, 0, UINT8_MAX)) { 64f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt const char *protoname = proto_to_name(proto, nolookup); 65f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt 66f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt if (protoname) 67f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt return xtables_find_match(protoname, tryload, matches); 68f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt } else 69f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt return xtables_find_match(pname, tryload, matches); 70f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt 71f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt return NULL; 72f6992cbb211a42f776333fe65dfad49f17455a3fJan Engelhardt} 73acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt 74acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt/* 75acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * Some explanations (after four different bugs in 3 different releases): If 76acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * we encounter a parameter, that has not been parsed yet, it's not an option 77acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * of an explicitly loaded match or a target. However, we support implicit 78acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * loading of the protocol match extension. '-p tcp' means 'l4 proto 6' and at 79acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * the same time 'load tcp protocol match on demand if we specify --dport'. 80acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * 81acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * To make this work, we need to make sure: 82acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * - the parameter has not been parsed by a match (m above) 83acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * - a protocol has been specified 84acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * - the protocol extension has not been loaded yet, or is loaded and unused 85acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * [think of ip6tables-restore!] 86acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt * - the protocol extension can be successively loaded 87acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt */ 88acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardtstatic bool should_load_proto(struct iptables_command_state *cs) 89acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt{ 90acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt if (cs->protocol == NULL) 91acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt return false; 92acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt if (find_proto(cs->protocol, XTF_DONT_LOAD, 93ee52e00adfb10250e1828b94e43d9482bb201827Jan Engelhardt cs->options & OPT_NUMERIC, NULL) == NULL) 94acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt return true; 95acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt return cs->proto_used; 96acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt} 97acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt 98acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardtstruct xtables_match *load_proto(struct iptables_command_state *cs) 99acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt{ 100acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt if (!should_load_proto(cs)) 101acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt return NULL; 102acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt return find_proto(cs->protocol, XTF_TRY_LOAD, 103acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt cs->options & OPT_NUMERIC, &cs->matches); 104acef6043f647806096c41294b00472f6ce7462d7Jan Engelhardt} 1059cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek 1069cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanekstatic mainfunc_t subcmd_get(const char *cmd, const struct subcommand *cb) 1079cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek{ 1089cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek for (; cb->name != NULL; ++cb) 1099cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek if (strcmp(cb->name, cmd) == 0) 1109cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek return cb->main; 1119cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek return NULL; 1129cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek} 1139cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek 1149cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanekint subcmd_main(int argc, char **argv, const struct subcommand *cb) 1159cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek{ 1169cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek const char *cmd = basename(*argv); 1179cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek mainfunc_t f = subcmd_get(cmd, cb); 1189cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek 1199cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek if (f == NULL && argc > 1) { 1209cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek /* 1219cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek * Unable to find a main method for our command name? 1229cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek * Let's try again with the first argument! 1239cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek */ 1249cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek ++argv; 1259cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek --argc; 1269cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek f = subcmd_get(*argv, cb); 1279cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek } 1289cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek 1299cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek /* now we should have a valid function pointer */ 1309cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek if (f != NULL) 1319cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek return f(argc, argv); 1329cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek 1339cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek fprintf(stderr, "ERROR: No valid subcommand given.\nValid subcommands:\n"); 1349cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek for (; cb->name != NULL; ++cb) 1359cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek fprintf(stderr, " * %s\n", cb->name); 1369cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek exit(EXIT_FAILURE); 1379cc4f24e72f87ca191c2e723e7cd293f6477481cStefan Tomanek} 138