1 /* ebt_ip
2 *
3 * Authors:
4 * Bart De Schuymer <bdschuym@pandora.be>
5 *
6 * Changes:
7 * added ip-sport and ip-dport; parsing of port arguments is
8 * based on code from iptables-1.2.7a
9 * Innominate Security Technologies AG <mhopf@innominate.com>
10 * September, 2002
11 *
12 * Adapted by Arturo Borrero Gonzalez <arturo@debian.org>
13 * to use libxtables for ebtables-compat in 2015.
14 */
15
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <getopt.h>
20 #include <netdb.h>
21 #include <inttypes.h>
22 #include <xtables.h>
23
24 #include "libxt_icmp.h"
25
26 #define EBT_IP_SOURCE 0x01
27 #define EBT_IP_DEST 0x02
28 #define EBT_IP_TOS 0x04
29 #define EBT_IP_PROTO 0x08
30 #define EBT_IP_SPORT 0x10
31 #define EBT_IP_DPORT 0x20
32 #define EBT_IP_ICMP 0x40
33 #define EBT_IP_IGMP 0x80
34 #define EBT_IP_MASK (EBT_IP_SOURCE | EBT_IP_DEST | EBT_IP_TOS | EBT_IP_PROTO |\
35 EBT_IP_SPORT | EBT_IP_DPORT | EBT_IP_ICMP | EBT_IP_IGMP)
36
37 struct ebt_ip_info {
38 __be32 saddr;
39 __be32 daddr;
40 __be32 smsk;
41 __be32 dmsk;
42 __u8 tos;
43 __u8 protocol;
44 __u8 bitmask;
45 __u8 invflags;
46 union {
47 __u16 sport[2];
48 __u8 icmp_type[2];
49 __u8 igmp_type[2];
50 };
51 union {
52 __u16 dport[2];
53 __u8 icmp_code[2];
54 };
55 };
56
57 #define IP_SOURCE '1'
58 #define IP_DEST '2'
59 #define IP_EBT_TOS '3' /* include/bits/in.h seems to already define IP_TOS */
60 #define IP_PROTO '4'
61 #define IP_SPORT '5'
62 #define IP_DPORT '6'
63 #define IP_EBT_ICMP '7'
64 #define IP_EBT_IGMP '8'
65
66 static const struct option brip_opts[] = {
67 { .name = "ip-source", .has_arg = true, .val = IP_SOURCE },
68 { .name = "ip-src", .has_arg = true, .val = IP_SOURCE },
69 { .name = "ip-destination", .has_arg = true, .val = IP_DEST },
70 { .name = "ip-dst", .has_arg = true, .val = IP_DEST },
71 { .name = "ip-tos", .has_arg = true, .val = IP_EBT_TOS },
72 { .name = "ip-protocol", .has_arg = true, .val = IP_PROTO },
73 { .name = "ip-proto", .has_arg = true, .val = IP_PROTO },
74 { .name = "ip-source-port", .has_arg = true, .val = IP_SPORT },
75 { .name = "ip-sport", .has_arg = true, .val = IP_SPORT },
76 { .name = "ip-destination-port",.has_arg = true, .val = IP_DPORT },
77 { .name = "ip-dport", .has_arg = true, .val = IP_DPORT },
78 { .name = "ip-icmp-type", .has_arg = true, .val = IP_EBT_ICMP },
79 { .name = "ip-igmp-type", .has_arg = true, .val = IP_EBT_IGMP },
80 XT_GETOPT_TABLEEND,
81 };
82
83 static const struct xt_icmp_names icmp_codes[] = {
84 { "echo-reply", 0, 0, 0xFF },
85 /* Alias */ { "pong", 0, 0, 0xFF },
86
87 { "destination-unreachable", 3, 0, 0xFF },
88 { "network-unreachable", 3, 0, 0 },
89 { "host-unreachable", 3, 1, 1 },
90 { "protocol-unreachable", 3, 2, 2 },
91 { "port-unreachable", 3, 3, 3 },
92 { "fragmentation-needed", 3, 4, 4 },
93 { "source-route-failed", 3, 5, 5 },
94 { "network-unknown", 3, 6, 6 },
95 { "host-unknown", 3, 7, 7 },
96 { "network-prohibited", 3, 9, 9 },
97 { "host-prohibited", 3, 10, 10 },
98 { "TOS-network-unreachable", 3, 11, 11 },
99 { "TOS-host-unreachable", 3, 12, 12 },
100 { "communication-prohibited", 3, 13, 13 },
101 { "host-precedence-violation", 3, 14, 14 },
102 { "precedence-cutoff", 3, 15, 15 },
103
104 { "source-quench", 4, 0, 0xFF },
105
106 { "redirect", 5, 0, 0xFF },
107 { "network-redirect", 5, 0, 0 },
108 { "host-redirect", 5, 1, 1 },
109 { "TOS-network-redirect", 5, 2, 2 },
110 { "TOS-host-redirect", 5, 3, 3 },
111
112 { "echo-request", 8, 0, 0xFF },
113 /* Alias */ { "ping", 8, 0, 0xFF },
114
115 { "router-advertisement", 9, 0, 0xFF },
116
117 { "router-solicitation", 10, 0, 0xFF },
118
119 { "time-exceeded", 11, 0, 0xFF },
120 /* Alias */ { "ttl-exceeded", 11, 0, 0xFF },
121 { "ttl-zero-during-transit", 11, 0, 0 },
122 { "ttl-zero-during-reassembly", 11, 1, 1 },
123
124 { "parameter-problem", 12, 0, 0xFF },
125 { "ip-header-bad", 12, 0, 0 },
126 { "required-option-missing", 12, 1, 1 },
127
128 { "timestamp-request", 13, 0, 0xFF },
129
130 { "timestamp-reply", 14, 0, 0xFF },
131
132 { "address-mask-request", 17, 0, 0xFF },
133
134 { "address-mask-reply", 18, 0, 0xFF }
135 };
136
137 static const struct xt_icmp_names igmp_types[] = {
138 { "membership-query", 0x11 },
139 { "membership-report-v1", 0x12 },
140 { "membership-report-v2", 0x16 },
141 { "leave-group", 0x17 },
142 { "membership-report-v3", 0x22 },
143 };
144
brip_print_help(void)145 static void brip_print_help(void)
146 {
147 printf(
148 "ip options:\n"
149 "--ip-src [!] address[/mask]: ip source specification\n"
150 "--ip-dst [!] address[/mask]: ip destination specification\n"
151 "--ip-tos [!] tos : ip tos specification\n"
152 "--ip-proto [!] protocol : ip protocol specification\n"
153 "--ip-sport [!] port[:port] : tcp/udp source port or port range\n"
154 "--ip-dport [!] port[:port] : tcp/udp destination port or port range\n"
155 "--ip-icmp-type [!] type[[:type]/code[:code]] : icmp type/code or type/code range\n"
156 "--ip-igmp-type [!] type[:type] : igmp type or type range\n");
157
158 printf("\nValid ICMP Types:\n");
159 xt_print_icmp_types(icmp_codes, ARRAY_SIZE(icmp_codes));
160 printf("\nValid IGMP Types:\n");
161 xt_print_icmp_types(igmp_types, ARRAY_SIZE(igmp_types));
162 }
163
brip_init(struct xt_entry_match * match)164 static void brip_init(struct xt_entry_match *match)
165 {
166 struct ebt_ip_info *info = (struct ebt_ip_info *)match->data;
167
168 info->invflags = 0;
169 info->bitmask = 0;
170 }
171
172 static void
parse_port_range(const char * protocol,const char * portstring,uint16_t * ports)173 parse_port_range(const char *protocol, const char *portstring, uint16_t *ports)
174 {
175 char *buffer;
176 char *cp;
177
178 buffer = strdup(portstring);
179 if ((cp = strchr(buffer, ':')) == NULL)
180 ports[0] = ports[1] = xtables_parse_port(buffer, NULL);
181 else {
182 *cp = '\0';
183 cp++;
184
185 ports[0] = buffer[0] ? xtables_parse_port(buffer, NULL) : 0;
186 ports[1] = cp[0] ? xtables_parse_port(cp, NULL) : 0xFFFF;
187
188 if (ports[0] > ports[1])
189 xtables_error(PARAMETER_PROBLEM,
190 "invalid portrange (min > max)");
191 }
192 free(buffer);
193 }
194
195 /* original code from ebtables: useful_functions.c */
undot_ip(char * ip,unsigned char * ip2)196 static int undot_ip(char *ip, unsigned char *ip2)
197 {
198 char *p, *q, *end;
199 long int onebyte;
200 int i;
201 char buf[20];
202
203 strncpy(buf, ip, sizeof(buf) - 1);
204
205 p = buf;
206 for (i = 0; i < 3; i++) {
207 if ((q = strchr(p, '.')) == NULL)
208 return -1;
209 *q = '\0';
210 onebyte = strtol(p, &end, 10);
211 if (*end != '\0' || onebyte > 255 || onebyte < 0)
212 return -1;
213 ip2[i] = (unsigned char)onebyte;
214 p = q + 1;
215 }
216
217 onebyte = strtol(p, &end, 10);
218 if (*end != '\0' || onebyte > 255 || onebyte < 0)
219 return -1;
220 ip2[3] = (unsigned char)onebyte;
221
222 return 0;
223 }
224
ip_mask(char * mask,unsigned char * mask2)225 static int ip_mask(char *mask, unsigned char *mask2)
226 {
227 char *end;
228 long int bits;
229 uint32_t mask22;
230
231 if (undot_ip(mask, mask2)) {
232 /* not the /a.b.c.e format, maybe the /x format */
233 bits = strtol(mask, &end, 10);
234 if (*end != '\0' || bits > 32 || bits < 0)
235 return -1;
236 if (bits != 0) {
237 mask22 = htonl(0xFFFFFFFF << (32 - bits));
238 memcpy(mask2, &mask22, 4);
239 } else {
240 mask22 = 0xFFFFFFFF;
241 memcpy(mask2, &mask22, 4);
242 }
243 }
244 return 0;
245 }
246
ebt_parse_ip_address(char * address,uint32_t * addr,uint32_t * msk)247 static void ebt_parse_ip_address(char *address, uint32_t *addr, uint32_t *msk)
248 {
249 char *p;
250
251 /* first the mask */
252 if ((p = strrchr(address, '/')) != NULL) {
253 *p = '\0';
254 if (ip_mask(p + 1, (unsigned char *)msk)) {
255 xtables_error(PARAMETER_PROBLEM,
256 "Problem with the IP mask '%s'", p + 1);
257 return;
258 }
259 } else
260 *msk = 0xFFFFFFFF;
261
262 if (undot_ip(address, (unsigned char *)addr)) {
263 xtables_error(PARAMETER_PROBLEM,
264 "Problem with the IP address '%s'", address);
265 return;
266 }
267 *addr = *addr & *msk;
268 }
269
parse_range(const char * str,unsigned int res[])270 static char *parse_range(const char *str, unsigned int res[])
271 {
272 char *next;
273
274 if (!xtables_strtoui(str, &next, &res[0], 0, 255))
275 return NULL;
276
277 res[1] = res[0];
278 if (*next == ':') {
279 str = next + 1;
280 if (!xtables_strtoui(str, &next, &res[1], 0, 255))
281 return NULL;
282 }
283
284 return next;
285 }
286
ebt_parse_icmp(const struct xt_icmp_names * codes,size_t n_codes,const char * icmptype,uint8_t type[],uint8_t code[])287 static int ebt_parse_icmp(const struct xt_icmp_names *codes, size_t n_codes,
288 const char *icmptype, uint8_t type[], uint8_t code[])
289 {
290 unsigned int match = n_codes;
291 unsigned int i, number[2];
292
293 for (i = 0; i < n_codes; i++) {
294 if (strncasecmp(codes[i].name, icmptype, strlen(icmptype)))
295 continue;
296 if (match != n_codes)
297 xtables_error(PARAMETER_PROBLEM, "Ambiguous ICMP type `%s':"
298 " `%s' or `%s'?",
299 icmptype, codes[match].name,
300 codes[i].name);
301 match = i;
302 }
303
304 if (match < n_codes) {
305 type[0] = type[1] = codes[match].type;
306 if (code) {
307 code[0] = codes[match].code_min;
308 code[1] = codes[match].code_max;
309 }
310 } else {
311 char *next = parse_range(icmptype, number);
312 if (!next) {
313 xtables_error(PARAMETER_PROBLEM, "Unknown ICMP type `%s'",
314 icmptype);
315 return -1;
316 }
317
318 type[0] = (uint8_t) number[0];
319 type[1] = (uint8_t) number[1];
320 switch (*next) {
321 case 0:
322 if (code) {
323 code[0] = 0;
324 code[1] = 255;
325 }
326 return 0;
327 case '/':
328 if (code) {
329 next = parse_range(next+1, number);
330 code[0] = (uint8_t) number[0];
331 code[1] = (uint8_t) number[1];
332 if (next == NULL)
333 return -1;
334 if (next && *next == 0)
335 return 0;
336 }
337 /* fallthrough */
338 default:
339 xtables_error(PARAMETER_PROBLEM, "unknown character %c", *next);
340 return -1;
341 }
342 }
343 return 0;
344 }
345
print_icmp_code(uint8_t * code)346 static void print_icmp_code(uint8_t *code)
347 {
348 if (!code)
349 return;
350
351 if (code[0] == code[1])
352 printf("/%"PRIu8 " ", code[0]);
353 else
354 printf("/%"PRIu8":%"PRIu8 " ", code[0], code[1]);
355 }
356
ebt_print_icmp_type(const struct xt_icmp_names * codes,size_t n_codes,uint8_t * type,uint8_t * code)357 static void ebt_print_icmp_type(const struct xt_icmp_names *codes,
358 size_t n_codes, uint8_t *type, uint8_t *code)
359 {
360 unsigned int i;
361
362 if (type[0] != type[1]) {
363 printf("%"PRIu8 ":%" PRIu8, type[0], type[1]);
364 print_icmp_code(code);
365 return;
366 }
367
368 for (i = 0; i < n_codes; i++) {
369 if (codes[i].type != type[0])
370 continue;
371
372 if (!code || (codes[i].code_min == code[0] &&
373 codes[i].code_max == code[1])) {
374 printf("%s ", codes[i].name);
375 return;
376 }
377 }
378 printf("%"PRIu8, type[0]);
379 print_icmp_code(code);
380 }
381
382 static int
brip_parse(int c,char ** argv,int invert,unsigned int * flags,const void * entry,struct xt_entry_match ** match)383 brip_parse(int c, char **argv, int invert, unsigned int *flags,
384 const void *entry, struct xt_entry_match **match)
385 {
386 struct ebt_ip_info *info = (struct ebt_ip_info *)(*match)->data;
387
388 switch (c) {
389 case IP_SOURCE:
390 if (invert)
391 info->invflags |= EBT_IP_SOURCE;
392 ebt_parse_ip_address(optarg, &info->saddr, &info->smsk);
393 info->bitmask |= EBT_IP_SOURCE;
394 break;
395 case IP_DEST:
396 if (invert)
397 info->invflags |= EBT_IP_DEST;
398 ebt_parse_ip_address(optarg, &info->daddr, &info->dmsk);
399 info->bitmask |= EBT_IP_DEST;
400 break;
401 case IP_SPORT:
402 if (invert)
403 info->invflags |= EBT_IP_SPORT;
404 parse_port_range(NULL, optarg, info->sport);
405 info->bitmask |= EBT_IP_SPORT;
406 break;
407 case IP_DPORT:
408 if (invert)
409 info->invflags |= EBT_IP_DPORT;
410 parse_port_range(NULL, optarg, info->dport);
411 info->bitmask |= EBT_IP_DPORT;
412 break;
413 case IP_EBT_ICMP:
414 if (invert)
415 info->invflags |= EBT_IP_ICMP;
416 ebt_parse_icmp(icmp_codes, ARRAY_SIZE(icmp_codes), optarg,
417 info->icmp_type, info->icmp_code);
418 info->bitmask |= EBT_IP_ICMP;
419 break;
420 case IP_EBT_IGMP:
421 if (invert)
422 info->invflags |= EBT_IP_IGMP;
423 ebt_parse_icmp(igmp_types, ARRAY_SIZE(igmp_types), optarg,
424 info->igmp_type, NULL);
425 info->bitmask |= EBT_IP_IGMP;
426 break;
427 case IP_EBT_TOS: {
428 uintmax_t tosvalue;
429
430 if (invert)
431 info->invflags |= EBT_IP_TOS;
432 if (!xtables_strtoul(optarg, NULL, &tosvalue, 0, 255))
433 xtables_error(PARAMETER_PROBLEM,
434 "Problem with specified IP tos");
435 info->tos = tosvalue;
436 info->bitmask |= EBT_IP_TOS;
437 }
438 break;
439 case IP_PROTO:
440 if (invert)
441 info->invflags |= EBT_IP_PROTO;
442 info->protocol = xtables_parse_protocol(optarg);
443 info->bitmask |= EBT_IP_PROTO;
444 break;
445 default:
446 return 0;
447 }
448
449 *flags |= info->bitmask;
450 return 1;
451 }
452
brip_final_check(unsigned int flags)453 static void brip_final_check(unsigned int flags)
454 {
455 if (!flags)
456 xtables_error(PARAMETER_PROBLEM,
457 "You must specify proper arguments");
458 }
459
print_port_range(uint16_t * ports)460 static void print_port_range(uint16_t *ports)
461 {
462 if (ports[0] == ports[1])
463 printf("%d ", ports[0]);
464 else
465 printf("%d:%d ", ports[0], ports[1]);
466 }
467
brip_print(const void * ip,const struct xt_entry_match * match,int numeric)468 static void brip_print(const void *ip, const struct xt_entry_match *match,
469 int numeric)
470 {
471 struct ebt_ip_info *info = (struct ebt_ip_info *)match->data;
472 struct in_addr *addrp, *maskp;
473
474 if (info->bitmask & EBT_IP_SOURCE) {
475 printf("--ip-src ");
476 if (info->invflags & EBT_IP_SOURCE)
477 printf("! ");
478 addrp = (struct in_addr *)&info->saddr;
479 maskp = (struct in_addr *)&info->smsk;
480 printf("%s%s ", xtables_ipaddr_to_numeric(addrp),
481 xtables_ipmask_to_numeric(maskp));
482 }
483 if (info->bitmask & EBT_IP_DEST) {
484 printf("--ip-dst ");
485 if (info->invflags & EBT_IP_DEST)
486 printf("! ");
487 addrp = (struct in_addr *)&info->daddr;
488 maskp = (struct in_addr *)&info->dmsk;
489 printf("%s%s ", xtables_ipaddr_to_numeric(addrp),
490 xtables_ipmask_to_numeric(maskp));
491 }
492 if (info->bitmask & EBT_IP_TOS) {
493 printf("--ip-tos ");
494 if (info->invflags & EBT_IP_TOS)
495 printf("! ");
496 printf("0x%02X ", info->tos);
497 }
498 if (info->bitmask & EBT_IP_PROTO) {
499 struct protoent *pe;
500
501 printf("--ip-proto ");
502 if (info->invflags & EBT_IP_PROTO)
503 printf("! ");
504 pe = getprotobynumber(info->protocol);
505 if (pe == NULL) {
506 printf("%d ", info->protocol);
507 } else {
508 printf("%s ", pe->p_name);
509 }
510 }
511 if (info->bitmask & EBT_IP_SPORT) {
512 printf("--ip-sport ");
513 if (info->invflags & EBT_IP_SPORT)
514 printf("! ");
515 print_port_range(info->sport);
516 }
517 if (info->bitmask & EBT_IP_DPORT) {
518 printf("--ip-dport ");
519 if (info->invflags & EBT_IP_DPORT)
520 printf("! ");
521 print_port_range(info->dport);
522 }
523 if (info->bitmask & EBT_IP_ICMP) {
524 printf("--ip-icmp-type ");
525 if (info->invflags & EBT_IP_ICMP)
526 printf("! ");
527 ebt_print_icmp_type(icmp_codes, ARRAY_SIZE(icmp_codes),
528 info->icmp_type, info->icmp_code);
529 }
530 if (info->bitmask & EBT_IP_IGMP) {
531 printf("--ip-igmp-type ");
532 if (info->invflags & EBT_IP_IGMP)
533 printf("! ");
534 ebt_print_icmp_type(igmp_types, ARRAY_SIZE(igmp_types),
535 info->igmp_type, NULL);
536 }
537 }
538
brip_xlate_proto_to_name(uint8_t proto)539 static const char *brip_xlate_proto_to_name(uint8_t proto)
540 {
541 switch (proto) {
542 case IPPROTO_TCP:
543 return "tcp";
544 case IPPROTO_UDP:
545 return "udp";
546 case IPPROTO_UDPLITE:
547 return "udplite";
548 case IPPROTO_SCTP:
549 return "sctp";
550 case IPPROTO_DCCP:
551 return "dccp";
552 default:
553 return NULL;
554 }
555 }
556
brip_xlate_icmp(struct xt_xlate * xl,const struct ebt_ip_info * info,int bit)557 static void brip_xlate_icmp(struct xt_xlate *xl,
558 const struct ebt_ip_info *info, int bit)
559 {
560 if ((info->bitmask & bit) == 0)
561 return;
562
563 xt_xlate_add(xl, "icmp type ");
564 if (info->invflags & bit)
565 xt_xlate_add(xl, "!= ");
566 if (info->icmp_type[0] == info->icmp_type[1])
567 xt_xlate_add(xl, "%d ", info->icmp_type[0]);
568 else
569 xt_xlate_add(xl, "%d-%d ", info->icmp_type[0],
570 info->icmp_type[1]);
571 if (info->icmp_code[0] == 0 &&
572 info->icmp_code[1] == 0xff)
573 return;
574
575 xt_xlate_add(xl, "icmp code ");
576 if (info->invflags & bit)
577 xt_xlate_add(xl, "!= ");
578 if (info->icmp_code[0] == info->icmp_code[1])
579 xt_xlate_add(xl, "%d ", info->icmp_code[0]);
580 else
581 xt_xlate_add(xl, "%d-%d ", info->icmp_code[0],
582 info->icmp_code[1]);
583 }
584
brip_xlate_igmp(struct xt_xlate * xl,const struct ebt_ip_info * info,int bit)585 static void brip_xlate_igmp(struct xt_xlate *xl,
586 const struct ebt_ip_info *info, int bit)
587 {
588 if ((info->bitmask & bit) == 0)
589 return;
590
591 xt_xlate_add(xl, "@th,0,8 ");
592 if (info->invflags & bit)
593 xt_xlate_add(xl, "!= ");
594 if (info->icmp_type[0] == info->icmp_type[1])
595 xt_xlate_add(xl, "%d ", info->icmp_type[0]);
596 else
597 xt_xlate_add(xl, "%d-%d ", info->icmp_type[0],
598 info->icmp_type[1]);
599 }
600
brip_xlate_th(struct xt_xlate * xl,const struct ebt_ip_info * info,int bit,const char * pname)601 static void brip_xlate_th(struct xt_xlate *xl,
602 const struct ebt_ip_info *info, int bit,
603 const char *pname)
604 {
605 const uint16_t *ports;
606
607 if ((info->bitmask & bit) == 0)
608 return;
609
610 switch (bit) {
611 case EBT_IP_SPORT:
612 if (pname)
613 xt_xlate_add(xl, "%s sport ", pname);
614 else
615 xt_xlate_add(xl, "@th,0,16 ");
616
617 ports = info->sport;
618 break;
619 case EBT_IP_DPORT:
620 if (pname)
621 xt_xlate_add(xl, "%s dport ", pname);
622 else
623 xt_xlate_add(xl, "@th,16,16 ");
624
625 ports = info->dport;
626 break;
627 default:
628 return;
629 }
630
631 if (info->invflags & bit)
632 xt_xlate_add(xl, "!= ");
633
634 if (ports[0] == ports[1])
635 xt_xlate_add(xl, "%d ", ports[0]);
636 else
637 xt_xlate_add(xl, "%d-%d ", ports[0], ports[1]);
638 }
639
brip_xlate_nh(struct xt_xlate * xl,const struct ebt_ip_info * info,int bit)640 static void brip_xlate_nh(struct xt_xlate *xl,
641 const struct ebt_ip_info *info, int bit)
642 {
643 struct in_addr *addrp, *maskp;
644
645 if ((info->bitmask & bit) == 0)
646 return;
647
648 switch (bit) {
649 case EBT_IP_SOURCE:
650 xt_xlate_add(xl, "ip saddr ");
651 addrp = (struct in_addr *)&info->saddr;
652 maskp = (struct in_addr *)&info->smsk;
653 break;
654 case EBT_IP_DEST:
655 xt_xlate_add(xl, "ip daddr ");
656 addrp = (struct in_addr *)&info->daddr;
657 maskp = (struct in_addr *)&info->dmsk;
658 break;
659 default:
660 return;
661 }
662
663 if (info->invflags & bit)
664 xt_xlate_add(xl, "!= ");
665
666 xt_xlate_add(xl, "%s%s ", xtables_ipaddr_to_numeric(addrp),
667 xtables_ipmask_to_numeric(maskp));
668 }
669
brip_xlate(struct xt_xlate * xl,const struct xt_xlate_mt_params * params)670 static int brip_xlate(struct xt_xlate *xl,
671 const struct xt_xlate_mt_params *params)
672 {
673 const struct ebt_ip_info *info = (const void *)params->match->data;
674 const char *pname = NULL;
675
676 brip_xlate_nh(xl, info, EBT_IP_SOURCE);
677 brip_xlate_nh(xl, info, EBT_IP_DEST);
678
679 if (info->bitmask & EBT_IP_TOS) {
680 xt_xlate_add(xl, "ip dscp ");
681 if (info->invflags & EBT_IP_TOS)
682 xt_xlate_add(xl, "!= ");
683 xt_xlate_add(xl, "0x%02x ", info->tos & 0x3f); /* remove ECN bits */
684 }
685 if (info->bitmask & EBT_IP_PROTO) {
686 struct protoent *pe;
687
688 if (info->bitmask & (EBT_IP_SPORT|EBT_IP_DPORT|EBT_IP_ICMP) &&
689 (info->invflags & EBT_IP_PROTO) == 0) {
690 /* port number or icmp given and not inverted, no need to print this */
691 pname = brip_xlate_proto_to_name(info->protocol);
692 } else {
693 xt_xlate_add(xl, "ip protocol ");
694 if (info->invflags & EBT_IP_PROTO)
695 xt_xlate_add(xl, "!= ");
696 pe = getprotobynumber(info->protocol);
697 if (pe == NULL)
698 xt_xlate_add(xl, "%d ", info->protocol);
699 else
700 xt_xlate_add(xl, "%s ", pe->p_name);
701 }
702 }
703
704 brip_xlate_th(xl, info, EBT_IP_SPORT, pname);
705 brip_xlate_th(xl, info, EBT_IP_DPORT, pname);
706
707 brip_xlate_icmp(xl, info, EBT_IP_ICMP);
708 brip_xlate_igmp(xl, info, EBT_IP_IGMP);
709
710 return 1;
711 }
712
713 static struct xtables_match brip_match = {
714 .name = "ip",
715 .revision = 0,
716 .version = XTABLES_VERSION,
717 .family = NFPROTO_BRIDGE,
718 .size = XT_ALIGN(sizeof(struct ebt_ip_info)),
719 .userspacesize = XT_ALIGN(sizeof(struct ebt_ip_info)),
720 .init = brip_init,
721 .help = brip_print_help,
722 .parse = brip_parse,
723 .final_check = brip_final_check,
724 .print = brip_print,
725 .xlate = brip_xlate,
726 .extra_opts = brip_opts,
727 };
728
_init(void)729 void _init(void)
730 {
731 xtables_register_match(&brip_match);
732 }
733