1/* Shared library add-on to iptables to add ipv4 options matching support. */ 2#include <stdio.h> 3#include <netdb.h> 4#include <string.h> 5#include <stdlib.h> 6#include <getopt.h> 7 8#include <iptables.h> 9#include <linux/netfilter_ipv4/ipt_ipv4options.h> 10 11#ifndef XTABLES_VERSION 12#define XTABLES_VERSION IPTABLES_VERSION 13#endif 14 15#ifdef IPT_LIB_DIR 16#define xtables_target iptables_target 17#define xtables_register_target register_target 18#endif 19 20/* Function which prints out usage message. */ 21static void 22help(void) 23{ 24 printf( 25"ipv4options v%s options:\n" 26" --ssrr (match strict source routing flag)\n" 27" --lsrr (match loose source routing flag)\n" 28" --no-srr (match packets with no source routing)\n\n" 29" [!] --rr (match record route flag)\n\n" 30" [!] --ts (match timestamp flag)\n\n" 31" [!] --ra (match router-alert option)\n\n" 32" [!] --any-opt (match any option or no option at all if used with '!')\n", 33XTABLES_VERSION); 34} 35 36static struct option opts[] = { 37 { "ssrr", 0, 0, '1' }, 38 { "lsrr", 0, 0, '2' }, 39 { "no-srr", 0, 0, '3'}, 40 { "rr", 0, 0, '4'}, 41 { "ts", 0, 0, '5'}, 42 { "ra", 0, 0, '6'}, 43 { "any-opt", 0, 0, '7'}, 44 {0} 45}; 46 47/* Function which parses command options; returns true if it 48 ate an option */ 49static int 50parse(int c, char **argv, int invert, unsigned int *flags, 51#ifdef _XTABLES_H 52 const void *entry, struct xt_entry_match **match) 53#else 54 const struct ipt_entry *entry, unsigned int *nfcache, struct ipt_entry_match **match) 55#endif 56{ 57 struct ipt_ipv4options_info *info = (struct ipt_ipv4options_info *)(*match)->data; 58 59 switch (c) 60 { 61 /* strict-source-routing */ 62 case '1': 63 if (invert) 64 exit_error(PARAMETER_PROBLEM, 65 "ipv4options: unexpected `!' with --ssrr"); 66 if (*flags & IPT_IPV4OPTION_MATCH_SSRR) 67 exit_error(PARAMETER_PROBLEM, 68 "Can't specify --ssrr twice"); 69 if (*flags & IPT_IPV4OPTION_MATCH_LSRR) 70 exit_error(PARAMETER_PROBLEM, 71 "Can't specify --ssrr with --lsrr"); 72 if (*flags & IPT_IPV4OPTION_DONT_MATCH_SRR) 73 exit_error(PARAMETER_PROBLEM, 74 "Can't specify --ssrr with --no-srr"); 75 76 info->options |= IPT_IPV4OPTION_MATCH_SSRR; 77 *flags |= IPT_IPV4OPTION_MATCH_SSRR; 78 break; 79 80 /* loose-source-routing */ 81 case '2': 82 if (invert) 83 exit_error(PARAMETER_PROBLEM, 84 "ipv4options: unexpected `!' with --lsrr"); 85 if (*flags & IPT_IPV4OPTION_MATCH_SSRR) 86 exit_error(PARAMETER_PROBLEM, 87 "Can't specify --lsrr twice"); 88 if (*flags & IPT_IPV4OPTION_MATCH_LSRR) 89 exit_error(PARAMETER_PROBLEM, 90 "Can't specify --lsrr with --ssrr"); 91 if (*flags & IPT_IPV4OPTION_DONT_MATCH_SRR) 92 exit_error(PARAMETER_PROBLEM, 93 "Can't specify --lsrr with --no-srr"); 94 info->options |= IPT_IPV4OPTION_MATCH_LSRR; 95 *flags |= IPT_IPV4OPTION_MATCH_LSRR; 96 break; 97 98 /* no-source-routing */ 99 case '3': 100 if (invert) 101 exit_error(PARAMETER_PROBLEM, 102 "ipv4options: unexpected `!' with --no-srr"); 103 if (*flags & IPT_IPV4OPTION_DONT_MATCH_SRR) 104 exit_error(PARAMETER_PROBLEM, 105 "Can't specify --no-srr twice"); 106 if (*flags & IPT_IPV4OPTION_MATCH_SSRR) 107 exit_error(PARAMETER_PROBLEM, 108 "Can't specify --no-srr with --ssrr"); 109 if (*flags & IPT_IPV4OPTION_MATCH_LSRR) 110 exit_error(PARAMETER_PROBLEM, 111 "Can't specify --no-srr with --lsrr"); 112 info->options |= IPT_IPV4OPTION_DONT_MATCH_SRR; 113 *flags |= IPT_IPV4OPTION_DONT_MATCH_SRR; 114 break; 115 116 /* record-route */ 117 case '4': 118 if ((!invert) && (*flags & IPT_IPV4OPTION_MATCH_RR)) 119 exit_error(PARAMETER_PROBLEM, 120 "Can't specify --rr twice"); 121 if (invert && (*flags & IPT_IPV4OPTION_DONT_MATCH_RR)) 122 exit_error(PARAMETER_PROBLEM, 123 "Can't specify ! --rr twice"); 124 if ((!invert) && (*flags & IPT_IPV4OPTION_DONT_MATCH_RR)) 125 exit_error(PARAMETER_PROBLEM, 126 "Can't specify --rr with ! --rr"); 127 if (invert && (*flags & IPT_IPV4OPTION_MATCH_RR)) 128 exit_error(PARAMETER_PROBLEM, 129 "Can't specify ! --rr with --rr"); 130 if (invert) { 131 info->options |= IPT_IPV4OPTION_DONT_MATCH_RR; 132 *flags |= IPT_IPV4OPTION_DONT_MATCH_RR; 133 } 134 else { 135 info->options |= IPT_IPV4OPTION_MATCH_RR; 136 *flags |= IPT_IPV4OPTION_MATCH_RR; 137 } 138 break; 139 140 /* timestamp */ 141 case '5': 142 if ((!invert) && (*flags & IPT_IPV4OPTION_MATCH_TIMESTAMP)) 143 exit_error(PARAMETER_PROBLEM, 144 "Can't specify --ts twice"); 145 if (invert && (*flags & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP)) 146 exit_error(PARAMETER_PROBLEM, 147 "Can't specify ! --ts twice"); 148 if ((!invert) && (*flags & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP)) 149 exit_error(PARAMETER_PROBLEM, 150 "Can't specify --ts with ! --ts"); 151 if (invert && (*flags & IPT_IPV4OPTION_MATCH_TIMESTAMP)) 152 exit_error(PARAMETER_PROBLEM, 153 "Can't specify ! --ts with --ts"); 154 if (invert) { 155 info->options |= IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP; 156 *flags |= IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP; 157 } 158 else { 159 info->options |= IPT_IPV4OPTION_MATCH_TIMESTAMP; 160 *flags |= IPT_IPV4OPTION_MATCH_TIMESTAMP; 161 } 162 break; 163 164 /* router-alert */ 165 case '6': 166 if ((!invert) && (*flags & IPT_IPV4OPTION_MATCH_ROUTER_ALERT)) 167 exit_error(PARAMETER_PROBLEM, 168 "Can't specify --ra twice"); 169 if (invert && (*flags & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT)) 170 exit_error(PARAMETER_PROBLEM, 171 "Can't specify ! --rr twice"); 172 if ((!invert) && (*flags & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT)) 173 exit_error(PARAMETER_PROBLEM, 174 "Can't specify --ra with ! --ra"); 175 if (invert && (*flags & IPT_IPV4OPTION_MATCH_ROUTER_ALERT)) 176 exit_error(PARAMETER_PROBLEM, 177 "Can't specify ! --ra with --ra"); 178 if (invert) { 179 info->options |= IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT; 180 *flags |= IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT; 181 } 182 else { 183 info->options |= IPT_IPV4OPTION_MATCH_ROUTER_ALERT; 184 *flags |= IPT_IPV4OPTION_MATCH_ROUTER_ALERT; 185 } 186 break; 187 188 /* any option */ 189 case '7' : 190 if ((!invert) && (*flags & IPT_IPV4OPTION_MATCH_ANY_OPT)) 191 exit_error(PARAMETER_PROBLEM, 192 "Can't specify --any-opt twice"); 193 if (invert && (*flags & IPT_IPV4OPTION_MATCH_ANY_OPT)) 194 exit_error(PARAMETER_PROBLEM, 195 "Can't specify ! --any-opt with --any-opt"); 196 if (invert && (*flags & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT)) 197 exit_error(PARAMETER_PROBLEM, 198 "Can't specify ! --any-opt twice"); 199 if ((!invert) && 200 ((*flags & IPT_IPV4OPTION_DONT_MATCH_SRR) || 201 (*flags & IPT_IPV4OPTION_DONT_MATCH_RR) || 202 (*flags & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) || 203 (*flags & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT))) 204 exit_error(PARAMETER_PROBLEM, 205 "Can't specify --any-opt with any other negative ipv4options match"); 206 if (invert && 207 ((*flags & IPT_IPV4OPTION_MATCH_LSRR) || 208 (*flags & IPT_IPV4OPTION_MATCH_SSRR) || 209 (*flags & IPT_IPV4OPTION_MATCH_RR) || 210 (*flags & IPT_IPV4OPTION_MATCH_TIMESTAMP) || 211 (*flags & IPT_IPV4OPTION_MATCH_ROUTER_ALERT))) 212 exit_error(PARAMETER_PROBLEM, 213 "Can't specify ! --any-opt with any other positive ipv4options match"); 214 if (invert) { 215 info->options |= IPT_IPV4OPTION_DONT_MATCH_ANY_OPT; 216 *flags |= IPT_IPV4OPTION_DONT_MATCH_ANY_OPT; 217 } 218 else { 219 info->options |= IPT_IPV4OPTION_MATCH_ANY_OPT; 220 *flags |= IPT_IPV4OPTION_MATCH_ANY_OPT; 221 } 222 break; 223 224 default: 225 return 0; 226 } 227 return 1; 228} 229 230static void 231final_check(unsigned int flags) 232{ 233 if (flags == 0) 234 exit_error(PARAMETER_PROBLEM, 235 "ipv4options match: you must specify some parameters. See iptables -m ipv4options --help for help.'"); 236} 237 238/* Prints out the matchinfo. */ 239static void 240#ifdef _XTABLES_H 241print(const void *ip, 242 const struct xt_entry_match *match, 243#else 244print(const struct ipt_ip *ip, 245 const struct ipt_entry_match *match, 246#endif 247 int numeric) 248{ 249 struct ipt_ipv4options_info *info = ((struct ipt_ipv4options_info *)match->data); 250 251 printf(" IPV4OPTS"); 252 if (info->options & IPT_IPV4OPTION_MATCH_SSRR) 253 printf(" SSRR"); 254 else if (info->options & IPT_IPV4OPTION_MATCH_LSRR) 255 printf(" LSRR"); 256 else if (info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) 257 printf(" !SRR"); 258 if (info->options & IPT_IPV4OPTION_MATCH_RR) 259 printf(" RR"); 260 else if (info->options & IPT_IPV4OPTION_DONT_MATCH_RR) 261 printf(" !RR"); 262 if (info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) 263 printf(" TS"); 264 else if (info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) 265 printf(" !TS"); 266 if (info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) 267 printf(" RA"); 268 else if (info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) 269 printf(" !RA"); 270 if (info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) 271 printf(" ANYOPT "); 272 else if (info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) 273 printf(" NOOPT"); 274 275 printf(" "); 276} 277 278/* Saves the data in parsable form to stdout. */ 279static void 280#ifdef _XTABLES_H 281save(const void *ip, 282 const struct xt_entry_match *match) 283#else 284save(const struct ipt_ip *ip, 285 const struct ipt_entry_match *match) 286#endif 287{ 288 struct ipt_ipv4options_info *info = ((struct ipt_ipv4options_info *)match->data); 289 290 if (info->options & IPT_IPV4OPTION_MATCH_SSRR) 291 printf(" --ssrr"); 292 else if (info->options & IPT_IPV4OPTION_MATCH_LSRR) 293 printf(" --lsrr"); 294 else if (info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) 295 printf(" --no-srr"); 296 if (info->options & IPT_IPV4OPTION_MATCH_RR) 297 printf(" --rr"); 298 else if (info->options & IPT_IPV4OPTION_DONT_MATCH_RR) 299 printf(" ! --rr"); 300 if (info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) 301 printf(" --ts"); 302 else if (info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) 303 printf(" ! --ts"); 304 if (info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) 305 printf(" --ra"); 306 else if (info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) 307 printf(" ! --ra"); 308 if (info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) 309 printf(" --any-opt"); 310 if (info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) 311 printf(" ! --any-opt"); 312 313 printf(" "); 314} 315 316static struct xtables_match ipv4options_struct = { 317 .next = NULL, 318 .name = "ipv4options", 319 .version = XTABLES_VERSION, 320 .size = IPT_ALIGN(sizeof(struct ipt_ipv4options_info)), 321 .userspacesize = IPT_ALIGN(sizeof(struct ipt_ipv4options_info)), 322 .help = &help, 323 .parse = &parse, 324 .final_check = &final_check, 325 .print = &print, 326 .save = &save, 327 .extra_opts = opts 328}; 329 330void _init(void) 331{ 332 xtables_register_match(&ipv4options_struct); 333} 334