| Jan Engelhardt | f6992cb | 2011-02-07 03:05:49 +0100 | [diff] [blame] | 1 | #include <netdb.h> |
| Jan Engelhardt | acef604 | 2011-02-07 03:18:53 +0100 | [diff] [blame] | 2 | #include <stdbool.h> |
| Jan Engelhardt | f6992cb | 2011-02-07 03:05:49 +0100 | [diff] [blame] | 3 | #include <stdint.h> |
| Jan Engelhardt | f89c171 | 2009-06-12 20:48:52 +0200 | [diff] [blame] | 4 | #include <stdio.h> |
| 5 | #include <xtables.h> |
| 6 | #include "xshared.h" |
| 7 | |
| 8 | /* |
| 9 | * Print out any special helps. A user might like to be able to add a --help |
| 10 | * to the commandline, and see expected results. So we call help for all |
| 11 | * specified matches and targets. |
| 12 | */ |
| 13 | void print_extension_helps(const struct xtables_target *t, |
| 14 | const struct xtables_rule_match *m) |
| 15 | { |
| 16 | for (; t != NULL; t = t->next) { |
| 17 | if (t->used) { |
| 18 | printf("\n"); |
| 19 | if (t->help == NULL) |
| 20 | printf("%s does not take any options\n", |
| 21 | t->name); |
| 22 | else |
| 23 | t->help(); |
| 24 | } |
| 25 | } |
| 26 | for (; m != NULL; m = m->next) { |
| 27 | printf("\n"); |
| 28 | if (m->match->help == NULL) |
| 29 | printf("%s does not take any options\n", |
| 30 | m->match->name); |
| 31 | else |
| 32 | m->match->help(); |
| 33 | } |
| 34 | } |
| Jan Engelhardt | f6992cb | 2011-02-07 03:05:49 +0100 | [diff] [blame] | 35 | |
| 36 | const char * |
| 37 | proto_to_name(uint8_t proto, int nolookup) |
| 38 | { |
| 39 | unsigned int i; |
| 40 | |
| 41 | if (proto && !nolookup) { |
| 42 | struct protoent *pent = getprotobynumber(proto); |
| 43 | if (pent) |
| 44 | return pent->p_name; |
| 45 | } |
| 46 | |
| 47 | for (i = 0; xtables_chain_protos[i].name != NULL; ++i) |
| 48 | if (xtables_chain_protos[i].num == proto) |
| 49 | return xtables_chain_protos[i].name; |
| 50 | |
| 51 | return NULL; |
| 52 | } |
| 53 | |
| Jan Engelhardt | acef604 | 2011-02-07 03:18:53 +0100 | [diff] [blame] | 54 | static struct xtables_match * |
| Jan Engelhardt | f6992cb | 2011-02-07 03:05:49 +0100 | [diff] [blame] | 55 | find_proto(const char *pname, enum xtables_tryload tryload, |
| 56 | int nolookup, struct xtables_rule_match **matches) |
| 57 | { |
| 58 | unsigned int proto; |
| 59 | |
| 60 | if (xtables_strtoui(pname, NULL, &proto, 0, UINT8_MAX)) { |
| 61 | const char *protoname = proto_to_name(proto, nolookup); |
| 62 | |
| 63 | if (protoname) |
| 64 | return xtables_find_match(protoname, tryload, matches); |
| 65 | } else |
| 66 | return xtables_find_match(pname, tryload, matches); |
| 67 | |
| 68 | return NULL; |
| 69 | } |
| Jan Engelhardt | acef604 | 2011-02-07 03:18:53 +0100 | [diff] [blame] | 70 | |
| 71 | /* |
| 72 | * Some explanations (after four different bugs in 3 different releases): If |
| 73 | * we encounter a parameter, that has not been parsed yet, it's not an option |
| 74 | * of an explicitly loaded match or a target. However, we support implicit |
| 75 | * loading of the protocol match extension. '-p tcp' means 'l4 proto 6' and at |
| 76 | * the same time 'load tcp protocol match on demand if we specify --dport'. |
| 77 | * |
| 78 | * To make this work, we need to make sure: |
| 79 | * - the parameter has not been parsed by a match (m above) |
| 80 | * - a protocol has been specified |
| 81 | * - the protocol extension has not been loaded yet, or is loaded and unused |
| 82 | * [think of ip6tables-restore!] |
| 83 | * - the protocol extension can be successively loaded |
| 84 | */ |
| 85 | static bool should_load_proto(struct iptables_command_state *cs) |
| 86 | { |
| 87 | if (cs->protocol == NULL) |
| 88 | return false; |
| 89 | if (find_proto(cs->protocol, XTF_DONT_LOAD, |
| Jan Engelhardt | ee52e00 | 2011-03-01 02:45:34 +0100 | [diff] [blame] | 90 | cs->options & OPT_NUMERIC, NULL) == NULL) |
| Jan Engelhardt | acef604 | 2011-02-07 03:18:53 +0100 | [diff] [blame] | 91 | return true; |
| 92 | return cs->proto_used; |
| 93 | } |
| 94 | |
| 95 | struct xtables_match *load_proto(struct iptables_command_state *cs) |
| 96 | { |
| 97 | if (!should_load_proto(cs)) |
| 98 | return NULL; |
| 99 | return find_proto(cs->protocol, XTF_TRY_LOAD, |
| 100 | cs->options & OPT_NUMERIC, &cs->matches); |
| 101 | } |