diff --git a/sys/contrib/ipfilter/netinet/fil.c b/sys/contrib/ipfilter/netinet/fil.c index 1d142165c34..e0f90e7e2eb 100644 --- a/sys/contrib/ipfilter/netinet/fil.c +++ b/sys/contrib/ipfilter/netinet/fil.c @@ -4411,6 +4411,35 @@ ipf_matchicmpqueryreply(v, ic, icmp, rev) return 0; } +static inline int +ipf_ifnames_compare(const int *ifnames1, const int *ifnames2, + const char *base1, const char *base2) +{ + int i; + + for(i = 0; i < 4; i++) { + if ((ifnames1[i] != -1 && ifnames2[i] == -1) || + (ifnames1[i] == -1 && ifnames2[i] != -1) || + (ifnames1[i] == -1 && ifnames2[i] == -1 && + strcmp(base1 + ifnames1[i], base2 + ifnames2[i]))) + return(1); + } + return(0); +} + +static inline int +ipf_dest_compare(const frdest_t *d1, const frdest_t *d2, + const char *base1, const char *base2) +{ + if (d1->fd_addr != d2->fd_addr || d1->fd_type != d2->fd_type || + (d1->fd_name != -1 && d2->fd_name == -1) || + (d1->fd_name == -1 && d2->fd_name != -1) || + (d1->fd_name != -1 && d2->fd_name != -1 && + d1->fd_type == FRD_NORMAL && + strcmp(base1 + d1->fd_name, base2 + d2->fd_name))) + return(1); + return(0); +} /* ------------------------------------------------------------------------ */ /* Function: ipf_rule_compare */ @@ -4430,8 +4459,25 @@ ipf_rule_compare(frentry_t *fr1, frentry_t *fr2) return 2; if (fr1->fr_dsize != fr2->fr_dsize) return 3; - if (bcmp((char *)&fr1->fr_func, (char *)&fr2->fr_func, - fr1->fr_size - offsetof(struct frentry, fr_func)) != 0) + if (memcmp(&fr1->fr_func, &fr2->fr_func, + offsetof(struct frentry, fr_ifnames) - + offsetof(struct frentry, fr_func)) != 0) + return 4; + if (ipf_ifnames_compare(fr1->fr_ifnames, fr2->fr_ifnames, + fr1->fr_names, fr2->fr_names)) + return 4; + if (memcmp(&fr1->fr_func, &fr2->fr_func, + offsetof(struct frentry, fr_tifs) - + offsetof(struct frentry, fr_isctag)) != 0) + return 4; + if (ipf_dest_compare(&fr1->fr_tifs[0], &fr2->fr_tifs[0], + fr1->fr_names, fr2->fr_names)) + return 4; + if (ipf_dest_compare(&fr1->fr_tifs[1], &fr2->fr_tifs[1], + fr1->fr_names, fr2->fr_names)) + return 4; + if (ipf_dest_compare(&fr1->fr_dif, &fr2->fr_dif, + fr1->fr_names, fr2->fr_names)) return 4; if (fr1->fr_data && !fr2->fr_data) return 5; @@ -4914,11 +4960,26 @@ frrequest(softc, unit, req, data, set, makecopy) * the constant part of the filter rule to make comparisons quicker * (this meaning no pointers are included). */ - for (fp->fr_cksum = 0, p = (u_int *)&fp->fr_func, pp = &fp->fr_cksum; + fp->fr_cksum = 0; + for (p = (u_int *)&fp->fr_func, pp = (u_int *)fp->fr_ifnames; + p < pp; p++) + fp->fr_cksum += *p; + for (p = (u_int *)&fp->fr_isctag, pp = (u_int *)fp->fr_tifs; p < pp; p++) fp->fr_cksum += *p; - pp = (u_int *)(fp->fr_caddr + fp->fr_dsize); - for (p = (u_int *)fp->fr_data; p < pp; p++) + { + int i; + for (i = 0; i <= 1; i++) + for (p = (u_int *)&fp->fr_tifs[i].fd_addr, + pp = (u_int *)&fp->fr_tifs[i].fd_name; + p < pp; p++) + fp->fr_cksum += *p; + } + for (p = (u_int *)&fp->fr_dif.fd_addr, pp = (u_int *)&fp->fr_dif.fd_name; + p < pp; p++) + fp->fr_cksum += *p; + for (p = (u_int *)fp->fr_data, pp = (u_int *)(fp->fr_caddr + fp->fr_dsize); + p < pp; p++) fp->fr_cksum += *p; WRITE_ENTER(&softc->ipf_mutex);