From owner-svn-src-all@FreeBSD.ORG Wed Mar 4 02:09:13 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 39E701065672; Wed, 4 Mar 2009 02:09:13 +0000 (UTC) (envelope-from bms@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 18F7A8FC17; Wed, 4 Mar 2009 02:09:13 +0000 (UTC) (envelope-from bms@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n2429CaU028173; Wed, 4 Mar 2009 02:09:12 GMT (envelope-from bms@svn.freebsd.org) Received: (from bms@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n2429Cj6028172; Wed, 4 Mar 2009 02:09:12 GMT (envelope-from bms@svn.freebsd.org) Message-Id: <200903040209.n2429Cj6028172@svn.freebsd.org> From: Bruce M Simpson Date: Wed, 4 Mar 2009 02:09:12 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r189340 - head/usr.sbin/mtest X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 04 Mar 2009 02:09:13 -0000 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 #include -/* 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