libxt_policy.c revision bf97128c7262f17a02fec41cdae75b472ba77f88
1ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta/* Shared library add-on to iptables to add policy support. */ 2ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#include <stdio.h> 3ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#include <netdb.h> 4ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#include <string.h> 5ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#include <stdlib.h> 6ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#include <syslog.h> 7ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#include <getopt.h> 8ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#include <netdb.h> 9ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#include <errno.h> 10ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#include <sys/socket.h> 11ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#include <netinet/in.h> 12ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#include <arpa/inet.h> 13ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#include <xtables.h> 14ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta 15ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta#include <linux/netfilter/xt_policy.h> 16ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta 17ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta/* 18ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta * HACK: global pointer to current matchinfo for making 19ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta * final checks and adjustments in final_check. 20ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta */ 21ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptastatic struct xt_policy_info *policy_info; 22ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta 23ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptastatic void policy_help(void) 24ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta{ 25ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta printf( 26ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta"policy match options:\n" 27ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta" --dir in|out match policy applied during decapsulation/\n" 28ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta" policy to be applied during encapsulation\n" 29ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta" --pol none|ipsec match policy\n" 30ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta" --strict match entire policy instead of single element\n" 31ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta" at any position\n" 32ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta"[!] --reqid reqid match reqid\n" 33ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta"[!] --spi spi match SPI\n" 34ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta"[!] --proto proto match protocol (ah/esp/ipcomp)\n" 35ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta"[!] --mode mode match mode (transport/tunnel)\n" 36ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta"[!] --tunnel-src addr/mask match tunnel source\n" 37ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta"[!] --tunnel-dst addr/mask match tunnel destination\n" 38ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta" --next begin next element in policy\n"); 39ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta} 40ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta 41ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptastatic const struct option policy_opts[] = 42ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta{ 43ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta { 44ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta .name = "dir", 45ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta .has_arg = 1, 46ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta .val = '1', 47ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta }, 48ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta { 49ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta .name = "pol", 50ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta .has_arg = 1, 51ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta .val = '2', 52ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta }, 53ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta { 54ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta .name = "strict", 55ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta .val = '3' 56ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta }, 57ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta { 58ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta .name = "reqid", 59ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta .has_arg = 1, 60ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta .val = '4', 61ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta }, 62ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta { 63ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta .name = "spi", 64ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta .has_arg = 1, 65ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta .val = '5' 66ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta }, 67ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta { 68ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta .name = "tunnel-src", 69ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta .has_arg = 1, 70ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta .val = '6' 71ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta }, 72ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta { 73ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta .name = "tunnel-dst", 74ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta .has_arg = 1, 75ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta .val = '7' 76ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta }, 77ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta { 78ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta .name = "proto", 79ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta .has_arg = 1, 80ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta .val = '8' 81ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta }, 82ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta { 83ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta .name = "mode", 84ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta .has_arg = 1, 85ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta .val = '9' 86ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta }, 87ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta { 88ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta .name = "next", 89ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta .val = 'a' 90ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta }, 91ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta { .name = NULL } 92ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta}; 93ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta 94ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptastatic int parse_direction(char *s) 95ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta{ 96ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta if (strcmp(s, "in") == 0) 97ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta return XT_POLICY_MATCH_IN; 98ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta if (strcmp(s, "out") == 0) 99ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta return XT_POLICY_MATCH_OUT; 100ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta xtables_error(PARAMETER_PROBLEM, "policy_match: invalid dir \"%s\"", s); 101ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta} 102ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta 103ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptastatic int parse_policy(char *s) 104ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta{ 105ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta if (strcmp(s, "none") == 0) 106ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta return XT_POLICY_MATCH_NONE; 107ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta if (strcmp(s, "ipsec") == 0) 108ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta return 0; 109ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta xtables_error(PARAMETER_PROBLEM, "policy match: invalid policy \"%s\"", s); 110ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta} 111ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta 112ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptastatic int parse_mode(char *s) 113ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta{ 114ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta if (strcmp(s, "transport") == 0) 115ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta return XT_POLICY_MODE_TRANSPORT; 116ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta if (strcmp(s, "tunnel") == 0) 117ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta return XT_POLICY_MODE_TUNNEL; 118ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta xtables_error(PARAMETER_PROBLEM, "policy match: invalid mode \"%s\"", s); 119ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta} 120ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta 121ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Guptastatic int policy_parse(int c, char **argv, int invert, unsigned int *flags, 122ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta struct xt_policy_info *info, uint8_t family) 123ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta{ 124ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta struct xt_policy_elem *e = &info->pol[info->len]; 125ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta struct in_addr *addr = NULL, mask; 126ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta struct in6_addr *addr6 = NULL, mask6; 127ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta unsigned int naddr = 0, num; 128ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta int mode; 129ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta 130ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta xtables_check_inverse(optarg, &invert, &optind, 0, argv); 131ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta 132ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta switch (c) { 133ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta case '1': 134ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta if (info->flags & (XT_POLICY_MATCH_IN | XT_POLICY_MATCH_OUT)) 135ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta xtables_error(PARAMETER_PROBLEM, 136ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta "policy match: double --dir option"); 137ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta if (invert) 138ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta xtables_error(PARAMETER_PROBLEM, 139ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta "policy match: can't invert --dir option"); 140ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta 141ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta info->flags |= parse_direction(optarg); 142ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta break; 143ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta case '2': 144ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta if (invert) 145ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta xtables_error(PARAMETER_PROBLEM, 146ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta "policy match: can't invert --policy option"); 147ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta 148ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta info->flags |= parse_policy(optarg); 149ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta break; 150ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta case '3': 151ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta if (info->flags & XT_POLICY_MATCH_STRICT) 152ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta xtables_error(PARAMETER_PROBLEM, 153ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta "policy match: double --strict option"); 154ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta 155ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta if (invert) 156ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta xtables_error(PARAMETER_PROBLEM, 157ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta "policy match: can't invert --strict option"); 158ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta 159ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta info->flags |= XT_POLICY_MATCH_STRICT; 160ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta break; 161ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta case '4': 162ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta if (e->match.reqid) 163ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta xtables_error(PARAMETER_PROBLEM, 164ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta "policy match: double --reqid option"); 165ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta 166ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta e->match.reqid = 1; 167ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta e->invert.reqid = invert; 168ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX)) 169ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta xtables_param_act(XTF_BAD_VALUE, "policy", "--spi", optarg); 170ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta e->reqid = num; 171ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta break; 172ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta case '5': 173ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta if (e->match.spi) 174ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta xtables_error(PARAMETER_PROBLEM, 175ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta "policy match: double --spi option"); 176ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta 177ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta e->match.spi = 1; 178ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta e->invert.spi = invert; 179ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX)) 180ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta xtables_param_act(XTF_BAD_VALUE, "policy", "--spi", optarg); 181ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta e->spi = num; 182ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta break; 183ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta case '6': 184ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta if (e->match.saddr) 185ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta xtables_error(PARAMETER_PROBLEM, 186ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta "policy match: double --tunnel-src option"); 187ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta 188ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta if (family == NFPROTO_IPV6) 189ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta xtables_ip6parse_any(optarg, &addr6, &mask6, &naddr); 190ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta else 191ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta xtables_ipparse_any(optarg, &addr, &mask, &naddr); 192ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta if (naddr > 1) 193ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta xtables_error(PARAMETER_PROBLEM, 194ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta "policy match: name resolves to multiple IPs"); 195ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta 196ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta e->match.saddr = 1; 197ce24765fe7620c34e8d88ed4f826c8a6917582b2Hemant Gupta e->invert.saddr = invert; 198 if (family == NFPROTO_IPV6) { 199 memcpy(&e->saddr.a6, addr6, sizeof(*addr6)); 200 memcpy(&e->smask.a6, &mask6, sizeof(mask6)); 201 } else { 202 e->saddr.a4 = addr[0]; 203 e->smask.a4 = mask; 204 } 205 break; 206 case '7': 207 if (e->match.daddr) 208 xtables_error(PARAMETER_PROBLEM, 209 "policy match: double --tunnel-dst option"); 210 211 if (family == NFPROTO_IPV6) 212 xtables_ip6parse_any(optarg, &addr6, &mask6, &naddr); 213 else 214 xtables_ipparse_any(optarg, &addr, &mask, &naddr); 215 if (naddr > 1) 216 xtables_error(PARAMETER_PROBLEM, 217 "policy match: name resolves to multiple IPs"); 218 219 e->match.daddr = 1; 220 e->invert.daddr = invert; 221 if (family == NFPROTO_IPV6) { 222 memcpy(&e->daddr.a6, addr6, sizeof(*addr6)); 223 memcpy(&e->dmask.a6, &mask6, sizeof(mask6)); 224 } else { 225 e->daddr.a4 = addr[0]; 226 e->dmask.a4 = mask; 227 } 228 break; 229 case '8': 230 if (e->match.proto) 231 xtables_error(PARAMETER_PROBLEM, 232 "policy match: double --proto option"); 233 234 e->proto = xtables_parse_protocol(optarg); 235 if (e->proto != IPPROTO_AH && e->proto != IPPROTO_ESP && 236 e->proto != IPPROTO_COMP) 237 xtables_error(PARAMETER_PROBLEM, 238 "policy match: protocol must ah/esp/ipcomp"); 239 e->match.proto = 1; 240 e->invert.proto = invert; 241 break; 242 case '9': 243 if (e->match.mode) 244 xtables_error(PARAMETER_PROBLEM, 245 "policy match: double --mode option"); 246 247 mode = parse_mode(optarg); 248 e->match.mode = 1; 249 e->invert.mode = invert; 250 e->mode = mode; 251 break; 252 case 'a': 253 if (invert) 254 xtables_error(PARAMETER_PROBLEM, 255 "policy match: can't invert --next option"); 256 257 if (++info->len == XT_POLICY_MAX_ELEM) 258 xtables_error(PARAMETER_PROBLEM, 259 "policy match: maximum policy depth reached"); 260 break; 261 default: 262 return 0; 263 } 264 265 policy_info = info; 266 return 1; 267} 268 269static int policy4_parse(int c, char **argv, int invert, unsigned int *flags, 270 const void *entry, struct xt_entry_match **match) 271{ 272 return policy_parse(c, argv, invert, flags, (void *)(*match)->data, 273 NFPROTO_IPV4); 274} 275 276static int policy6_parse(int c, char **argv, int invert, unsigned int *flags, 277 const void *entry, struct xt_entry_match **match) 278{ 279 return policy_parse(c, argv, invert, flags, (void *)(*match)->data, 280 NFPROTO_IPV6); 281} 282 283static void policy_check(unsigned int flags) 284{ 285 struct xt_policy_info *info = policy_info; 286 struct xt_policy_elem *e; 287 int i; 288 289 if (info == NULL) 290 xtables_error(PARAMETER_PROBLEM, 291 "policy match: no parameters given"); 292 293 if (!(info->flags & (XT_POLICY_MATCH_IN | XT_POLICY_MATCH_OUT))) 294 xtables_error(PARAMETER_PROBLEM, 295 "policy match: neither --in nor --out specified"); 296 297 if (info->flags & XT_POLICY_MATCH_NONE) { 298 if (info->flags & XT_POLICY_MATCH_STRICT) 299 xtables_error(PARAMETER_PROBLEM, 300 "policy match: policy none but --strict given"); 301 302 if (info->len != 0) 303 xtables_error(PARAMETER_PROBLEM, 304 "policy match: policy none but policy given"); 305 } else 306 info->len++; /* increase len by 1, no --next after last element */ 307 308 if (!(info->flags & XT_POLICY_MATCH_STRICT) && info->len > 1) 309 xtables_error(PARAMETER_PROBLEM, 310 "policy match: multiple elements but no --strict"); 311 312 for (i = 0; i < info->len; i++) { 313 e = &info->pol[i]; 314 315 if (info->flags & XT_POLICY_MATCH_STRICT && 316 !(e->match.reqid || e->match.spi || e->match.saddr || 317 e->match.daddr || e->match.proto || e->match.mode)) 318 xtables_error(PARAMETER_PROBLEM, 319 "policy match: empty policy element"); 320 321 if ((e->match.saddr || e->match.daddr) 322 && ((e->mode == XT_POLICY_MODE_TUNNEL && e->invert.mode) || 323 (e->mode == XT_POLICY_MODE_TRANSPORT && !e->invert.mode))) 324 xtables_error(PARAMETER_PROBLEM, 325 "policy match: --tunnel-src/--tunnel-dst " 326 "is only valid in tunnel mode"); 327 } 328} 329 330static void print_mode(const char *prefix, u_int8_t mode, int numeric) 331{ 332 printf("%smode ", prefix); 333 334 switch (mode) { 335 case XT_POLICY_MODE_TRANSPORT: 336 printf("transport "); 337 break; 338 case XT_POLICY_MODE_TUNNEL: 339 printf("tunnel "); 340 break; 341 default: 342 printf("??? "); 343 break; 344 } 345} 346 347static void print_proto(const char *prefix, u_int8_t proto, int numeric) 348{ 349 struct protoent *p = NULL; 350 351 printf("%sproto ", prefix); 352 if (!numeric) 353 p = getprotobynumber(proto); 354 if (p != NULL) 355 printf("%s ", p->p_name); 356 else 357 printf("%u ", proto); 358} 359 360#define PRINT_INVERT(x) \ 361do { \ 362 if (x) \ 363 printf("! "); \ 364} while(0) 365 366static void print_entry(const char *prefix, const struct xt_policy_elem *e, 367 bool numeric, uint8_t family) 368{ 369 if (e->match.reqid) { 370 PRINT_INVERT(e->invert.reqid); 371 printf("%sreqid %u ", prefix, e->reqid); 372 } 373 if (e->match.spi) { 374 PRINT_INVERT(e->invert.spi); 375 printf("%sspi 0x%x ", prefix, e->spi); 376 } 377 if (e->match.proto) { 378 PRINT_INVERT(e->invert.proto); 379 print_proto(prefix, e->proto, numeric); 380 } 381 if (e->match.mode) { 382 PRINT_INVERT(e->invert.mode); 383 print_mode(prefix, e->mode, numeric); 384 } 385 if (e->match.daddr) { 386 PRINT_INVERT(e->invert.daddr); 387 if (family == NFPROTO_IPV6) 388 printf("%stunnel-dst %s%s ", prefix, 389 xtables_ip6addr_to_numeric(&e->daddr.a6), 390 xtables_ip6mask_to_numeric(&e->dmask.a6)); 391 else 392 printf("%stunnel-dst %s%s ", prefix, 393 xtables_ipaddr_to_numeric(&e->daddr.a4), 394 xtables_ipmask_to_numeric(&e->dmask.a4)); 395 } 396 if (e->match.saddr) { 397 PRINT_INVERT(e->invert.saddr); 398 if (family == NFPROTO_IPV6) 399 printf("%stunnel-src %s%s ", prefix, 400 xtables_ip6addr_to_numeric(&e->saddr.a6), 401 xtables_ip6mask_to_numeric(&e->smask.a6)); 402 else 403 printf("%stunnel-src %s%s ", prefix, 404 xtables_ipaddr_to_numeric(&e->saddr.a4), 405 xtables_ipmask_to_numeric(&e->smask.a4)); 406 } 407} 408 409static void print_flags(char *prefix, const struct xt_policy_info *info) 410{ 411 if (info->flags & XT_POLICY_MATCH_IN) 412 printf("%sdir in ", prefix); 413 else 414 printf("%sdir out ", prefix); 415 416 if (info->flags & XT_POLICY_MATCH_NONE) 417 printf("%spol none ", prefix); 418 else 419 printf("%spol ipsec ", prefix); 420 421 if (info->flags & XT_POLICY_MATCH_STRICT) 422 printf("%sstrict ", prefix); 423} 424 425static void policy4_print(const void *ip, const struct xt_entry_match *match, 426 int numeric) 427{ 428 const struct xt_policy_info *info = (void *)match->data; 429 unsigned int i; 430 431 printf("policy match "); 432 print_flags("", info); 433 for (i = 0; i < info->len; i++) { 434 if (info->len > 1) 435 printf("[%u] ", i); 436 print_entry("", &info->pol[i], numeric, NFPROTO_IPV4); 437 } 438} 439 440static void policy6_print(const void *ip, const struct xt_entry_match *match, 441 int numeric) 442{ 443 const struct xt_policy_info *info = (void *)match->data; 444 unsigned int i; 445 446 printf("policy match "); 447 print_flags("", info); 448 for (i = 0; i < info->len; i++) { 449 if (info->len > 1) 450 printf("[%u] ", i); 451 print_entry("", &info->pol[i], numeric, NFPROTO_IPV6); 452 } 453} 454 455static void policy4_save(const void *ip, const struct xt_entry_match *match) 456{ 457 const struct xt_policy_info *info = (void *)match->data; 458 unsigned int i; 459 460 print_flags("--", info); 461 for (i = 0; i < info->len; i++) { 462 print_entry("--", &info->pol[i], false, NFPROTO_IPV4); 463 if (i + 1 < info->len) 464 printf("--next "); 465 } 466} 467 468static void policy6_save(const void *ip, const struct xt_entry_match *match) 469{ 470 const struct xt_policy_info *info = (void *)match->data; 471 unsigned int i; 472 473 print_flags("--", info); 474 for (i = 0; i < info->len; i++) { 475 print_entry("--", &info->pol[i], false, NFPROTO_IPV6); 476 if (i + 1 < info->len) 477 printf("--next "); 478 } 479} 480 481static struct xtables_match policy_mt_reg[] = { 482 { 483 .name = "policy", 484 .version = XTABLES_VERSION, 485 .family = NFPROTO_IPV4, 486 .size = XT_ALIGN(sizeof(struct xt_policy_info)), 487 .userspacesize = XT_ALIGN(sizeof(struct xt_policy_info)), 488 .help = policy_help, 489 .parse = policy4_parse, 490 .final_check = policy_check, 491 .print = policy4_print, 492 .save = policy4_save, 493 .extra_opts = policy_opts, 494 }, 495 { 496 .name = "policy", 497 .version = XTABLES_VERSION, 498 .family = NFPROTO_IPV6, 499 .size = XT_ALIGN(sizeof(struct xt_policy_info)), 500 .userspacesize = XT_ALIGN(sizeof(struct xt_policy_info)), 501 .help = policy_help, 502 .parse = policy6_parse, 503 .final_check = policy_check, 504 .print = policy6_print, 505 .save = policy6_save, 506 .extra_opts = policy_opts, 507 }, 508}; 509 510void _init(void) 511{ 512 xtables_register_matches(policy_mt_reg, ARRAY_SIZE(policy_mt_reg)); 513} 514