diff options
Diffstat (limited to 'sbin/ipfw/ipfw.c')
-rw-r--r-- | sbin/ipfw/ipfw.c | 962 |
1 files changed, 962 insertions, 0 deletions
diff --git a/sbin/ipfw/ipfw.c b/sbin/ipfw/ipfw.c new file mode 100644 index 0000000..7487b21 --- /dev/null +++ b/sbin/ipfw/ipfw.c @@ -0,0 +1,962 @@ +/* + * Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp + * Copyright (c) 1994 Ugen J.S.Antsilevich + * + * Idea and grammar partially left from: + * 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. + * + * NEW command line interface for IP firewall facility + * + * $Id: ipfw.c,v 1.34 1996/10/17 01:05:03 alex Exp $ + * + */ + +#include <sys/types.h> +#include <sys/queue.h> +#include <sys/socket.h> +#include <sys/sockio.h> +#include <sys/time.h> + +#include <ctype.h> +#include <err.h> +#include <limits.h> +#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#include <net/if.h> +#include <netinet/in.h> +#include <netinet/ip_fw.h> +#include <netinet/tcp.h> +#include <arpa/inet.h> + +int lineno = -1; +char progname[BUFSIZ]; /* Program name for errors */ + +int s; /* main RAW socket */ +int do_resolv=0; /* Would try to resolv all */ +int do_acct=0; /* Show packet/byte count */ +int do_time=0; /* Show time stamps */ +int do_force=0; /* Don't ask for confirmation */ + +int +mask_bits(m_ad) + struct in_addr m_ad; +{ + int h_fnd=0,h_num=0,i; + u_long mask; + + mask=ntohl(m_ad.s_addr); + for (i=0;i<sizeof(u_long)*CHAR_BIT;i++) { + if (mask & 1L) { + h_fnd=1; + h_num++; + } else { + if (h_fnd) + return -1; + } + mask=mask>>1; + } + return h_num; +} + +void +print_port(prot, port, comma) + u_char prot; + u_short port; + const char *comma; +{ + struct servent *se; + struct protoent *pe; + const char *protocol; + int printed = 0; + + if (do_resolv) { + pe = getprotobynumber(prot); + if (pe) + protocol = pe->p_name; + else + protocol = NULL; + + se = getservbyport(htons(port), protocol); + if (se) { + printf("%s%s", comma, se->s_name); + printed = 1; + } + } + if (!printed) + printf("%s%d",comma,port); +} + +void +show_ipfw(chain) + struct ip_fw *chain; +{ + char *comma; + u_long adrt; + struct hostent *he; + struct protoent *pe; + int i, mb; + + if (do_resolv) + setservent(1/*stayopen*/); + + printf("%05u ", chain->fw_number); + + if (do_acct) + printf("%10lu %10lu ",chain->fw_pcnt,chain->fw_bcnt); + + if (do_time) + { + if (chain->timestamp) + { + char timestr[30]; + + strcpy(timestr, ctime((time_t *)&chain->timestamp)); + *strchr(timestr, '\n') = '\0'; + printf("%s ", timestr); + } + else + printf(" "); + } + + switch (chain->fw_flg & IP_FW_F_COMMAND) + { + case IP_FW_F_ACCEPT: + printf("allow"); + break; + case IP_FW_F_DIVERT: + printf("divert %u", chain->fw_divert_port); + break; + case IP_FW_F_COUNT: + printf("count"); + break; + case IP_FW_F_DENY: + if (chain->fw_flg & IP_FW_F_ICMPRPL) + printf("reject"); + else + printf("deny"); + break; + default: + errx(1, "impossible"); + } + + if (chain->fw_flg & IP_FW_F_PRN) + printf(" log"); + + pe = getprotobynumber(chain->fw_prot); + if (pe) + printf(" %s", pe->p_name); + else + printf("%u", chain->fw_prot); + + printf(" from "); + + adrt=ntohl(chain->fw_smsk.s_addr); + if (adrt==ULONG_MAX && do_resolv) { + adrt=(chain->fw_src.s_addr); + he=gethostbyaddr((char *)&adrt,sizeof(u_long),AF_INET); + if (he==NULL) { + printf(inet_ntoa(chain->fw_src)); + } else + printf("%s",he->h_name); + } else { + if (adrt!=ULONG_MAX) { + mb=mask_bits(chain->fw_smsk); + if (mb == 0) { + printf("any"); + } else { + if (mb > 0) { + printf(inet_ntoa(chain->fw_src)); + printf("/%d",mb); + } else { + printf(inet_ntoa(chain->fw_src)); + printf(":"); + printf(inet_ntoa(chain->fw_smsk)); + } + } + } else + printf(inet_ntoa(chain->fw_src)); + } + + if (chain->fw_prot != IPPROTO_IP) { + comma = " "; + for (i=0;i<chain->fw_nsp; i++ ) { + print_port(chain->fw_prot, chain->fw_pts[i], comma); + if (i==0 && (chain->fw_flg & IP_FW_F_SRNG)) + comma = "-"; + else + comma = ","; + } + } + + printf(" to "); + + adrt=ntohl(chain->fw_dmsk.s_addr); + if (adrt==ULONG_MAX && do_resolv) { + adrt=(chain->fw_dst.s_addr); + he=gethostbyaddr((char *)&adrt,sizeof(u_long),AF_INET); + if (he==NULL) { + printf(inet_ntoa(chain->fw_dst)); + } else + printf("%s",he->h_name); + } else { + if (adrt!=ULONG_MAX) { + mb=mask_bits(chain->fw_dmsk); + if (mb == 0) { + printf("any"); + } else { + if (mb > 0) { + printf(inet_ntoa(chain->fw_dst)); + printf("/%d",mb); + } else { + printf(inet_ntoa(chain->fw_dst)); + printf(":"); + printf(inet_ntoa(chain->fw_dmsk)); + } + } + } else + printf(inet_ntoa(chain->fw_dst)); + } + + comma = " "; + for (i=0;i<chain->fw_ndp;i++) { + print_port(chain->fw_prot, chain->fw_pts[chain->fw_nsp+i], + comma); + if (i==0 && (chain->fw_flg & IP_FW_F_DRNG)) + comma = "-"; + else + comma = ","; + } + + if ((chain->fw_flg & IP_FW_F_IN) && (chain->fw_flg & IP_FW_F_OUT)) + ; + else if (chain->fw_flg & IP_FW_F_IN) + printf(" in"); + else if (chain->fw_flg & IP_FW_F_OUT) + printf(" out"); + + if (chain->fw_flg&IP_FW_F_IFNAME && chain->fw_via_name[0]) { + char ifnb[FW_IFNLEN+1]; + printf(" via "); + strncpy(ifnb,chain->fw_via_name,FW_IFNLEN); + ifnb[FW_IFNLEN]='\0'; + if (chain->fw_flg & IP_FW_F_IFUWILD) + printf("%s*",ifnb); + else + printf("%s%d",ifnb,chain->fw_via_unit); + } else if (chain->fw_via_ip.s_addr) { + printf(" via "); + printf(inet_ntoa(chain->fw_via_ip)); + } + + if (chain->fw_flg & IP_FW_F_FRAG) + printf(" frag"); + + if (chain->fw_ipopt || chain->fw_ipnopt) { + int _opt_printed = 0; +#define PRINTOPT(x) {if (_opt_printed) printf(",");\ + printf(x); _opt_printed = 1;} + + printf(" ipopt "); + if (chain->fw_ipopt & IP_FW_IPOPT_SSRR) PRINTOPT("ssrr"); + if (chain->fw_ipnopt & IP_FW_IPOPT_SSRR) PRINTOPT("!ssrr"); + if (chain->fw_ipopt & IP_FW_IPOPT_LSRR) PRINTOPT("lsrr"); + if (chain->fw_ipnopt & IP_FW_IPOPT_LSRR) PRINTOPT("!lsrr"); + if (chain->fw_ipopt & IP_FW_IPOPT_RR) PRINTOPT("rr"); + if (chain->fw_ipnopt & IP_FW_IPOPT_RR) PRINTOPT("!rr"); + if (chain->fw_ipopt & IP_FW_IPOPT_TS) PRINTOPT("ts"); + if (chain->fw_ipnopt & IP_FW_IPOPT_TS) PRINTOPT("!ts"); + } + + if (chain->fw_tcpf & IP_FW_TCPF_ESTAB) + printf(" established"); + else if (chain->fw_tcpf == IP_FW_TCPF_SYN && + chain->fw_tcpnf == IP_FW_TCPF_ACK) + printf(" setup"); + else if (chain->fw_tcpf || chain->fw_tcpnf) { + int _flg_printed = 0; +#define PRINTFLG(x) {if (_flg_printed) printf(",");\ + printf(x); _flg_printed = 1;} + + printf(" tcpflg "); + if (chain->fw_tcpf & IP_FW_TCPF_FIN) PRINTFLG("fin"); + if (chain->fw_tcpnf & IP_FW_TCPF_FIN) PRINTFLG("!fin"); + if (chain->fw_tcpf & IP_FW_TCPF_SYN) PRINTFLG("syn"); + if (chain->fw_tcpnf & IP_FW_TCPF_SYN) PRINTFLG("!syn"); + if (chain->fw_tcpf & IP_FW_TCPF_RST) PRINTFLG("rst"); + if (chain->fw_tcpnf & IP_FW_TCPF_RST) PRINTFLG("!rst"); + if (chain->fw_tcpf & IP_FW_TCPF_PSH) PRINTFLG("psh"); + if (chain->fw_tcpnf & IP_FW_TCPF_PSH) PRINTFLG("!psh"); + if (chain->fw_tcpf & IP_FW_TCPF_ACK) PRINTFLG("ack"); + if (chain->fw_tcpnf & IP_FW_TCPF_ACK) PRINTFLG("!ack"); + if (chain->fw_tcpf & IP_FW_TCPF_URG) PRINTFLG("urg"); + if (chain->fw_tcpnf & IP_FW_TCPF_URG) PRINTFLG("!urg"); + } + if (chain->fw_flg & IP_FW_F_ICMPBIT) { + int type_index; + int first = 1; + + printf(" icmptype"); + + for (type_index = 0; type_index < 256; ++type_index) + if (chain->fw_icmptypes[type_index / (sizeof(unsigned) * 8)] & + (1U << (type_index % (sizeof(unsigned) * 8)))) { + printf("%c%d", first == 1 ? ' ' : ',', type_index); + first = 0; + } + } + printf("\n"); + if (do_resolv) + endservent(); +} + +void +list(ac, av) + int ac; + char **av; +{ + struct ip_fw *r; + struct ip_fw rules[1024]; + int l,i; + + memset(rules,0,sizeof rules); + l = sizeof rules; + i = getsockopt(s, IPPROTO_IP, IP_FW_GET, rules, &l); + if (i < 0) + err(2,"getsockopt(IP_FW_GET)"); + for (r=rules; l >= sizeof rules[0]; r++, l-=sizeof rules[0]) + show_ipfw(r); +} + +void +show_usage(str) + char *str; +{ + if (str) + fprintf(stderr,"%s: ERROR - %s\n",progname,str); + fprintf(stderr, +"Usage:\n" +"\t%s [options]\n" +"\t\tflush\n" +"\t\tadd [number] rule\n" +"\t\tdelete number\n" +"\t\tlist [number]\n" +"\t\tzero [number]\n" +"\trule:\taction proto src dst extras...\n" +"\t\taction: {allow|deny|reject|count|divert port} [log]\n" +"\t\tproto: {ip|tcp|udp|icmp|<number>}}\n" +"\t\tsrc: from {any|ip[{/bits|:mask}]} [{port|port-port},[port],...]\n" +"\t\tdst: to {any|ip[{/bits|:mask}]} [{port|port-port},[port],...]\n" +"\textras:\n" +"\t\tfragment\n" +"\t\t{in|out|inout}\n" +"\t\tvia {ifname|ip}\n" +"\t\t{established|setup}\n" +"\t\ttcpflags [!]{syn|fin|rst|ack|psh|urg},...\n" +"\t\tipoptions [!]{ssrr|lsrr|rr|ts},...\n" +"\t\ticmptypes {type},...\n" +"\t\tproto {ipproto},...\n" +, progname +); + + + fprintf(stderr,"See man %s(8) for proper usage.\n",progname); + exit (1); +} + +int +lookup_host (host, ipaddr) + char *host; + struct in_addr *ipaddr; +{ + struct hostent *he = gethostbyname(host); + + if (!he) + return(-1); + + *ipaddr = *(struct in_addr *)he->h_addr_list[0]; + + return(0); +} + +void +fill_ip(ipno, mask, acp, avp) + struct in_addr *ipno, *mask; + int *acp; + char ***avp; +{ + int ac = *acp; + char **av = *avp; + char *p = 0, md = 0; + + if (ac && !strncmp(*av,"any",strlen(*av))) { + ipno->s_addr = mask->s_addr = 0; av++; ac--; + } else { + p = strchr(*av, '/'); + if (!p) + p = strchr(*av, ':'); + if (p) { + md = *p; + *p++ = '\0'; + } + + if (lookup_host(*av,ipno) != 0) + show_usage("ip number\n"); + switch (md) { + case ':': + if (!inet_aton(p,mask)) + show_usage("ip number\n"); + break; + case '/': + if (atoi(p) == 0) { + mask->s_addr = 0; + } else { + mask->s_addr = htonl(0xffffffff << (32 - atoi(p))); + } + break; + default: + mask->s_addr = htonl(0xffffffff); + break; + } + ipno->s_addr &= mask->s_addr; + av++; + ac--; + } + *acp = ac; + *avp = av; +} + +void +add_port(cnt, ptr, off, port) + u_short *cnt, *ptr, off, port; +{ + if (off + *cnt >= IP_FW_MAX_PORTS) + errx(1, "too many ports (max is %d)", IP_FW_MAX_PORTS); + ptr[off+*cnt] = port; + (*cnt)++; +} + +int +fill_port(cnt, ptr, off, arg) + u_short *cnt, *ptr, off; + char *arg; +{ + char *s; + int initial_range = 0; + + s = strchr(arg,'-'); + if (s) { + *s++ = '\0'; + if (strchr(arg, ',')) + errx(1, "port range must be first in list"); + add_port(cnt, ptr, off, *arg ? atoi(arg) : 0x0000); + arg = s; + s = strchr(arg,','); + if (s) + *s++ = '\0'; + add_port(cnt, ptr, off, *arg ? atoi(arg) : 0xffff); + arg = s; + initial_range = 1; + } + while (arg != NULL) { + s = strchr(arg,','); + if (s) + *s++ = '\0'; + add_port(cnt, ptr, off, atoi(arg)); + arg = s; + } + return initial_range; +} + +void +fill_tcpflag(set, reset, vp) + u_char *set, *reset; + char **vp; +{ + char *p = *vp,*q; + u_char *d; + + while (p && *p) { + struct tpcflags { + char * name; + u_char value; + } flags[] = { + { "syn", IP_FW_TCPF_SYN }, + { "fin", IP_FW_TCPF_FIN }, + { "ack", IP_FW_TCPF_ACK }, + { "psh", IP_FW_TCPF_PSH }, + { "rst", IP_FW_TCPF_RST }, + { "urg", IP_FW_TCPF_URG } + }; + int i; + + if (*p == '!') { + p++; + d = reset; + } else { + d = set; + } + q = strchr(p, ','); + if (q) + *q++ = '\0'; + for (i = 0; i < sizeof(flags) / sizeof(flags[0]); ++i) + if (!strncmp(p, flags[i].name, strlen(p))) { + *d |= flags[i].value; + break; + } + if (i == sizeof(flags) / sizeof(flags[0])) + show_usage("invalid tcp flag\n"); + p = q; + } +} + +void +fill_ipopt(set, reset, vp) + u_char *set, *reset; + char **vp; +{ + char *p = *vp,*q; + u_char *d; + + while (p && *p) { + if (*p == '!') { + p++; + d = reset; + } else { + d = set; + } + q = strchr(p, ','); + if (q) + *q++ = '\0'; + if (!strncmp(p,"ssrr",strlen(p))) *d |= IP_FW_IPOPT_SSRR; + if (!strncmp(p,"lsrr",strlen(p))) *d |= IP_FW_IPOPT_LSRR; + if (!strncmp(p,"rr",strlen(p))) *d |= IP_FW_IPOPT_RR; + if (!strncmp(p,"ts",strlen(p))) *d |= IP_FW_IPOPT_TS; + p = q; + } +} + +void +fill_icmptypes(types, vp, fw_flg) + u_long *types; + char **vp; + u_short *fw_flg; +{ + char *c = *vp; + + while (*c) + { + unsigned long icmptype; + + if ( *c == ',' ) + ++c; + + icmptype = strtoul(c, &c, 0); + + if ( *c != ',' && *c != '\0' ) + show_usage("invalid ICMP type"); + + if (icmptype > 255) + show_usage("ICMP types are between 0 and 255 inclusive"); + + types[icmptype / (sizeof(unsigned) * 8)] |= + 1 << (icmptype % (sizeof(unsigned) * 8)); + *fw_flg |= IP_FW_F_ICMPBIT; + } +} + +void +delete(ac,av) + int ac; + char **av; +{ + struct ip_fw rule; + int i; + + memset(&rule, 0, sizeof rule); + + av++; ac--; + + /* Rule number */ + if (ac && isdigit(**av)) { + rule.fw_number = atoi(*av); av++; ac--; + } + + i = setsockopt(s, IPPROTO_IP, IP_FW_DEL, &rule, sizeof rule); + if (i) + err(1,"setsockopt(IP_FW_DEL)"); +} + +int +verify_interface(rule) + struct ip_fw *rule; +{ + struct ifreq ifr; + + /* + * If a unit was specified, check for that exact interface. + * If a wildcard was specified, check for unit 0. + */ + snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", + rule->fw_via_name, + rule->fw_flg & IP_FW_F_IFUWILD ? 0 : rule->fw_via_unit); + + if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) + return(-1); /* interface isn't recognized by the kernel */ + + return(0); /* interface exists */ +} + +void +add(ac,av) + int ac; + char **av; +{ + struct ip_fw rule; + int i; + u_char proto; + struct protoent *pe; + + memset(&rule, 0, sizeof rule); + + av++; ac--; + + /* Rule number */ + if (ac && isdigit(**av)) { + rule.fw_number = atoi(*av); av++; ac--; + } + + /* Action */ + if (ac && (!strncmp(*av,"accept",strlen(*av)) + || !strncmp(*av,"pass",strlen(*av)) + || !strncmp(*av,"allow",strlen(*av)) + || !strncmp(*av,"permit",strlen(*av)))) { + rule.fw_flg |= IP_FW_F_ACCEPT; av++; ac--; + } else if (ac && !strncmp(*av,"count",strlen(*av))) { + rule.fw_flg |= IP_FW_F_COUNT; av++; ac--; + } else if (ac && !strncmp(*av,"divert",strlen(*av))) { + rule.fw_flg |= IP_FW_F_DIVERT; av++; ac--; + if (!ac) + show_usage("missing divert port"); + rule.fw_divert_port = strtoul(*av, NULL, 0); av++; ac--; + if (rule.fw_divert_port == 0) + show_usage("illegal divert port"); + } else if (ac && (!strncmp(*av,"deny",strlen(*av)))) { + rule.fw_flg |= IP_FW_F_DENY; av++; ac--; + } else if (ac && !strncmp(*av,"reject",strlen(*av))) { + rule.fw_flg |= IP_FW_F_DENY|IP_FW_F_ICMPRPL; av++; ac--; + } else { + show_usage("missing/unrecognized action\n"); + } + + /* [log] */ + if (ac && !strncmp(*av,"log",strlen(*av))) { + rule.fw_flg |= IP_FW_F_PRN; av++; ac--; + } + + /* protocol */ + if (ac) { + if ((proto = atoi(*av)) > 0) { + rule.fw_prot = proto; av++; ac--; + } else if (!strncmp(*av,"all",strlen(*av))) { + rule.fw_prot = IPPROTO_IP; av++; ac--; + } else if ((pe = getprotobyname(*av)) != NULL) { + rule.fw_prot = pe->p_proto; av++; ac--; + } else { + show_usage("invalid protocol\n"); + } + } else + show_usage("missing protocol\n"); + + /* from */ + if (ac && !strncmp(*av,"from",strlen(*av))) { av++; ac--; } + else show_usage("missing ``from''\n"); + + fill_ip(&rule.fw_src, &rule.fw_smsk, &ac, &av); + + if (ac && isdigit(**av)) { + if (fill_port(&rule.fw_nsp, &rule.fw_pts, 0, *av, 0)) + rule.fw_flg |= IP_FW_F_SRNG; + av++; ac--; + } + + /* to */ + if (ac && !strncmp(*av,"to",strlen(*av))) { av++; ac--; } + else show_usage("missing ``to''\n"); + + if (!ac) show_usage("Missing arguments\n"); + + fill_ip(&rule.fw_dst, &rule.fw_dmsk, &ac, &av); + + if (ac && isdigit(**av)) { + if (fill_port(&rule.fw_ndp, &rule.fw_pts, rule.fw_nsp, *av, 0)) + rule.fw_flg |= IP_FW_F_DRNG; + av++; ac--; + } + + if ((rule.fw_prot != IPPROTO_TCP) && + (rule.fw_prot != IPPROTO_UDP) && + (rule.fw_nsp || rule.fw_ndp)) { + show_usage("only TCP and UDP protocols are valid with port specifications"); + } + + while (ac) { + if (ac && !strncmp(*av,"via",strlen(*av))) { + if (rule.fw_via_ip.s_addr || (rule.fw_flg & IP_FW_F_IFNAME)) { + show_usage("multiple 'via' options specified"); + } + + av++; ac--; + if (!isdigit(**av)) { + char *q; + + strcpy(rule.fw_via_name, *av); + for (q = rule.fw_via_name; *q && !isdigit(*q) && *q != '*'; q++) + continue; + if (*q == '*') + rule.fw_flg |= IP_FW_F_IFUWILD; + else + rule.fw_via_unit = atoi(q); + *q = '\0'; + rule.fw_flg |= IP_FW_F_IFNAME; + if (verify_interface(&rule) != 0) + fprintf(stderr, "Warning: interface does not exist\n"); + } else if (inet_aton(*av,&rule.fw_via_ip) == INADDR_NONE) { + show_usage("bad IP# after via\n"); + } + av++; ac--; + continue; + } + if (!strncmp(*av,"fragment",strlen(*av))) { + rule.fw_flg |= IP_FW_F_FRAG; av++; ac--; continue; + } + if (!strncmp(*av,"in",strlen(*av))) { + rule.fw_flg |= IP_FW_F_IN; av++; ac--; continue; + } + if (!strncmp(*av,"out",strlen(*av))) { + rule.fw_flg |= IP_FW_F_OUT; av++; ac--; continue; + } + if (ac > 1 && !strncmp(*av,"ipoptions",strlen(*av))) { + av++; ac--; + fill_ipopt(&rule.fw_ipopt, &rule.fw_ipnopt, av); + av++; ac--; continue; + } + if (rule.fw_prot == IPPROTO_TCP) { + if (!strncmp(*av,"established",strlen(*av))) { + rule.fw_tcpf |= IP_FW_TCPF_ESTAB; + av++; ac--; continue; + } + if (!strncmp(*av,"setup",strlen(*av))) { + rule.fw_tcpf |= IP_FW_TCPF_SYN; + rule.fw_tcpnf |= IP_FW_TCPF_ACK; + av++; ac--; continue; + } + if (ac > 1 && !strncmp(*av,"tcpflags",strlen(*av))) { + av++; ac--; + fill_tcpflag(&rule.fw_tcpf, &rule.fw_tcpnf, av); + av++; ac--; continue; + } + } + if (rule.fw_prot == IPPROTO_ICMP) { + if (ac > 1 && !strncmp(*av,"icmptypes",strlen(*av))) { + av++; ac--; + fill_icmptypes(rule.fw_icmptypes, av, &rule.fw_flg); + av++; ac--; continue; + } + } + printf("%d %s\n",ac,*av); + show_usage("Unknown argument\n"); + } + + show_ipfw(&rule); + i = setsockopt(s, IPPROTO_IP, IP_FW_ADD, &rule, sizeof rule); + if (i) + err(1,"setsockopt(IP_FW_ADD)"); +} + +void +zero (ac, av) + int ac; + char **av; +{ + av++; ac--; + + if (!ac) { + /* clear all entries */ + if (setsockopt(s,IPPROTO_IP,IP_FW_ZERO,NULL,0)<0) { + fprintf(stderr,"%s: setsockopt failed.\n",progname); + exit(1); + } + printf("Accounting cleared.\n"); + } else { + /* clear a specific entry */ + struct ip_fw rule; + + memset(&rule, 0, sizeof rule); + + /* Rule number */ + if (isdigit(**av)) { + rule.fw_number = atoi(*av); av++; ac--; + + if (setsockopt(s, IPPROTO_IP, IP_FW_ZERO, &rule, sizeof rule)) + err(1, "setsockopt(Zero)"); + printf("Entry %d cleared\n", rule.fw_number); + } + else { + show_usage("expected number"); + } + } +} + +int +ipfw_main(ac,av) + int ac; + char **av; +{ + + char ch; + extern int optind; + + + if ( ac == 1 ) { + show_usage(NULL); + } + + /* Set the force flag for non-interactive processes */ + do_force = !isatty(STDIN_FILENO); + + while ((ch = getopt(ac, av ,"aftN")) != EOF) + switch(ch) { + case 'a': + do_acct=1; + break; + case 'f': + do_force=1; + break; + case 't': + do_time=1; + break; + case 'N': + do_resolv=1; + break; + default: + show_usage("Unrecognised switch"); + } + + ac -= optind; + if (*(av+=optind)==NULL) { + show_usage("Bad arguments"); + } + + if (!strncmp(*av, "add", strlen(*av))) { + add(ac,av); + } else if (!strncmp(*av, "delete", strlen(*av))) { + delete(ac,av); + } else if (!strncmp(*av, "flush", strlen(*av))) { + int do_flush = 0; + + if ( do_force ) + do_flush = 1; + else { + int c; + + /* Ask the user */ + printf("Are you sure? [yn] "); + do { + fflush(stdout); + c = toupper(getc(stdin)); + while (c != '\n' && getc(stdin) != '\n') + if (feof(stdin)) + return (0); + } while (c != 'Y' && c != 'N'); + printf("\n"); + if (c == 'Y') + do_flush = 1; + } + if ( do_flush ) { + if (setsockopt(s,IPPROTO_IP,IP_FW_FLUSH,NULL,0)<0) { + fprintf(stderr,"%s: setsockopt failed.\n",progname); + exit(1); + } + printf("Flushed all rules.\n"); + } + } else if (!strncmp(*av, "zero", strlen(*av))) { + zero(ac,av); + } else if (!strncmp(*av, "print", strlen(*av))) { + list(--ac,++av); + } else if (!strncmp(*av, "list", strlen(*av))) { + list(--ac,++av); + } else { + show_usage("Bad arguments"); + } + return 0; +} + +int +main(ac, av) + int ac; + char **av; +{ +#define MAX_ARGS 32 + char buf[BUFSIZ]; + char *args[MAX_ARGS]; + char linename[10]; + int i; + FILE *f; + + strcpy(progname,*av); + + s = socket( AF_INET, SOCK_RAW, IPPROTO_RAW ); + if ( s < 0 ) { + fprintf(stderr,"%s: Can't open raw socket.\n" + "Must be root to use this program.\n",progname); + exit(1); + } + + setbuf(stdout,0); + + if (av[1] && !access(av[1], R_OK)) { + lineno = 0; + f = fopen(av[1], "r"); + while (fgets(buf, BUFSIZ, f)) { + if (buf[strlen(buf)-1]=='\n') + buf[strlen(buf)-1] = 0; + + lineno++; + sprintf(linename, "Line %d", lineno); + args[0] = linename; + + args[1] = buf; + while(*args[1] == ' ') + args[1]++; + i = 2; + while((args[i] = strchr(args[i-1],' '))) { + *(args[i]++) = 0; + while(*args[i] == ' ') + args[i]++; + i++; + } + if (*args[i-1] == 0) + i--; + args[i] = NULL; + + ipfw_main(i, args); + } + fclose(f); + } else + ipfw_main(ac,av); + return 0; +} |