Binding getaddrinfo to particular interface (source IP) - c

I use getaddrinfo() to get IP Address corresponding to a server using a URL. It essentially sends DNS query to the DNS server. I want to be able to send that query from a particular outbound interface. Basically I have multiple interfaces through which DNS query could be sent out. Currently, getaddrinfo() doesn't have a way to dictate which interface it should use to send out the DNS query. Is the only option to change getaddrinfo() routine? Does anyone know of any other way to achieve this?

The fundamental issue with the question is that you seem to expect getaddrinfo to work with DNS only, and then to be able to fine-tune the specifics of that DNS lookup. However, that is not what it does - it will use all name-resolving facilities on the system, which typically means it will do a hosts file lookup, and whatever else is configured in nsswitch.conf, which is usually DNS. For some of these non-DNS lookups, a source address binding may not make any sense, so it's not part of the least-common-denominator interface.
If you know that for your specific purpose you will never need the response of a name lookup from anywhere other than DNS, then you can use a DNS-specific function instead, one that will enable you to do this kind of fine-tuning.
There are several examples of DNS C libraries listed at gethostbyname dual network interfaces, select which one to use

The interface chosen to access a given IP address is dictated by the routing tables.
Since you presumably have the IP of the DNS server, it will be accessed by whatever interface the routing table says to use for that IP address, regardless of which application sends the request.
You would need to modify the routing table to force traffic over a particular interface. If it's only the DNS server that should use a fixed interface, you would add a route for that specific IP to the routing table for the interface you want.
On Linux, you can modify the routing table via the ip route command line tool.

rfc 3484 details an algorithm of which source addr (i.e. interface) to use when none is specified, but this works I think only for ipv6...
see /etc/gai.conf

Related

What is getservbyname() — do I understand it right?

I don't really know what to write in the first parameter of getservbyname().
I read that if I give the name and protocol such as TCP I get a struct back with information to the server, but what should I write in there?
So, for example, getservbyname("www.google.com", "tcp")
This is wrong but what needs to be in the first parameter to get, for example, the port from Google or other websites or am I understanding this absolutely wrong?
getservbyname looks up service names from this list and gives you back port numbers. "http" is an example of a service name that you can look up in this table.
www.google.com is a host name, not a service name. gethostbyname looks up host names and gives you IPv4 addresses; to connect to Google's web server you need its address as well as the service's port number. Nowadays it is usually better to do both lookups at once, using getaddrinfo, which also seamlessly handles IPv6.
"www.google.com" is a hostname, not a service. getservbyname() is just a fancy way to read information from the /etc/services file on your local machine, so the first argument to the function might be something like "telnet" or "ftp". i.e. it is used to find out what port a particular service is expected to be running on, on your local machine.
If you want to get information about a hostname (e.g. its IP address), you can get that via a different API call like gethostbyname(), or (for a more modern/flexible implementation) getaddrinfo().

RPC windows get client IP address

I have read loads of Microsoft documentation regarding RPC programming and still do not figure out how do we get from RPC server the IP address of the connecting client.
I am sure there is a simple way to get client IP address from server when connecting, but do not know how to do this :/
Thanks for helping, a simple pointer to a documentation would be great.
No - there is no documented way to accomplish this. Windows RPC by design abstracts the network transport (and associated metadata like network addresses) from it's clients.
If you really need something like this, you could bake it into your interface (e.g. implement a Connect() method where your client provides it's IP address that you could stash in a Context Handle). This assumes of course, that you can trust your clients to provide valid IP addresses...
It should be possible using RpcBindingServerFromClient. Quoting documentation for RpcBindingServerFromClient:
To query a client's address, an application starts by calling the RpcBindingServerFromClient function to obtain a partially bound server binding handle. The server binding handle can be used to obtain a string binding by invoking RpcBindingToStringBinding. The server can then call RpcStringBindingParse to extract the client's network address from the string binding.
UPDATE 16/05/2017: There is also undocumented function I_RpcServerInqRemoteConnAddress() that most likely return client IP address. But I didn't try it yet.

Difference binding to INADDR_ANY and a specific IP

I'm confused about the use and consequences of INADDR_ANY when binding a socket. Of course the INADDR_ANY listens to all the local interfaces. My question as about what consequences this does have.
I remember reading that binding to a specific IP address allows the kernel to handle the demultiplexing but can't find the reference any more.
Will the use of INADDR_ANY have consequences of this kind or will I simply just receive data from all my local ip's? What are the benifits and problems of using each kind of binding?
Other questions that discuss this:
bind with INADDR_ANY
Question about INADDR_ANY
EDIT: Found the reference. It's from Unix Network Programming (Stevens)
One advantage in binding a non-wildcard IP address is that the
demultiplexing of a given destination IP address to a given server
process is then done by the kernel.
What does this really mean?
Binding to specific interfaces is something to use only in very special circumstances, when the application needs to "know" the local IP addresses and the immediate network layout. A routing daemon program is perhaps the best example.
Another, more pedestrian example: if you have a multi-homed machine (i.e. a machine with more than one connection to the Internet, possibly different ISPs) you can bind to a specific interface to make sure that the connection goes through a given connection. Binding separately to each network interface, the application could detect link down etc.
Implementations of protocols that need to "know" the local IP address (infamous examples: FTP, SIP, UPnP) tend to bind sockets to specific interfaces. (I consider them to be bad protocols, since they violate the isolation between transport and application layers).
Save for these cases, it is normally over-engineering to bind to specific interfaces, because addresses and interfaces may change, and the program must detect these conditions to update the respective sockets.
You are not going to be able to measure any performance difference between using a specific IP or all of them. You might wish to use a specific one based on the needs of your application... for example, if you know you should never have a (legitimate) connection from an external facing IP, you would not want to receive input from it, for security reasons.

Measuring upload/download rates with libpcap

I'm using libpcap (and winpcap on Windows) in a C application to monitor network traffic. I need to differentiate between upload and download traffic on each network adapter, to produce connection speed stats, but the filter expressions used by the library don't seem to support this very easily (ie there are no 'incoming'/'outgoing' operators).
One approach that I have considered is to query the IP address of each adapter, and then use filters such as src host 1.2.3.4 (to measure uploads) and dst host 1.2.3.4 (to measure downloads).
My questions are:
Is there a better/simpler approach than the one above (something that would let me use the same filter expression for each adapter would be nice)?
If the above approach is the way to go, then is there any chance that a single adapter could have more than 1 IP address associated with it? The reason I ask is that the pcap_addr struct which holds the address details of a single adapter (in struct pcap_if) has a 'next' member suggesting that this is possible.
Firstly, remember, pcap sees only packets. It doesn't see "outgoing" or "incoming" - simply packets. So yes, you must filter using the src/dst in the ip headers. There is no other way to tell whether the packet is incoming or outgoing.
Secondly, yes, there is nothing stopping an adapter having multiple IP addresses. So you need to grab the IP addresses configured from that adapter. pcap_findalldevs() (WinPCap Documentation) ought to help you here, from which you should be able to deduce which devices you want to monitor.
Have you considered looking at pmacct - I have personally contributed to this in time past. This is a C tool that uses libpcap to passively monitor network traffic for accounting purposes.
Try tcpdump

How does getaddrinfo() do DNS lookup?

getaddrinfo() is a function we need to use before creating a socket() or connect()ing, right? Then how does getaddrinfo communicate with DNS server in the first place?
PS: Where can I see the complete source of getaddrinfo?
The short answer is "it asks the system", which in turn knows how to do DNS lookups and which servers to use.
getaddrinfo() is documented by the getaddrinfo(3) manual page, which means it's a C library function. It is also a POSIX function, so there is no canonical "source"; each standard C library of an operating system that conforms to POSIX will implement its own version. Either way the source to just that function is probably not too enlightening, since it would just call other functions and OS APIs, and you'd have to drill down pretty far to get to the actual DNS mechanism. You'd be better off reading documentation of the DNS protocol itself if you're interested in how that works.
It is not necessary to call getaddrinfo() before creating a socket or connecting. It is used to translate a domain name, like stackoverflow.com, to an IP address like 69.59.196.211. If you know the IP address then you can connect directly to that address and there is no need to use getaddrinfo(). getaddrinfo() uses the DNS protocol to talk to your name servers, which are configured using their IP address.
The glibc source code is here.
Does your Unix system have the file /etc/nsswitch.conf? If so, then the "hosts" entry gives the search order for resolving hostnames into IP addresses. Does your system have the file /etc/resolv.conf? If so, then it specifies what DNS servers to use.
As you can see, getaddrinfo() can do quite a bit (and can take a while)!
getaddrinfo() likely does make a connect() call behind the scenes, however it already knows the IP address of the DNS server it needs to connect to in order to query for the address of the host you are asking it to query for.
getaddrinfo() is only needed if you want to map "www.somehost.com" to an IP address, it's not needed as a primer to call connect().
You can probably find the complete source code for getaddrinfo() in glibc sources which you'd be able to find here (among other places).
Hope that clarifies things for you.
It is using DNS protocol (UDP)
http://www.freesoft.org/CIE/Topics/77.htm

Resources