Home | History | Annotate | Download | only in extensions
      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