svn commit: r189340 - head/usr.sbin/mtest

Bruce M Simpson bms at FreeBSD.org
Tue Mar 3 18:09:13 PST 2009


Author: bms
Date: Wed Mar  4 02:09:12 2009
New Revision: 189340
URL: http://svn.freebsd.org/changeset/base/189340

Log:
  Add full SSM stack support to mtest(8) diagnostic tool.

Modified:
  head/usr.sbin/mtest/mtest.c

Modified: head/usr.sbin/mtest/mtest.c
==============================================================================
--- head/usr.sbin/mtest/mtest.c	Wed Mar  4 02:08:20 2009	(r189339)
+++ head/usr.sbin/mtest/mtest.c	Wed Mar  4 02:09:12 2009	(r189340)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2007 Bruce M. Simpson.
+ * Copyright (c) 2007-2009 Bruce Simpson.
  * Copyright (c) 2000 Wilbert De Graaf.
  * All rights reserved.
  *
@@ -55,26 +55,21 @@ __FBSDID("$FreeBSD$");
 #include <err.h>
 #include <unistd.h>
 
-/* The following two socket options are private to the kernel and libc. */
-
-#ifndef IP_SETMSFILTER
-#define IP_SETMSFILTER 74 /* atomically set filter list */
-#endif
-#ifndef IP_GETMSFILTER
-#define IP_GETMSFILTER 75 /* get filter list */
-#endif
-
 static void	process_file(char *, int);
 static void	process_cmd(char*, int, FILE *fp);
 static void	usage(void);
-#ifdef WITH_IGMPV3
-static int	inaddr_cmp(const void *a, const void *b);
-#endif
 
 #define	MAX_ADDRS	20
 #define	STR_SIZE	20
 #define	LINE_LENGTH	80
 
+static int
+inaddr_cmp(const void *a, const void *b)
+{
+	return ((int)((const struct in_addr *)a)->s_addr -
+	    ((const struct in_addr *)b)->s_addr);
+}
+
 int
 main(int argc, char **argv)
 {
@@ -145,17 +140,13 @@ process_cmd(char *cmd, int s, FILE *fp _
 	char			 str1[STR_SIZE];
 	char			 str2[STR_SIZE];
 	char			 str3[STR_SIZE];
-#ifdef WITH_IGMPV3
-	char			 filtbuf[IP_MSFILTER_SIZE(MAX_ADDRS)];
-#endif
+	struct in_addr		 sources[MAX_ADDRS];
 	struct ifreq		 ifr;
 	struct ip_mreq		 imr;
 	struct ip_mreq_source	 imrs;
-#ifdef WITH_IGMPV3
-	struct ip_msfilter	*imsfp;
-#endif
 	char			*line;
-	int			 n, opt, f, flags;
+	uint32_t		 fmode;
+	int			 i, n, opt, f, flags;
 
 	line = cmd;
 	while (isblank(*++line))
@@ -181,20 +172,51 @@ process_cmd(char *cmd, int s, FILE *fp _
 
 	case 'j':
 	case 'l':
-		sscanf(line, "%s %s", str1, str2);
-		if (((imr.imr_multiaddr.s_addr = inet_addr(str1)) ==
-		    INADDR_NONE) ||
-		    ((imr.imr_interface.s_addr = inet_addr(str2)) ==
-		    INADDR_NONE)) {
-			printf("-1\n");
-			break;
+		str3[0] = '\0';
+		sscanf(line, "%s %s %s", str1, str2, str3);
+		if ((imrs.imr_sourceaddr.s_addr = inet_addr(str3)) !=
+		    INADDR_NONE) {
+			/*
+			 * inclusive mode join with source, possibly
+			 * on existing membership.
+			 */
+			if (((imrs.imr_multiaddr.s_addr = inet_addr(str1)) ==
+			    INADDR_NONE) ||
+			    ((imrs.imr_interface.s_addr = inet_addr(str2)) ==
+			    INADDR_NONE)) {
+				printf("-1\n");
+				break;
+			}
+			opt = (*cmd == 'j') ? IP_ADD_SOURCE_MEMBERSHIP :
+			    IP_DROP_SOURCE_MEMBERSHIP;
+			if (setsockopt( s, IPPROTO_IP, opt, &imrs,
+			    sizeof(imrs)) != 0) {
+				warn("setsockopt %s", (*cmd == 'j') ?
+				    "IP_ADD_SOURCE_MEMBERSHIP" :
+				    "IP_DROP_SOURCE_MEMBERSHIP");
+			} else {
+				printf("ok\n");
+			}
+		} else {
+			/* exclusive mode join w/o source. */
+			if (((imr.imr_multiaddr.s_addr = inet_addr(str1)) ==
+			    INADDR_NONE) ||
+			    ((imr.imr_interface.s_addr = inet_addr(str2)) ==
+			    INADDR_NONE)) {
+				printf("-1\n");
+				break;
+			}
+			opt = (*cmd == 'j') ? IP_ADD_MEMBERSHIP :
+			    IP_DROP_MEMBERSHIP;
+			if (setsockopt( s, IPPROTO_IP, opt, &imr,
+			    sizeof(imr)) != 0) {
+				warn("setsockopt %s", (*cmd == 'j') ?
+				    "IP_ADD_MEMBERSHIP" :
+				    "IP_DROP_MEMBERSHIP");
+			} else {
+				printf("ok\n");
+			}
 		}
-		opt = (*cmd == 'j') ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
-		if (setsockopt( s, IPPROTO_IP, opt, &imr,
-		    sizeof(imr)) != 0)
-			warn("setsockopt IP_ADD_MEMBERSHIP/IP_DROP_MEMBERSHIP");
-		else
-			printf("ok\n");
 		break;
 
 	case 'a':
@@ -233,6 +255,7 @@ process_cmd(char *cmd, int s, FILE *fp _
 		printf("warning: IFF_ALLMULTI cannot be set from userland "
 		    "in FreeBSD; command ignored.\n");
 		break;
+
 	case 'p':
 		if (sscanf(line, "%s %u", ifr.ifr_name, &f) != 2) {
 			printf("-1\n");
@@ -257,7 +280,6 @@ process_cmd(char *cmd, int s, FILE *fp _
 			printf( "changed to 0x%08x\n", flags );
 		break;
 
-#ifdef WITH_IGMPV3
 	/*
 	 * Set the socket to include or exclude filter mode, and
 	 * add some sources to the filterlist, using the full-state,
@@ -265,42 +287,38 @@ process_cmd(char *cmd, int s, FILE *fp _
 	 */
 	case 'i':
 	case 'e':
-		/* XXX: SIOCSIPMSFILTER will be made an internal API. */
+		n = 0;
+		fmode = (*cmd == 'i') ? MCAST_INCLUDE : MCAST_EXCLUDE;
 		if ((sscanf(line, "%s %s %d", str1, str2, &n)) != 3) {
 			printf("-1\n");
 			break;
 		}
-		imsfp = (struct ip_msfilter *)filtbuf;
-		if (((imsfp->imsf_multiaddr.s_addr = inet_addr(str1)) ==
+		/* recycle imrs struct for convenience */
+		if (((imrs.imr_multiaddr.s_addr = inet_addr(str1)) ==
 		    INADDR_NONE) ||
-		    ((imsfp->imsf_interface.s_addr = inet_addr(str2)) ==
-		    INADDR_NONE) || (n > MAX_ADDRS)) {
+		    ((imrs.imr_interface.s_addr = inet_addr(str2)) ==
+		    INADDR_NONE) || (n < 0 || n > MAX_ADDRS)) {
 			printf("-1\n");
 			break;
 		}
-		imsfp->imsf_fmode = (*cmd == 'i') ? MCAST_INCLUDE :
-		    MCAST_EXCLUDE;
-		imsfp->imsf_numsrc = n;
 		for (i = 0; i < n; i++) {
 			fgets(str1, sizeof(str1), fp);
-			if ((imsfp->imsf_slist[i].s_addr = inet_addr(str1)) ==
+			if ((sources[i].s_addr = inet_addr(str1)) ==
 			    INADDR_NONE) {
 				printf("-1\n");
 				return;
 			}
 		}
-		if (ioctl(s, SIOCSIPMSFILTER, imsfp) != 0)
-			warn("setsockopt SIOCSIPMSFILTER");
+		if (setipv4sourcefilter(s, imrs.imr_interface,
+		    imrs.imr_multiaddr, fmode, n, sources) != 0)
+			warn("getipv4sourcefilter");
 		else
 			printf("ok\n");
 		break;
-#endif /* WITH_IGMPV3 */
 
 	/*
 	 * Allow or block traffic from a source, using the
 	 * delta based api.
-	 * XXX: Currently we allow this to be used with the ASM-only
-	 *      implementation of RFC3678 in FreeBSD 7. 
 	 */
 	case 't':
 	case 'b':
@@ -314,24 +332,14 @@ process_cmd(char *cmd, int s, FILE *fp _
 			printf("-1\n");
 			break;
 		}
-
-#ifdef WITH_IGMPV3
-		/* XXX: SIOCSIPMSFILTER will be made an internal API. */
-		/* First determine out current filter mode. */
-		imsfp = (struct ip_msfilter *)filtbuf;
-		imsfp->imsf_multiaddr.s_addr = imrs.imr_multiaddr.s_addr;
-		imsfp->imsf_interface.s_addr = imrs.imr_interface.s_addr;
-		imsfp->imsf_numsrc = 5;
-		if (ioctl(s, SIOCSIPMSFILTER, imsfp) != 0) {
-			/* It's only okay for 't' to fail */
-			if (*cmd != 't') {
-				warn("ioctl SIOCSIPMSFILTER");
-				break;
-			} else {
-				imsfp->imsf_fmode = MCAST_INCLUDE;
-			}
+		/* First determine our current filter mode. */
+		n = 0;
+		if (getipv4sourcefilter(s, imrs.imr_interface,
+		    imrs.imr_multiaddr, &fmode, &n, NULL) != 0) {
+			warn("getipv4sourcefilter");
+			break;
 		}
-		if (imsfp->imsf_fmode == MCAST_EXCLUDE) {
+		if (fmode == MCAST_EXCLUDE) {
 			/* Any source */
 			opt = (*cmd == 't') ? IP_UNBLOCK_SOURCE :
 			    IP_BLOCK_SOURCE;
@@ -340,60 +348,37 @@ process_cmd(char *cmd, int s, FILE *fp _
 			opt = (*cmd == 't') ? IP_ADD_SOURCE_MEMBERSHIP :
 			    IP_DROP_SOURCE_MEMBERSHIP;
 		}
-#else /* !WITH_IGMPV3 */
-		/*
-		 * Don't look before we leap; we may only block or unblock
-		 * sources on a socket in exclude mode.
-		 */
-		opt = (*cmd == 't') ? IP_UNBLOCK_SOURCE : IP_BLOCK_SOURCE;
-#endif /* WITH_IGMPV3 */
 		if (setsockopt(s, IPPROTO_IP, opt, &imrs, sizeof(imrs)) == -1)
 			warn("ioctl IP_ADD_SOURCE_MEMBERSHIP/IP_DROP_SOURCE_MEMBERSHIP/IP_UNBLOCK_SOURCE/IP_BLOCK_SOURCE");
 		else
 			printf("ok\n");
 		break;
 
-#ifdef WITH_IGMPV3
 	case 'g':
-		/* XXX: SIOCSIPMSFILTER will be made an internal API. */
 		if ((sscanf(line, "%s %s %d", str1, str2, &n)) != 3) {
 			printf("-1\n");
 			break;
 		}
-		imsfp = (struct ip_msfilter *)filtbuf;
-		if (((imsfp->imsf_multiaddr.s_addr = inet_addr(str1)) ==
+		/* recycle imrs struct for convenience */
+		if (((imrs.imr_multiaddr.s_addr = inet_addr(str1)) ==
 		    INADDR_NONE) ||
-		    ((imsfp->imsf_interface.s_addr = inet_addr(str2)) ==
+		    ((imrs.imr_interface.s_addr = inet_addr(str2)) ==
 		    INADDR_NONE) || (n < 0 || n > MAX_ADDRS)) {
 			printf("-1\n");
 			break;
 		}
-		imsfp->imsf_numsrc = n;
-		if (ioctl(s, SIOCSIPMSFILTER, imsfp) != 0) {
-			warn("setsockopt SIOCSIPMSFILTER");
+		if (getipv4sourcefilter(s, imrs.imr_interface,
+		    imrs.imr_multiaddr, &fmode, &n, sources) != 0) {
+			warn("getipv4sourcefilter");
 			break;
 		}
-		printf("%s\n", (imsfp->imsf_fmode == MCAST_INCLUDE) ?
-		    "include" : "exclude");
-		printf("%d\n", imsfp->imsf_numsrc);
-		if (n >= imsfp->imsf_numsrc) {
-			n = imsfp->imsf_numsrc;
-			qsort(imsfp->imsf_slist, n, sizeof(struct in_addr),
-			    &inaddr_cmp);
-			for (i = 0; i < n; i++)
-				printf("%s\n", inet_ntoa(imsfp->imsf_slist[i]));
-		}
-		break;
-#endif	/* !WITH_IGMPV3 */
-
-#ifndef WITH_IGMPV3
-	case 'i':
-	case 'e':
-	case 'g':
-		printf("warning: IGMPv3 is not supported by this version "
-		    "of FreeBSD; command ignored.\n");
+		printf("%s\n", (fmode == MCAST_INCLUDE) ? "include" :
+		    "exclude");
+		printf("%d\n", n);
+		qsort(sources, n, sizeof(struct in_addr), &inaddr_cmp);
+		for (i = 0; i < n; i++)
+			printf("%s\n", inet_ntoa(sources[i]));
 		break;
-#endif	/* WITH_IGMPV3 */
 
 	case '\n':
 		break;
@@ -407,31 +392,18 @@ static void
 usage(void)
 {
 
-	printf("j g.g.g.g i.i.i.i          - join IP multicast group\n");
-	printf("l g.g.g.g i.i.i.i          - leave IP multicast group\n");
+	printf("j g.g.g.g i.i.i.i [s.s.s.s] - join IP multicast group\n");
+	printf("l g.g.g.g i.i.i.i [s.s.s.s] - leave IP multicast group\n");
 	printf("a ifname e.e.e.e.e.e       - add ether multicast address\n");
 	printf("d ifname e.e.e.e.e.e       - delete ether multicast address\n");
 	printf("m ifname 1/0               - set/clear ether allmulti flag\n");
 	printf("p ifname 1/0               - set/clear ether promisc flag\n");
-#ifdef WITH_IGMPv3
 	printf("i g.g.g.g i.i.i.i n        - set n include mode src filter\n");
 	printf("e g.g.g.g i.i.i.i n        - set n exclude mode src filter\n");
-#endif
 	printf("t g.g.g.g i.i.i.i s.s.s.s  - allow traffic from src\n");
 	printf("b g.g.g.g i.i.i.i s.s.s.s  - block traffic from src\n");
-#ifdef WITH_IGMPV3
 	printf("g g.g.g.g i.i.i.i n        - get and show n src filters\n");
-#endif
 	printf("f filename                 - read command(s) from file\n");
 	printf("s seconds                  - sleep for some time\n");
 	printf("q                          - quit\n");
 }
-
-#ifdef WITH_IGMPV3
-static int
-inaddr_cmp(const void *a, const void *b)
-{
-	return((int)((const struct in_addr *)a)->s_addr -
-	    ((const struct in_addr *)b)->s_addr);
-}
-#endif


More information about the svn-src-head mailing list