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