2 * ebtables ebt_ip: IP extension module for userspace
5 * Bart De Schuymer <bdschuym@pandora.be>
8 * added ip-sport and ip-dport; parsing of port arguments is
9 * based on code from iptables-1.2.7a
10 * Innominate Security Technologies AG <mhopf@innominate.com>
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
34 #include "../include/ebtables_u.h"
35 #include <linux/netfilter_bridge/ebt_ip.h>
39 #define IP_myTOS '3' /* include/bits/in.h seems to already define IP_TOS */
44 static struct option opts[] =
46 { "ip-source" , required_argument, 0, IP_SOURCE },
47 { "ip-src" , required_argument, 0, IP_SOURCE },
48 { "ip-destination" , required_argument, 0, IP_DEST },
49 { "ip-dst" , required_argument, 0, IP_DEST },
50 { "ip-tos" , required_argument, 0, IP_myTOS },
51 { "ip-protocol" , required_argument, 0, IP_PROTO },
52 { "ip-proto" , required_argument, 0, IP_PROTO },
53 { "ip-source-port" , required_argument, 0, IP_SPORT },
54 { "ip-sport" , required_argument, 0, IP_SPORT },
55 { "ip-destination-port" , required_argument, 0, IP_DPORT },
56 { "ip-dport" , required_argument, 0, IP_DPORT },
60 /* put the ip string into 4 bytes */
61 static int undot_ip(char *ip, unsigned char *ip2)
68 strncpy(buf, ip, sizeof(buf) - 1);
71 for (i = 0; i < 3; i++) {
72 if ((q = strchr(p, '.')) == NULL)
75 onebyte = strtol(p, &end, 10);
76 if (*end != '\0' || onebyte > 255 || onebyte < 0)
78 ip2[i] = (unsigned char)onebyte;
82 onebyte = strtol(p, &end, 10);
83 if (*end != '\0' || onebyte > 255 || onebyte < 0)
85 ip2[3] = (unsigned char)onebyte;
90 /* put the mask into 4 bytes */
91 static int ip_mask(char *mask, unsigned char *mask2)
97 if (undot_ip(mask, mask2)) {
98 /* not the /a.b.c.e format, maybe the /x format */
99 bits = strtol(mask, &end, 10);
100 if (*end != '\0' || bits > 32 || bits < 0)
103 mask22 = htonl(0xFFFFFFFF << (32 - bits));
104 memcpy(mask2, &mask22, 4);
107 memcpy(mask2, &mask22, 4);
113 /* set the ip mask and ip address */
114 void parse_ip_address(char *address, uint32_t *addr, uint32_t *msk)
119 if ((p = strrchr(address, '/')) != NULL) {
121 if (ip_mask(p + 1, (unsigned char *)msk))
122 print_error("Problem with the IP mask");
127 if (undot_ip(address, (unsigned char *)addr))
128 print_error("Problem with the IP address");
129 *addr = *addr & *msk;
132 /* transform the ip mask into a string ready for output */
133 char *mask_to_dotted(uint32_t mask)
137 uint32_t maskaddr, bits;
139 maskaddr = ntohl(mask);
141 /* don't print /32 */
142 if (mask == 0xFFFFFFFFL) {
148 bits = 0xFFFFFFFEL; /* case 0xFFFFFFFF has just been dealt with */
149 while (--i >= 0 && maskaddr != bits)
153 sprintf(buf, "/%d", i);
157 /* mask was not a decent combination of 1's and 0's */
158 sprintf(buf, "/%d.%d.%d.%d", ((unsigned char *)&mask)[0],
159 ((unsigned char *)&mask)[1], ((unsigned char *)&mask)[2],
160 ((unsigned char *)&mask)[3]);
165 /* transform a protocol and service name into a port number */
166 static uint16_t parse_port(const char *protocol, const char *name)
168 struct servent *service;
172 port = strtol(name, &end, 10);
175 (service = getservbyname(name, protocol)) != NULL)
176 return ntohs(service->s_port);
178 else if (port >= 0 || port <= 0xFFFF) {
181 print_error("Problem with specified %s port '%s'",
182 protocol?protocol:"", name);
183 return 0; /* never reached */
187 parse_port_range(const char *protocol, const char *portstring, uint16_t *ports)
192 buffer = strdup(portstring);
193 if ((cp = strchr(buffer, ':')) == NULL)
194 ports[0] = ports[1] = parse_port(protocol, buffer);
198 ports[0] = buffer[0] ? parse_port(protocol, buffer) : 0;
199 ports[1] = cp[0] ? parse_port(protocol, cp) : 0xFFFF;
201 if (ports[0] > ports[1])
202 print_error("Invalid portrange (min > max)");
207 static void print_port_range(uint16_t *ports)
209 if (ports[0] == ports[1])
210 printf("%d ", ports[0]);
212 printf("%d:%d ", ports[0], ports[1]);
215 static void print_help()
219 "--ip-src [!] address[/mask]: ip source specification\n"
220 "--ip-dst [!] address[/mask]: ip destination specification\n"
221 "--ip-tos [!] tos : ip tos specification\n"
222 "--ip-proto [!] protocol : ip protocol specification\n"
223 "--ip-sport [!] port[:port] : tcp/udp source port or port range\n"
224 "--ip-dport [!] port[:port] : tcp/udp destination port or port range\n");
227 static void init(struct ebt_entry_match *match)
229 struct ebt_ip_info *ipinfo = (struct ebt_ip_info *)match->data;
231 ipinfo->invflags = 0;
235 #define OPT_SOURCE 0x01
236 #define OPT_DEST 0x02
238 #define OPT_PROTO 0x08
239 #define OPT_SPORT 0x10
240 #define OPT_DPORT 0x20
241 static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry,
242 unsigned int *flags, struct ebt_entry_match **match)
244 struct ebt_ip_info *ipinfo = (struct ebt_ip_info *)(*match)->data;
250 check_option(flags, OPT_SOURCE);
251 ipinfo->bitmask |= EBT_IP_SOURCE;
255 check_option(flags, OPT_DEST);
256 ipinfo->bitmask |= EBT_IP_DEST;
258 if (check_inverse(optarg)) {
260 ipinfo->invflags |= EBT_IP_SOURCE;
262 ipinfo->invflags |= EBT_IP_DEST;
266 print_error("Missing IP address argument");
268 parse_ip_address(argv[optind - 1], &ipinfo->saddr,
271 parse_ip_address(argv[optind - 1], &ipinfo->daddr,
278 check_option(flags, OPT_SPORT);
279 ipinfo->bitmask |= EBT_IP_SPORT;
280 if (check_inverse(optarg))
281 ipinfo->invflags |= EBT_IP_SPORT;
283 check_option(flags, OPT_DPORT);
284 ipinfo->bitmask |= EBT_IP_DPORT;
285 if (check_inverse(optarg))
286 ipinfo->invflags |= EBT_IP_DPORT;
289 print_error("Missing port argument");
291 parse_port_range(NULL, argv[optind - 1], ipinfo->sport);
293 parse_port_range(NULL, argv[optind - 1], ipinfo->dport);
297 check_option(flags, OPT_TOS);
298 if (check_inverse(optarg))
299 ipinfo->invflags |= EBT_IP_TOS;
302 print_error("Missing IP tos argument");
303 i = strtol(argv[optind - 1], &end, 16);
304 if (i < 0 || i > 255 || *end != '\0')
305 print_error("Problem with specified IP tos");
307 ipinfo->bitmask |= EBT_IP_TOS;
311 check_option(flags, OPT_PROTO);
312 if (check_inverse(optarg))
313 ipinfo->invflags |= EBT_IP_PROTO;
315 print_error("Missing IP protocol argument");
316 (unsigned char) i = strtoul(argv[optind - 1], &end, 10);
320 pe = getprotobyname(argv[optind - 1]);
323 ("Unknown specified IP protocol - %s",
325 ipinfo->protocol = pe->p_proto;
327 ipinfo->protocol = (unsigned char) i;
329 ipinfo->bitmask |= EBT_IP_PROTO;
337 static void final_check(const struct ebt_u_entry *entry,
338 const struct ebt_entry_match *match, const char *name,
339 unsigned int hookmask, unsigned int time)
341 struct ebt_ip_info *ipinfo = (struct ebt_ip_info *)match->data;
343 if (entry->ethproto != ETH_P_IP || entry->invflags & EBT_IPROTO)
344 print_error("For IP filtering the protocol must be "
345 "specified as IPv4");
347 if (ipinfo->bitmask & (EBT_IP_SPORT|EBT_IP_DPORT) &&
348 (!(ipinfo->bitmask & EBT_IP_PROTO) ||
349 ipinfo->invflags & EBT_IP_PROTO ||
350 (ipinfo->protocol!=IPPROTO_TCP &&
351 ipinfo->protocol!=IPPROTO_UDP)))
352 print_error("For port filtering the IP protocol must be "
353 "either 6 (tcp) or 17 (udp)");
356 static void print(const struct ebt_u_entry *entry,
357 const struct ebt_entry_match *match)
359 struct ebt_ip_info *ipinfo = (struct ebt_ip_info *)match->data;
362 if (ipinfo->bitmask & EBT_IP_SOURCE) {
364 if (ipinfo->invflags & EBT_IP_SOURCE)
366 for (j = 0; j < 4; j++)
367 printf("%d%s",((unsigned char *)&ipinfo->saddr)[j],
368 (j == 3) ? "" : ".");
369 printf("%s ", mask_to_dotted(ipinfo->smsk));
371 if (ipinfo->bitmask & EBT_IP_DEST) {
373 if (ipinfo->invflags & EBT_IP_DEST)
375 for (j = 0; j < 4; j++)
376 printf("%d%s", ((unsigned char *)&ipinfo->daddr)[j],
377 (j == 3) ? "" : ".");
378 printf("%s ", mask_to_dotted(ipinfo->dmsk));
380 if (ipinfo->bitmask & EBT_IP_TOS) {
382 if (ipinfo->invflags & EBT_IP_TOS)
384 printf("0x%02X ", ipinfo->tos);
386 if (ipinfo->bitmask & EBT_IP_PROTO) {
389 printf("--ip-proto ");
390 if (ipinfo->invflags & EBT_IP_PROTO)
392 pe = getprotobynumber(ipinfo->protocol);
394 printf("%d ", ipinfo->protocol);
396 printf("%s ", pe->p_name);
399 if (ipinfo->bitmask & EBT_IP_SPORT) {
400 printf("--ip-sport ");
401 if (ipinfo->invflags & EBT_IP_SPORT) {
404 print_port_range(ipinfo->sport);
406 if (ipinfo->bitmask & EBT_IP_DPORT) {
407 printf("--ip-dport ");
408 if (ipinfo->invflags & EBT_IP_DPORT) {
411 print_port_range(ipinfo->dport);
415 static int compare(const struct ebt_entry_match *m1,
416 const struct ebt_entry_match *m2)
418 struct ebt_ip_info *ipinfo1 = (struct ebt_ip_info *)m1->data;
419 struct ebt_ip_info *ipinfo2 = (struct ebt_ip_info *)m2->data;
421 if (ipinfo1->bitmask != ipinfo2->bitmask)
423 if (ipinfo1->invflags != ipinfo2->invflags)
425 if (ipinfo1->bitmask & EBT_IP_SOURCE) {
426 if (ipinfo1->saddr != ipinfo2->saddr)
428 if (ipinfo1->smsk != ipinfo2->smsk)
431 if (ipinfo1->bitmask & EBT_IP_DEST) {
432 if (ipinfo1->daddr != ipinfo2->daddr)
434 if (ipinfo1->dmsk != ipinfo2->dmsk)
437 if (ipinfo1->bitmask & EBT_IP_TOS) {
438 if (ipinfo1->tos != ipinfo2->tos)
441 if (ipinfo1->bitmask & EBT_IP_PROTO) {
442 if (ipinfo1->protocol != ipinfo2->protocol)
445 if (ipinfo1->bitmask & EBT_IP_SPORT) {
446 if (ipinfo1->sport[0] != ipinfo2->sport[0] ||
447 ipinfo1->sport[1] != ipinfo2->sport[1])
450 if (ipinfo1->bitmask & EBT_IP_DPORT) {
451 if (ipinfo1->dport[0] != ipinfo2->dport[0] ||
452 ipinfo1->dport[1] != ipinfo2->dport[1])
458 static struct ebt_u_match ip_match =
460 .name = EBT_IP_MATCH,
461 .size = sizeof(struct ebt_ip_info),
465 .final_check = final_check,
471 static void _init(void) __attribute((constructor));
472 static void _init(void)
474 register_match(&ip_match);