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