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