Sending packets on a defined Ethernet Interface - c

I have 2 Ethernet interfaces configured in my Linux Machine.
Lets say Interface A and Interface B.
I am writing a tcp client socket program and need to send the packets on the defined interface.
For example.
./client -intf interface A/B
if it the input is interface A, then the client has to send packets only via interface A and vice versa.
Could anyone provides some hint on how to implement this?.
Thanks in advance!!!

You can use bind() before you call connect() to bind your client socket to a particular IP address. You can use getifaddrs() to list the interfaces and their associated IP addresses.

Had to do something similar before, have you tried this?
https://austinmarton.wordpress.com/2011/09/14/sending-raw-ethernet-packets-from-a-specific-interface-in-c-on-linux/

Related

Sending multicast udp from multihomed computer

I need to send a multicast udp from multihomed computer. Found that in case socket is not bound to some specific interface, default interface will be used (whatever it could mean). My question: is it possible to specify something like inaddr_any to send multicast udp from all available interfaces or is it only possible to do that by enumerating all interfaces and manually send from each? Is there a standard for that?
Thank you
You can set which network interface IPv4 multicast packets leave from by setting the IP_MULTICAST_IF socket option. The value passed to setsockopt should be the address of a struct in_addr containing the IP address of the interface in question.
If you want to send a multicast packet on multiple interfaces, you'll need to call sendto multiple times, setting the IP_MULTICAST_IF option before each one.

C RAW socket communication with custom ETH type

So I have two userspace applications (lets say app A and B) running on linux 2.6 kernel.
app A sends raw packet with a custom ethernet type (ETH_FOO) using the socket below
socket(PF_PACKET, SOCK_RAW, htons(ETH_FOO));
if app B opens a raw socket with ETH_P_ALL and listens to all interfaces without binding, it can successfully receive pkts sent by A with type ETH_FOO.
But if B opens the socket with type ETH_FOO, no packet is observed. I just want to capture ETH_FOO pkts. What may be the problem?
This is my first question here. Pardon my mistakes if there is any. Also I can not copy the entire code since it's not mine and somewhat propriatery.
When you use ETH_P_ALL, you are listening all packets, both ingoing and outgoing.
If you are in the same machine, using the same network interface, when you send a packet, there is no ingoing packet. Using ETH_P_ALL will get you the outgoing packet.
When you specify other value than ETH_P_ALL, only incoming packets are listened to. And you get nothing if using the Ethernet interface in the same machine.
You have two options here:
use different machines
in the same machine, use the loopback adapter (which creates an ingoing packet for every outgoing packet). The loopback adapter is listed together with the Ethernet adapter when you type ip a.
It took me some time to learn this, and I did it here, where you can learn a bit more.

Check incoming interface on TCP socket

In network programming (C & Linux) with a TCP socket, how can I check the interface that received the packet. I know this can be done very easily with a SOCK_DGRAM and the IP option IP_PKTINFO, but this option does not work on SOCK_STREAM. In this case (for what im programming) I must know the interface that received the packet (the respond that gives back the server depends on that).
One possible solution that I found is to use SOCK_RAW and IPPROTO_TCP (with SOCK_RAW I can set the IP_PKTINFO option) but that implies that i'll be receiving all the TCP traffic that arrives to the machine and i don't want that. Another possible solution that I'm thinking is to check the destination IP against the routing table and get the exit interface from there but what about IPv6? What if the destiny IP its IPv6 link-local?
If anyone has another solution or idea I'll be glad to read it. Thanks in advance
When your TCP server accepted a client connection, you will have a socket to represent the connection, you could call getsockname on the socket, it will give you the address associated on the socket, namely the ip addresses on your side.
Next step, you can call getifaddrs to get all the interfaces and their information on your system, including name(like eth0) and ip address. At this point, you can search this list with the ip obtained previously via getsockname, you can get the interface you want as a result.
reference:
http://linux.die.net/man/2/getsockname
http://linux.die.net/man/3/getifaddrs

How to receive a packet UDP with a known destination MAC different to that of the listening interface

I am trying to listen for a specific discovery packet that will be sent over UDP destined for a known MAC address. This MAC address will not be the same as the MAC address of the interface I am receiving on.
I have tried Beej's UDP listener but it only receives packets with the correct MAC.
When I listen with tcpdump I can see the packets are making it to the device.
It looks like I could receive on a raw socket (although haven't got that working yet) but would there be a way to filter only the destination MAC I want?
Can anyone give me any guidance with this?
Your interface does not normally receive packets that are not sent to its own address. It just ignores them.
You need to set your network interface in promiscuous mode and use a packet capture interface provided by Linux.
Have a look at libpcap, the manual page is here.
This is the same mechanism that tcpdump uses. It is a library which provides an interface and a filter to the packet capture mechanism in the kernel.

How do I send UDP packet from a specific interface on Linux?

How do I send UDP packet from a specific interface on Linux using C? Should I use bind? Is it possible to send UDP from the interface not having IP address?
Thanks.
Use bind. You cannot send UDP packets via an interface that does not have an IP address, because UDP uses the Internet Protocol and the Internet Protocol requires an IP address.
You can bind a socket to a specific interface by using the SO_BINDTODEVICE socket option, however this requires root privileges.
Alternately, you can set the IP_PKTINFO option, and use sendmsg for sending, setting the in_pktinfo's ipi_ifindex to the index of your interface.
You need to use socket option IP_MULTICAST_IF.
See here: Multicast-HOWTO-6.html

Resources