0

in a usual socket programming, lets say, simple UDP sockets, is it possible to get the receiving interface information also in the application which is receiving the data ? How ?

For example, i receive a pkt from interface eth1, so, is there any way that along with the packet data, i also get the information that pkt has ingressed from eth1 device ?

Abhishek Sagar
  • 1,189
  • 4
  • 20
  • 44
  • May be one way is to parse the ethernet header and get the destination mac address. Then Query the linux kernel to get the information regarding which interface has this ARP. But looks like this is not a cleaner way of doing this. ALso, this strategy would work only with RAW sockets. – Abhishek Sagar May 20 '16 at 19:30
  • 1
    Why would you want to know this? – Ed Heal May 20 '16 at 19:30
  • well. i think this is very basic thing to do. May be you would want your application to keep a track of which interface has received what type of packets and how many. There are ample of scenarios where you would want this. For example, if you are looking to develop multicast application and receiver sends a join request on one of the interface of a router, your application should know on which interface the join msg has come so that it can deliver the data to the joinee. – Abhishek Sagar May 20 '16 at 19:33
  • 1
    I would look into IP packets. The lower levels do not matter as long as there is a route.It would be fine for a IP packet to use any of the ethernet cards as long as it ends up at the destination – Ed Heal May 20 '16 at 19:37
  • 1
    It is still unclear why you need it. Such things matter for protocol stack implementations, but protocol stack implementors usually do not ask **such** questions on SO. What exactly are you trying to do? – SergeyA May 20 '16 at 19:42
  • well, i would recommend you to read IGMP/PIM multicast protocols. They just cannot function if you dont know through which interface you have received the packet (the control packets). – Abhishek Sagar May 20 '16 at 19:42
  • There is an answer [here](http://stackoverflow.com/questions/25070649/linux-bind-udp-listening-socket-to-specific-interface-or-find-out-the-interfac). Basically he just creates socket for every NIC, binds it to that NIC only and then uses the socket to tell which NIC was used. – Honza Remeš May 20 '16 at 19:48
  • 1
    I think, I am more or less familiar with IGMP and multicast. The point I am making is that IGMP is already implemented. When you are using socket abstraction, all you need to do is join the group. The rest is handled by protocol stack. So, I repeat the question: are you implementing a protocol stack? – SergeyA May 20 '16 at 19:48
  • NO, i am not implementing any protocol stack. And, yes, IGMP is already present in linux kernel, but kernel version of IGMP (and other protocols) is never used out there in network industry. They implement their own such protocols in user space. There, it is required that he who wants to join a multicast group would send a IGMP membership msg to the router, which is eventually processed by user space IGMP. IGMP will store (ingress if, Group) information. Any data received on that router with destination address = Group would be forwarded down the ingress if. – Abhishek Sagar May 20 '16 at 19:59
  • 'Never used'? Really? Evidence? In any case your question is fundamentally flawed in concept due to the weak end system model. – user207421 May 20 '16 at 23:09

2 Answers2

0

In a nutshell, not using sockets. The reason, in one word, is "routing".

When your machine has more than one interface, the kernel is routing UDP and TCP packets between them. Even when forwarding is turned off, local targets (IP addresses) are not very firmly affixed to network interfaces.

You can see this when you have two interfaces on the same network with different IPs. When you issue an ARP request for an IP address that belongs to one of the interfaces, you will actually get ARP responses with both MACs (this is from memory).

The point I'm getting at is that the kernel truly doesn't care which interface a specific UDP packet arrived through.

While you cannot get the interface name the message arrived from (at least, not without requiring root access, such as setting iptables filters, or using raw sockets), I was sure you could get the IP address this packet was sent to. Going over the docs, however, I cannot find such an option. You can get the IP address of the sender (source address) by using the msg_name field for recvmsg, but not the destination address.

My advice for you, if this information is important to you, open one socket per interface, and bind that socket to the interface. You can use IP based binding via the bind command, or you can use an IOCTL to force the socket to only send packets through that interface (but I'm having a hard time seeing why you'd want to do such a thing).

Shachar Shemesh
  • 8,193
  • 6
  • 25
  • 57
  • You *can* get the destination address from `recvmsg()`, via the `IP_PKTINFO` and `IPV6_PKTINFO` message headers. You might be thinking of `recvfrom()` instead, which only reports the sender's address. – Remy Lebeau May 21 '16 at 00:18
  • @Remy Lebeau Yes, that is the solution here. Thanks for pointing it out. I am able to receive ingress interface information in my application along with the packet. More precisely saying, Ancillary Data is the solution here. http://stackoverflow.com/questions/14128345/how-does-ancillary-data-in-sendmsg-work – Abhishek Sagar Jul 01 '16 at 04:27
  • destination address you can fetch from ipheader itself. – Abhishek Sagar Jul 01 '16 at 06:30
  • @AbhishekSagar yes, but you don't have access to the IP header unless you are using an `AF_PACKET` RAW socket, or sniffing the network with pcap or similar technology. – Remy Lebeau Jul 01 '16 at 16:41
  • No, Any RAW_SOCKET will get you access to IP header in user space. – Abhishek Sagar Jul 01 '16 at 16:42
-1

I suppose some of my friends are not yet convinced with my question's legitimacy. Here is one more attempt.

Linux kernel (Or any OS) do not require user to know the outgoing interface leading to destination machine. All he needs to know the destination ip address to send the pkt to. OS take care to route the packet and egress out of the correct OIF. Agreed.

In the industry, we dont use kernel/OS for real traffic routing. There is hardware (ASICs) which has abilities to forward the traffic with much great speeds which is not feasible by software based forwarding.

Now, In hardware when pkt arrives, all it knows the following rule : if Src_addr = x, dest_addr = y, then send out the pkt out of ethz. It do not do ARP resolve Or lookup some routing table etc to decide which interface the pkt is supposed to forward to, like kernel.

Now, eventually, your application needs to install such rules in hardware, hence, it needs to know the triplet to install in hardware. Here, intf is calculated by processing the control pkts arrived on the interface. Read PIM, you will see everywhere is maintain the (,G) database which says, if pkt arrives for any source (), for multicast group G, then egress out the packet to 'n' local interfaces and not 'n' ip-addresses (receivers).

Coming to the Answer I am able to receive ingress interface information in my application along with the packet. More precisely saying, Ancillary Data is the solution here.

copy paste my own answer here from a different related Question:

For Unix Domain sockets, Ancillary data is used to send Or receive file descriptors between processes to share or load balance the tasks. Note : Unix Domain sockets transfer the information between processes running on same machine and not between processes running on different machines.

Ancillary data is used to receive the EXTRA packet related services/information from the kernel to user space application, which is not available otherwise. For example, say machine B receives some packet on wire and you want to know the ingress interface the packet arrived from ? How would you know this ? Ancillary Data come to the rescue.

Ancillary data are kind of flags set in ancillary control buffer and passed to kernel when sendmsg()/recvmsg() is called, which tells the kernel that when packet is send or arrive, what extra services/information is to be provided to application invoking the calls.

Ancillary Data is the means Communication between kernel and user space application Or between processes on same machine in case of UNIX sockets. It is not something the packet on wire has.

Abhishek Sagar
  • 1,189
  • 4
  • 20
  • 44
  • *What* application needs to install such rules in hardware? What exactly are your writing here? – user207421 Jul 01 '16 at 05:11
  • well, entire multicast - IGMP and PIM does. i am saying, there are ample of application, whose prototype may not require to know the interface the packet is received from, but when you deploy such applications in intense traffic routing environment, you need to forward the traffic based on outgoing interface, and not next hop. Outgoing interface will be known only if application knows which ingress packet the multicast join pkts has arrived. I suggest you read PIM (protocol independent multicast). – Abhishek Sagar Jul 01 '16 at 07:08