How to check if port is available - c

Is there an API function on Linux (kernel 2.6.20) which can be used to check if a given TCP/IP port is used - bound and/or connected ?
Is bind() the only solution (binding to the given port using a socket with the SO_REUSEADDR option, and then closing it) ?

Hmm,
According to strace -o trace.out netstat -at
netstat does this by looking at
/proc/net/tcp
and
/proc/net/tcp6
The used ports are in hex in the second field of the entries in that file.
You can get the state of the connection by looking at the 4th field, for example 0A is LISTEN and 01 is ESTABLISHED.

The holy portable BSD socket API won't allow you to know whether the port is in use before you try to allocate it. Don't try to outsmart the API. I know how tempting it is, I've been in that situation before. But any superficially smart way of doing this (by e.g. the proc filesystem) is prone to subtle errors, compatibility problems in the future, race conditions and so forth.

Grab the source of the netstat command and see how it sees. However, you will always have a race. Also, SO_REUSEADDR won't let you use a port someone else is actively using, of course, just one in close-wait.

Related

How do I get PID from socket port on Windows?

Given a socket port how do you find the process ID (process name) of the process on Windows 10 that uses this port? I am aware of netstat command but I would like to do it with C code only.
How about there, it appears there's a way: the IP Helper library.
Ref: https://learn.microsoft.com/en-us/windows/win32/iphlp/ip-helper-start-page
I haven't used it for this, but it's clearly going down the right road by providing everything you need to basically roll your own netstat.exe.
The low-level object that contains all the info is MIB_TCPROW2, which has the local and remote address + port, plus dwOwningPid. So we know there's a way.
Drilling down we ultimately need the GetTcpTable2() call, and Microsoft's web page helpfully has what appears to be fully-functional C code to do all this yourself.
https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-gettcptable2
Finding this was the best surprise of my day!

Set TCP ECN on a socket (C Linux)

Is it there a way to set TCP ECN on an unprivileged TCP socket in a C linux program?
Does any congestion algorythm that can be set through setsockopt() involve ECN?
Thank you!
Short answer: no and technically yes (but based on the question it won't help and I don't think it is yes to what you wanted to ask).
ECN is turned on by echoing 1 to /proc/sys/net/ipv4/tcp_ecn. See
ip_sysctl.txt. By default it should be 2 which enables ECN when the peer requests it, but does not initiate requests for it. To set this would require "privileges" and can't be done via a socket so the 1st answer is no.
Congestion algorithms may be set on a per socket basis and may involve ECN, trivially the default one does. So technically, yes. But even though the congestion algorithms may involve ECN, the code in tcp_input.c and tcp_output.c makes it clear that without the sysctl flag set, it won't use it, so it won't help.
See the very good information in this answer

C capture ICMP packet

I need to test code which deals with ICMP packets, but there is no activity at all. So i thought is there any system function to trigger tsome activity, for instance to make port 80 work you usually do system("wget 'webaddress'");. Is there anything similar to that for ICMP? thanks beforehand
The ping command would get you close. Modern implementations often default to a random UDP port, but the documentation on your system (e.g. man ping) should tell you the option to pass to tell it to use ICMP instead.

Converting an AF_INET socket to use AF_UNIX via LD_PRELOAD

I'm wondering how feasible it is to be able to convert an AF_INET socket to use an AF_UNIX instead. The reason for this is that I've got a program which will open a TCP socket, but which we cannot change. To reduce overhead we would therefore like to instead tie this socket to use an AF_UNIX one for its communication instead.
So far, my idea has been to use LD_PRELOAD to achieve this---intercepting bind() and accept(), however it is not clear how best to achieve this, or even if this is the best approach.
So far, bind in bind(), if the socket type is AF_INET and its IP/port is the socket I wish to convert to AF_UNIX, I then close the sockd here, and open an AF_UNIX one. However, this seems to be causing problems further on in accept() -- because I am unsure what to do when the sockfd in accept() matches the one I wish to tell to use an AF_UNIX socket.
Any help kindly appreciated.
Jason
Your idea sounds perfectly feasible. In fact, I think it sounds like the best way to achieve what you want. I wouldn't expect very different, or even measurably different, overhead/performance though.
Of course you'd also have to intercept socket() in addition to bind() and accept(). In bind(), you could, for example, converted the requested TCP port to a fixed pathname /tmp/converted_socket.<port-number> or something like that.
I had a similar problem and came up with unsock, a shim library that does what you describe, and more.
unsock supports other address types like AF_VSOCK and AF_TIPC, and the Firecracker VM multiplexing proxy as well.
There are three key insights I want to share:
Since sockets are created for a particular address family using socket(2), and then later connected or bound using connect(2)/bind(2), you may be tempted to simply intercept socket and fix the address there.
One problem is that you may want to selectively intercept certain addresses only, which you don't know at the time of the call.
The other problem is that file descriptors may be passed upon you from another process (e.g., via AF_UNIX auxiliary mes, so you may not be able to intercept socket(2) in the first place.
In other words, you need to intercept connect(2), bind(2), and sendto(2).
When you intercept connect(2), bind(2), and sendto(2), you need to retroactively change the address family for socket(2). Thankfully, you can just create a new socket and use dup3(2) to reassign the new socket to the existing file descriptor. This saves a lot of housekeeping!
accept(2) and recvfrom(2) also need to be intercepted, and the returned addresses converted back to something the caller understands. This will inevitably break certain assumptions unless you do maintain a mapping back to the actual, non-AF_INET address.

Get random port for UDP socket

I need to create a program that will communicate with other programs on the same computer via UDP sockets. It will read commands from stdin, and some of this commands will make it to send/receive packets without halting execution. I've read some information out there, but since I'm not familiar with socket programming and need to get this done quickly, I have the following questions:
I need to get a random unused port for the program to listen to, and reserve it so other programs can communicate with this and also the port isn't reserved by another program. I also need to store the port number on a variable for future usage.
Since the communication is across processes on the same machine, I'm wondering if I can use PF_LOCAL.
Also a code sample of the setup of such socket would be welcome, as well as an example of sending/receiving character strings.
Call bind() specifying port 0. That will allow the OS to pick an unused port. You can then use getsockname() to retreive the chosen port.
Answer by Remy Lebeau is good if you need a temporary port. It is not so good if you need a persistent reserved port because other software also uses the same method to get a port (including OS TCP stack that needs a new temporary port for each connection).
So the following might happen:
You call bind with 0 and getsockname() to get a port;
then save it into config (or into several configs) for future uses;
software that needs this port starts and binds the port.
Then you need to e.g. restart the software:
software stops and unbinds the port: the port can now be returned by bind(0) and getsockname() again;
e.g. TCP stack needs a port and binds your port;
software can't start because port is already bound.
So for "future uses" you need a port that is not in ephemeral port range (that's the range from which bind(host, 0) returns a port).
My solution for this issue is the port-for command-line utility.
If it being a random port is actually important, you should do something like:
srand(time(NULL));
rand() % NUM_PORTS; // NUM_PORTS isn't a system #define
Then specify that port in bind. If it fails, pick a new one (no need to re-seed the random generator. If the random port isn't important, look at Remy Lebeau's answer.

Resources