home *** CD-ROM | disk | FTP | other *** search
- /*
- ********************************************************************************
- *
- * Copyright (c) 1993 Daniel Boulet
- *
- * Redistribution and use in source forms, with and without modification,
- * are permitted provided that this entire comment appears intact.
- *
- * Redistribution in binary form may occur without any restrictions.
- * Obviously, it would be nice if you gave credit where credit is due
- * but requiring it would be too onerous.
- *
- * This software is provided ``AS IS'' without any warranties of any kind.
- *
- ********************************************************************************
- *
- *
- * Linux port (c) 1994 Bob Beck
- *
- * Redistribution and use in source forms, with and without modification,
- * are permitted provided that this entire comment appears intact.
- *
- * This software is provided ``AS IS'' without any warranties of any kind.
- *
- ********************************************************************************
- *
- * Drastically cleaned up: Alan Cox <Alan.Cox@linux.org>
- * More (major) cleanups and bug fixes by Salvador Abreu <spa@fct.unl.pt>
- * Additional options Lutz Pre"sler <Lutz.Pressler@med-stat.gwdg.de>
- * Masquerade client support added <Alan.Cox@linux.org>
- */
-
- #include <sys/types.h>
- #ifdef _LINUX_TYPES_H
- /* Yep. it's Linux */
- #ifndef LINUX
- #define LINUX
- #endif
- #endif
- #include <sys/socket.h>
- #define IPFIREWALL
- #include <netinet/in.h>
- #include <netinet/ip.h>
- #include <netinet/tcp.h>
- #include <netinet/udp.h>
- #ifndef LINUX
- #include <netinet/ip_fw.h>
- #else
- #include <linux/ip_fw.h> /* Until it gets into stdinc */
- #endif
- #include <netdb.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
- #ifdef LINUX
- #include <ctype.h>
- #define IPVERSION 4
- #endif
-
- #ifdef IP_FW_F_MASQ
- #define DO_MASQUERADE
- #endif
-
- typedef enum
- {
- IPF_BLOCKING = 0,
- IPF_FORWARDING = 1,
- IPF_ACCOUNTING = 2,
- IPF_MASQUERADE = 3
- } ipf_kind;
-
- static char *ipf_names[4] = {"blocking", "forwarding", "accounting", "maquerading"};
- static long ipf_addfunc[4] = {IP_FW_ADD_BLK, IP_FW_ADD_FWD, IP_ACCT_ADD, IP_FW_ADD_FWD};
- static long ipf_delfunc[4] = {IP_FW_DEL_BLK, IP_FW_DEL_FWD, IP_ACCT_DEL, IP_FW_DEL_FWD};
- static int lookup = 1;
-
- void show_usage()
- {
- fprintf(stderr, "usage: ipfirewall [-n] l[ist]\n");
- fprintf(stderr, "\t\t| f[lush] a[ccounting]\n");
- fprintf(stderr, "\t\t| f[lush] f[irewall]\n");
- fprintf(stderr, "\t\t| c[heck] b[locking] <type> from <src> to <dst>\n");
- fprintf(stderr, "\t\t| c[heck] f[orwarding] <type> from <src> to <dst>\n");
- fprintf(stderr, "\t\t| a[dd] a[ccounting] <type> from <src> to <dst>\n");
- fprintf(stderr, "\t\t| a[dd] b[locking] <type> from <src> to <dst>\n");
- fprintf(stderr, "\t\t| a[dd] f[orwarding] <type> from <src> to <dst>\n");
- #ifdef DO_MASQUERADE
- fprintf(stderr, "\t\t| a[dd] m[asquerade] <type> from <src> to <dst>\n");
- #endif
- fprintf(stderr, "\t\t| d[el] a[ccounting] <type> from <src> to <dst>\n");
- fprintf(stderr, "\t\t| d[el] b[locking] <type> from <src> to <dst>\n");
- fprintf(stderr, "\t\t| d[el] f[orwarding] <type> from <src> to <dst>\n");
- #ifdef DO_MASQUERADE
- fprintf(stderr, "\t\t| d[el] m[asquerade] <type> from <src> to <dst>\n");
- #endif
- fprintf(stderr, "\t\t| zero[accounting]\n");
- }
-
- /*
- * I'm not sure that this is practical ...
- */
-
- void show_help()
- {
- show_usage();
- fprintf(stderr, "where:\n");
- fprintf(stderr, " <src> ::= <host>:<port> /* for TCP or UDP */\n");
- fprintf(stderr, " <src> ::= <host> /* for ICMP */\n");
- fprintf(stderr, " <host> ::= <byte>.<byte>.<byte>.<byte>[/<width>]\n");
- fprintf(stderr, " | <hostname>\n");
- fprintf(stderr, " <port> ::= <short> | <servicename>\n");
- fprintf(stderr, " <short> ::= an integer in the range 1-65535\n");
- fprintf(stderr, " <byte> ::= an integer in the range 0-255\n");
- fprintf(stderr, " <width> ::= an integer in the range 0-32\n");
- exit(1);
- }
-
- static char *fmtip(u_long uaddr)
- {
- static char tbuf[100];
-
- sprintf(tbuf, "%d.%d.%d.%d",
- ((char *) &uaddr)[0] & 0xff,
- ((char *) &uaddr)[1] & 0xff,
- ((char *) &uaddr)[2] & 0xff,
- ((char *) &uaddr)[3] & 0xff);
-
- return (&tbuf[0]);
- }
-
- static void print_ports(int cnt, int range, u_short * ports)
- {
- int ix;
- char *pad;
-
- if (range)
- {
- if (cnt < 2)
- {
- fprintf(stderr,
- "ipfw: range flag set but only %d ports\n", cnt);
- exit(1);
- }
- printf("%d:%d", ports[0], ports[1]);
- ix = 2;
- pad = " ";
- }
- else
- {
- ix = 0;
- pad = "";
- }
-
- while (ix < cnt)
- {
- printf("%s%d", pad, ports[ix]);
- pad = " ";
- ix += 1;
- }
- }
-
- static int do_setsockopt(char *what, int fd, int proto, int cmd, void *data, int datalen, int ok_errno)
- {
- char *cmdname;
-
- #define CASE(NAME) case IP_##NAME: cmdname = "IP_" #NAME; break
-
- switch (cmd)
- {
- CASE(FW_FLUSH);
- CASE(FW_CHK_BLK);
- CASE(FW_CHK_FWD);
- CASE(FW_ADD_BLK);
- CASE(FW_ADD_FWD);
- CASE(FW_DEL_BLK);
- CASE(FW_DEL_FWD);
- CASE(ACCT_ADD);
- CASE(ACCT_DEL);
- CASE(ACCT_FLUSH);
- CASE(ACCT_ZERO);
- default:
- fprintf(stderr, "ipfw: "
- "unknown command (%d) passed to do_setsockopt - bye!\n", cmd);
- exit(1);
- }
-
- #undef CASE
-
- if (fd < 0)
- {
- printf("setsockopt(%d, %d, %s, 0x%x, 0x%x)\n",
- fd, proto, cmdname, (int) data, datalen);
- if (cmd == IP_FW_CHK_BLK || cmd == IP_FW_CHK_FWD)
- {
- struct iphdr *ip = (struct iphdr *) data;
- struct tcphdr *tcp = (struct tcphdr *) &(((int *) ip)[ip->ihl]);
- if (ip->ihl != sizeof(struct iphdr) / sizeof(int))
- {
- fprintf(stderr, "ip header length %d, should be %d\n",
- ip->ihl, sizeof(struct iphdr) / sizeof(int));
- }
- if (ip->protocol != IPPROTO_TCP && ip->protocol != IPPROTO_UDP)
- exit(1);
- printf("data = struct iphdr : struct %shdr {\n",
- ip->protocol == IPPROTO_TCP ? "tcp" : "udp");
- printf("\tsrc=%s ", fmtip(ip->saddr));
- printf("%d\n", ntohs(tcp->th_sport));
- printf("\tdst=%s ", fmtip(ip->daddr));
- printf("%d\n", ntohs(tcp->th_dport));
- printf("}\n");
- }
- else if (cmd == IP_FW_ADD_BLK ||
- cmd == IP_FW_ADD_FWD ||
- cmd == IP_ACCT_ADD)
- {
- struct ip_fw *fp = (struct ip_fw *) data;
- int fmt_ports = 0;
- printf("data = struct ip_fw {\n");
- if (fp->flags & IP_FW_F_ACCEPT)
- {
- printf("\taccept ");
- }
- else
- {
- printf("\tdeny ");
- }
- switch (fp->flags & IP_FW_F_KIND)
- {
- case IP_FW_F_ALL:
- printf("\tuniversal\n");
- fmt_ports = 0;
- break;
- case IP_FW_F_TCP:
- printf("tcp\n");
- fmt_ports = 1;
- break;
- case IP_FW_F_UDP:
- printf("udp\n");
- fmt_ports = 1;
- break;
- case IP_FW_F_ICMP:
- printf("icmp\n");
- fmt_ports = 0;
- break;
- }
- printf("\tsrc=%s:", fmtip(fp->src.s_addr));
- printf("%s ", fmtip(fp->src_mask.s_addr));
- if (fmt_ports)
- {
- print_ports(fp->n_src_p, fp->flags & IP_FW_F_SRNG, &fp->ports[0]);
- }
- else if (fp->flags & (IP_FW_F_SRNG | IP_FW_F_DRNG))
- {
- exit(1);
- }
- else if (fp->n_src_p > 0 || fp->n_dst_p > 0)
- {
- exit(1);
- }
- printf("\n");
- printf("\tdst=%s:", fmtip(fp->dst.s_addr));
- printf("%s ", fmtip(fp->dst_mask.s_addr));
- if (fmt_ports)
- {
- print_ports(fp->n_dst_p,
- fp->flags & IP_FW_F_DRNG,
- &fp->ports[fp->n_src_p]);
- }
- printf("\n");
- printf("}\n");
- }
- }
- else
- {
- if (setsockopt(fd, proto, cmd, data, datalen) < 0)
- {
- char msg[128];
-
- if (errno == ok_errno)
- {
- return (errno);
- }
- sprintf(msg, "ipfw: setsockopt(%s)", cmdname);
- perror(msg);
- exit(1);
- }
- }
- return (0);
- }
-
- void show_parms(char **argv)
- {
- while (*argv)
- {
- printf("%s ", *argv++);
- }
- }
-
- int get_protocol(char *arg, void (*cmd_usage) (ipf_kind), ipf_kind kind)
- {
- if (arg == NULL)
- {
- fprintf(stderr, "ipfw: missing protocol name\n");
- }
- else if (strcmp(arg, "tcp") == 0)
- {
- return (IP_FW_F_TCP);
- }
- else if (strcmp(arg, "udp") == 0)
- {
- return (IP_FW_F_UDP);
- }
- else if (strcmp(arg, "icmp") == 0)
- {
- return (IP_FW_F_ICMP);
- }
- else if (strcmp(arg, "all") == 0)
- {
- return (IP_FW_F_ALL);
- }
- else
- {
- fprintf(stderr, "illegal protocol name \"%s\"\n", arg);
- }
- (*cmd_usage) (kind);
- exit(1);
- return (0);
- }
-
- void get_ipaddr(char *arg, struct in_addr *addr, struct in_addr *mask, void (*usage) (ipf_kind), ipf_kind kind)
- {
- char *p, *tbuf;
- int period_cnt, non_digit;
- struct hostent *hptr;
-
- if (arg == NULL)
- {
- fprintf(stderr, "ipfw: missing ip address\n");
- exit(1);
- }
- period_cnt = 0;
- non_digit = 0;
- for (p = arg; *p != '\0' && *p != '/' && *p != ':'; p += 1)
- {
- if (*p == '.')
- {
- if (p > arg && *(p - 1) == '.')
- {
- fprintf(stderr, "ipfw: two periods in a row in ip address (%s)\n", arg);
- exit(1);
- }
- period_cnt += 1;
- }
- else if (!isdigit(*p))
- {
- non_digit = 1;
- }
- }
-
- tbuf = malloc(p - arg + 1);
- strncpy(tbuf, arg, p - arg);
- tbuf[p - arg] = '\0';
-
- if (non_digit)
- {
- hptr = gethostbyname(tbuf);
- if (hptr == NULL)
- {
- fprintf(stderr, "ipfw: unknown host \"%s\"\n", tbuf);
- exit(1);
- }
- if (hptr->h_length != sizeof(struct in_addr))
- {
- fprintf(stderr,
- "ipfw: hostentry addr length = %d, expected %d"
- "(i.e. sizeof(struct in_addr))\n",
- hptr->h_length, sizeof(struct in_addr));
- exit(1);
- }
- bcopy(hptr->h_addr, addr, sizeof(struct in_addr));
- }
- else
- {
- if (period_cnt == 3)
- {
-
- int a1, a2, a3, a4, matched;
-
- if ((matched = sscanf(tbuf, "%d.%d.%d.%d", &a1, &a2, &a3, &a4))
- != 4)
- {
- fprintf(stderr,
- "ipfw: Only %d fields matched in IP address!\n",
- matched);
- /* should this exit here? or catch it later? -BB */
- }
- if (a1 > 255 || a2 > 255 || a3 > 255 || a4 > 255)
- {
- fprintf(stderr, "ipfw: number too large in ip address (%s)\n", arg);
- exit(1);
- }
- ((char *) addr)[0] = a1;
- ((char *) addr)[1] = a2;
- ((char *) addr)[2] = a3;
- ((char *) addr)[3] = a4;
-
- }
- else if (strcmp(tbuf, "0") == 0)
- {
-
- ((char *) addr)[0] = 0;
- ((char *) addr)[1] = 0;
- ((char *) addr)[2] = 0;
- ((char *) addr)[3] = 0;
-
- }
- else
- {
-
- fprintf(stderr, "ipfw: incorrect ip address format \"%s\" (expected 3 periods)\n", tbuf);
- exit(1);
- }
- }
-
- free(tbuf);
-
- if (mask == NULL)
- {
- if (*p != '\0')
- {
- fprintf(stderr, "ipfw: ip netmask not allowed here (%s)\n", (char *) addr);
- exit(1);
- }
- }
- else
- {
- if (*p == ':')
- {
- get_ipaddr(p + 1, mask, NULL, usage, kind);
- }
- else if (*p == '/')
- {
- int bits;
- char *end;
-
- p += 1;
- if (*p == '\0')
- {
- fprintf(stderr, "ipfw: missing mask value (%s)\n", arg);
- exit(1);
- }
- else if (!isdigit(*p))
- {
- fprintf(stderr, "ipfw: non-numeric mask value (%s)\n", arg);
- exit(1);
- }
- bits = strtol(p, &end, 10);
- if (*end != '\0')
- {
- fprintf(stderr, "ipfw: junk after mask (%s)\n", arg);
- exit(1);
- }
- if (bits < 0 || bits > sizeof(u_long) * 8)
- {
- fprintf(stderr, "ipfw: mask length value out of range (%s)\n", arg);
- exit(1);
- }
- if (bits == 0)
- { /* left shifts of 32 aren't defined */
- mask->s_addr = 0;
- }
- else
- {
- ((char *) mask)[0] = (-1 << (32 - bits)) >> 24;
- ((char *) mask)[1] = (-1 << (32 - bits)) >> 16;
- ((char *) mask)[2] = (-1 << (32 - bits)) >> 8;
- ((char *) mask)[3] = (-1 << (32 - bits)) >> 0;
- }
-
- }
- else if (*p == '\0')
- {
- mask->s_addr = 0xffffffff;
- }
- else
- {
- fprintf(stderr, "ipfw: junk after ip address (%s)\n", arg);
- exit(1);
- }
-
- /*
- * Mask off any bits in the address that are zero in the mask.
- * This allows the user to describe a network by specifying
- * any host on the network masked with the network's netmask.
- */
- addr->s_addr &= mask->s_addr;
-
- }
-
- }
-
- u_short get_one_port(char *arg, void (*usage) (ipf_kind), ipf_kind kind, const char *proto_name)
- {
- int slen = strlen(arg);
-
- if (slen > 0 && strspn(arg, "0123456789") == slen)
- {
- int port;
- char *end;
-
- port = strtol(arg, &end, 10);
- if (*end != '\0')
- {
- fprintf(stderr, "ipfw: illegal port number (%s)\n", arg);
- exit(1);
- }
- if (port <= 0 || port > 65535)
- {
- fprintf(stderr, "ipfw: port number out of range (%d)\n", port);
- exit(1);
- }
- return (port);
- }
- else
- {
- struct servent *sptr;
-
- sptr = getservbyname(arg, proto_name);
-
- if (sptr == NULL)
- {
- fprintf(stderr, "ipfw: unknown %s service \"%s\"\n", proto_name, arg);
- exit(1);
- }
- return (ntohs(sptr->s_port));
- }
- }
-
- int get_ports(char ***argv_ptr, u_short * ports, int min_ports, int max_ports, void (*usage) (ipf_kind), ipf_kind kind, const char *proto_name)
- {
- int ix;
- char *arg;
- int sign;
-
- ix = 0;
- sign = 1;
- while ((arg = **argv_ptr) != NULL &&
- strcmp(arg, "from") != 0 &&
- strcmp(arg, "to") != 0)
- {
- char *p;
-
- /*
- * Check that we havn't found too many port numbers.
- * We do this here instead of with another condition on the while loop
- * so that the caller can assume that the next parameter is NOT a
- * port number.
- */
-
- if (ix >= max_ports)
- {
- fprintf(stderr, "ipfw: too many port numbers "
- "(max %d, got at least %d, next parm=\"%s\")\n",
- max_ports, max_ports + 1, arg);
- exit(1);
- }
- if ((p = strchr(arg, ':')) == NULL)
- {
- ports[ix++] = get_one_port(arg, usage, kind, proto_name);
- }
- else
- {
- if (ix > 0)
- {
- fprintf(stderr, "ipfw: "
- "port ranges are only allowed for "
- "the first port value pair (%s)\n", arg);
- exit(1);
- }
- if (max_ports > 1)
- {
- char *tbuf;
-
- tbuf = malloc((p - arg) + 1);
- strncpy(tbuf, arg, p - arg);
- tbuf[p - arg] = '\0';
-
- ports[ix++] = get_one_port(tbuf, usage, kind, proto_name);
- ports[ix++] = get_one_port(p + 1, usage, kind, proto_name);
- sign = -1;
- }
- else
- {
- fprintf(stderr,
- "ipfw: port range not allowed here (%s)\n", arg);
- exit(1);
- }
- }
-
- *argv_ptr += 1;
- }
-
- if (ix < min_ports)
- {
- if (min_ports == 1)
- {
- fprintf(stderr, "ipfw: missing port number%s\n",
- max_ports == 1 ? "" : "(s)");
- }
- else
- {
- fprintf(stderr,
- "ipfw: not enough port numbers (expected %d, got %d)\n",
- min_ports, ix);
- }
- exit(1);
- }
- return (sign * ix);
- }
-
- void check_usage(ipf_kind kind)
- {
- fprintf(stderr, "usage: ipfirewall check %s ...\n", ipf_names[kind]);
- }
-
- void check(ipf_kind kind, int socket_fd, char **argv)
- {
- int protocol;
- struct iphdr *packet;
- char *proto_name;
-
- packet = (struct iphdr *) malloc
- (sizeof(struct iphdr) + sizeof(struct tcphdr));
- packet->version = IPVERSION;
- packet->ihl = sizeof(struct iphdr) / sizeof(int);
- printf("check %s ", kind == IPF_BLOCKING ? "blocking" : "forwarding");
- show_parms(argv);
- printf("\n");
-
- proto_name = *argv++;
- protocol = get_protocol(proto_name, check_usage, kind);
- switch (protocol)
- {
- case IP_FW_F_TCP:
- packet->protocol = IPPROTO_TCP;
- break;
- case IP_FW_F_UDP:
- packet->protocol = IPPROTO_UDP;
- break;
- default:
- fprintf(stderr, "ipfw: can only check TCP or UDP packets\n");
- break;
- }
-
- if (*argv == NULL)
- {
- fprintf(stderr, "ipfw: missing \"from\" keyword\n");
- exit(1);
- }
- if (strcmp(*argv, "from") == 0)
- {
- argv += 1;
- get_ipaddr(*argv++, (struct in_addr *) &packet->saddr,
- NULL, check_usage, kind);
- if (protocol == IP_FW_F_TCP || protocol == IP_FW_F_UDP)
- {
- get_ports(&argv, &((struct tcphdr *) (&packet[1]))->th_sport,
- 1, 1, check_usage, kind, proto_name);
- ((struct tcphdr *) (&packet[1]))->th_sport = htons(
- ((struct tcphdr *) (&packet[1]))->th_sport);
- }
- }
- else
- {
- fprintf(stderr,
- "ipfw: expected \"from\" keyword, got \"%s\"\n", *argv);
- exit(1);
- }
-
- if (*argv == NULL)
- {
- fprintf(stderr, "ipfw: missing \"to\" keyword\n");
- exit(1);
- }
- if (strcmp(*argv, "to") == 0)
- {
- argv += 1;
- get_ipaddr(*argv++, (struct in_addr *) &packet->daddr,
- NULL, check_usage, kind);
- if (protocol == IP_FW_F_TCP || protocol == IP_FW_F_UDP)
- {
- get_ports(&argv, &((struct tcphdr *) (&packet[1]))->th_dport,
- 1, 1, check_usage, kind, proto_name);
- ((struct tcphdr *) (&packet[1]))->th_dport = htons(
- ((struct tcphdr *) (&packet[1]))->th_dport);
- }
- }
- else
- {
- fprintf(stderr,
- "ipfw: expected \"to\" keyword, got \"%s\"\n", *argv);
- exit(1);
- }
-
- if (*argv == NULL)
- {
- if (do_setsockopt(kind == IPF_BLOCKING ? "checkblocking" : "checkforwarding",
- socket_fd, IPPROTO_IP,
- kind == IPF_BLOCKING ? IP_FW_CHK_BLK : IP_FW_CHK_FWD,
- packet,
- sizeof(struct iphdr) + sizeof(struct tcphdr),
- EACCES) == 0)
- {
- printf("packet accepted by %s firewall\n",
- kind == IPF_BLOCKING ? "blocking" : "forwarding");
- }
- else
- {
- printf("packet rejected by %s firewall\n",
- kind == IPF_BLOCKING ? "blocking" : "forwarding");
- }
-
- return;
- }
- else
- {
- fprintf(stderr, "ipfw: extra parameters at end of command (");
- show_parms(argv);
- fprintf(stderr, ")\n");
- exit(1);
- }
- }
-
- void add_usage(ipf_kind kind)
- {
- fprintf(stderr, "usage: ipfirewall add %s ...\n", ipf_names[kind]);
- }
-
- void add(ipf_kind kind, int socket_fd, char **argv)
- {
- int protocol, accept_firewall, src_range, dst_range;
- struct ip_fw firewall;
- char *proto_name;
-
- printf("add %s ", ipf_names[kind]);
- show_parms(argv);
- printf("\n");
-
- if (kind != IPF_ACCOUNTING && kind != IPF_MASQUERADE)
- {
- if (*argv == NULL)
- {
- fprintf(stderr, "ipfw: missing \"accept\" or \"deny\" keyword\n");
- exit(1);
- }
- if (strcmp(*argv, "deny") == 0)
- {
- accept_firewall = 0;
- }
- else if (strcmp(*argv, "accept") == 0)
- {
- accept_firewall = IP_FW_F_ACCEPT;
- }
- else
- {
- fprintf(stderr,
- "ipfw: expected \"accept\" or \"deny\", got \"%s\"\n",
- *argv);
- exit(1);
- }
-
- argv += 1;
- }
- else
- accept_firewall = 1;
- proto_name = *argv++;
- protocol = get_protocol(proto_name, add_usage, kind);
-
- if (*argv == NULL)
- {
- fprintf(stderr, "ipfw: missing \"from\" keyword\n");
- exit(1);
- }
- if (strcmp(*argv, "from") == 0)
- {
- argv++;
- get_ipaddr(*argv++, &firewall.src, &firewall.src_mask, add_usage, kind);
- if (protocol == IP_FW_F_TCP || protocol == IP_FW_F_UDP)
- {
- int cnt;
- cnt = get_ports(&argv, &firewall.ports[0], 0, IP_FW_MAX_PORTS,
- add_usage, kind, proto_name);
- if (cnt < 0)
- {
- src_range = IP_FW_F_SRNG;
- cnt = -cnt;
- }
- else
- {
- src_range = 0;
- }
- firewall.n_src_p = cnt;
- }
- else
- {
- firewall.n_src_p = 0;
- src_range = 0;
- }
- }
- else
- {
- fprintf(stderr, "ipfw: expected \"from\", got \"%s\"\n", *argv);
- exit(1);
- }
-
- if (*argv == NULL)
- {
- fprintf(stderr, "ipfw: missing \"to\" keyword\n");
- exit(1);
- }
- if (strcmp(*argv, "to") == 0)
- {
- argv++;
- get_ipaddr(*argv++, &firewall.dst, &firewall.dst_mask, add_usage, kind);
- if (protocol == IP_FW_F_TCP || protocol == IP_FW_F_UDP)
- {
- int cnt;
- cnt = get_ports(&argv, &firewall.ports[firewall.n_src_p], 0,
- IP_FW_MAX_PORTS - firewall.n_src_p,
- add_usage, kind, proto_name);
- if (cnt < 0)
- {
- dst_range = IP_FW_F_DRNG;
- cnt = -cnt;
- }
- else
- {
- dst_range = 0;
- }
- firewall.n_dst_p = cnt;
- }
- else
- {
- firewall.n_dst_p = 0;
- dst_range = 0;
- }
- }
- else
- {
- fprintf(stderr, "ipfw: expected \"to\", got \"%s\"\n", *argv);
- exit(1);
- }
-
- if (*argv == NULL)
- {
- firewall.flags = protocol | accept_firewall | src_range | dst_range;
- #ifdef DO_MASQUERADE
- if (kind == IPF_MASQUERADE)
- firewall.flags |= IP_FW_F_MASQ;
- #endif
- (void) do_setsockopt(ipf_names[kind],
- socket_fd, IPPROTO_IP,
- ipf_addfunc[kind],
- &firewall,
- sizeof(firewall),
- 0);
- }
- else
- {
- fprintf(stderr, "ipfw: extra parameters at end of command (");
- show_parms(argv);
- fprintf(stderr, ")\n");
- exit(1);
- }
- }
-
- void del_usage(ipf_kind kind)
- {
- fprintf(stderr, "usage: ipfirewall delete %s ...\n", ipf_names[kind]);
- }
-
- void del(ipf_kind kind, int socket_fd, char **argv)
- {
- int protocol, accept_firewall, src_range, dst_range;
- struct ip_fw firewall;
- char *proto_name;
-
- printf("delete %s ", ipf_names[kind]);
- show_parms(argv);
- printf("\n");
-
- if (kind != IPF_ACCOUNTING && kind != IPF_MASQUERADE)
- {
- if (*argv == NULL)
- {
- fprintf(stderr, "ipfw: missing \"accept\" or \"deny\" keyword\n");
- exit(1);
- }
- if (strcmp(*argv, "deny") == 0)
- {
- accept_firewall = 0;
- }
- else if (strcmp(*argv, "accept") == 0)
- {
- accept_firewall = IP_FW_F_ACCEPT;
- }
- else
- {
- fprintf(stderr,
- "ipfw: expected \"accept\" or \"deny\", got \"%s\"\n",
- *argv);
- exit(1);
- }
-
- argv += 1;
- }
- else
- accept_firewall = 1;
- proto_name = *argv++;
- protocol = get_protocol(proto_name, del_usage, kind);
-
- if (*argv == NULL)
- {
- fprintf(stderr, "ipfw: missing \"from\" keyword\n");
- exit(1);
- }
- if (strcmp(*argv, "from") == 0)
- {
- argv++;
- get_ipaddr(*argv++, &firewall.src, &firewall.src_mask, del_usage, kind);
- if (protocol == IP_FW_F_TCP || protocol == IP_FW_F_UDP)
- {
- int cnt;
- cnt = get_ports(&argv, &firewall.ports[0], 0, IP_FW_MAX_PORTS,
- del_usage, kind, proto_name);
- if (cnt < 0)
- {
- src_range = IP_FW_F_SRNG;
- cnt = -cnt;
- }
- else
- {
- src_range = 0;
- }
- firewall.n_src_p = cnt;
- }
- else
- {
- firewall.n_src_p = 0;
- src_range = 0;
- }
- }
- else
- {
- fprintf(stderr, "ipfw: expected \"from\", got \"%s\"\n", *argv);
- exit(1);
- }
-
- if (*argv == NULL)
- {
- fprintf(stderr, "ipfw: missing \"to\" keyword\n");
- exit(1);
- }
- if (strcmp(*argv, "to") == 0)
- {
- argv++;
- get_ipaddr(*argv++, &firewall.dst, &firewall.dst_mask, del_usage, kind);
- if (protocol == IP_FW_F_TCP || protocol == IP_FW_F_UDP)
- {
- int cnt;
- cnt = get_ports(&argv, &firewall.ports[firewall.n_src_p], 0,
- IP_FW_MAX_PORTS - firewall.n_src_p,
- del_usage, kind, proto_name);
- if (cnt < 0)
- {
- dst_range = IP_FW_F_DRNG;
- cnt = -cnt;
- }
- else
- {
- dst_range = 0;
- }
- firewall.n_dst_p = cnt;
- }
- else
- {
- firewall.n_dst_p = 0;
- dst_range = 0;
- }
- }
- else
- {
- fprintf(stderr, "ipfw: expected \"to\", got \"%s\"\n", *argv);
- exit(1);
- }
-
- if (*argv == NULL)
- {
- firewall.flags = protocol | accept_firewall | src_range | dst_range;
- #ifdef DO_MASQUERADE
- if (kind == IPF_MASQUERADE)
- firewall.flags |= IP_FW_F_MASQ;
- #endif
- (void) do_setsockopt(ipf_names[kind],
- socket_fd, IPPROTO_IP,
- ipf_delfunc[kind],
- &firewall,
- sizeof(firewall),
- 0);
- }
- else
- {
- fprintf(stderr, "ipfw: extra parameters at end of command (");
- show_parms(argv);
- fprintf(stderr, ")\n");
- exit(1);
- }
- }
-
- static int count_mask(unsigned long mask)
- {
- int ct;
- for (ct = 0; (mask & 0x80000000); ct++)
- mask <<= 1;
- return ct;
- }
-
- typedef struct
- {
- int acct;
- unsigned long sa, da, sm, dm;
- unsigned int nsp, ndp;
- unsigned long npkt, nbyt;
- unsigned int ports[10];
- int flags;
- } fw_rec;
-
- #define MIN(a,b) ((a)<(b)? (a): (b))
- #define SRC(x) ((x)->sa & (x)->sm)
- #define DST(x) ((x)->da & (x)->dm)
-
- static int int_order(const void *L, const void *R)
- {
- return (*(unsigned int *) R - *(unsigned int *) L);
- }
-
- static int list_order(const void *L, const void *R)
- {
- register const fw_rec *l = L;
- register const fw_rec *r = R;
-
- register int result =
- ((r->flags & IP_FW_F_KIND) - (l->flags & IP_FW_F_KIND)) ? :
- (MIN(SRC(r), DST(r)) - MIN(SRC(l), DST(l)));
-
- if (result == 0 && (l->flags & (IP_FW_F_TCP | IP_FW_F_UDP)))
- {
- unsigned int nlp, lp[10], nrp, rp[10];
- unsigned int i;
-
- bzero(lp, 10 * sizeof(unsigned int));
- bzero(rp, 10 * sizeof(unsigned int));
-
- bcopy(l->ports, lp, (nlp = l->nsp + l->ndp) * sizeof(unsigned int));
- bcopy(r->ports, rp, (nrp = r->nsp + r->ndp) * sizeof(unsigned int));
-
- qsort(lp, nlp, sizeof(unsigned int), int_order);
- qsort(rp, nrp, sizeof(unsigned int), int_order);
-
- for (i = 0; i < 10; ++i)
- if (lp[i] != rp[i])
- return (lp[i] - rp[i]);
- }
- return result;
- }
-
- static char *addr_to_name(unsigned int a, unsigned int m)
- {
- static char tbuf[128];
- struct hostent *hptr;
- struct netent *nptr;
-
- if (m == 0)
- strcpy(tbuf, "anywhere");
- else
- {
- int mask_len = count_mask(m);
- struct in_addr ia =
- {htonl(a)};
-
- if (lookup && (hptr = gethostbyaddr((char *) &ia, sizeof ia, AF_INET)))
- strcpy(tbuf, hptr->h_name);
- else if (lookup && (nptr = getnetbyaddr(a, AF_INET)))
- sprintf(tbuf, "=%s", nptr->n_name);
- else
- sprintf(tbuf, "%s/%d", fmtip(htonl(a)), mask_len);
- }
-
- return tbuf;
- }
-
- void list_file(char *path, int acct)
- {
- FILE *f = fopen(path, "r");
- int nrecs = 8;
- int nused = 0;
- fw_rec *recs = (void *) malloc(sizeof(fw_rec) * nrecs);
- fw_rec *rec;
- char buf[256];
- struct servent *sptr;
-
- if (f == NULL)
- {
- perror(path);
- exit(1);
- }
- fgets(buf, 255, f); /* skip title */
- while (fgets(buf, 255, f))
- { /* read in the data */
- if (nused >= nrecs)
- {
- nrecs <<= 1;
- recs = (void *) realloc(recs, sizeof(fw_rec) * nrecs);
- }
- rec = &recs[nused++];
-
- rec->acct = acct;
- sscanf(buf,
- "%lX/%lX->%lX/%lX %X %u %u %lu %lu %u %u %u %u %u %u %u %u %u %u",
- &rec->sa, &rec->sm, &rec->da, &rec->dm,
- &rec->flags, &rec->nsp, &rec->ndp, &rec->npkt, &rec->nbyt,
- &rec->ports[0], &rec->ports[1], &rec->ports[2], &rec->ports[3],
- &rec->ports[4], &rec->ports[5], &rec->ports[6], &rec->ports[7],
- &rec->ports[8], &rec->ports[9]);
- }
- fclose(f);
-
- qsort(recs, nused, sizeof(fw_rec), list_order);
-
- if (acct)
- printf("Packets\t Bytes\t");
- else
- printf("Type\t");
- printf("Proto %19.19s %19.19s Ports\n",
- "From ", "To ");
-
- for (rec = recs; nused-- > 0; ++rec)
- {
- unsigned int *pp = &rec->ports[0];
-
- if (!rec->acct)
- {
- #ifdef DO_MASQUERADE
- if (rec->flags & IP_FW_F_MASQ)
- printf("(masquerade");
- else
- #endif
- {
- if (rec->flags & IP_FW_F_ACCEPT)
- printf("accept\t");
- else
- printf("deny\t");
- }
- }
- else
- {
- printf("%7lu\t", rec->npkt);
- if (rec->nbyt > 100 * 1024)
- {
- unsigned long kbyt = (rec->nbyt + 1023) / 1024;
- if (kbyt > 100 * 1024)
- {
- unsigned long mbyt = (kbyt + 1023) / 1024;
- printf("%6luM\t", mbyt);
- }
- else
- printf("%6luK\t", kbyt);
- }
- else
- printf("%6lu \t", rec->nbyt);
- }
-
- switch (rec->flags & IP_FW_F_KIND)
- {
- case IP_FW_F_ALL:
- printf("all ");
- break;
- case IP_FW_F_TCP:
- printf("tcp ");
- break;
- case IP_FW_F_UDP:
- printf("udp ");
- break;
- case IP_FW_F_ICMP:
- printf("icmp ");
- break;
- }
-
- printf("%-19.19s ", addr_to_name(rec->sa, rec->sm));
- printf("%-19.19s ", addr_to_name(rec->da, rec->dm));
-
- if (rec->flags & (IP_FW_F_TCP | IP_FW_F_UDP))
- {
- char *sep = "";
- char *proto = (rec->flags & IP_FW_F_TCP) ? "tcp" : "udp";
-
- if (rec->nsp == 0)
- printf("any");
- else
- {
- if (rec->flags & IP_FW_F_SRNG)
- {
- printf("%u-%u", pp[0], pp[1]);
- sep = ",";
- pp += 2;
- rec->nsp -= 2;
- }
- while (rec->nsp-- > 0)
- {
- sptr = getservbyport(htons(*pp), proto);
- if (sptr)
- printf("%s%s", sep, sptr->s_name);
- else
- printf("%s%u", sep, *pp);
- ++pp;
- sep = ",";
- }
- }
-
- printf(" -> ");
-
- sep = "";
- if (rec->ndp == 0)
- printf("any");
- else
- {
- if (rec->flags & IP_FW_F_DRNG)
- {
- printf("%u-%u", pp[0], pp[1]);
- sep = ",";
- pp += 2;
- }
- while (rec->ndp-- > 0)
- {
- sptr = getservbyport(htons(*pp), proto);
- if (sptr)
- printf("%s%s", sep, sptr->s_name);
- else
- printf("%s%u", sep, *pp);
- ++pp;
- sep = ",";
- }
- }
- }
- printf("\n");
- }
- endservent();
- }
-
- void list(int socket_fd, char **argv)
- {
- if (*argv == NULL || !**argv)
- {
- fprintf(stderr, "blocking, forwarding or accounting keyword expected.\n");
- exit(1);
- }
- if (strncmp(*argv, "blocking", strlen(*argv)) == 0)
- {
- list_file("/proc/net/ip_block", 0);
- return;
- }
- if (strncmp(*argv, "forwarding", strlen(*argv)) == 0)
- {
- list_file("/proc/net/ip_forward", 0);
- return;
- }
- if (strncmp(*argv, "accounting", strlen(*argv)) == 0)
- {
- list_file("/proc/net/ip_acct", 1);
- return;
- }
- fprintf(stderr, "Found '%s': 'blocking', 'forwarding' or 'accounting' keyword expected.\n", *argv);
- exit(1);
- }
-
- #define MATCH(in,pat) ( in && in[0] && (strncmp(in, pat, strlen(in)) == 0) )
-
- void main(argc, argv)
- int argc;
- char **argv;
- {
- int socket_fd;
- char *type = NULL;
-
- socket_fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
-
- if (socket_fd < 0)
- {
- perror("ipfw: raw socket creation");
- exit(1);
- }
- /* -n disables nameserver lookups */
-
- if (argv[1] && strcmp(argv[1], "-n")==0)
- {
- argc--;
- argv++;
- lookup = 0;
- }
- if (argc == 1)
- {
- show_usage();
- exit(1);
- }
- if (MATCH(argv[1], "list"))
- {
- type = "list";
- list(socket_fd, &argv[2]);
- }
- else if (MATCH(argv[1], "flush"))
- {
- if (MATCH(argv[2], "accounting"))
- {
- /* Same kludge as above, see above ranting and griping -BB */
- unsigned long fred = 1;
- (void) do_setsockopt(argv[1], socket_fd, IPPROTO_IP, IP_ACCT_FLUSH, &fred, sizeof(unsigned long), 0);
-
- }
- else if (MATCH(argv[2], "firewall"))
- {
- /* Same kludge as above, see above ranting and griping -BB */
- unsigned long fred = 1;
- (void) do_setsockopt(argv[1], socket_fd, IPPROTO_IP, IP_FW_FLUSH, &fred, sizeof(unsigned long), 0);
- }
- else
- {
- fprintf(stderr,
- "ipfw: expected \"accounting\" or \"firewall\".");
- exit(1);
-
-
- }
- }
- else if (MATCH(argv[1], "check"))
- {
- if (MATCH(argv[2], "blocking"))
- check(IPF_BLOCKING, socket_fd, &argv[3]);
-
- else if (MATCH(argv[2], "forwarding"))
- check(IPF_FORWARDING, socket_fd, &argv[3]);
-
- else
- {
- fprintf(stderr, "ipfw: illegal `check' keyword: %s\n",
- argv[2]);
- show_usage();
- exit(1);
- }
- }
- else
- {
- int is_add = MATCH(argv[1], "add");
- int is_del = MATCH(argv[1], "delete");
- char *op = NULL;
-
- if (is_add)
- {
- type = "add";
- if (MATCH(argv[2], "blocking"))
- add(IPF_BLOCKING, socket_fd, &argv[3]);
- else if (MATCH(argv[2], "forwarding"))
- add(IPF_FORWARDING, socket_fd, &argv[3]);
- else if (MATCH(argv[2], "accounting"))
- add(IPF_ACCOUNTING, socket_fd, &argv[3]);
- #ifdef DO_MASQUERADE
- else if (MATCH(argv[2], "masquerade"))
- add(IPF_MASQUERADE, socket_fd, &argv[3]);
- #endif
- else
- op = argv[2] ? : "(missing)";
- }
- else if (is_del)
- {
- type = "del";
- if (MATCH(argv[2], "blocking"))
- del(IPF_BLOCKING, socket_fd, &argv[3]);
- else if (MATCH(argv[2], "forwarding"))
- del(IPF_FORWARDING, socket_fd, &argv[3]);
- else if (MATCH(argv[2], "accounting"))
- del(IPF_ACCOUNTING, socket_fd, &argv[3]);
- #ifdef DO_MASQUERADE
- else if (MATCH(argv[2], "masquerade"))
- del(IPF_MASQUERADE, socket_fd, &argv[3]);
- #endif
- else
- op = argv[2] ? : "(missing)";
- }
- else if (MATCH(argv[1], "zeroaccounting"))
- {
- unsigned long fred = 1;
- type = "zero";
- /* Same kludge as above, see above ranting and griping -BB */
- (void) do_setsockopt(argv[1], socket_fd, IPPROTO_IP, IP_ACCT_ZERO, &fred, sizeof(unsigned long), 0);
-
- }
- if (!type)
- {
- fprintf(stderr, "ipfw: unknown command `%s'\n\n", argv[1]);
- show_help();
- exit(1);
- }
- else if (op)
- {
- fprintf(stderr, "ipfw: unknown `%s' keyword: `%s'\n",
- type, op);
- show_usage();
- exit(1);
- }
- }
-
- exit(0);
- }
-