Determining IP address and port of an incoming TCP/IP connection in Erlang - sockets

I would like to fetch the IP address and port number of an incoming TCP/IP connection. Unfortunately gen_tcp's accept and recv functions only give back a socket, while gen_udp's recv function also gives back the address information. Is there a straightforward way to collect address information belonging to a socket in Erlang?

You need inet/peername 1. From the Erlang inet docs:
peername(Socket) -> {ok, {Address, Port}} | {error, posix()}
Types:
Socket = socket()
Address = ip_address()
Port = int()
Returns the address and port for the other end of a connection.

Related

Binding to UDP socket *from* a specific IP address

I have packets coming from a specific device directly connected to my machine. When I do a tcpdump -i eno3 -n -n, I can see the packets:
23:58:22.831239 IP 192.168.0.3.6516 > 255.255.255.255.6516: UDP, length 130
eno3 is configured as 192.168.0.10/24
When I set the socket the typical way:
gOptions.sockfd = socket(AF_INET, SOCK_DGRAM, 0);
memset((void *)&gOptions.servaddr, 0, sizeof(struct sockaddr_in));
gOptions.servaddr.sin_family = AF_INET;
inet_pton(AF_INET, gOptions.sourceIP, &(gOptions.servaddr.sin_addr));
gOptions.servaddr.sin_port = htons(gOptions.udpPort);
bind(gOptions.sockfd, (struct sockaddr *)&gOptions.servaddr, sizeof(struct sockaddr_in));
And I use the sourceIP of "255.255.255.255" on port "6516" - it connects and reads.
What I want to do, however, is bind such that I am limiting my connection from the source IP - "192.168.0.3". I have figured out how to connect on the device using either device name ("eno3") of the iface of that device ("192.168.0.10") - but that doesn't help as I may have multiple devices connected to "192.168.0.10" that blab on that port, but I only want the packets from 192.168.0.3 for port 6516.
I thought s_addr - part of sin.addr - was the source IP... but it is not.
You can't bind() to a remote IP/port, only to a local IP/port. So, for what you have described, you need to bind() to the IP/port where the packets are being sent to (192.168.0.10:6516).
Now, you have two options to choose from. You can either:
use recvfrom() to receive packets, using its src_addr parameter to be given each sender's IP/port, and then you can discard packets that were not sent from the desired sender (192.168.0.3:6516).
or, use connect() to statically assign the desired sender's IP/port (192.168.0.3:6516), and then you can use recv() (not recvfrom()) to receive packets from only that sender.

What is the difference between the Source Port and the StunServerPort

I am developing a peer to peer call. I am using de.javawi.jstun.test .
I found this constructor in de.javawi.jstun.test.DiscoveryTest .
public DiscoveryTest(InetAddress sourceIaddress, int sourcePort, String stunServer, int stunServerPort) {
this.sourceIaddress = sourceIaddress;
this.sourcePort = sourcePort;
this.stunServer = stunServer;
this.stunServerPort = stunServerPort;
}
My question is What is the difference between the Source Port and the StunServerPort??
stunServerPort is the port the STUN server listens on for incoming binding requests. This is typically one of the standard STUN ports: 3478 or 3479.
sourcePort is the port the client behind a NAT has obtained locally to create a socket with. Most often, the client attempting to do P2P will ask the OS to randomly pick an available local port to send/receive from. You can probably pass 0 for sourcePort and let it pick the port for you as well. Or if you already have a socket, use the same port as your local, and DiscoveryTest will set the reuseaddr flag so it can have a socket co-exist.

LibGDX: Error making a socket connection to *ip-adress*

I want to make 2 devices communicate via sockets.
I use this code for the client socket:
Socket socket = Gdx.net.newClientSocket(Net.Protocol.TCP, adress, 1337, socketHints);
(SocketHints: timeout = 4000)
I get a GdxRuntimeException each time this line is being executed. What is wrong with the socket?
Screenshot of stack trace
You get that message because the socket couldn't be opened.
Note the last line about the return in the API:
newClientSocket:
Socket newClientSocket(Net.Protocol protocol,
java.lang.String host,
int port,
SocketHints hints)
Creates a new TCP client socket that connects to the given host and port.
Parameters:
host - the host address
port - the port
hints - additional SocketHints used to create the socket. Input null to use the default setting provided by the system.
Returns:
GdxRuntimeException in case the socket couldn't be opened
Try doing some debugging to find out why you are getting this error.
Is the port already in use? Are you trying to open more than one connection on the same port? Is the server IP valid? Maybe something else is causing the issue?

Can I detect whether an UDP-socket or a connected UDP socket is used?

Can I detect whether a client application uses an UDP-socket or a connected UDP-socket?
If yes, how? If no, why?
As I said in my comment above, code call connect on a UDP socket. That enforces only traffic to/from the connection address is allowed (and all other packets get dropped) and allows you to use send instead of sendto, but the traffic is still UDP.
But you can use the netstat command from the command line to see if the datagram socket has a remote address association:
For example, imagine if the code did this:
// create a datagram socket that listens on port 12345
sock = socket(AF_INET, SOCK_DGRAM, 0);
port = 12345;
addrLocal.sin_family = AF_INET;
addrLocal.sin_port = htons(port);
result = bind(sock, (sockaddr*)&addrLocal, sizeof(addrLocal));
// associate the socket only with packets arriving from 1.2.3.4:6666
addrRemote.sin_family = AF_INET;
addrRemote.sin_port = htons(6666);
addrRemote.sin_addr.s_addr = ipaddress; // e.g. "1.2.3.4"
result = connect(sock, (sockaddr*)&addrRemote, sizeof(addrRemote));
A corresponding netstat -a -u will reveal the following:
ubuntu#ip-10-0-0-15:~$ netstat -u -a
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
udp 0 0 ip-10-0-0-15:12345 1.2.3.4:6666 ESTABLISHED
The presence of a value that isn't *:* in the Foreign Address column for the UDP socket will reveal if the socket has connection address associated with it.

how does Operating System map port number to process that use it

For a simple python server using TCP socket as below, when there comes a TCP packet, and transport layer get port number, how does OS/transport layer know which thread/process to wake up(assuming the thread/process is blocking because of recv() system call)? for the code below, both parent thread and child thread have the connectionsocket file descriptor, how OS know which one to wake up? Thanks
host = 'localhost'
port = 55567
buf = 1024
addr = (host, port)
welcomesocket = socket(AF_INET, SOCK_STREAM)
welcomesocket.bind(addr)
welcomesocket.listen(2)
while 1:
connectionsocket, clientaddr = serversocket.accept()
thread.start_new_thread(handler, (connectionsocket, clientaddr))
serversocket.close()
There is an hash map tracking all used port in the kernel space.
When a packet arrives, kernel lookup the table using the port information in the packet, find the associated socket, and notify it
Here is how linux do it http://lxr.free-electrons.com/source/net/ipv4/udp.c#L489