From: Yan Zheng <yanzheng@21cn.com>
To: netdev@vger.kernel.org, David Stevens <dlstevens@us.ibm.com>
Cc: linux-kernel@vger.kernel.org
Subject: [PATCH 1/2][MCAST] Fix for is_in(...)
Date: Wed, 09 Nov 2005 19:57:43 +0800 [thread overview]
Message-ID: <4371E437.90306@21cn.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 2141 bytes --]
Hi.
Include/exclude count of source filter also need check when type is MLD2_MODE_IS_INCLUDE or MLD2_MODE_IS_EXCLUDE.
If the check is ignored, MODE_IS_EXCLUDE report may include sources that have include count greater than zero.
You can check this bug by test.c and query.c in the attachments.
test.c create two socket and make both of them join multicast address M.
The first socket set it's filter mode to INCLUDE{X} and the second set it's filter mode to EXCLUDE{Y}.
Now the interface state for multicast address M should be EXCLUDE{Y}.
let's send a Multicast Address Specific Query by query.c.
You will notice that both X and Y are included in the MODE_IS_EXCLUDE report's source address list.
I hope I provide enough information this time. :-)
Regards
Signed-off-by: Yan Zheng<yanzheng@21cn.com>
Index:net/ipv6/mcast.c
==============================================================
--- linux-2.6.14/net/ipv6/mcast.c 2005-11-09 16:00:48.000000000 +0800
+++ linux/net/ipv6/mcast.c 2005-11-09 18:44:37.000000000 +0800
@@ -1273,22 +1273,27 @@ static int is_in(struct ifmcaddr6 *pmc,
{
switch (type) {
case MLD2_MODE_IS_INCLUDE:
- case MLD2_MODE_IS_EXCLUDE:
+ case MLD2_CHANGE_TO_INCLUDE:
if (gdeleted || sdeleted)
return 0;
+ if (psf->sf_count[MCAST_INCLUDE] == 0)
+ return 0; // maybe never happen
+ if (type == MLD2_CHANGE_TO_INCLUDE)
+ return 1;
return !((pmc->mca_flags & MAF_GSQUERY) && !psf->sf_gsresp);
- case MLD2_CHANGE_TO_INCLUDE:
- if (gdeleted || sdeleted)
- return 0;
- return psf->sf_count[MCAST_INCLUDE] != 0;
+ case MLD2_MODE_IS_EXCLUDE:
case MLD2_CHANGE_TO_EXCLUDE:
if (gdeleted || sdeleted)
return 0;
if (pmc->mca_sfcount[MCAST_EXCLUDE] == 0 ||
psf->sf_count[MCAST_INCLUDE])
return 0;
- return pmc->mca_sfcount[MCAST_EXCLUDE] ==
- psf->sf_count[MCAST_EXCLUDE];
+ if (pmc->mca_sfcount[MCAST_EXCLUDE] !=
+ psf->sf_count[MCAST_EXCLUDE])
+ return 0;
+ if (type == MLD2_CHANGE_TO_EXCLUDE)
+ return 1;
+ return !((pmc->mca_flags & MAF_GSQUERY) && !psf->sf_gsresp);
case MLD2_ALLOW_NEW_SOURCES:
if (gdeleted || !psf->sf_crcount)
return 0;
[-- Attachment #2: test.c --]
[-- Type: text/x-csrc, Size: 1298 bytes --]
#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#define IFINDEX 5 //Please adjust me first.
int main(int argc, char argv[])
{
int sockfds[2];
struct ipv6_mreq req;
struct group_filter filter;
struct sockaddr_in6 *psin6;
req.ipv6mr_interface = IFINDEX;
inet_pton(PF_INET6, "FF02::2000", &req.ipv6mr_multiaddr);
sockfds[0] = socket(PF_INET6, SOCK_DGRAM, 0);
sockfds[1] = socket(PF_INET6, SOCK_DGRAM, 0);
filter.gf_interface = IFINDEX;
filter.gf_fmode = MCAST_INCLUDE;
filter.gf_numsrc = 1;
psin6 = (struct sockaddr_in6 *)&filter.gf_group;
psin6->sin6_family = AF_INET6;
inet_pton(PF_INET6, "FF02::2000", &psin6->sin6_addr);
psin6 = (struct sockaddr_in6 *)&filter.gf_slist[0];
psin6->sin6_family = AF_INET6;
inet_pton(PF_INET6, "2002:de12:1780::1", &psin6->sin6_addr);
setsockopt(sockfds[0], SOL_IPV6, IPV6_ADD_MEMBERSHIP, &req, sizeof(req));
setsockopt(sockfds[0], SOL_IPV6, MCAST_MSFILTER, &filter, sizeof(filter));
filter.gf_fmode = MCAST_EXCLUDE;
inet_pton(PF_INET6, "2002:de12:1780::2", &psin6->sin6_addr);
setsockopt(sockfds[1], SOL_IPV6, IPV6_ADD_MEMBERSHIP, &req, sizeof(req));
setsockopt(sockfds[1], SOL_IPV6, MCAST_MSFILTER, &filter, sizeof(filter));
pause();
return 0;
}
[-- Attachment #3: query.c --]
[-- Type: text/x-csrc, Size: 945 bytes --]
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#define IFINDEX 5 //Please adjust me first.
struct mld2_query {
uint8_t type;
uint8_t code;
uint16_t csum;
uint16_t mrc;
uint16_t resv1;
struct in6_addr mca;
uint8_t qrv:3,
suppress:1,
resv2:4;
uint8_t qqic;
uint16_t nsrcs;
struct in6_addr srcs[0];
};
int main(int argc ,char *argv[]) {
int len, sockfd;
struct mld2_query query;
struct sockaddr_in6 addr;
memset(&addr, 0x00, sizeof(addr));
addr.sin6_family = AF_INET6;
addr.sin6_scope_id = IFINDEX;
inet_pton(PF_INET6, "FF02::1", &addr.sin6_addr);
memset(&query, 0x00, sizeof(query));
query.type = 130;
inet_pton(PF_INET6, "FF02::2000", &query.mca);
sockfd = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
sendto(sockfd, &query, sizeof(query), 0,
(struct sockaddr *)&addr, sizeof(addr));
}
reply other threads:[~2005-11-09 11:57 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4371E437.90306@21cn.com \
--to=yanzheng@21cn.com \
--cc=dlstevens@us.ibm.com \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).