From: Jean Tourrilhes <jt@bougret.hpl.hp.com>
To: Linux kernel mailing list <linux-kernel@vger.kernel.org>
Subject: Re: Kernel Multicast
Date: Tue, 28 Aug 2001 14:28:29 -0700 [thread overview]
Message-ID: <20010828142829.F8147@bougret.hpl.hp.com> (raw)
In-Reply-To: <87009604743AD411B1F600508BA0F95994CA6A@XOVER.dedham.mindspeed.com>
In-Reply-To: <87009604743AD411B1F600508BA0F95994CA6A@XOVER.dedham.mindspeed.com>; from mark.clayton@netplane.com on Tue, Aug 28, 2001 at 04:12:23PM -0400
On Tue, Aug 28, 2001 at 04:12:23PM -0400, Clayton, Mark wrote:
>
> I think this is what I recall doing:
>
> socket(AF_INET, SOCK_DGRAM, 0);
>
> setsockopt(SO_REUSEADDR)
>
> if ((remote_addr & 0xF0000000) == 0xE0000000) then saddr.sin_addr.s_addr
> is INADDR_ANY otherwise use local_addr. Port is local_port
> bind(saddr);
>
> ipMreq.imr_multiaddr.s_addr = htonl(multicast_addr);
> ipMreq.imr_address.s_addr = htonl(local_addr);
> ipMreq.imr_ifindex = if_index (from /sbin/ipmaddr)
> setsockopt(IP_ADD_MEMBERSHIP, ipMreq
>
> /* mcast sends */
> ifAddr.s_addr = htonl(local_addr)
> setsockopt(IP_MULTICAST_IF, ifAddr);
>
> setsockopt(SIOCGIFNAME, if_index);
>
> setsockopt(SO_BINDTODEVICE)
>
> Also, I think that for SOCK_RAW there needs to be a second
> socket just for reading. But I don't recall the details.
>
> If this helps, feel free to post the details to the list
> in a summary. Please remove references to me though.
>
> Thanks,
> Mark
I did my little investigation and looked int he kernel for
answers.
I was already looking at SO_BINDTODEVICE. This is very
powerful, unfortunately, it's reserved for ROOT. Maybe running my
program as root is not the brightest idea.
Also, one might wonder why IP_MULTICAST_IF doesn't set
sk->bound_dev_if itself, which would be logical (it only checks that
the interface is the same as sk->bound_dev_if but seem to forget to
set it in .../net/ipv4/sockglue.c).
Anyway, doing this definitely fix the problem :
------------------------------------------
socket(AF_INET, SOCK_DGRAM, 0);
setsockopt(SO_BINDTODEVICE, ONE_INTERFACE);
bind(sock, INADDR_ANY, MY_PORT);
setsockopt(IP_ADD_MEMBERSHIP, INADDR_ALLHOSTS_GROUP, ONE_INTERFACE);
setsockopt(IP_MULTICAST_IF, ONE_INTERFACE);
------------------------------------------
Works as advertised : you can have one and only one socket per
interface.
Now, let's have a bit of fun... If you do :
------------------------------------------
socket(AF_INET, SOCK_DGRAM, 0);
bind(sock, INADDR_ANY, MY_PORT);
setsockopt(SO_BINDTODEVICE, ONE_INTERFACE);
setsockopt(IP_ADD_MEMBERSHIP, INADDR_ALLHOSTS_GROUP, ONE_INTERFACE);
setsockopt(IP_MULTICAST_IF, ONE_INTERFACE);
------------------------------------------
In that case, the kernel let you open more than one socket per
interface (two, there...). I don't know if its intended, but it works
fine ;-)
And you can also do this :
------------------------------------------
socket(AF_INET, SOCK_DGRAM, 0);
bind(sock, INADDR_ANY, MY_PORT);
setsockopt(IP_ADD_MEMBERSHIP, INADDR_ALLHOSTS_GROUP, ONE_INTERFACE);
setsockopt(IP_MULTICAST_IF, ONE_INTERFACE);
setsockopt(SO_BINDTODEVICE, ANOTHER_INTERFACE);
------------------------------------------
This will send packet on ANOTHER_INTERFACE, but the source
address of those packet will be the one of ONE_INTERFACE.
And if you look in .../net/core/sock.c, you will realise that
these two calls are handled very differently :
------------------------------------------
setsockopt(SO_BINDTODEVICE, "", 0);
setsockopt(SO_BINDTODEVICE, "", IFNAMSIZ);
------------------------------------------
Which mean the man page need to be fixed ;-)
Anyway, I don't really want to rely on SO_BINDTODEVICE,
because it needs ROOT capability.
Now, you suggestions to use SO_REUSEADDR is spot on. It works
as any user. I get a little bit more than I bargained for (I want only
one socket per interface), but that's ok...
In other words, this works :
------------------------------------------
socket(AF_INET, SOCK_DGRAM, 0);
setsockopt(SO_REUSEADDR, 1);
bind(sock, INADDR_ANY, MY_PORT);
setsockopt(IP_ADD_MEMBERSHIP, INADDR_ALLHOSTS_GROUP, ONE_INTERFACE);
setsockopt(IP_MULTICAST_IF, ONE_INTERFACE);
------------------------------------------
With one little caveat : such socket seems to receive
multicast comming from all interfaces. In other words, it seem that
IP_MULTICAST_IF only act on the outgoing path.
In other words, IP_MULTICAST_IF doesn't do much... At least,
much less that what you would believe it to do...
Also, using both SO_BINDTODEVICE and SO_REUSEADDR may be
overkill...
That's it...
Jean
next parent reply other threads:[~2001-08-28 21:28 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <87009604743AD411B1F600508BA0F95994CA6A@XOVER.dedham.mindspeed.com>
2001-08-28 21:28 ` Jean Tourrilhes [this message]
[not found] <87009604743AD411B1F600508BA0F95994CA68@XOVER.dedham.mindspeed.com>
2001-08-28 18:13 ` Jean Tourrilhes
2001-08-28 18:30 ` Ion Badulescu
2001-08-28 18:34 ` Jean Tourrilhes
2001-08-28 17:19 Jean Tourrilhes
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=20010828142829.F8147@bougret.hpl.hp.com \
--to=jt@bougret.hpl.hp.com \
--cc=jt@hpl.hp.com \
--cc=linux-kernel@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
all inboxes | Powered by JetHome®