Big sweep over ipfw, picking up where Poul left off:

- Filter based on ICMP types.
  - Accept interface wildcards (e.g. ppp*).
  - Resolve service names with the -N option.
  - Accept host names in 'from' and 'to' specifications
  - Display chain entry time stamps with the -t option.
  - Added URG to tcpflags.
  - Print usage if an unknown tcpflag is used.
  - Ability to zero individual accounting entries.
  - Clarify usage of port ranges.
  - Misc code cleanup.

Closes PRs: 1193, 1220, and 1266.
This commit is contained in:
Alexander Langer 1996-06-09 23:46:22 +00:00
parent 7a99108603
commit b55b9e3f1d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=16267

View File

@ -1,4 +1,5 @@
/*
* Copyright (c) 1996 Alex Nash
* Copyright (c) 1996 Poul-Henning Kamp
* Copyright (c) 1994 Ugen J.S.Antsilevich
* Idea and grammar partially left from:
@ -15,7 +16,7 @@
*
* NEW command line interface for IP firewall facility
*
* $Id: ipfw.c,v 1.23 1996/04/03 13:49:10 phk Exp $
* $Id: ipfw.c,v 1.24 1996/05/11 20:31:55 phk Exp $
*
*/
@ -27,6 +28,7 @@
#include <stdlib.h>
#include <netdb.h>
#include <limits.h>
#include <time.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <netinet/in.h>
@ -40,6 +42,7 @@ 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
mask_bits(m_ad)
@ -62,6 +65,40 @@ mask_bits(m_ad)
return h_num;
}
void
print_port(port, comma, flg)
u_short port,flg;
const char *comma;
{
int printed = 0;
if (do_resolv) {
struct servent *se;
const char *protocol;
switch (flg & IP_FW_F_KIND) {
case IP_FW_F_TCP:
protocol = "tcp";
break;
case IP_FW_F_UDP:
protocol = "udp";
break;
default:
protocol = NULL;
break;
}
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;
@ -71,12 +108,28 @@ show_ipfw(chain)
struct hostent *he;
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(" ");
}
if (chain->fw_flg & IP_FW_F_ACCEPT)
printf("allow");
else if (chain->fw_flg & IP_FW_F_ICMPRPL)
@ -136,7 +189,7 @@ show_ipfw(chain)
comma = " ";
for (i=0;i<chain->fw_nsp; i++ ) {
printf("%s%d",comma,chain->fw_pts[i]);
print_port(chain->fw_pts[i], comma, chain->fw_flg);
if (i==0 && (chain->fw_flg & IP_FW_F_SRNG))
comma = "-";
else
@ -174,7 +227,7 @@ show_ipfw(chain)
comma = " ";
for (i=0;i<chain->fw_ndp;i++) {
printf("%s%d",comma,chain->fw_pts[chain->fw_nsp+i]);
print_port(chain->fw_pts[chain->fw_nsp+i], comma, chain->fw_flg);
if (i==0 && (chain->fw_flg & IP_FW_F_DRNG))
comma = "-";
else
@ -193,7 +246,10 @@ show_ipfw(chain)
printf(" via ");
strncpy(ifnb,chain->fw_via_name,FW_IFNLEN);
ifnb[FW_IFNLEN]='\0';
printf("%s%d",ifnb,chain->fw_via_unit);
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));
@ -242,7 +298,22 @@ show_ipfw(chain)
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
@ -281,15 +352,16 @@ show_usage(str)
"\trule:\taction proto src dst extras...\n"
"\t\taction: {allow|deny|reject|count} [log]\n"
"\t\tproto: {ip|tcp|udp|icmp}}\n"
"\t\tsrc: from {any|ip[{/bits|:mask}]} [{port|port-port},...]\n"
"\t\tdst: to {any|ip[{/bits|:mask}]} [{port|port-port},...]\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},...\n"
"\t\ttcpflags [!]{syn|fin|rst|ack|psh|urg},...\n"
"\t\tipoptions [!]{ssrr|lsrr|rr|ts},...\n"
"\t\ticmptypes {type},...\n"
, progname
);
@ -298,6 +370,21 @@ show_usage(str)
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;
@ -319,7 +406,7 @@ fill_ip(ipno, mask, acp, avp)
*p++ = '\0';
}
if (!inet_aton(*av,ipno))
if (lookup_host(*av,ipno) != 0)
show_usage("ip number\n");
if (md == ':' && !inet_aton(p,mask))
show_usage("ip number\n");
@ -349,7 +436,7 @@ fill_port(cnt, ptr, off, arg)
u_short *cnt, *ptr, off;
char *arg;
{
char *s, *comma;
char *s;
int initial_range = 0;
s = strchr(arg,'-');
@ -385,6 +472,19 @@ fill_tcpflag(set, reset, vp)
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;
@ -394,11 +494,13 @@ fill_tcpflag(set, reset, vp)
q = strchr(p, ',');
if (q)
*q++ = '\0';
if (!strncmp(p,"syn",strlen(p))) *d |= IP_FW_TCPF_SYN;
if (!strncmp(p,"fin",strlen(p))) *d |= IP_FW_TCPF_FIN;
if (!strncmp(p,"ack",strlen(p))) *d |= IP_FW_TCPF_ACK;
if (!strncmp(p,"psh",strlen(p))) *d |= IP_FW_TCPF_PSH;
if (!strncmp(p,"rst",strlen(p))) *d |= IP_FW_TCPF_RST;
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;
}
}
@ -429,6 +531,35 @@ fill_ipopt(set, reset, vp)
}
}
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;
@ -537,9 +668,12 @@ add(ac,av)
char *q;
strcpy(rule.fw_via_name, *av);
for (q = rule.fw_via_name; *q && !isdigit(*q); q++)
for (q = rule.fw_via_name; *q && !isdigit(*q) && *q != '*'; q++)
continue;
rule.fw_via_unit = atoi(q);
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;
} else if (inet_aton(*av,&rule.fw_via_ip) == INADDR_NONE) {
@ -579,6 +713,13 @@ add(ac,av)
av++; ac--; continue;
}
}
if ((rule.fw_flg & IP_FW_F_KIND) == IP_FW_F_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");
}
@ -589,6 +730,40 @@ add(ac,av)
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;
@ -603,11 +778,14 @@ ipfw_main(ac,av)
show_usage(NULL);
}
while ((ch = getopt(ac, av ,"aN")) != EOF)
while ((ch = getopt(ac, av ,"atN")) != EOF)
switch(ch) {
case 'a':
do_acct=1;
break;
case 't':
do_time=1;
break;
case 'N':
do_resolv=1;
break;
@ -632,11 +810,7 @@ ipfw_main(ac,av)
}
printf("Flushed all rules.\n");
} else if (!strncmp(*av, "zero", strlen(*av))) {
if (setsockopt(s,IPPROTO_IP,IP_FW_ZERO,NULL,0)<0) {
fprintf(stderr,"%s: setsockopt failed.\n",progname);
exit(1);
}
printf("Accounting cleared.\n");
zero(ac,av);
} else if (!strncmp(*av, "print", strlen(*av))) {
list(--ac,++av);
} else if (!strncmp(*av, "list", strlen(*av))) {
@ -662,7 +836,7 @@ main(ac, 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 programm. \n",progname);
"Must be root to use this program.\n",progname);
exit(1);
}