On Friday 27 February 2015 13:50:55 Lankswert, Patrick wrote:
> BSD sockets as the standard for IP communication clearly expresses UDP
> packet
> routing and interface expression. However, it is expressed several ways.
> 
> 1) They are bound BEFORE use, but given it is bound to all interfaces
> (inaddr_any), you can send via any interface as long as the routing tables
> agree.
> 2) However, binding to inaddr_any does not work for multicast as the IP
> stack
> select only one interface as the default multicast interface. You usually
> bind
> multiple sockets to each multicast interface to control which one to use.
> 3) Receiving is even more complicated but not hard.

Right.

> So, how would we suggest proceeding. Assuming that we are just talking about
> broadcast/multicast/discovery operations, it may be nice to have an old
> select() style mask where you can enumerate your interfaces by index and use
> a
> bitmask on broadcast/multicast/discovery operations. In this world, the
> (crude)
> interface might look like (pick on the approach/thought, not the code,
> please):
> 
> // The following struct COULD be one of the standard netlink or BSD structs
> // This is just for example purposes
> struct iface {
>   uint8_t wan : 1;
>   uint8_t wireless : 1;
>   uint8_t secure: 1;
>   char name[8];
> // blah
> }

There is a macro with the maximum name length (IFNAMESIZE), so we can use 
that.

What are the bits supposed to mean? Detecting the WAN interface may not be so 
simple. It might be possible to do this on the majority of cases by scanning 
the routing table, but it will fail on edge cases (e.g., my laptop when 
connected to both Intel office's wired and wireless). But that same algorithm 
would conclude that my regular wireless on my laptop is WAN.

That said, I do agree we should provide a heuristic approach to trying to 
detect which interface is connected to the outside world, if we can. We just 
need to document the assumptions so people know when it may fail.

Why does the user care if the interface is wired or not? How about the bridge 
interface that is both wired and wireless?

What is secure?

> int getIFaceCount(); // Returns the max index
> struct iface* getIFace(int index); // Returns NULL or iface record

Good idea. But remember that interface indexes don't have to be contiguous (my 
router has 1-9 and 12-16).

Unless you meant our own interface numbers, separate from the interface index 
from the OS, which would be used on sin6_scope_id in the IPv6 sockets.

> // If there is not a convenience method to get the mask for non-wan
> interfaces
> // The following would build the mask from scratch
> int mask = 0;
> 
> for (int index = 0; index < MAX_IFACE && index < getIFaceCount(); ++index) {
> struct iface* temp = getIFace(index);
>     if (temp && temp.wan != 0) {
>         mask |= 1<<index;
>     }
> }
> 
> sendToAll(buffer, <blah>, <blah>, mask);
> 
> // If you want to send to all use some macro like ALL_INTERFACE which is
> 0xFF

Interface numbers can easily go above 32 or even 64, so a number representing 
a bitfield may not be enough. We'd need something like fd_set for that.

So select / fd_set isn't a bad idea, but it won't be in a plain integer.

It should also support operating on "negative mode": all interfaces except the 
ones added to the set.

> Does that make sense? I think that this approach handles some of the issues
> that
> Thiago raised including multiple radios of the same type (ie. eth0, eth1,
> wan0, wan1, etc.)

FYI, here's what my router reports:

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode 
DEFAULT group default 
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP 
mode DEFAULT group default qlen 1000
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP 
mode DEFAULT group default qlen 1000
4: sit0: <NOARP> mtu 1480 qdisc noop state DOWN mode DEFAULT group default 
5: ifb0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN mode DEFAULT group 
default qlen 32
6: ifb1: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN mode DEFAULT group 
default qlen 32
7: gre0: <NOARP> mtu 1476 qdisc noop state DOWN mode DEFAULT group default 
8: gretap0: <BROADCAST,MULTICAST> mtu 1476 qdisc noop state DOWN mode DEFAULT 
group default qlen 1000
9: teql0: <NOARP> mtu 1500 qdisc noop state DOWN mode DEFAULT group default 
qlen 100
12: br-lan: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
mode DEFAULT group default 
13: eth0.1 at eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue 
master br-lan state UP mode DEFAULT group default 
14: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq master br-lan 
state UP mode DEFAULT group default qlen 1000
15: wlan1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq master br-lan 
state UP mode DEFAULT group default qlen 1000
16: wlan0-1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode 
DEFAULT group default qlen 1000

I have no idea what ifb0, ifb1, teql0 are. I know sit0 is the IPv4-in-IPv6 
interface, while "GRE" is a tunnelling protocol so I assume gre0 and gretap0 
are interfaces for that.

eth1 is connected to the WAN port on the router, while eth0 is connected to 
the internal switch, which is why there's an eth0.1 at eth0 (a VLAN interface). 
wlan0 is the 2.4 GHz radio and wlan1 is the 5 GHz one; wlan0-1 is the second 
SSID on the 2.4 GHz radio (guest / free network).

Finally, br-lan is the bridge interface, linking eth0, wlan0 and wlan1 
together.

-- 
Thiago Macieira - thiago.macieira (AT) intel.com
  Software Architect - Intel Open Source Technology Center

Reply via email to