blob: 0b11457b1da022ba71b42cd2c7e3fa111faac425 [file] [log] [blame]
Harald Welte2e2d3f32001-09-02 15:34:18 +00001/* Shared library add-on to iptables to add realm matching support. */
Sampsa Rantad6aa9662001-07-30 13:30:14 +00002#include <stdio.h>
3#include <netdb.h>
4#include <string.h>
5#include <stdlib.h>
Simon Lodalca9d8c22006-09-02 12:37:48 +00006#include <errno.h>
7#include <ctype.h>
Sampsa Rantad6aa9662001-07-30 13:30:14 +00008#include <getopt.h>
9#if defined(__GLIBC__) && __GLIBC__ == 2
10#include <net/ethernet.h>
11#else
12#include <linux/if_ether.h>
13#endif
14#include <iptables.h>
15#include <linux/netfilter_ipv4/ipt_realm.h>
16
17/* Function which prints out usage message. */
18static void
19help(void)
20{
21 printf(
Simon Lodala895b9c2006-05-24 16:25:09 +000022"realm v%s options:\n"
Sampsa Rantad6aa9662001-07-30 13:30:14 +000023" --realm [!] value[/mask]\n"
24" Match realm\n"
Harald Welte80fe35d2002-05-29 13:08:15 +000025"\n", IPTABLES_VERSION);
Sampsa Rantad6aa9662001-07-30 13:30:14 +000026}
27
Jan Engelhardt661f1122007-07-30 14:46:51 +000028static const struct option opts[] = {
Sampsa Rantad6aa9662001-07-30 13:30:14 +000029 { "realm", 1, 0, '1' },
30 {0}
31};
32
Simon Lodalca9d8c22006-09-02 12:37:48 +000033struct realmname {
34 int id;
35 char* name;
36 int len;
37 struct realmname* next;
38};
39
40/* array of realms from /etc/iproute2/rt_realms */
41static struct realmname *realms = NULL;
42/* 1 if loading failed */
43static int rdberr = 0;
44
45
46void load_realms()
47{
48 const char* rfnm = "/etc/iproute2/rt_realms";
49 char buf[512];
50 FILE *fil;
51 char *cur, *nxt;
52 int id;
53 struct realmname *oldnm = NULL, *newnm = NULL;
54
55 fil = fopen(rfnm, "r");
56 if (!fil) {
57 rdberr = 1;
58 return;
59 }
60
61 while (fgets(buf, sizeof(buf), fil)) {
62 cur = buf;
63 while ((*cur == ' ') || (*cur == '\t'))
64 cur++;
65 if ((*cur == '#') || (*cur == '\n') || (*cur == 0))
66 continue;
67
68 /* iproute2 allows hex and dec format */
69 errno = 0;
70 id = strtoul(cur, &nxt, strncmp(cur, "0x", 2) ? 10 : 16);
71 if ((nxt == cur) || errno)
72 continue;
73
74 /* same boundaries as in iproute2 */
75 if (id < 0 || id > 255)
76 continue;
77 cur = nxt;
78
79 if (!isspace(*cur))
80 continue;
81 while ((*cur == ' ') || (*cur == '\t'))
82 cur++;
83 if ((*cur == '#') || (*cur == '\n') || (*cur == 0))
84 continue;
85 nxt = cur;
86 while ((*nxt != 0) && !isspace(*nxt))
87 nxt++;
88 if (nxt == cur)
89 continue;
90
91 /* found valid data */
92 newnm = (struct realmname*)malloc(sizeof(struct realmname));
93 if (newnm == NULL) {
94 perror("libipt_realm: malloc failed");
95 exit(1);
96 }
97 newnm->id = id;
98 newnm->len = nxt - cur;
99 newnm->name = (char*)malloc(newnm->len + 1);
100 if (newnm->name == NULL) {
101 perror("libipt_realm: malloc failed");
102 exit(1);
103 }
104 strncpy(newnm->name, cur, newnm->len);
105 newnm->name[newnm->len] = 0;
106 newnm->next = NULL;
107
108 if (oldnm)
109 oldnm->next = newnm;
110 else
111 realms = newnm;
112 oldnm = newnm;
113 }
114
115 fclose(fil);
116}
117
118/* get realm id for name, -1 if error/not found */
119int realm_name2id(const char* name)
120{
121 struct realmname* cur;
122
123 if ((realms == NULL) && (rdberr == 0))
124 load_realms();
125 cur = realms;
126 if (cur == NULL)
127 return -1;
128 while (cur) {
129 if (!strncmp(name, cur->name, cur->len + 1))
130 return cur->id;
131 cur = cur->next;
132 }
133 return -1;
134}
135
136/* get realm name for id, NULL if error/not found */
137const char* realm_id2name(int id)
138{
139 struct realmname* cur;
140
141 if ((realms == NULL) && (rdberr == 0))
142 load_realms();
143 cur = realms;
144 if (cur == NULL)
145 return NULL;
146 while (cur) {
147 if (id == cur->id)
148 return cur->name;
149 cur = cur->next;
150 }
151 return NULL;
152}
153
154
Sampsa Rantad6aa9662001-07-30 13:30:14 +0000155/* Function which parses command options; returns true if it
156 ate an option */
157static int
158parse(int c, char **argv, int invert, unsigned int *flags,
Yasuyuki KOZAKAIc0a9ab92007-07-24 06:02:05 +0000159 const void *entry,
Sampsa Rantad6aa9662001-07-30 13:30:14 +0000160 unsigned int *nfcache,
Yasuyuki KOZAKAI193df8e2007-07-24 05:57:28 +0000161 struct xt_entry_match **match)
Sampsa Rantad6aa9662001-07-30 13:30:14 +0000162{
163 struct ipt_realm_info *realminfo = (struct ipt_realm_info *)(*match)->data;
Simon Lodalca9d8c22006-09-02 12:37:48 +0000164 int id;
Sampsa Rantad6aa9662001-07-30 13:30:14 +0000165
166 switch (c) {
167 char *end;
168 case '1':
Harald Welte69558bf2005-02-13 18:17:11 +0000169 check_inverse(argv[optind-1], &invert, &optind, 0);
Simon Lodalca9d8c22006-09-02 12:37:48 +0000170 end = optarg = argv[optind-1];
Sampsa Rantad6aa9662001-07-30 13:30:14 +0000171 realminfo->id = strtoul(optarg, &end, 0);
Simon Lodalca9d8c22006-09-02 12:37:48 +0000172 if (end != optarg && (*end == '/' || *end == '\0')) {
173 if (*end == '/')
174 realminfo->mask = strtoul(end+1, &end, 0);
175 else
176 realminfo->mask = 0xffffffff;
177 if (*end != '\0' || end == optarg)
178 exit_error(PARAMETER_PROBLEM,
179 "Bad realm value `%s'", optarg);
180 } else {
181 id = realm_name2id(optarg);
182 if (id == -1)
183 exit_error(PARAMETER_PROBLEM,
184 "Realm `%s' not found", optarg);
185 realminfo->id = (u_int32_t)id;
Sampsa Rantad6aa9662001-07-30 13:30:14 +0000186 realminfo->mask = 0xffffffff;
Simon Lodalca9d8c22006-09-02 12:37:48 +0000187 }
Sampsa Rantad6aa9662001-07-30 13:30:14 +0000188 if (invert)
189 realminfo->invert = 1;
190 *flags = 1;
191 break;
192
193 default:
194 return 0;
195 }
196 return 1;
197}
198
199static void
Simon Lodalca9d8c22006-09-02 12:37:48 +0000200print_realm(unsigned long id, unsigned long mask, int numeric)
Sampsa Rantad6aa9662001-07-30 13:30:14 +0000201{
Simon Lodalca9d8c22006-09-02 12:37:48 +0000202 const char* name = NULL;
203
Harald Welte61d274f2005-02-08 15:54:17 +0000204 if (mask != 0xffffffff)
Sampsa Rantad6aa9662001-07-30 13:30:14 +0000205 printf("0x%lx/0x%lx ", id, mask);
Simon Lodalca9d8c22006-09-02 12:37:48 +0000206 else {
207 if (numeric == 0)
208 name = realm_id2name(id);
209 if (name)
210 printf("%s ", name);
211 else
212 printf("0x%lx ", id);
213 }
Sampsa Rantad6aa9662001-07-30 13:30:14 +0000214}
215
216/* Prints out the matchinfo. */
217static void
Yasuyuki KOZAKAIc0a9ab92007-07-24 06:02:05 +0000218print(const void *ip,
Yasuyuki KOZAKAI193df8e2007-07-24 05:57:28 +0000219 const struct xt_entry_match *match,
Sampsa Rantad6aa9662001-07-30 13:30:14 +0000220 int numeric)
221{
Harald Welte61d274f2005-02-08 15:54:17 +0000222 struct ipt_realm_info *ri = (struct ipt_realm_info *) match->data;
223
224 if (ri->invert)
225 printf("! ");
226
Simon Lodala895b9c2006-05-24 16:25:09 +0000227 printf("realm ");
Simon Lodalca9d8c22006-09-02 12:37:48 +0000228 print_realm(ri->id, ri->mask, numeric);
Sampsa Rantad6aa9662001-07-30 13:30:14 +0000229}
230
231
232/* Saves the union ipt_matchinfo in parsable form to stdout. */
233static void
Yasuyuki KOZAKAIc0a9ab92007-07-24 06:02:05 +0000234save(const void *ip, const struct xt_entry_match *match)
Sampsa Rantad6aa9662001-07-30 13:30:14 +0000235{
Harald Welte61d274f2005-02-08 15:54:17 +0000236 struct ipt_realm_info *ri = (struct ipt_realm_info *) match->data;
237
238 if (ri->invert)
239 printf("! ");
240
Sampsa Rantad6aa9662001-07-30 13:30:14 +0000241 printf("--realm ");
Simon Lodalca9d8c22006-09-02 12:37:48 +0000242 print_realm(ri->id, ri->mask, 0);
Sampsa Rantad6aa9662001-07-30 13:30:14 +0000243}
244
245/* Final check; must have specified --mark. */
246static void
247final_check(unsigned int flags)
248{
249 if (!flags)
250 exit_error(PARAMETER_PROBLEM,
Simon Lodala895b9c2006-05-24 16:25:09 +0000251 "realm match: You must specify `--realm'");
Sampsa Rantad6aa9662001-07-30 13:30:14 +0000252}
253
Pablo Neira8caee8b2004-12-28 13:11:59 +0000254static struct iptables_match realm = { NULL,
255 .name = "realm",
256 .version = IPTABLES_VERSION,
257 .size = IPT_ALIGN(sizeof(struct ipt_realm_info)),
258 .userspacesize = IPT_ALIGN(sizeof(struct ipt_realm_info)),
259 .help = &help,
Pablo Neira8caee8b2004-12-28 13:11:59 +0000260 .parse = &parse,
261 .final_check = &final_check,
262 .print = &print,
263 .save = &save,
264 .extra_opts = opts
Sampsa Rantad6aa9662001-07-30 13:30:14 +0000265};
266
267void _init(void)
268{
269 register_match(&realm);
270}
271
272