This question already has an answer here:
Getting my own IP address by connect()ing using UDP socket?
(1 answer)
Closed 8 years ago.
I'm trying to get my own IP address by trying to connect() to 8.8.8.8 using UDP socket and then calling getsockname() function.
I've written a function get_my_ip(), and the code worked when it was placed in my server program, but as a separate function, it fails. It prints some strange characters instead of my IP address.
The only thing I changed from the code in my server program was return NULL instead of return 1, or return 2, because it was inside int main().
Can anyone see why my program is not working?
Thank you.
You must initialize addrlen.
addrlen = sizeof remoteaddr;
getsockname(sockfd, (struct sockaddr*)&remoteaddr, &addrlen);
You must cast the sin_addr in your inet_ntop() call. It should be like this:
inet_ntop(AF_INET, &(((struct sockaddr_in *)sa)->sin_addr), remoteIP, addrlen);
inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)sa)->sin6_addr), remoteIP, addrlen);
Related
I believe the inet_ntop() is supposed to convert a struct sockaddr address to a string, currently I have :
sin_size = sizeof their_addr;
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)&their_addr)->sin6_addr), s, sizeof s);
printf("server: got connection from %s\n", s);
If I make a connection from http://localhost:3490/thispage.html, I expect the code to print out
http://localhost:3490/thispage.html but all it prints out is "server: got connection from ::1".
I don't understand why this is happening - basically what I'm trying to do is get the html page name from the url and I wanted to extract it from the returned string, but the string is not returning what I was expected.
The inet_ntop function takes a structure containing an IP address and converts it to a string format. It doesn't know anything about URLs.
When accept returns, all that's happened at this point is that a TCP connection was made, and their_addr contains the IP address of the endpoint which connected, in this case ::1, which is what is printed.
You need to further read from the socket, which presumably contains HTTP, to learn what URL was called.
I need to get the local port used by a (client) socket.
It was my understanding that Windows Sockets performs an implicit bind function call, therefore getsockname() after sendto() should provide the assigned port. However, it always sets 0 as the port number. Am I missing something?
ex:
if (sendto(sockfd, ...) != SOCKET_ERROR)
printf("Sent\n");
if (getsockname(sockfd, (struct sockaddr*)&sin, &sinlen) != SOCKET_ERROR)
printf("port = %u\n", ntohs(sin.sin_port);
else
printf("Error");
//result: Sent, port = 0
Problem solved with a restart of the computer. Still unknown as to the actual cause, but at this point I'm just happy it's working.
If anyone has an idea for fixing the issue without a restart (for future readers), feel free to post.
The only ambiguity I can see in your example code is what size you assigned to sinlen before calling. (you do not show it) If you are using winsock, it should be defined, and assigned int sinlen = sizeof(sin);
I used this code on my system, and it returns a non-zero value for the port I am connecting through:
struct sockaddr_in sin;
int len = sizeof(sin);
if (getsockname(sock, (struct sockaddr *)&sin, &len) == -1)
//handle error
else
printf("port number %d\n", ntohs(sin.sin_port));
By the way, The ntohs function function returns the value in host byte order. If [ sin.sin_port ] is already in host byte order, then this function will reverse it. It is up to [your] application to determine if the byte order must be reversed. [text in brackets are my emphasis]
In answer to comment question ( getsockname() ):
The function prototype for getsockname():
int getsockname(
_In_ SOCKET s,
_Out_ struct sockaddr *name,
_Inout_ int *namelen //int, not socklen_t
);
For more discussion on socklen_t
Edit (address possible approach to re-setting sockets without rebooting PC.)
If winsock API calls cease to work predictably, you can re-start sockets without rebooting the PC by using WSAStartup and WSACleanup (see code example at bottom of link for WSAStartup)
You say you want to know the LOCAL port, but your line
sendto(sockfd, ...)
implies sockfd is the REMOTE descriptor. Your later code may therefore give you info about the REMOTE port, not the LOCAL one. 'sockets' are not both ends, meaning one connection. A socket is one end, meaning the IP and port number of one end of the connection. The first parameter of your getsockname() is not a reference or a pointer, it is therefore not an output from the function, but an input. You're telling the function to use the same socket descriptor that you just sent to, ie. the remote one.
Formatting error. ntohs() returns unsigned short so the format should be %hu, not %u or %d. If you grab too many bytes they are not the port.
Answer. After using sendto() try using gethostname() then getaddrinfo() on the name that comes back. Note: the addrinfo structures you get back will give you struct sockaddr pointers which you will need to re-cast to struct sockaddr_in pointers to access the local port number.
To find the local port number the kernel dreamed up when you issued a sendto() function perhaps you could write a routine to parse the output from the (gnu linux) commands 'ss' or 'netstat'. (Not sure if these are POSIX compatible.) Or maybe you could access /proc/net if you have the privilege.
So I want to obtain the address of the machine a process (subscriber) is working on, so I can send it in a message to the server (intermediary), next to a specific port, so the server can answer on that other port.
That is, they are going to be connected, but I want the answer in another port. So I want to forward the port next to the address of the suscriber so the server can connect.
I believe ONE way of doing it would be similar to an example found
http://beej.us/guide/bgnet/output/html/multipage/getaddrinfoman.html
so I would use getaddrinfo to do something like this
if ((rv = getaddrinfo(NULL, "3490", &hints, &servinfo)) != 0) {
and then I would look in the linked list for the address in
dir_tcp_srv.sin_addr.s_addr
But I think this is in fact not the correct use. I don't fully understand but I believe this is not quite the way of doing it.
I guess there are many ways of doing this but essentially I want to obtain the data (I already have the port number) so that the client and server roles switch, and the server makes a connection to the client
Edit: Ok so I'm reading time and time again how the server knows the address of the client once it's connected. I'm re-reading man pages to know how to obtain that info but can't find it yet.
Also, I found this:
https://suite.io/guy-lecky-thompson/7sd21g
But I can't say I quite get it.
Edit2: I think I've had a concept wrong for a long time.
In my code I make accept like this:
fdSocketDevuelto = accept(sock_tcp, (struct sockaddr )&dir_tcp_srv, (socklen_t) &sizeSock);
Which I now believe is overwriting the info previously stored in the struct, that I used to bind, listen, all that, with the client's info. If someone can confirm this I can comment to my own question with this as the answer or delete the whole thing since it was something I never fully understood/used.
I understand the question as you are wanting to have server find the client's IP address and Port. Take a look at getpeername():
From Beej's guide:
http://beej.us/guide/bgnet/output/html/multipage/getpeernameman.html
// assume s is a connected socket
socklen_t len;
struct sockaddr_storage addr;
char ipstr[INET6_ADDRSTRLEN];
int port;
len = sizeof addr;
getpeername(s, (struct sockaddr*)&addr, &len);
// deal with both IPv4 and IPv6:
if (addr.ss_family == AF_INET) {
struct sockaddr_in *s = (struct sockaddr_in *)&addr;
port = ntohs(s->sin_port);
inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof ipstr);
} else { // AF_INET6
struct sockaddr_in6 *s = (struct sockaddr_in6 *)&addr;
port = ntohs(s->sin6_port);
inet_ntop(AF_INET6, &s->sin6_addr, ipstr, sizeof ipstr);
}
printf("Peer IP address: %s\n", ipstr);
printf("Peer port : %d\n", port);
This question already has an answer here:
getpeername always gives bad file descriptor
(1 answer)
Closed 8 years ago.
I am attaching my process (with root privileges) to a browser process to intercepts its system calls using ptrace. To decode the parameters of the connect() system call i got the sockfd. But i have been trying from days to get the ip address of the other end of that socket but with no success.
i came accross these 2 questions while looking around
1)Get IP address from socket descriptor?
2)Getting IP address, port and connection type from a socket fd
I followed the suggestion of the 1st question, but somehow it was giving error. something error: ‘struct sockaddr_in’ has no member named ‘sa_data’. I digged deeper into the internet and got another hint, which i used to write this code
temp = getpeername(regs.rdi, (struct sockaddr *)&ip_addr_struct, &ip_addr_structlen);
struct sockaddr_in *s = (struct sockaddr_in *)&ip_addr_struct;
int port = ntohs(s->sin_port);
inet_ntop(AF_INET, &s->sin_addr, ip_addr, 1024);
printf("%d-%s\n", port, ip_addr);
here regs.rdi is the sockfd. But even with this code everytime i get 0-0.0.0.0
as output. please help anyone. Is there any other way to get the ip addrres or am i doing something wrong?
If your requirement is to get the IP address of the connecting client, use this :)
struct sockaddr_in their_addr;
if ((*cli_fd = accept(listener, (struct sockaddr *)&their_addr,&sin_size)) == -1)
{
close (*cli_fd);
return -1;
}
This is the client ip address ==> inet_ntoa(their_addr.sin_addr)
I am writing my first sockets program on Linux and am trying to print the IP address and port of the peer I have connected to. I use getpeername() along with inet_ntop() and ntohs() to get the data out of the sockaddr_in struct. When I look at the results, I get an IP address that does not go to any server that I know of (ping fails) and says that I am listening to a port that netstat says is not being used.
What am I doing wrong? I should be getting 130.215.28.181:39000, but instead I am getting 209.94.72.137:18825 every time I run the program. Looking at netstat shows that I am indeed listening on port 39000.
Here is a snippet from my client program:
connect(sockfd,&serv_addr,sizeof(serv_addr))
// print welcome message
char ipstr[INET6_ADDRSTRLEN];
bzero(ipstr, 50);
struct sockaddr_in *address;
socklen_t address_len = sizeof(*address);
getpeername(sockfd, (struct sockaddr *) address, &address_len);
inet_ntop(AF_INET, &address->sin_addr, ipstr, sizeof(ipstr));
printf("Connection established successfully with %s:%i!\n", ipstr, ntohs(address->sin_port));
You're not allocating any memory for your sockaddr_in structure, you's just passing a pointer to some random memory location. Instead, allocate the address structure on the stack:
struct sockaddr_in addr;
socklen_t addr_len = sizeof(addr);
int err = getpeername(sockfd, (struct sockaddr *) &addr, &addr_len);
if (err != 0) {
// error
}
You should also be checking the return value of every function that is documented to return an error code. In particular, both connect and getpeername return error codes that you should be checking.