diff options
author | cy <cy@FreeBSD.org> | 2016-04-07 01:42:09 +0000 |
---|---|---|
committer | cy <cy@FreeBSD.org> | 2016-04-07 01:42:09 +0000 |
commit | cc1aaf5a1a88524a7d9ff817b98dcfb66049f5f8 (patch) | |
tree | ea431559766b6f13c272fccd4ee28f27b3770578 /sys/contrib/ipfilter | |
parent | 6da26de1ae88bf0f8bdbbd72ea8695e9df179c75 (diff) | |
download | FreeBSD-src-cc1aaf5a1a88524a7d9ff817b98dcfb66049f5f8.zip FreeBSD-src-cc1aaf5a1a88524a7d9ff817b98dcfb66049f5f8.tar.gz |
Add DTrace probes for packets flagged as bad by ipfilter. All probes
for bad packets are named ipf_fi_bad_*. An example of its use might be:
dtrace -n 'sdt:::ipf_fi_bad_* { stack(); }'
Reviewed by: Darren Reed <darrenr@reed.wattle.id.au>
Diffstat (limited to 'sys/contrib/ipfilter')
-rw-r--r-- | sys/contrib/ipfilter/netinet/fil.c | 50 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_fil_freebsd.c | 8 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_frag.c | 3 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_state.c | 12 |
4 files changed, 62 insertions, 11 deletions
diff --git a/sys/contrib/ipfilter/netinet/fil.c b/sys/contrib/ipfilter/netinet/fil.c index 58d9028..0aeb44b 100644 --- a/sys/contrib/ipfilter/netinet/fil.c +++ b/sys/contrib/ipfilter/netinet/fil.c @@ -629,6 +629,7 @@ ipf_pr_ipv6hdr(fin) ipf_main_softc_t *softc = fin->fin_main_soft; fin->fin_flx |= FI_BAD; + DT2(ipf_fi_bad_ipv6_frag_1, fr_info_t *, fin, int, go); LBUMPD(ipf_stats[fin->fin_out], fr_v6_badfrag); LBUMP(ipf_stats[fin->fin_out].fr_v6_bad); } @@ -687,6 +688,7 @@ ipf_pr_ipv6exthdr(fin, multiple, proto) if (shift > fin->fin_dlen) { /* Nasty extension header length? */ fin->fin_flx |= FI_BAD; + DT3(ipf_fi_bad_pr_ipv6exthdr_len, fr_info_t *, fin, u_short, shift, u_short, fin->fin_dlen); LBUMPD(ipf_stats[fin->fin_out], fr_v6_ext_hlen); return NULL; } @@ -708,9 +710,10 @@ ipf_pr_ipv6exthdr(fin, multiple, proto) * Most IPv6 extension headers are only allowed once. */ if ((multiple == 0) && - ((fin->fin_optmsk & ip6exthdr[i].ol_bit) != 0)) + ((fin->fin_optmsk & ip6exthdr[i].ol_bit) != 0)) { fin->fin_flx |= FI_BAD; - else + DT2(ipf_fi_bad_ipv6exthdr_once, fr_info_t *, fin, u_int, (fin->fin_optmsk & ip6exthdr[i].ol_bit)); + } else fin->fin_optmsk |= ip6exthdr[i].ol_bit; break; } @@ -790,6 +793,7 @@ ipf_pr_routing6(fin) ipf_main_softc_t *softc = fin->fin_main_soft; fin->fin_flx |= FI_BAD; + DT1(ipf_fi_bad_routing6, fr_info_t *, fin); LBUMPD(ipf_stats[fin->fin_out], fr_v6_rh_bad); return IPPROTO_NONE; } @@ -852,8 +856,10 @@ ipf_pr_fragment6(fin) * Any fragment that isn't the last fragment must have its * length as a multiple of 8. */ - if ((fin->fin_plen & 7) != 0) + if ((fin->fin_plen & 7) != 0) { fin->fin_flx |= FI_BAD; + DT2(ipf_fi_bad_frag_not_8, fr_info_t *, fin, u_int, (fin->fin_plen & 7)); + } } fin->fin_fraghdr = frag; @@ -865,8 +871,10 @@ ipf_pr_fragment6(fin) /* * Jumbograms aren't handled, so the max. length is 64k */ - if ((fin->fin_off << 3) + fin->fin_dlen > 65535) + if ((fin->fin_off << 3) + fin->fin_dlen > 65535) { fin->fin_flx |= FI_BAD; + DT2(ipf_fi_bad_jumbogram, fr_info_t *, fin, u_int, ((fin->fin_off << 3) + fin->fin_dlen)); + } /* * We don't know where the transport layer header (or whatever is next @@ -970,8 +978,10 @@ ipf_pr_icmp6(fin) icmp6 = fin->fin_dp; ip6 = (ip6_t *)((char *)icmp6 + ICMPERR_ICMPHLEN); if (IP6_NEQ(&fin->fin_fi.fi_dst, - (i6addr_t *)&ip6->ip6_src)) + (i6addr_t *)&ip6->ip6_src)) { fin->fin_flx |= FI_BAD; + DT1(ipf_fi_bad_icmp6, fr_info_t *, fin); + } break; default : break; @@ -1283,8 +1293,10 @@ ipf_pr_icmp(fin) case ICMP_UNREACH : #ifdef icmp_nextmtu if (icmp->icmp_code == ICMP_UNREACH_NEEDFRAG) { - if (icmp->icmp_nextmtu < softc->ipf_icmpminfragmtu) + if (icmp->icmp_nextmtu < softc->ipf_icmpminfragmtu) { fin->fin_flx |= FI_BAD; + DT3(ipf_fi_bad_icmp_nextmtu, fr_info_t *, fin, u_int, icmp->icmp_nextmtu, u_int, softc->ipf_icmpminfragmtu); + } } #endif case ICMP_SOURCEQUENCH : @@ -1303,16 +1315,20 @@ ipf_pr_icmp(fin) * fragment. */ oip = (ip_t *)((char *)fin->fin_dp + ICMPERR_ICMPHLEN); - if ((ntohs(oip->ip_off) & IP_OFFMASK) != 0) + if ((ntohs(oip->ip_off) & IP_OFFMASK) != 0) { fin->fin_flx |= FI_BAD; + DT2(ipf_fi_bad_icmp_err, fr_info_t, fin, u_int, (ntohs(oip->ip_off) & IP_OFFMASK)); + } /* * If the destination of this packet doesn't match the * source of the original packet then this packet is * not correct. */ - if (oip->ip_src.s_addr != fin->fin_daddr) + if (oip->ip_src.s_addr != fin->fin_daddr) { fin->fin_flx |= FI_BAD; + DT1(ipf_fi_bad_src_ne_dst, fr_info_t *, fin); + } break; default : break; @@ -1372,6 +1388,7 @@ ipf_pr_tcpcommon(fin) if (tlen < sizeof(tcphdr_t)) { LBUMPD(ipf_stats[fin->fin_out], fr_tcp_small); fin->fin_flx |= FI_BAD; + DT3(ipf_fi_bad_tlen, fr_info_t, fin, u_int, tlen, u_int, sizeof(tcphdr_t)); return 1; } @@ -1385,6 +1402,7 @@ ipf_pr_tcpcommon(fin) */ if ((flags & TH_URG) != 0 && (tcp->th_urp == 0)) { fin->fin_flx |= FI_BAD; + DT3(ipf_fi_bad_th_urg, fr_info_t*, fin, u_int, (flags & TH_URG), u_int, tcp->th_urp); #if 0 } else if ((flags & TH_URG) == 0 && (tcp->th_urp != 0)) { /* @@ -1392,11 +1410,13 @@ ipf_pr_tcpcommon(fin) * traffic with bogus values in the urgent pointer field. */ fin->fin_flx |= FI_BAD; + DT3(ipf_fi_bad_th_urg0, fr_info_t *, fin, u_int, (flags & TH_URG), u_int, tcp->th_urp); #endif } else if (((flags & (TH_SYN|TH_FIN)) != 0) && ((flags & (TH_RST|TH_ACK)) == TH_RST)) { /* TH_FIN|TH_RST|TH_ACK seems to appear "naturally" */ fin->fin_flx |= FI_BAD; + DT1(ipf_fi_bad_th_fin_rst_ack, fr_info_t, fin); #if 1 } else if (((flags & TH_SYN) != 0) && ((flags & (TH_URG|TH_PUSH)) != 0)) { @@ -1405,6 +1425,7 @@ ipf_pr_tcpcommon(fin) * possible(?) with T/TCP...but who uses T/TCP? */ fin->fin_flx |= FI_BAD; + DT1(ipf_fi_bad_th_syn_urg_psh, fr_info_t *, fin); #endif } else if (!(flags & TH_ACK)) { /* @@ -1423,10 +1444,13 @@ ipf_pr_tcpcommon(fin) * achieved. */ /*fin->fin_flx |= FI_BAD*/; + /*DT1(ipf_fi_bad_th_syn_ack, fr_info_t *, fin);*/ } else if (!(flags & (TH_RST|TH_SYN))) { fin->fin_flx |= FI_BAD; + DT1(ipf_fi_bad_th_rst_syn, fr_info_t *, fin); } else if ((flags & (TH_URG|TH_PUSH|TH_FIN)) != 0) { fin->fin_flx |= FI_BAD; + DT1(ipf_fi_bad_th_urg_push_fin, fr_info_t *, fin); } } if (fin->fin_flx & FI_BAD) { @@ -1757,6 +1781,7 @@ ipf_pr_ipv4hdr(fin) * must be an even multiple of 8. */ fi->fi_flx |= FI_BAD; + DT1(ipf_fi_bad_fragbody_gt_65535, fr_info_t *, fin); } } } @@ -1840,6 +1865,7 @@ ipf_pr_ipv4hdr(fin) case IPOPT_SECURITY : if (optmsk & op->ol_bit) { fin->fin_flx |= FI_BAD; + DT2(ipf_fi_bad_ipopt_security, fr_info_t *, fin, u_short, (optmsk & op->ol_bit)); } else { doi = ipf_checkripso(s); secmsk = doi >> 16; @@ -1851,6 +1877,7 @@ ipf_pr_ipv4hdr(fin) if (optmsk & op->ol_bit) { fin->fin_flx |= FI_BAD; + DT2(ipf_fi_bad_ipopt_cipso, fr_info_t *, fin, u_short, (optmsk & op->ol_bit)); } else { doi = ipf_checkcipso(fin, s, ol); @@ -1949,6 +1976,7 @@ ipf_checkcipso(fin, s, ol) if (ol < 6 || ol > 40) { LBUMPD(ipf_stats[fin->fin_out], fr_v4_cipso_bad); fin->fin_flx |= FI_BAD; + DT2(ipf_fi_bad_checkcipso_ol, fr_info_t *, fin, u_int, ol); return 0; } @@ -1966,6 +1994,7 @@ ipf_checkcipso(fin, s, ol) if (tlen > len || tlen < 4 || tlen > 34) { LBUMPD(ipf_stats[fin->fin_out], fr_v4_cipso_tlen); fin->fin_flx |= FI_BAD; + DT2(ipf_fi_bad_checkcipso_tlen, fr_info_t *, fin, u_int, tlen); return 0; } @@ -1976,10 +2005,12 @@ ipf_checkcipso(fin, s, ol) */ if (tag == 0) { fin->fin_flx |= FI_BAD; + DT2(ipf_fi_bad_checkcipso_tag, fr_info_t *, fin, u_int, tag); continue; } else if (tag == 1) { if (*(t + 2) != 0) { fin->fin_flx |= FI_BAD; + DT2(ipf_fi_bad_checkcipso_tag1_t2, fr_info_t *, fin, u_int, (*t + 2)); continue; } sensitivity = *(t + 3); @@ -1988,6 +2019,7 @@ ipf_checkcipso(fin, s, ol) } else if (tag == 4) { if (*(t + 2) != 0) { fin->fin_flx |= FI_BAD; + DT2(ipf_fi_bad_checkcipso_tag4_t2, fr_info_t *, fin, u_int, (*t + 2)); continue; } sensitivity = *(t + 3); @@ -1996,6 +2028,7 @@ ipf_checkcipso(fin, s, ol) } else if (tag == 5) { if (*(t + 2) != 0) { fin->fin_flx |= FI_BAD; + DT2(ipf_fi_bad_checkcipso_tag5_t2, fr_info_t *, fin, u_int, (*t + 2)); continue; } sensitivity = *(t + 3); @@ -2006,6 +2039,7 @@ ipf_checkcipso(fin, s, ol) ; } else { fin->fin_flx |= FI_BAD; + DT2(ipf_fi_bad_checkcipso_tag127, fr_info_t *, fin, u_int, tag); continue; } diff --git a/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c b/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c index 8a5a90d..3b74f8c 100644 --- a/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c +++ b/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c @@ -1091,6 +1091,7 @@ ipf_checkv4sum(fin) CSUM_IP_CHECKED) { fin->fin_cksum = FI_CK_BAD; fin->fin_flx |= FI_BAD; + DT2(ipf_fi_bad_checkv4sum_csum_ip_checked, fr_info_t *, fin, u_int, m->m_pkthdr.csum_flags & (CSUM_IP_CHECKED|CSUM_IP_VALID)); return -1; } if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) { @@ -1120,6 +1121,7 @@ ipf_checkv4sum(fin) if (sum != 0) { fin->fin_cksum = FI_CK_BAD; fin->fin_flx |= FI_BAD; + DT2(ipf_fi_bad_checkv4sum_sum, fr_info_t *, fin, u_int, sum); } else { fin->fin_cksum = FI_CK_SUMOK; return 0; @@ -1143,12 +1145,14 @@ skipauto: if (manual != 0) { if (ipf_checkl4sum(fin) == -1) { fin->fin_flx |= FI_BAD; + DT2(ipf_fi_bad_checkv4sum_manual, fr_info_t *, fin, u_int, manual); return -1; } } #else if (ipf_checkl4sum(fin) == -1) { fin->fin_flx |= FI_BAD; + DT2(ipf_fi_bad_checkv4sum_checkl4sum, fr_info_t *, fin, u_int, -1); return -1; } #endif @@ -1162,16 +1166,20 @@ ipf_checkv6sum(fin) fr_info_t *fin; { if ((fin->fin_flx & FI_NOCKSUM) != 0) + DT(ipf_checkv6sum_fi_nocksum); return 0; if ((fin->fin_flx & FI_SHORT) != 0) + DT(ipf_checkv6sum_fi_short); return 1; if (fin->fin_cksum != FI_CK_NEEDED) + DT(ipf_checkv6sum_fi_ck_needed); return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1; if (ipf_checkl4sum(fin) == -1) { fin->fin_flx |= FI_BAD; + DT2(ipf_fi_bad_checkv6sum_checkl4sum, fr_info_t *, fin, u_int, -1); return -1; } return 0; diff --git a/sys/contrib/ipfilter/netinet/ip_frag.c b/sys/contrib/ipfilter/netinet/ip_frag.c index 7e3457a..e0cc5f3 100644 --- a/sys/contrib/ipfilter/netinet/ip_frag.c +++ b/sys/contrib/ipfilter/netinet/ip_frag.c @@ -719,6 +719,8 @@ ipf_frag_lookup(softc, softf, fin, table FBUMP(ifs_overlap); DT2(ifs_overlap, u_short, off, ipfr_t *, f); + DT3(ipf_fi_bad_ifs_overlap, fr_info_t *, fin, u_short, off, + ipfr_t *, f); fin->fin_flx |= FI_BAD; break; } @@ -901,6 +903,7 @@ ipf_frag_known(fin, passp) if (fin->fin_flx & FI_BAD) { fr = &ipfr_block; fin->fin_reason = FRB_BADFRAG; + DT2(ipf_frb_badfrag, fr_info_t *, fin, uint, fra); } else { fr = fra->ipfr_rule; } diff --git a/sys/contrib/ipfilter/netinet/ip_state.c b/sys/contrib/ipfilter/netinet/ip_state.c index 2ceec32..34a64f0 100644 --- a/sys/contrib/ipfilter/netinet/ip_state.c +++ b/sys/contrib/ipfilter/netinet/ip_state.c @@ -1611,8 +1611,10 @@ ipf_state_add(softc, fin, stsave, flags) TH_SYN && (TCP_OFF(tcp) > (sizeof(tcphdr_t) >> 2))) { if (ipf_tcpoptions(softs, fin, tcp, - &is->is_tcp.ts_data[0]) == -1) + &is->is_tcp.ts_data[0]) == -1) { fin->fin_flx |= FI_BAD; + DT1(ipf_fi_bad_tcpoptions_th_fin_ack_ecnall, fr_info_t *, fin); + } } if ((fin->fin_out != 0) && (pass & FR_NEWISN) != 0) { @@ -2068,8 +2070,10 @@ ipf_state_tcp(softc, softs, fin, tcp, is) is->is_s0[!source] = ntohl(tcp->th_seq) + 1; if ((TCP_OFF(tcp) > (sizeof(tcphdr_t) >> 2))) { if (ipf_tcpoptions(softs, fin, tcp, - fdata) == -1) + fdata) == -1) { fin->fin_flx |= FI_BAD; + DT1(ipf_fi_bad_winscale_syn_ack, fr_info_t *, fin); + } } if ((fin->fin_out != 0) && (is->is_pass & FR_NEWISN)) ipf_checknewisn(fin, is); @@ -2077,8 +2081,10 @@ ipf_state_tcp(softc, softs, fin, tcp, is) is->is_s0[source] = ntohl(tcp->th_seq) + 1; if ((TCP_OFF(tcp) > (sizeof(tcphdr_t) >> 2))) { if (ipf_tcpoptions(softs, fin, tcp, - fdata) == -1) + fdata) == -1) { fin->fin_flx |= FI_BAD; + DT1(ipf_fi_bad_winscale_syn, fr_info_t *, fin); + } } if ((fin->fin_out != 0) && (is->is_pass & FR_NEWISN)) |