iptables-1.2.9-2.3.1.src.rpm
[iptables.git] / extensions / libipt_mark.c
1 /* Shared library add-on to iptables to add NFMARK 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_mark.h>
10
11 /* Function which prints out usage message. */
12 static void
13 help(void)
14 {
15         printf(
16 "MARK match v%s options:\n"
17 "[!] --mark value[/mask]         Match nfmark value with optional mask\n"
18 "\n",
19 IPTABLES_VERSION);
20 }
21
22 static struct option opts[] = {
23         { "mark", 1, 0, '1' },
24         {0}
25 };
26
27 /* Initialize the match. */
28 static void
29 init(struct ipt_entry_match *m, unsigned int *nfcache)
30 {
31         /* Can't cache this. */
32         *nfcache |= NFC_UNKNOWN;
33 }
34
35 /* Function which parses command options; returns true if it
36    ate an option */
37 static int
38 parse(int c, char **argv, int invert, unsigned int *flags,
39       const struct ipt_entry *entry,
40       unsigned int *nfcache,
41       struct ipt_entry_match **match)
42 {
43         struct ipt_mark_info *markinfo = (struct ipt_mark_info *)(*match)->data;
44
45         switch (c) {
46                 char *end;
47         case '1':
48                 check_inverse(optarg, &invert, &optind, 0);
49                 markinfo->mark = strtoul(optarg, &end, 0);
50                 if (*end == '/') {
51                         markinfo->mask = strtoul(end+1, &end, 0);
52                 } else
53                         markinfo->mask = 0xffffffff;
54                 if (*end != '\0' || end == optarg)
55                         exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg);
56                 if (invert)
57                         markinfo->invert = 1;
58                 *flags = 1;
59                 break;
60
61         default:
62                 return 0;
63         }
64         return 1;
65 }
66
67 static void
68 print_mark(unsigned long mark, unsigned long mask, int numeric)
69 {
70         if(mask != 0xffffffff)
71                 printf("0x%lx/0x%lx ", mark, mask);
72         else
73                 printf("0x%lx ", mark);
74 }
75
76 /* Final check; must have specified --mark. */
77 static void
78 final_check(unsigned int flags)
79 {
80         if (!flags)
81                 exit_error(PARAMETER_PROBLEM,
82                            "MARK match: You must specify `--mark'");
83 }
84
85 /* Prints out the matchinfo. */
86 static void
87 print(const struct ipt_ip *ip,
88       const struct ipt_entry_match *match,
89       int numeric)
90 {
91         struct ipt_mark_info *info = (struct ipt_mark_info *)match->data;
92
93         printf("MARK match ");
94
95         if (info->invert)
96                 printf("!");
97         
98         print_mark(info->mark, info->mask, numeric);
99 }
100
101 /* Saves the union ipt_matchinfo in parsable form to stdout. */
102 static void
103 save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
104 {
105         struct ipt_mark_info *info = (struct ipt_mark_info *)match->data;
106
107         if (info->invert)
108                 printf("! ");
109         
110         printf("--mark ");
111         print_mark(info->mark, info->mask, 0);
112 }
113
114 static
115 struct iptables_match mark
116 = { NULL,
117     "mark",
118     IPTABLES_VERSION,
119     IPT_ALIGN(sizeof(struct ipt_mark_info)),
120     IPT_ALIGN(sizeof(struct ipt_mark_info)),
121     &help,
122     &init,
123     &parse,
124     &final_check,
125     &print,
126     &save,
127     opts
128 };
129
130 void _init(void)
131 {
132         register_match(&mark);
133 }