/* * test case for mask_match() bug */ #include #include #include #include #include #include #include #include #include #include #include #include /* XXX */ struct encaptab { int af; int proto; struct sockaddr_storage src; struct sockaddr_storage srcmask; struct sockaddr_storage dst; struct sockaddr_storage dstmask; }; int mask_match(ep, sp, dp) const struct encaptab *ep; const struct sockaddr *sp; const struct sockaddr *dp; { struct sockaddr_storage s; struct sockaddr_storage d; int i; const u_int8_t *p, *q; u_int8_t *r; int matchlen; if (sp->sa_len > sizeof(s) || dp->sa_len > sizeof(d)) { fprintf(stderr, "lengths too big\n"); return 0; } if (sp->sa_family != ep->af || dp->sa_family != ep->af) { fprintf(stderr, "af dont match \n"); return 0; } if (sp->sa_len != ep->src.ss_len || dp->sa_len != ep->dst.ss_len) { fprintf(stderr, "lengths dont match \n"); return 0; } matchlen = 0; p = (const u_int8_t *)sp; q = (const u_int8_t *)&ep->srcmask; r = (u_int8_t *)&s; for (i = 0 ; i < sp->sa_len; i++) { r[i] = p[i] & q[i]; /* XXX estimate */ matchlen += (q[i] ? 8 : 0); } p = (const u_int8_t *)dp; q = (const u_int8_t *)&ep->dstmask; r = (u_int8_t *)&d; for (i = 0 ; i < dp->sa_len; i++) { r[i] = p[i] & q[i]; /* XXX rough estimate */ matchlen += (q[i] ? 8 : 0); } /* need to overwrite len/family portion as we don't compare them */ s.ss_len = sp->sa_len; s.ss_family = sp->sa_family; d.ss_len = dp->sa_len; d.ss_family = dp->sa_family; if (bcmp(&s, &ep->src, ep->src.ss_len) == 0 && bcmp(&d, &ep->dst, ep->dst.ss_len) == 0) { fprintf(stderr, "match\n"); return matchlen; } else { fprintf(stderr, "no match\n"); return 0; } } int main(int argc, char *argv[]) { struct encaptab e; struct sockaddr_storage ss1; struct sockaddr_storage ss2; struct sockaddr_in *psin_1; struct sockaddr_in *psin_2; int result; bzero(&e, sizeof(e)); e.af = AF_INET; e.proto = -1; psin_1 = (struct sockaddr_in *)&e.src; psin_1->sin_family = AF_INET; psin_1->sin_len = sizeof(struct sockaddr_in); psin_1->sin_addr.s_addr = inet_addr("1.2.3.4"); psin_1 = (struct sockaddr_in *)&e.srcmask; psin_1->sin_family = AF_INET; psin_1->sin_len = sizeof(struct sockaddr_in); psin_1->sin_addr.s_addr = inet_addr("255.255.255.0"); psin_1 = (struct sockaddr_in *)&e.dst; psin_1->sin_family = AF_INET; psin_1->sin_len = sizeof(struct sockaddr_in); psin_1->sin_addr.s_addr = inet_addr("4.3.2.1"); psin_1 = (struct sockaddr_in *)&e.dstmask; psin_1->sin_family = AF_INET; psin_1->sin_len = sizeof(struct sockaddr_in); psin_1->sin_addr.s_addr = inet_addr("0.0.0.0"); bzero(&ss1, sizeof(ss1)); bzero(&ss2, sizeof(ss2)); psin_1 = (struct sockaddr_in *)&ss1; psin_2 = (struct sockaddr_in *)&ss2; psin_1->sin_len = sizeof(struct sockaddr_in); psin_1->sin_family = AF_INET; psin_1->sin_addr.s_addr = inet_addr("192.168.0.1"); psin_2->sin_len = sizeof(struct sockaddr_in); psin_2->sin_family = AF_INET; psin_2->sin_addr.s_addr = inet_addr("4.3.2.2"); result = mask_match(&e, &ss1, &ss2); printf("result is %d\n", result); exit(0); }