diff --git a/sbin/ipfw/ipfw.c b/sbin/ipfw/ipfw.c index e19ac7e8e77b..4c7179b4870c 100644 --- a/sbin/ipfw/ipfw.c +++ b/sbin/ipfw/ipfw.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -61,12 +62,19 @@ u_short flags=0; /* New entry flags */ #define IS_TOKEN(x) (IS_TO(x) || IS_FROM(x) || IS_VIA(x) ||\ IS_IPOPT(x) || IS_TCPFLG(x)) - #define IPO_LSRR "ls" #define IPO_SSRR "ss" #define IPO_RR "rr" #define IPO_TS "ts" +#define TCPF_FIN "fin" +#define TCPF_SYN "syn" +#define TCPF_RST "rst" +#define TCPF_PUSH "pus" +#define TCPF_ACK "ack" +#define TCPF_URG "urg" + + #define P_AC "a" /* of "accept" for policy action */ #define P_DE "d" /* of "deny" for policy action */ @@ -285,19 +293,25 @@ else he=gethostbyaddr((char *)&adrt,sizeof(u_long),AF_INET); if (he==NULL) { printf(inet_ntoa(chain->fw_src)); - printf(":"); - printf(inet_ntoa(chain->fw_smsk)); } else printf("%s",he->h_name); } else { - printf(inet_ntoa(chain->fw_src)); - if (adrt!=ULONG_MAX) - if ((mb=mask_bits(chain->fw_smsk))>=0) - printf("/%d",mb); - else { - printf(":"); - printf(inet_ntoa(chain->fw_smsk)); + 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)); } comma = " "; @@ -320,19 +334,25 @@ else he=gethostbyaddr((char *)&adrt,sizeof(u_long),AF_INET); if (he==NULL) { printf(inet_ntoa(chain->fw_dst)); - printf(":"); - printf(inet_ntoa(chain->fw_dmsk)); } else printf("%s",he->h_name); } else { - printf(inet_ntoa(chain->fw_dst)); - if (adrt!=ULONG_MAX) - if ((mb=mask_bits(chain->fw_dmsk))>=0) - printf("/%d",mb); - else { - printf(":"); - printf(inet_ntoa(chain->fw_dmsk)); + 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 = " "; @@ -364,7 +384,7 @@ if (chain->fw_via_ip.s_addr) { if (do_short) printf("]"); - if (chain->fw_ipopt && chain->fw_ipnopt) { + if (chain->fw_ipopt || chain->fw_ipnopt) { if (do_short) { printf("["); if (chain->fw_ipopt & IP_FW_IPOPT_SSRR) @@ -389,7 +409,7 @@ if (do_short) #define PRINTOPT(x) {if (_opt_printed) printf(",");\ printf(x); _opt_printed = 1;} - printf("ipopt "); + printf(" ipopt "); if (chain->fw_ipopt & IP_FW_IPOPT_SSRR) PRINTOPT("ssrr"); if (chain->fw_ipnopt & IP_FW_IPOPT_SSRR) @@ -408,6 +428,67 @@ if (do_short) PRINTOPT("!ts"); } } + + if (chain->fw_tcpf || chain->fw_tcpnf) { + if (do_short) { + printf("[*"); + if (chain->fw_tcpf & IP_FW_TCPF_FIN) + printf("F"); + if (chain->fw_tcpnf & IP_FW_TCPF_FIN) + printf("f"); + if (chain->fw_tcpf & IP_FW_TCPF_SYN) + printf("S"); + if (chain->fw_tcpnf & IP_FW_TCPF_SYN) + printf("s"); + if (chain->fw_tcpf & IP_FW_TCPF_RST) + printf("R"); + if (chain->fw_tcpnf & IP_FW_TCPF_RST) + printf("r"); + if (chain->fw_tcpf & IP_FW_TCPF_PUSH) + printf("P"); + if (chain->fw_tcpnf & IP_FW_TCPF_PUSH) + printf("p"); + if (chain->fw_tcpf & IP_FW_TCPF_ACK) + printf("A"); + if (chain->fw_tcpnf & IP_FW_TCPF_ACK) + printf("a"); + if (chain->fw_tcpf & IP_FW_TCPF_URG) + printf("U"); + if (chain->fw_tcpnf & IP_FW_TCPF_URG) + printf("u"); + printf("]"); + } else { + 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_PUSH) + PRINTFLG("push"); + if (chain->fw_tcpnf & IP_FW_TCPF_PUSH) + PRINTFLG("!push"); + 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"); + } + } printf("\n"); } @@ -711,7 +792,7 @@ u_char *optr; p_str = str; while ((t_str = strtok(p_str,",")) != NULL) { p_str = NULL; -printf("tstr = %s\n", t_str); + if (t_str[0] == '!') { optr = &(frwl->fw_ipnopt); t_str ++; @@ -730,7 +811,49 @@ printf("tstr = %s\n", t_str); if (!strncmp(t_str, IPO_TS, strlen(IPO_TS))) *(optr) |= IP_FW_IPOPT_TS; else { - fprintf(stderr,"%s: bad ipoption.\n", progname); + fprintf(stderr,"%s: bad ip option.\n", progname); + exit(1); + } + } +} + + +void set_entry_tcpflgs(str, frwl) + char *str; + struct ip_fw *frwl; +{ +char *t_str,*p_str; +u_char *fptr; + + p_str = str; + while ((t_str = strtok(p_str,",")) != NULL) { + p_str = NULL; + + if (t_str[0] == '!') { + fptr = &(frwl->fw_tcpnf); + t_str ++; + } else + fptr = &(frwl->fw_tcpf); + + if (!strncmp(t_str, TCPF_FIN, strlen(TCPF_FIN))) + *(fptr) |= IP_FW_TCPF_FIN; + else + if (!strncmp(t_str, TCPF_SYN, strlen(TCPF_SYN))) + *(fptr) |= IP_FW_TCPF_SYN; + else + if (!strncmp(t_str, TCPF_RST, strlen(TCPF_RST))) + *(fptr) |= IP_FW_TCPF_RST; + else + if (!strncmp(t_str, TCPF_PUSH, strlen(TCPF_PUSH))) + *(fptr) |= IP_FW_TCPF_PUSH; + else + if (!strncmp(t_str, TCPF_ACK, strlen(TCPF_ACK))) + *(fptr) |= IP_FW_TCPF_ACK; + else + if (!strncmp(t_str, TCPF_URG, strlen(TCPF_URG))) + *(fptr) |= IP_FW_TCPF_URG; + else { + fprintf(stderr,"%s: bad tcp flag.\n", progname); exit(1); } } @@ -760,6 +883,8 @@ int token; frwl->fw_ndp=0; frwl->fw_ipopt = 0; frwl->fw_ipnopt = 0; + frwl->fw_tcpf = 0; + frwl->fw_tcpnf = 0; frwl->fw_via_ip.s_addr=0L; frwl->fw_src.s_addr=0L; frwl->fw_dst.s_addr=0L; @@ -845,6 +970,23 @@ int token; got_ipopt = 1; } + if (IS_TCPFLG(*av)) { + token = T_TCPFLG; + + if (got_tcpflg) { + show_usage("Redefined 'tcpflags'."); + exit(1); + } + + if (*(++av)==NULL) { + show_usage("Missing 'tcpflags' specification."); + exit(1); + } + + set_entry_tcpflgs(*av, frwl); + + got_tcpflg = 1; + } if (*(++av)==NULL) { return; @@ -904,7 +1046,7 @@ char **av; } else { printf("All accounting entries flushed.\n"); } - exit(0); + return; } if (!strncmp(*av,CH_FW,strlen(CH_FW))) { if (setsockopt(s,IPPROTO_IP,IP_FW_FLUSH,NULL,0)<0) { @@ -912,7 +1054,7 @@ char **av; exit(1); } else { printf("All firewall entries flushed.\n"); - exit(0); + return; } } if (!strncmp(*av,CH_AC,strlen(CH_AC))) { @@ -921,7 +1063,7 @@ char **av; exit(1); } else { printf("All accounting entries flushed.\n"); - exit(0); + return; } } @@ -974,7 +1116,7 @@ if (setsockopt(s,IPPROTO_IP,IP_FW_POLICY,&p,sizeof(p))<0) { printf("Policy set to DENY.\n"); else printf("Policy set to ACCEPT.\n"); - exit(0); + return; } } @@ -987,11 +1129,11 @@ zero() exit(1); } else { printf("Accounting cleared.\n"); - exit(0); + return; } } -main(ac,av) +ipfw_main(ac,av) int ac; char **av; { @@ -1062,16 +1204,16 @@ struct ip_fw frwl; break; case A_FLUSH: flush(++av); - exit(0); /* successful exit */ + return; case A_LIST: list(++av); - exit(0); /* successful exit */ + return; case A_ZERO: zero(); - exit(0); /* successful exit */ + return; case A_POLICY: policy(++av); - exit(0); /* we never get here */ + return; default: int_t=(AC|FW); int_notdef=1; @@ -1243,4 +1385,44 @@ struct ip_fw frwl; close(s); } +void main(ac, av) + int ac; + char **av; +{ +#define MAX_ARGS 32 + char buf[_POSIX_ARG_MAX]; + char *args[MAX_ARGS]; + char linename[10]; + int lineno = 0, i, j; + FILE *f; + if (av[1] && !access(av[1], R_OK)) { + f = fopen(av[1], "r"); + while (fgets(buf, _POSIX_ARG_MAX, 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] = findchar(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); +} diff --git a/sys/netinet/ip_fw.c b/sys/netinet/ip_fw.c index a40506d8817e..aa6fc226eab7 100644 --- a/sys/netinet/ip_fw.c +++ b/sys/netinet/ip_fw.c @@ -99,6 +99,24 @@ port_match(portptr, nports, port, range_flag) return FALSE; } +int +tcpflg_match(tcp, f) + struct tcphdr *tcp; + struct ip_fw *f; +{ + u_char flg_set, flg_clr; + + flg_set = tcp->th_flags & f->fw_tcpf; + flg_clr = tcp->th_flags & f->fw_tcpnf; + + if (flg_set != f->fw_tcpf) + return 0; + if (flg_clr != f->fw_tcpnf) + return 0; + + return 1; +} + int ipopts_match(ip, f) @@ -109,14 +127,11 @@ ipopts_match(ip, f) int opt, optlen, cnt; u_char opts, nopts, nopts_sve; -printf("Here\n"); - cp = (u_char *)(ip + 1); cnt = (ip->ip_hl << 2) - sizeof (struct ip); opts = f->fw_ipopt; nopts = nopts_sve = f->fw_ipnopt; -printf("opts = %x, nopts = %x\n", opts, nopts); -printf("Cnt = %d\n", cnt); + for (; cnt > 0; cnt -= optlen, cp += optlen) { opt = cp[IPOPT_OPTVAL]; if (opt == IPOPT_EOL) @@ -135,7 +150,6 @@ printf("Cnt = %d\n", cnt); break; case IPOPT_LSRR: -printf("Has LSRR\n"); opts &= ~IP_FW_IPOPT_LSRR; nopts &= ~IP_FW_IPOPT_LSRR; break; @@ -157,7 +171,6 @@ printf("Has LSRR\n"); if (opts == nopts) break; } -printf("opts = %x, nopts = %x\n", opts, nopts); if (opts == 0 && nopts == nopts_sve) return 1; else @@ -314,15 +327,21 @@ ip_fw_chk(m, ip, rif, chain) * Specific firewall - packet's protocol must * match firewall's */ - if (prt == f_prt) { - if (prt == IP_FW_F_ICMP || - (port_match(&f->fw_pts[0], f->fw_nsp, src_port, - f->fw_flg & IP_FW_F_SRNG) && - port_match(&f->fw_pts[f->fw_nsp], f->fw_ndp, dst_port, - f->fw_flg & IP_FW_F_DRNG))) { + if (prt != f_prt) + continue; + if (prt == IP_FW_F_ICMP) + goto got_match; + if (prt == IP_FW_F_TCP) + if (f->fw_tcpf != f->fw_tcpnf) + if (!tcpflg_match(tcp, f)) + continue; + + if (port_match(&f->fw_pts[0], f->fw_nsp, + src_port, f->fw_flg & IP_FW_F_SRNG) && + port_match(&f->fw_pts[f->fw_nsp], f->fw_ndp, + dst_port, f->fw_flg & IP_FW_F_DRNG)) goto got_match; - } /* Ports match */ - } /* Proto matches */ + } /* ALL/Specific */ } /* IP addr/mask matches */ /* @@ -719,6 +738,16 @@ add_entry(chainptr, frwl) if (n_dr > o_dr) addb4--; + if (n_dr == o_dr && n_sr == o_sr && + oldkind == IP_FW_F_TCP) { + if (ftmp->fw_tcpf != 0 && + chtmp->fw_tcpf == 0) + addb4++; + if (ftmp->fw_tcpnf != 0 && + chtmp->fw_tcpnf == 0) + addb4++; + } + skip_check: } if (ftmp->fw_ipopt != 0 && chtmp->fw_ipopt == 0)