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:
parent
7a99108603
commit
b55b9e3f1d
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=16267
220
sbin/ipfw/ipfw.c
220
sbin/ipfw/ipfw.c
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user