inet_ntop() not printing url - c

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.

Related

How to find out IP address of a given process connected through TCP

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);

getpeername Invalid argument after running a server several times

I've got this, taken from beej guide and slightly adapted:
socklen_t len;
struct sockaddr_storage addr;
char ipstr[INET6_ADDRSTRLEN];
char nombreSubscriptor[INET6_ADDRSTRLEN+sizeof(int)];
int port;
len = sizeof(addr);
if(getpeername(fdSocketDevuelto, (struct sockaddr*)&addr, &len)<0){
perror("GETPEERNAME error");
close(fdSocketDevuelto);
exit(1);
}
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);
So I run the client and server and send messages to the server, everything works fine, showing like this
Peer IP address: 127.0.0.1
Peer port : 42639
But if I close and open several times (sometimes it's in the first 1-2 times I try it, but this has happened less), at some point I'm getting this:
GETPEERNAME error: Invalid argument
And before I used the perror and exit(1) in the getpeername I was getting stuff similar to this (it changed slightly in the numbers):
Peer IP address: 2325:2ec7:c37f::
Peer port : 20423
I had already asked here Recv gives Bad file descriptor only sometimes (run the program it works fine, sometimes it does not work) but the question is flat out wrong since it's not the recv that has the failure, it's the getpeername function. And I decided to ask again with proper data this time, which I'm unsure if it's the right thing to do.
The question is: why would this happen? Why sometimes it passes and Ip is fine and sometimes is not? It's two completly different runs of the code, I close and run again, and do not compile or do anything. When it gives me the failure, I wait some minutes (this also looks to be changing from time to time) and I can run again and it works just fine again.

Getting my own IP address using getsockname() [duplicate]

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);

getpeername() Returns Wrong Data

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.

How to get the port number from struct addrinfo in unix c

I need to send some data to a remote server via UDP in a particular port and get receive a response from it. However, it is blocking and I do not get any response. I need to check if the addrinfo value that I get from the getaddrinfo(SERVER_NAME, port, &hints, &servinfo) is correct or not.
How do I get the port number from this data structure?
I know inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr), s, sizeof s) gives me server IP address. (I am using the method in Beej's guide.)
You do something similar to what Beej's get_in_addr function does:
// get port, IPv4 or IPv6:
in_port_t get_in_port(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET)
return (((struct sockaddr_in*)sa)->sin_port);
return (((struct sockaddr_in6*)sa)->sin6_port);
}
Also beware of the #1 pitfall dealing with port numbers in sockaddr_in (or sockaddr_in6) structures: port numbers are always stored in network byte order.
That means, for example, that if you print out the result of the get_in_port()call above, you need to throw in a ntohs():
printf("port is %d\n", ntohs(get_in_port((struct sockaddr *)p->ai_addr)));

Resources