Busybox: Upgrade to 1.21.1 (stable). lsof active.
[tomato.git] / release / src / router / iptables / extensions / libipt_realm.c
blob15646778eb3de803f0d84dfb0062c04d45a6245e
1 /* Shared library add-on to iptables to add realm matching support. */
2 #include <stdio.h>
3 #include <netdb.h>
4 #include <string.h>
5 #include <stdlib.h>
6 #include <errno.h>
7 #include <ctype.h>
8 #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>
17 /* Function which prints out usage message. */
18 static void
19 help(void)
21 printf(
22 "realm v%s options:\n"
23 " --realm [!] value[/mask]\n"
24 " Match realm\n"
25 "\n", IPTABLES_VERSION);
28 static struct option opts[] = {
29 { "realm", 1, 0, '1' },
30 {0}
33 struct realmname {
34 int id;
35 char* name;
36 int len;
37 struct realmname* next;
40 /* array of realms from /etc/iproute2/rt_realms */
41 static struct realmname *realms = NULL;
42 /* 1 if loading failed */
43 static int rdberr = 0;
46 void load_realms()
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;
55 fil = fopen(rfnm, "r");
56 if (!fil) {
57 rdberr = 1;
58 return;
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;
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;
74 /* same boundaries as in iproute2 */
75 if (id < 0 || id > 255)
76 continue;
77 cur = nxt;
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;
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);
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);
104 strncpy(newnm->name, cur, newnm->len);
105 newnm->name[newnm->len] = 0;
106 newnm->next = NULL;
108 if (oldnm)
109 oldnm->next = newnm;
110 else
111 realms = newnm;
112 oldnm = newnm;
115 fclose(fil);
118 /* get realm id for name, -1 if error/not found */
119 int realm_name2id(const char* name)
121 struct realmname* cur;
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;
133 return -1;
136 /* get realm name for id, NULL if error/not found */
137 const char* realm_id2name(int id)
139 struct realmname* cur;
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;
151 return NULL;
155 /* Function which parses command options; returns true if it
156 ate an option */
157 static int
158 parse(int c, char **argv, int invert, unsigned int *flags,
159 const struct ipt_entry *entry,
160 unsigned int *nfcache,
161 struct ipt_entry_match **match)
163 struct ipt_realm_info *realminfo = (struct ipt_realm_info *)(*match)->data;
164 int id;
166 switch (c) {
167 char *end;
168 case '1':
169 check_inverse(argv[optind-1], &invert, &optind, 0);
170 end = optarg = argv[optind-1];
171 realminfo->id = strtoul(optarg, &end, 0);
172 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;
186 realminfo->mask = 0xffffffff;
188 if (invert)
189 realminfo->invert = 1;
190 *flags = 1;
191 break;
193 default:
194 return 0;
196 return 1;
199 static void
200 print_realm(unsigned long id, unsigned long mask, int numeric)
202 const char* name = NULL;
204 if (mask != 0xffffffff)
205 printf("0x%lx/0x%lx ", id, mask);
206 else {
207 if (numeric == 0)
208 name = realm_id2name(id);
209 if (name)
210 printf("%s ", name);
211 else
212 printf("0x%lx ", id);
216 /* Prints out the matchinfo. */
217 static void
218 print(const struct ipt_ip *ip,
219 const struct ipt_entry_match *match,
220 int numeric)
222 struct ipt_realm_info *ri = (struct ipt_realm_info *) match->data;
224 if (ri->invert)
225 printf("! ");
227 printf("realm ");
228 print_realm(ri->id, ri->mask, numeric);
232 /* Saves the union ipt_matchinfo in parsable form to stdout. */
233 static void
234 save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
236 struct ipt_realm_info *ri = (struct ipt_realm_info *) match->data;
238 if (ri->invert)
239 printf("! ");
241 printf("--realm ");
242 print_realm(ri->id, ri->mask, 0);
245 /* Final check; must have specified --mark. */
246 static void
247 final_check(unsigned int flags)
249 if (!flags)
250 exit_error(PARAMETER_PROBLEM,
251 "realm match: You must specify `--realm'");
254 static 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,
260 .parse = &parse,
261 .final_check = &final_check,
262 .print = &print,
263 .save = &save,
264 .extra_opts = opts
267 void _init(void)
269 register_match(&realm);