PDA

View Full Version : determening on which interface UPD packets arrive


andreto
04-29-2003, 01:48 PM
This has probably been posted before(....) but I'm pretty stuck here - and I would like som final confirmation that my problem is indeed unsolvable(as it seems to me).

I am doing some work on a ad-hoc routing management daemon(for MANETS) on linux. Neighbors in the network announce themselves by _broadcasting_ HELLO UDP messages. My aim is to get the deamon to be able run on multiple interfaces on one node(example. one ethernet if an one wlan if).

The problem is that I cannot find a good way to determine on which interface these HELLO messages arrive - and this is essential to update the routing table correctly! Every routing table update is done via the neighbors(this is a multi-hop network) .

The way I am solving this now is by checking the senders address against the addresses of my interfaces to find if one of them is on the same network. I could also hve checked the broadcastaddresses - or have one socket bound to each interfaces broadcastaddress for that sake. The problem with all of these solutions is that NO TWO INTERFACES CAN BE ON THE SAME NETWORK for this to work.... And that limitation is something I would really like to avoid!

So is there any way of solving this(on socket level)?

PS. A big NO will make me happy too - then I'll just have to settle for my solution, but atleast I dont have to work more on this problem ;-)


thanks
Andreas T

andreto
04-29-2003, 07:16 PM
Hmmm.... I found a possible answer. Perhaps I could use setsockopt() with the SO_BINDTODEVICE flag to bind a socket to a interface? That means I'll have to create one socket for each interface.
Is this a possible solution?

from 'man socket(7)'

SO_BINDTODEVICE
Bind this socket to a particular device like
"eth0", as specified in the passed interface name.
If the name is an empty string or the option length
is zero, the socket device binding is removed. The
passed option is a variable-length null terminated
interface name string with the maximum size of
IFNAMSIZ. If a socket is bound to an interface,
only packets received from that particular inter-
face are processed by the socket. Note that this
only works for some socket types, particularly
AF_INET sockets. It is not supported for packet
sockets (use normal bind(8) there).

RobSeace
04-29-2003, 09:58 PM
Well, you don't even really need SO_BINDTODEVICE, I don't
think... Why can't you just have a separate socket for each
device, and just bind() each to the IP of the appropriate device?
But, yeah, I suppose SO_BINDTODEVICE should work
pretty much the same, just as well...

Another approach is the IP_PKTINFO sockopt... (I believe it's
Linux-specific, though...) With that, you can use recvmsg(),
and get the interface index and local destination IP in an
ancillary message...

andreto
04-29-2003, 10:04 PM
Thanks for you reply.

Well, you don't even really need SO_BINDTODEVICE, I don't
think... Why can't you just have a separate socket for each
device, and just bind() each to the IP of the appropriate device?
But, yeah, I suppose SO_BINDTODEVICE should work
pretty much the same, just as well...


Well - then I guess I have to bind the socket to the broadcast address... and that does not solve the problem(if two interfaces have the same bcast address)


Another approach is the IP_PKTINFO sockopt... (I believe it's
Linux-specific, though...) With that, you can use recvmsg(),
and get the interface index and local destination IP in an
ancillary message...

With this approach I will get the IP of the interface even toguh the message was broadcasted?

And again - thanks for bothering with this :-)

Andreas

andreto
04-29-2003, 10:15 PM
The IP_PKTINFO seems wery interesting. From the looks of it I think I'll be able to avoid creating multiple sockets with this solution.
I'll try it tomorrow!

Thanks again :D

Andreas

andreto
04-30-2003, 10:02 AM
Hmmm... I seem to be flooding my own thread here ;-)

Well - now I am using the SO_BINDTODEVICE approach with one socket for each interface. And it's working fine!! Now I just need to cange all the stuff that sends packets(so that it sends on the right socket).

I'm happy happy... yeeha :-D

RobSeace
04-30-2003, 02:02 PM
Well, if you're happy with the SO_BINDTODEVICE approach,
then that's fine... I see no problem with it...

However, in the case you were worried about (2 interfaces on
the same subnet, so with the same broadcast IP), wouldn't
BOTH interfaces then be receiving the same broadcast message
in any case?? They must, if they're both on that network... So,
I'm not sure I really see the point in needing to distinguish...

Did you try the IP_PKTINFO approach at all? That one sounds
like the slickest approach, to me... And, yes, would only need a
single socket, I think... I've never used it myself, but if it works
as advertised, it seems ideal...

andreto
04-30-2003, 02:31 PM
Well, if you're happy with the SO_BINDTODEVICE approach,
then that's fine... I see no problem with it...

However, in the case you were worried about (2 interfaces on
the same subnet, so with the same broadcast IP), wouldn't
BOTH interfaces then be receiving the same broadcast message
in any case?? They must, if they're both on that network... So,
I'm not sure I really see the point in needing to distinguish...


Well the case is that if one of the interfaces is wireless and the oter is wired than they will not nessecerly be able to reach the same nodes. So if they have the same broadcastaddr it's essential to be able to find out which interface one can reach nodes by - that is which interface one should route by to get to nodes. If 10.0.0.45 Broadcasts its precense to 10.255.255.255 then I don't really know if the node is reachable via say eth0(10.0.0.10) or wifi1/eth1(10.0.0.11)

If I just bind the socket to say 10.255.255.255 then I really dont konw if the neighbor can be reached by the 10.0.0.10 or 10.0.0.11 interface. If I just bind to the interface addresses then I won't be able to hear the HELLOS from the neighbors....



Did you try the IP_PKTINFO approach at all? That one sounds
like the slickest approach, to me... And, yes, would only need a
single socket, I think... I've never used it myself, but if it works
as advertised, it seems ideal...

My intentions were to try this - and I did for half an hour ;-) ... but I really couldn't find any code examples of the usage og rcvmsg() and defenetley not on how to access the in_pktinfo struct....

And as it turned out I couldn't have used this solution as I have to be able to specify on which interface I am to send data when interfaces are on the same subnet/braddr - for technical reasons(messing up different sequence numbers).

But again thanks for your reply :-)

Loco
04-30-2003, 04:14 PM
Well the case is that if one of the interfaces is wireless and the oter is wired than they will not nessecerly be able to reach the same nodes. So if they have the same broadcastaddr it's essential to be able to find out which interface one can reach nodes by - that is which interface one should route by to get to nodes. If 10.0.0.45 Broadcasts its precense to 10.255.255.255 then I don't really know if the node is reachable via say eth0(10.0.0.10) or wifi1/eth1(10.0.0.11)


If both physical networks belong to the same IP network (unless badly constructed or some kind of special setup) any broadcast packet you send from any of the two physical networks to that broadcast address will be recv'd by both interfaces in your computer.

And if you send packets to any of the hosts on any of the interfaces, tehy will be recv'd by the destination hosts.


If I just bind the socket to say 10.255.255.255 then I really dont konw if the neighbor can be reached by the 10.0.0.10 or 10.0.0.11 interface. If I just bind to the interface addresses then I won't be able to hear the HELLOS from the neighbors....


I think this is almost impossible to achieve on the IP layer, you should go down one layer to do it.

Regards

andreto
04-30-2003, 04:45 PM
If both physical networks belong to the same IP network (unless badly constructed or some kind of special setup) any broadcast packet you send from any of the two physical networks to that broadcast address will be recv'd by both interfaces in your computer.

And if you send packets to any of the hosts on any of the interfaces, they will be recv'd by the destination hosts.


Let me try to explain my problem again. This is a ad-hoc network where neighbors detect eachother by HELLO messages multicasted to every node in 1 hop reach. On a wireless network that means every node who can hear your transmission - on a wired network that means hopefully every node with the same broadcast address. The idea of multi hop ad-hoc networks is that every node can possible route/forward packets for other nodes who cannot reach their destinatioin in 1 hop(their radio range).

So neighbor-sensing is done by multicasting UDP HELLO messages. If I have two interfaces of different technologsy let's say one WLAN interface and one regular ethernet - than I have no guarantee that I am not the ONLY gateway between these networks. So when node 10.0.0.60 broadcasts a HELLO message I NEED TO KNOW ON WHICH INTERFACE THIS MESSAGE ARRIVED. Because when I am going to update my routingtable with this neghbor(and all nods which is to be routed by this neghbor) it is essential taht I use the correct interface or else my routingtable will be broken.
Example:
node 10.0.0.60 sends me an HELLO which i recieve at wifi1. But I register it internally(wrongfully) as eth0. I the update my routingtable with a (10.0.0.60, 1(cost), eth0) tuple. I then register more nodes(10.0.0.55, 10.0.0.70) via this node(by topology control TC messages). They will be routed (10.0.0.55, 10.0.0.60(gw), 2 (cost),eth0) and so on. And this is not correct! To reach 10.0.0.60 I need to use wifi1 - the node cannot be reached by eth0.
This goes for both cases: when both interfaces are on the same subnet/broadcastaddr and when they'r not. Only it was easy to avoid when they were not at the same network(see first post)

So -fair enough, I can broadcast to all the nodes on both networks(if interfaces are on the same network) no problem... but that does not solve anything for me... It rather makes problems.
The ad-hoc network is ment to contain nodes moving - so the control messages of this network is sent at a rather low interval(high speed). In the ethernet on the other hand that is not so important(as changes in that topology is not likely - and everybody is just one hop away) so here control messages are sent more seldom.
The control messages carry sequence numbers which as follows of the above will be different for differnent types of networks. So when I broadcast these messages I want to be able to do this at only one of the netwoks(one of the interfaces) at the time - or else the sequencenumbers of nodes listening will be messed up...

So SO_BINDTODEVICE seems to be the best solution for me.

I hope this made some sense :-)



I think this is almost impossible to achieve on the IP layer, you should go down one layer to do it.


I figue that's just what I achieved using SO_BINDTODEVICE..?

Thanks for you reply

Andreas

Loco
04-30-2003, 06:13 PM
With such a good explanation I finally got it :)

You are completely right...

RobSeace
04-30-2003, 09:04 PM
Ah, interesting... Yeah, I think I finally grok what you're trying
to do now, too... Basically, the separate interfaces really AREN'T
on the same network; you're just trying to make them appear
to be... Weird... ;-) But, it sounds quite nifty...

But, just to return to the IP_PKTINFO thing... I believe you can
use it to send one of those in_pktinfo structs via sendmsg() as
well, which will force it to use the given interface for sending, too...
But, there doesn't appear to be much benefit to going with this
method over your current SO_BINDTODEVICE method, except
for saving some socket FDs, so it's probably not worth changing...
(And, you're right that recvmsg()/sendmsg() aren't exactly the
easiest things to figure out how to properly use, especially when
you get into sending/receiving ancillary messages... ;-))

andreto
04-30-2003, 09:10 PM
I you by any chance would like to check this stuff out(ad- hoc/MANET) the protocol I'm working on is OLSR(optimized link state routing). The ietf draft can be found herehttp://www.ietf.org/internet-drafts/draft-ietf-manet-olsr-09.txt and the MANET workgroup is located here http://www.ietf.org/html.charters/manet-charter.html

And agin - thanks for bothering with this stuff and runnig this forum. Guys like you make life a lot easier for us non-guru folks ;-)

Andreas