kern/95277: [netinet] IP Encapsulation mask_match() returns
wrong results
Bruce M Simpson
bms at incunabulum.net
Thu Sep 28 10:10:27 PDT 2006
The following reply was made to PR kern/95277; it has been noted by GNATS.
From: Bruce M Simpson <bms at incunabulum.net>
To: freebsd-gnats-submit at FreeBSD.org
Cc:
Subject: Re: kern/95277: [netinet] IP Encapsulation mask_match() returns wrong
results
Date: Thu, 28 Sep 2006 18:07:34 +0100
This is a multi-part message in MIME format.
--------------050007060704060608050700
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
I don't quite get this. Test case attached.
--------------050007060704060608050700
Content-Type: text/x-csrc;
name="maskmatch.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="maskmatch.c"
/*
* test case for mask_match() bug
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/ip_mroute.h>
#include <stddef.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <err.h>
#include <errno.h>
/* 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);
}
--------------050007060704060608050700--
More information about the freebsd-bugs
mailing list