RPC windows get client IP address - c

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.

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().

Client Mongoose C app to query LAN DNS?

I'm experimenting with Cesanta's Mongoose server/"client" networking library in C. This is in Windows 7 x64 using Pelle's C. I'm trying to make a LAN-capable text messaging app on port 90 as two dialog-as-main executables (server and client) to support 20 connections to the server. FWIW, I'm using a fast timer to call mg_mgr_poll(&mgr, 0) which retains UI responsiveness and uses very little CPU.
Cesanta gives good examples of server communication setup and that works flawlessly. I can also get a client to connect to the server, but the server's IP address must be used in mg_connect().
Since the server's hostname is public to the LAN, I was hoping to ask the LAN for this host's IP. I had this working in VB awhile ago:
Dim host As New IPHostEntry
host = Dns.GetHostEntry(hostName)
Return host.AddressList.GetValue(0)
However as the VB project got bigger, VB got stranger and much more difficult, so I migrated to good old C. (Perhaps it was falling back to a NetBIOS name query, dunno.) No, I'd rather not migrate again to C# or C++/VS.
The Cesanta documentation on DNS resolution is quite vague. Code like mg_connect(&mgr, "MyServerPC:90", ev_handler); simply crashes, despite mg_connect stating it will try and resolve hostnames.
Can Mongoose resolve a local (LAN) hostname, and how? Or is this futile, and should everything be done manually in Winsock?
i have the same issue as you.
First i think that the mg_connect should not crashes, only if you try to do something with the returned connection which is null.
Second, mongoose try to resolve the address using DNS from specific location at the registry and it's take the first address he can find.
The location is :SYSTEM\\ControlSet001\\Services\\Tcpip\\Parameters\\Interfaces
,check here in each of the interfaces.
i think there is a bug here (i am going to open an issues for it and also try to fix it and created a pull request).
Little update:
i have opend an issue and create a pull request about this issue.
https://github.com/cesanta/mongoose/issues/832
https://github.com/cesanta/mongoose/pull/833
Mongoose check each interface for the Value of NameServer and DhcpNameServer ,and return the first one (which is not empty) it can find but if it found an empty value for NameServer it doesn't check DhcpNameServer(and therefore miss the correct address) which will cause an error and direct the name resolving to a default server(i think it's google DNS -8.8.8.8).
You can fix this by going to the registry and adding the value of your DNS address to the registry key-NameServer
this is a comment from mongoose code:
/*
* See https://github.com/cesanta/mongoose/issues/176
* The value taken from the registry can be empty, a single
* IP address, or multiple IP addresses separated by comma.
* If it's empty, check the next interface.
* If it's multiple IP addresses, take the first one.
*/

Binding getaddrinfo to particular interface (source IP)

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

Using gethostbyname() function on an external device

I'm using the client server program in C language on a Linux OS. In a first step, I programmed the code on the same machine using "localhost". Therefore, for the client to get the server information, I would use
server = gethostbyname("localhost")
since both the client and the server are running on the same machine.
However, now I would like to connect to an external device (using ssh). The device's username is of the following type
user#foxboard1
Although, I am not sure how to use the gethostbyname() function in this instance. I have tried
server = gethostbyname("user#foxboard1")
but that doesn't seem to work.
Any help would be appreciated!
P.s, I cannot copy and paste the code since it's on a different machine
EDIT
Instead of retreiving information about an external device, I would like to connect to the device using its IP address (an ssh connection through the connect() function.
gethostbyname() and its replacement getaddrinfo() are supposed to transform a host name or strin representation of an IP address into a "usable" structure.
This works very well on things like localhost, www.google.com, 1.2.3.4 etc.
But if you have a username embedded in the string, you'll have to split them up.
Of course, you'll have to become aware what kind of connection you want to establish and what the username is useful for.
If, as it seems, you want to do a SSH connection, it is probably best to use popen() and alike functions to start an external ssh process.

How to check if an IP address corresponds to localhost in C

In C on linux, is there a canonical way to check that an IP address corresponds to localhost?
That is, I'm looking for a function is_localhost such that if my computer has an external IP of "1.2.3.4", then calling is_localhost on any of "localhost", "127.0.0.1" or "1.2.3.4" should return true, and any other IP will return false.
On a side note, how difficult is it to spoof this information - does checking that the host is localhost in this way guarantee that the request actually came from this computer?
For context, I'm writing a management interface for a server. I'd like to make the read-only management bits, like viewing a list of connections, available over the network, but for anything dangerous, like manually killing a connection, you should be doing it by running a script on the server itself.
Thanks!
I think you may be trying to solve your problem in the wrong way - If you want to restrict access to your remotely accessible application by checking if its the local host or not then checking the IP address would be a very bad way to do it. A PC can have any number of easily configurable network interfaces with IP addresses of your own choosing. So it would be very easy to work around.
You may want to look into adding some basic authentication or simply don't allow certain functions to be run remotely. There would be many ways to achieve this, but I think the scope of the question ends here with -- Don't rely on checking for the IP address. :)

Resources