Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 28 Sep 2006 17:10:26 GMT
From:      Bruce M Simpson <bms@incunabulum.net>
To:        freebsd-bugs@FreeBSD.org
Subject:   Re: kern/95277: [netinet] IP Encapsulation mask_match() returns wrong results
Message-ID:  <200609281710.k8SHAQlw064697@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/95277; it has been noted by GNATS.

From: Bruce M Simpson <bms@incunabulum.net>
To: freebsd-gnats-submit@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--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200609281710.k8SHAQlw064697>