1 /* Copyright (C) 2000-2002 Joakim Axelsson <gozem (at) linux.nu> 2 * Patrick Schaaf <bof (at) bof.de> 3 * Martin Josefsson <gandalf (at) wlug.westbo.se> 4 * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec (at) blackhole.kfki.hu> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 */ 10 11 /* Shared library add-on to iptables to add IP set matching. */ 12 #include <stdio.h> 13 #include <netdb.h> 14 #include <string.h> 15 #include <stdlib.h> 16 #include <getopt.h> 17 #include <ctype.h> 18 #include <errno.h> 19 20 #include <iptables.h> 21 #include <linux/netfilter_ipv4/ip_conntrack.h> 22 #include <linux/netfilter_ipv4/ipt_set.h> 23 #include "libipt_2set.h" 24 25 /* Function which prints out usage message. */ 26 static void help(void) 27 { 28 printf("set v%s options:\n" 29 " [!] --set name flags\n" 30 " 'name' is the set name from to match,\n" 31 " 'flags' are the comma separated list of\n" 32 " 'src' and 'dst'.\n" 33 "\n", IPTABLES_VERSION); 34 } 35 36 static struct option opts[] = { 37 {"set", 1, 0, '1'}, 38 {0} 39 }; 40 41 /* Initialize the match. */ 42 static void init(struct ipt_entry_match *match, unsigned int *nfcache) 43 { 44 struct ipt_set_info_match *info = 45 (struct ipt_set_info_match *) match->data; 46 47 48 memset(info, 0, sizeof(struct ipt_set_info_match)); 49 50 } 51 52 /* Function which parses command options; returns true if it ate an option */ 53 static int 54 parse(int c, char **argv, int invert, unsigned int *flags, 55 const struct ipt_entry *entry, 56 unsigned int *nfcache, struct ipt_entry_match **match) 57 { 58 struct ipt_set_info_match *myinfo = 59 (struct ipt_set_info_match *) (*match)->data; 60 struct ipt_set_info *info = &myinfo->match_set; 61 62 switch (c) { 63 case '1': /* --set <set> <flag>[,<flag> */ 64 if (info->flags[0]) 65 exit_error(PARAMETER_PROBLEM, 66 "--set can be specified only once"); 67 68 check_inverse(optarg, &invert, &optind, 0); 69 if (invert) 70 info->flags[0] |= IPSET_MATCH_INV; 71 72 if (!argv[optind] 73 || argv[optind][0] == '-' 74 || argv[optind][0] == '!') 75 exit_error(PARAMETER_PROBLEM, 76 "--set requires two args."); 77 78 if (strlen(argv[optind-1]) > IP_SET_MAXNAMELEN - 1) 79 exit_error(PARAMETER_PROBLEM, 80 "setname `%s' too long, max %d characters.", 81 argv[optind-1], IP_SET_MAXNAMELEN - 1); 82 83 get_set_byname(argv[optind - 1], info); 84 parse_bindings(argv[optind], info); 85 DEBUGP("parse: set index %u\n", info->index); 86 optind++; 87 88 *flags = 1; 89 break; 90 91 default: 92 return 0; 93 } 94 95 return 1; 96 } 97 98 /* Final check; must have specified --set. */ 99 static void final_check(unsigned int flags) 100 { 101 if (!flags) 102 exit_error(PARAMETER_PROBLEM, 103 "You must specify `--set' with proper arguments"); 104 DEBUGP("final check OK\n"); 105 } 106 107 static void 108 print_match(const char *prefix, const struct ipt_set_info *info) 109 { 110 int i; 111 char setname[IP_SET_MAXNAMELEN]; 112 113 get_set_byid(setname, info->index); 114 printf("%s%s %s", 115 (info->flags[0] & IPSET_MATCH_INV) ? "! " : "", 116 prefix, 117 setname); 118 for (i = 0; i < IP_SET_MAX_BINDINGS; i++) { 119 if (!info->flags[i]) 120 break; 121 printf("%s%s", 122 i == 0 ? " " : ",", 123 info->flags[i] & IPSET_SRC ? "src" : "dst"); 124 } 125 printf(" "); 126 } 127 128 /* Prints out the matchinfo. */ 129 static void 130 print(const struct ipt_ip *ip, 131 const struct ipt_entry_match *match, int numeric) 132 { 133 struct ipt_set_info_match *info = 134 (struct ipt_set_info_match *) match->data; 135 136 print_match("set", &info->match_set); 137 } 138 139 /* Saves the matchinfo in parsable form to stdout. */ 140 static void save(const struct ipt_ip *ip, 141 const struct ipt_entry_match *match) 142 { 143 struct ipt_set_info_match *info = 144 (struct ipt_set_info_match *) match->data; 145 146 print_match("--set", &info->match_set); 147 } 148 149 static 150 struct iptables_match set = { 151 .name = "set", 152 .version = IPTABLES_VERSION, 153 .size = IPT_ALIGN(sizeof(struct ipt_set_info_match)), 154 .userspacesize = IPT_ALIGN(sizeof(struct ipt_set_info_match)), 155 .help = &help, 156 .init = &init, 157 .parse = &parse, 158 .final_check = &final_check, 159 .print = &print, 160 .save = &save, 161 .extra_opts = opts 162 }; 163 164 void ipt_2set_init(void) 165 { 166 register_match(&set); 167 } 168