a8e45e5f34
take this into BETA. Submitted by: ugen
968 lines
18 KiB
C
968 lines
18 KiB
C
/*
|
|
* 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
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <fcntl.h>
|
|
#include <limits.h>
|
|
#include <netdb.h>
|
|
#include <kvm.h>
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
#include <netinet/in_systm.h>
|
|
#include <netinet/ip.h>
|
|
#include <netinet/tcp.h>
|
|
#define IPFIREWALL
|
|
#define IPACCT
|
|
#include <netinet/ip_fw.h>
|
|
|
|
#define MAXSTR 25
|
|
|
|
char progname[MAXSTR]; /* Program name for errors */
|
|
char proto_name[MAXSTR]=""; /* Current line protocol */
|
|
int s; /* main RAW socket */
|
|
int do_resolv=1; /* Would try to resolv all */
|
|
int do_verbose=0; /* Verbose output(differs) */
|
|
int ports_ok=0; /* flag allowing ports */
|
|
u_short flags=0; /* New entry flags */
|
|
|
|
|
|
#define FW 1 /* Firewall action */
|
|
#define AC 2 /* Accounting action */
|
|
|
|
|
|
#define S_SEP1 "f" /* of "from" */
|
|
#define S_SEP2 "t" /* of "to" */
|
|
|
|
#define P_AC "a" /* of "accept" for policy action */
|
|
#define P_DE "d" /* of "deny" for policy action */
|
|
|
|
#define CH_FW "f" /* of "firewall" for chains in zero/flush */
|
|
#define CH_AC "a" /* of "accounting" for chain in zero/flush/list */
|
|
#define CH_BLK "b" /* of "blocking" for chain in list */
|
|
#define CH_FWD "f" /* of "forwarding" for chain in list */
|
|
|
|
char action_tab[][MAXSTR]={
|
|
"addb",
|
|
#define A_ADDB 0
|
|
"delb",
|
|
#define A_DELB 1
|
|
"chkb",
|
|
#define A_CHKB 2
|
|
"addf",
|
|
#define A_ADDF 3
|
|
"delf",
|
|
#define A_DELF 4
|
|
"chkf",
|
|
#define A_CHKF 5
|
|
"adda",
|
|
#define A_ADDA 6
|
|
"dela",
|
|
#define A_DELA 7
|
|
"f",
|
|
#define A_FLUSH 8
|
|
"z",
|
|
#define A_ZERO 9
|
|
"l",
|
|
#define A_LIST 10
|
|
"p",
|
|
#define A_POLICY 11
|
|
"",
|
|
#define A_NONE 12
|
|
};
|
|
|
|
|
|
char type_tab[][MAXSTR]={
|
|
"ac",
|
|
#define T_ACCEPT 0
|
|
"de",
|
|
#define T_DENY 1
|
|
"si",
|
|
#define T_SINGLE 2
|
|
"bi",
|
|
#define T_BIDIR 3
|
|
"",
|
|
#define T_NONE 4
|
|
};
|
|
|
|
|
|
char proto_tab[][MAXSTR]={
|
|
"all",
|
|
#define P_ALL 0
|
|
"icmp",
|
|
#define P_ICMP 1
|
|
"tcp",
|
|
#define P_TCP 2
|
|
"udp",
|
|
#define P_UDP 3
|
|
""
|
|
#define P_NONE 4
|
|
};
|
|
|
|
struct nlist nlf[]={
|
|
#define N_BCHAIN 0
|
|
{ "_ip_fw_blk_chain" },
|
|
#define N_FCHAIN 1
|
|
{ "_ip_fw_fwd_chain" },
|
|
#define N_POLICY 2
|
|
{ "_ip_fw_policy" },
|
|
"" ,
|
|
};
|
|
|
|
|
|
struct nlist nla[]={
|
|
#define N_ACHAIN 0
|
|
{ "_ip_acct_chain" },
|
|
"" ,
|
|
};
|
|
|
|
|
|
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
|
|
show_ipfw(chain,c_t)
|
|
struct ip_fw *chain;
|
|
int c_t;
|
|
{
|
|
char *comma;
|
|
u_long adrt;
|
|
struct hostent *he;
|
|
int i,mb;
|
|
|
|
|
|
if (do_verbose) {
|
|
printf("%8d:%8d ",chain->b_cnt,chain->p_cnt);
|
|
}
|
|
|
|
|
|
if (do_verbose)
|
|
if (c_t==FW) {
|
|
if (chain->flags & IP_FW_F_ACCEPT)
|
|
printf("A");
|
|
else
|
|
printf("D");
|
|
} else {
|
|
if (chain->flags & IP_FW_F_BIDIR)
|
|
printf("B");
|
|
else
|
|
printf("S");
|
|
}
|
|
else
|
|
if (c_t==FW) {
|
|
if (chain->flags & IP_FW_F_ACCEPT)
|
|
printf("accept ");
|
|
else
|
|
printf("deny ");
|
|
} else {
|
|
if (chain->flags & IP_FW_F_BIDIR)
|
|
printf("bidir ");
|
|
else
|
|
printf("single ");
|
|
}
|
|
|
|
if (do_verbose)
|
|
switch (chain->flags & IP_FW_F_KIND) {
|
|
case IP_FW_F_ICMP:
|
|
printf("I ");
|
|
break;
|
|
case IP_FW_F_TCP:
|
|
printf("T ");
|
|
break;
|
|
case IP_FW_F_UDP:
|
|
printf("U ");
|
|
break;
|
|
case IP_FW_F_ALL:
|
|
printf("A ");
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
else
|
|
switch (chain->flags & IP_FW_F_KIND) {
|
|
case IP_FW_F_ICMP:
|
|
printf("icmp ");
|
|
break;
|
|
case IP_FW_F_TCP:
|
|
printf("tcp ");
|
|
break;
|
|
case IP_FW_F_UDP:
|
|
printf("udp ");
|
|
break;
|
|
case IP_FW_F_ALL:
|
|
printf("all ");
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (do_verbose)
|
|
printf("[");
|
|
else
|
|
printf("from ");
|
|
|
|
adrt=ntohl(chain->src_mask.s_addr);
|
|
if (adrt==ULONG_MAX && do_resolv) {
|
|
adrt=(chain->src.s_addr);
|
|
he=gethostbyaddr((char *)&adrt,sizeof(u_long),AF_INET);
|
|
if (he==NULL) {
|
|
printf(inet_ntoa(chain->src));
|
|
printf(":");
|
|
printf(inet_ntoa(chain->src_mask));
|
|
} else
|
|
printf("%s",he->h_name);
|
|
} else {
|
|
printf(inet_ntoa(chain->src));
|
|
if (adrt!=ULONG_MAX)
|
|
if ((mb=mask_bits(chain->src_mask))>=0)
|
|
printf("/%d",mb);
|
|
else {
|
|
printf(":");
|
|
printf(inet_ntoa(chain->src_mask));
|
|
}
|
|
}
|
|
|
|
comma = " ";
|
|
for (i=0;i<chain->n_src_p; i++ ) {
|
|
printf("%s%d",comma,chain->ports[i]);
|
|
if (i==0 && (chain->flags & IP_FW_F_SRNG))
|
|
comma = ":";
|
|
else
|
|
comma = ",";
|
|
}
|
|
|
|
if (do_verbose)
|
|
printf("][");
|
|
else
|
|
printf(" to ");
|
|
|
|
adrt=ntohl(chain->dst_mask.s_addr);
|
|
if (adrt==ULONG_MAX && do_resolv) {
|
|
adrt=(chain->dst.s_addr);
|
|
he=gethostbyaddr((char *)&adrt,sizeof(u_long),AF_INET);
|
|
if (he==NULL) {
|
|
printf(inet_ntoa(chain->dst));
|
|
printf(":");
|
|
printf(inet_ntoa(chain->dst_mask));
|
|
} else
|
|
printf("%s",he->h_name);
|
|
} else {
|
|
printf(inet_ntoa(chain->dst));
|
|
if (adrt!=ULONG_MAX)
|
|
if ((mb=mask_bits(chain->dst_mask))>=0)
|
|
printf("/%d",mb);
|
|
else {
|
|
printf(":");
|
|
printf(inet_ntoa(chain->dst_mask));
|
|
}
|
|
}
|
|
|
|
comma = " ";
|
|
for (i=0;i<chain->n_dst_p;i++) {
|
|
printf("%s%d",comma,chain->ports[chain->n_src_p+i]);
|
|
if (i==chain->n_src_p && (chain->flags & IP_FW_F_DRNG))
|
|
comma = ":";
|
|
else
|
|
comma = ",";
|
|
}
|
|
|
|
if (do_verbose)
|
|
printf("]\n");
|
|
else
|
|
printf("\n");
|
|
}
|
|
|
|
|
|
list(av)
|
|
char **av;
|
|
{
|
|
kvm_t *kd;
|
|
static char errb[_POSIX2_LINE_MAX];
|
|
struct ip_fw b,*btmp;
|
|
|
|
if (!(kd=kvm_openfiles(NULL,NULL,NULL,O_RDONLY,errb))) {
|
|
fprintf(stderr,"%s: kvm_openfiles: %s\n",
|
|
progname,kvm_geterr(kd));
|
|
exit(1);
|
|
}
|
|
|
|
if (*av==NULL || !strncmp(*av,CH_BLK,strlen(CH_BLK))
|
|
|| !strncmp(*av,CH_FWD,strlen(CH_FWD))) {
|
|
if (kvm_nlist(kd,nlf)<0 || nlf[0].n_type==0) {
|
|
fprintf(stderr,"%s: kvm_nlist: no namelist in %s\n",
|
|
progname,getbootfile());
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
if (*av==NULL || !strncmp(*av,CH_BLK,strlen(CH_BLK))) {
|
|
kvm_read(kd,(u_long)nlf[N_BCHAIN].n_value,&b,sizeof(struct ip_fw));
|
|
printf("Blocking chain entries:\n");
|
|
while(b.next!=NULL) {
|
|
btmp=b.next;
|
|
kvm_read(kd,(u_long)btmp,&b,sizeof(struct ip_fw));
|
|
show_ipfw(&b,FW);
|
|
}
|
|
}
|
|
|
|
if (*av==NULL || !strncmp(*av,CH_FWD,strlen(CH_FWD))) {
|
|
kvm_read(kd,(u_long)nlf[N_FCHAIN].n_value,&b,sizeof(struct ip_fw));
|
|
printf("Forwarding chain entries:\n");
|
|
while(b.next!=NULL) {
|
|
btmp=b.next;
|
|
kvm_read(kd,(u_long)btmp,&b,sizeof(struct ip_fw));
|
|
show_ipfw(&b,FW);
|
|
}
|
|
}
|
|
|
|
|
|
if (*av==NULL || !strncmp(*av,CH_AC,strlen(CH_AC))) {
|
|
if (kvm_nlist(kd,nla)<0 || nla[0].n_type==0) {
|
|
fprintf(stderr,"%s: kvm_nlist: no namelist in %s\n",
|
|
progname,getbootfile());
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
if (*av==NULL || !strncmp(*av,CH_AC,strlen(CH_AC))) {
|
|
kvm_read(kd,(u_long)nla[N_ACHAIN].n_value,&b,sizeof(struct ip_fw));
|
|
printf("Accounting chain entries:\n");
|
|
while(b.next!=NULL) {
|
|
btmp=b.next;
|
|
kvm_read(kd,(u_long)btmp,&b,sizeof(struct ip_fw));
|
|
show_ipfw(&b,AC);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int get_num(str,tab)
|
|
char *str;
|
|
char tab[][MAXSTR];
|
|
{
|
|
int i=0;
|
|
while(tab[i][0]!='\0') {
|
|
if (strlen(str)>=strlen(tab[i]))
|
|
if (!strncmp(str,tab[i],strlen(tab[i])))
|
|
return i;
|
|
i++;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
|
|
|
|
void show_usage()
|
|
{
|
|
printf("%s: bad arguments\n",progname);
|
|
}
|
|
|
|
|
|
|
|
|
|
u_short get_port(str)
|
|
char *str;
|
|
{
|
|
struct servent *sptr;
|
|
char *end;
|
|
int port,slen = strlen(str);
|
|
|
|
if ((slen>0) && (strspn(str,"0123456789")==slen)) {
|
|
port = strtol(str,&end,10);
|
|
if (*end!='\0') {
|
|
fprintf(stderr,"%s: illegal port number :%s\n"
|
|
,progname,str);
|
|
exit(1);
|
|
}
|
|
|
|
if ((port<=0) || (port>USHRT_MAX)) {
|
|
fprintf(stderr,"%s: port number out of range :%d\n"
|
|
,progname,port);
|
|
exit(1);
|
|
}
|
|
return((u_short)port);
|
|
} else {
|
|
sptr = getservbyname(str,proto_name);
|
|
if (!sptr) {
|
|
fprintf(stderr,"%s: unknown service :%s\n"
|
|
,progname,str);
|
|
exit(1);
|
|
}
|
|
return((u_short)ntohs(sptr->s_port));
|
|
}
|
|
}
|
|
|
|
|
|
char *findchar(str,c)
|
|
char *str;
|
|
char c;
|
|
{
|
|
int i,len=strlen(str);
|
|
|
|
for (i=0;i<len;i++) {
|
|
if (str[i]==c)
|
|
return(char*)(&str[i]);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
int set_entry_ports(str,ports,a_max,is_range)
|
|
char *str;
|
|
u_short *ports;
|
|
int a_max;
|
|
int *is_range;
|
|
{
|
|
char *s_pr2,*s_h,*s_t,*cp;
|
|
u_short p1,p2;
|
|
int i=0;
|
|
|
|
(void)strtok(str,":");
|
|
s_pr2=strtok(NULL,"");
|
|
if (s_pr2) {
|
|
p1 = get_port(str);
|
|
p2 = get_port(s_pr2);
|
|
if (a_max<2) {
|
|
fprintf(stderr,"%s: too many ports.\n",progname);
|
|
exit(1);
|
|
}
|
|
ports[0]=p1;
|
|
ports[1]=p2;
|
|
*is_range=1;
|
|
return 2;
|
|
}
|
|
s_h=str;
|
|
while ((cp=findchar(s_h,','))!=NULL) {
|
|
if (i>a_max) {
|
|
fprintf(stderr,"%s: too many ports.\n",progname);
|
|
exit(1);
|
|
}
|
|
*cp='\0';
|
|
if ((s_t=(++cp))=='\0') {
|
|
fprintf(stderr,"%s: bad port list.\n",progname);
|
|
exit(1);
|
|
}
|
|
ports[i++]=get_port(s_h);
|
|
s_h=s_t;
|
|
}
|
|
if (i>a_max) {
|
|
fprintf(stderr,"%s: too many ports.\n",progname);
|
|
exit(1);
|
|
}
|
|
ports[i]=get_port(s_h);
|
|
*is_range=0;
|
|
return (i+1);
|
|
}
|
|
|
|
|
|
|
|
void set_entry_ip(str,addr,mask)
|
|
char *str;
|
|
struct in_addr *addr,*mask;
|
|
{
|
|
char *sm_bit,*sm_oct,*end;
|
|
int n_bit;
|
|
struct hostent *hptr;
|
|
|
|
(void)strtok(str,"/");
|
|
sm_bit=strtok(NULL,"");
|
|
(void)strtok(str,":");
|
|
sm_oct=strtok(NULL,"");
|
|
|
|
if (!inet_aton(str,addr)) {
|
|
if (do_resolv) {
|
|
if (!(hptr=gethostbyname(str))) {
|
|
fprintf(stderr,"%s: Unknown host name : %s\n",
|
|
progname,str);
|
|
exit(1);
|
|
} else {
|
|
addr->s_addr=*((u_long *)hptr->h_addr);
|
|
}
|
|
} else {
|
|
fprintf(stderr,"%s: Bad IP : %s\n",progname,str);
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
mask->s_addr=htonl(ULONG_MAX);
|
|
|
|
if (sm_bit) {
|
|
n_bit = strtol(sm_bit,&end,10);
|
|
if (*end!='\0') {
|
|
show_usage();
|
|
exit(1);
|
|
}
|
|
if (n_bit<0 || n_bit>sizeof(u_long)*CHAR_BIT) {
|
|
show_usage();
|
|
exit(1);
|
|
}
|
|
mask->s_addr=
|
|
htonl(ULONG_MAX<<(sizeof(u_long)*CHAR_BIT-n_bit));
|
|
}
|
|
|
|
if (sm_oct) {
|
|
if (!inet_aton(sm_oct,mask)) {
|
|
show_usage();
|
|
exit(1);
|
|
}
|
|
}
|
|
/*
|
|
* Ugh..better of corse do it in kernel so no error possible
|
|
* but faster here so this way it goes...
|
|
*/
|
|
|
|
addr->s_addr=mask->s_addr & addr->s_addr;
|
|
}
|
|
|
|
|
|
void set_entry(av,frwl)
|
|
char **av;
|
|
struct ip_fw * frwl;
|
|
{
|
|
int p_num=0,ir=0;
|
|
|
|
frwl->n_src_p=0;
|
|
frwl->n_dst_p=0;
|
|
|
|
if (strncmp(*av,S_SEP1,strlen(S_SEP1))) {
|
|
show_usage();
|
|
exit(1);
|
|
}
|
|
|
|
if (*(++av)==NULL) {
|
|
show_usage();
|
|
exit(1);
|
|
}
|
|
|
|
set_entry_ip(*av,&(frwl->src),&(frwl->src_mask));
|
|
|
|
if (*(++av)==NULL) {
|
|
show_usage();
|
|
exit(1);
|
|
}
|
|
|
|
if (!strncmp(*av,S_SEP2,strlen(S_SEP2)))
|
|
goto no_src_ports;
|
|
|
|
if (ports_ok) {
|
|
frwl->n_src_p=
|
|
set_entry_ports(*av,frwl->ports,IP_FW_MAX_PORTS,&ir);
|
|
if (ir)
|
|
flags|=IP_FW_F_SRNG;
|
|
|
|
if (*(++av)==NULL) {
|
|
show_usage();
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
no_src_ports:
|
|
|
|
if (strncmp(*av,S_SEP2,strlen(S_SEP2))) {
|
|
show_usage();
|
|
exit(1);
|
|
}
|
|
|
|
if (*(++av)==NULL) {
|
|
show_usage();
|
|
exit(1);
|
|
}
|
|
|
|
set_entry_ip(*av,&(frwl->dst),&(frwl->dst_mask));
|
|
|
|
if (*(++av)==NULL)
|
|
goto no_dst_ports;
|
|
|
|
if (ports_ok) {
|
|
frwl->n_dst_p=
|
|
set_entry_ports(*av,&(frwl->ports[frwl->n_src_p]),
|
|
(IP_FW_MAX_PORTS-frwl->n_src_p),&ir);
|
|
if (ir)
|
|
flags|=IP_FW_F_DRNG;
|
|
}
|
|
no_dst_ports:
|
|
|
|
}
|
|
|
|
|
|
|
|
flush(av)
|
|
char **av;
|
|
{
|
|
if (*av==NULL) {
|
|
if (setsockopt(s,IPPROTO_IP,IP_FW_FLUSH,NULL,0)<0) {
|
|
fprintf(stderr,"%s: setsockopt failed.\n",progname);
|
|
exit(1);
|
|
} else {
|
|
printf("All firewall entries flushed.\n");
|
|
}
|
|
if (setsockopt(s,IPPROTO_IP,IP_ACCT_FLUSH,NULL,0)<0) {
|
|
fprintf(stderr,"%s: setsockopt failed.\n",progname);
|
|
exit(1);
|
|
} else {
|
|
printf("All accounting entries flushed.\n");
|
|
}
|
|
exit(0);
|
|
}
|
|
if (!strncmp(*av,CH_FW,strlen(CH_FW))) {
|
|
if (setsockopt(s,IPPROTO_IP,IP_FW_FLUSH,NULL,0)<0) {
|
|
fprintf(stderr,"%s: setsockopt failed.\n",progname);
|
|
exit(1);
|
|
} else {
|
|
printf("All firewall entries flushed.\n");
|
|
exit(0);
|
|
}
|
|
}
|
|
if (!strncmp(*av,CH_AC,strlen(CH_AC))) {
|
|
if (setsockopt(s,IPPROTO_IP,IP_ACCT_FLUSH,NULL,0)<0) {
|
|
fprintf(stderr,"%s: setsockopt failed.\n",progname);
|
|
exit(1);
|
|
} else {
|
|
printf("All accounting entries flushed.\n");
|
|
exit(0);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void policy(av)
|
|
char **av;
|
|
{
|
|
int p;
|
|
kvm_t *kd;
|
|
static char errb[_POSIX2_LINE_MAX];
|
|
int b;
|
|
|
|
if (*av==NULL || strlen(*av)<=0)
|
|
{
|
|
if ( (kd=kvm_openfiles(NULL,NULL,NULL,O_RDONLY,errb)) == NULL) {
|
|
fprintf(stderr,"%s: kvm_openfiles: %s\n",progname,kvm_geterr(kd));
|
|
exit(1);
|
|
}
|
|
if (kvm_nlist(kd,nlf) < 0 || nlf[0].n_type == 0) {
|
|
fprintf(stderr,"%s: kvm_nlist: no namelist in %s\n",
|
|
progname,getbootfile());
|
|
exit(1);
|
|
}
|
|
|
|
kvm_read(kd,(u_long)nlf[N_POLICY].n_value,&b,sizeof(int));
|
|
|
|
if (b==1)
|
|
printf("Default policy: ACCEPT\n");
|
|
if (b==0)
|
|
printf("Default policy: DENY\n");
|
|
if (b!=0 && b!=1)
|
|
printf("Wrong policy value\n");
|
|
exit(1);
|
|
}
|
|
|
|
if (!strncmp(*av,P_DE,strlen(P_DE)))
|
|
p=0;
|
|
else
|
|
if (!strncmp(*av,P_AC,strlen(P_AC)))
|
|
p=1;
|
|
else {
|
|
fprintf(stderr,"%s: bad policy value.\n",progname);
|
|
exit(1);
|
|
}
|
|
|
|
if (setsockopt(s,IPPROTO_IP,IP_FW_POLICY,&p,sizeof(p))<0) {
|
|
fprintf(stderr,"%s: setsockopt failed.\n",progname);
|
|
exit(1);
|
|
} else {
|
|
if (p)
|
|
printf("Policy set to ACCEPT.\n");
|
|
else
|
|
printf("Policy set to DENY.\n");
|
|
exit(0);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
zero()
|
|
{
|
|
if (setsockopt(s,IPPROTO_IP,IP_ACCT_ZERO,NULL,0)<0) {
|
|
fprintf(stderr,"%s: setsockopt failed.\n",progname);
|
|
exit(1);
|
|
} else {
|
|
printf("Accounting cleared.\n");
|
|
exit(0);
|
|
}
|
|
}
|
|
|
|
main(ac,av)
|
|
int ac;
|
|
char **av;
|
|
{
|
|
|
|
char ch;
|
|
extern int optind;
|
|
int ctl,int_t,is_check=0;
|
|
struct ip_fw frwl;
|
|
|
|
strcpy(progname,*av);
|
|
|
|
s = socket( AF_INET, SOCK_RAW, IPPROTO_RAW );
|
|
if ( s < 0 ) {
|
|
fprintf(stderr,"%s: Can't open raw socket.Must be root to use this programm. \n",progname);
|
|
exit(1);
|
|
}
|
|
if ( ac == 1 ) {
|
|
show_usage();
|
|
exit(1);
|
|
}
|
|
|
|
while ((ch = getopt(ac, av ,"nv")) != EOF)
|
|
switch(ch) {
|
|
case 'n':
|
|
do_resolv=0;
|
|
break;
|
|
case 'v':
|
|
do_verbose=1;
|
|
break;
|
|
case '?':
|
|
default:
|
|
show_usage();
|
|
exit(1);
|
|
}
|
|
|
|
if (*(av+=optind)==NULL) {
|
|
show_usage();
|
|
exit(1);
|
|
}
|
|
|
|
switch(get_num(*av,action_tab)) {
|
|
case A_ADDB:
|
|
ctl=IP_FW_ADD_BLK;
|
|
int_t=FW;
|
|
break;
|
|
case A_DELB:
|
|
ctl=IP_FW_DEL_BLK;
|
|
int_t=FW;
|
|
break;
|
|
case A_CHKB:
|
|
ctl=IP_FW_CHK_BLK;
|
|
int_t=FW;
|
|
is_check=1;
|
|
break;
|
|
case A_ADDF:
|
|
ctl=IP_FW_ADD_FWD;
|
|
int_t=FW;
|
|
break;
|
|
case A_DELF:
|
|
ctl=IP_FW_DEL_FWD;
|
|
int_t=FW;
|
|
break;
|
|
case A_CHKF:
|
|
ctl=IP_FW_CHK_FWD;
|
|
int_t=FW;
|
|
is_check=1;
|
|
break;
|
|
case A_ADDA:
|
|
ctl=IP_ACCT_ADD;
|
|
int_t=AC;
|
|
break;
|
|
case A_DELA:
|
|
ctl=IP_ACCT_DEL;
|
|
int_t=AC;
|
|
break;
|
|
case A_FLUSH:
|
|
flush(++av);
|
|
exit(0); /* successful exit */
|
|
case A_LIST:
|
|
list(++av);
|
|
exit(0); /* successful exit */
|
|
case A_ZERO:
|
|
zero();
|
|
exit(0); /* successful exit */
|
|
case A_POLICY:
|
|
policy(++av);
|
|
exit(0); /* we never get here */
|
|
default:
|
|
show_usage();
|
|
exit(1);
|
|
} /* main action switch */
|
|
|
|
if (is_check)
|
|
goto proto_switch;
|
|
|
|
if (*(++av)==NULL) {
|
|
show_usage();
|
|
exit(1);
|
|
}
|
|
|
|
switch(get_num(*av,type_tab)) {
|
|
case T_DENY:
|
|
flags|=0; /* just to show it related to flags */
|
|
if (int_t!=FW) {
|
|
show_usage();
|
|
exit(1);
|
|
}
|
|
break;
|
|
case T_ACCEPT:
|
|
flags|=IP_FW_F_ACCEPT;
|
|
if (int_t!=FW) {
|
|
show_usage();
|
|
exit(1);
|
|
}
|
|
break;
|
|
case T_SINGLE:
|
|
flags|=0; /* just to show it related to flags */
|
|
if (int_t!=AC) {
|
|
show_usage();
|
|
exit(1);
|
|
}
|
|
break;
|
|
case T_BIDIR:
|
|
flags|=IP_FW_F_BIDIR;
|
|
if (int_t!=AC) {
|
|
show_usage();
|
|
exit(1);
|
|
}
|
|
break;
|
|
|
|
} /* type of switch */
|
|
|
|
proto_switch:
|
|
|
|
if (*(++av)==NULL) {
|
|
show_usage();
|
|
exit(1);
|
|
}
|
|
|
|
switch(get_num(*av,proto_tab)) {
|
|
case P_ALL:
|
|
flags|=IP_FW_F_ALL;
|
|
break;
|
|
case P_ICMP:
|
|
flags|=IP_FW_F_ICMP;
|
|
break;
|
|
case P_TCP:
|
|
flags|=IP_FW_F_TCP;
|
|
ports_ok=1;
|
|
strcpy(proto_name,"tcp");
|
|
break;
|
|
case P_UDP:
|
|
flags|=IP_FW_F_UDP;
|
|
ports_ok=1;
|
|
strcpy(proto_name,"udp");
|
|
break;
|
|
default:
|
|
show_usage();
|
|
exit(1);
|
|
}
|
|
|
|
if (*(++av)==NULL) {
|
|
show_usage();
|
|
exit(1);
|
|
}
|
|
|
|
set_entry(av,&frwl);
|
|
if (do_verbose)
|
|
flags|=IP_FW_F_PRN;
|
|
frwl.flags=flags;
|
|
|
|
if (is_check) {
|
|
struct ip *pkt;
|
|
struct tcphdr *th;
|
|
int p_len=sizeof(struct ip)+sizeof(struct tcphdr);
|
|
|
|
pkt=(struct ip*)malloc(p_len);
|
|
pkt->ip_v = IPVERSION;
|
|
pkt->ip_hl = sizeof(struct ip)/sizeof(int);
|
|
|
|
th=(struct tcphdr *)(pkt+1);
|
|
|
|
switch(get_num(proto_name,proto_tab)) {
|
|
case P_TCP:
|
|
pkt->ip_p = IPPROTO_TCP;
|
|
break;
|
|
case P_UDP:
|
|
pkt->ip_p = IPPROTO_UDP;
|
|
break;
|
|
default:
|
|
fprintf(stderr,"%s: can check TCP/UDP packets\
|
|
only.\n",progname);
|
|
exit(1);
|
|
}
|
|
if (frwl.n_src_p!=1 || frwl.n_dst_p!=1) {
|
|
fprintf(stderr,"%s: check needs one src/dst port.\n",
|
|
progname);
|
|
exit(1);
|
|
}
|
|
if (ntohl(frwl.src_mask.s_addr)!=ULONG_MAX ||
|
|
ntohl(frwl.dst_mask.s_addr)!=ULONG_MAX) {
|
|
fprintf(stderr,"%s: can't check masked IP.\n",progname);
|
|
exit(1);
|
|
}
|
|
pkt->ip_src.s_addr=frwl.src.s_addr;
|
|
pkt->ip_dst.s_addr=frwl.dst.s_addr;
|
|
|
|
th->th_sport=htons(frwl.ports[0]);
|
|
th->th_dport=htons(frwl.ports[frwl.n_src_p]);
|
|
|
|
if (setsockopt(s,IPPROTO_IP,ctl,pkt,p_len))
|
|
printf("Packet DENYED.\n");
|
|
else
|
|
printf("Packet ACCEPTED.\n");
|
|
exit(0);
|
|
} else {
|
|
if (setsockopt(s,IPPROTO_IP,ctl,&frwl,sizeof(frwl))<0) {
|
|
fprintf(stderr,"%s: setsockopt failed.\n",progname);
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Here the entry have to be added but not yet...
|
|
*/
|
|
|
|
close(s);
|
|
}
|
|
|
|
|