I've been using getaddrinfo for looking up socket addresses for basic socket commands. Recently, though, the addresses it returns to me are for bogus IP addresses, which I have found using inet_ntop. I've tried my code, as well as that provided in Beej's Guide, and they both produce the same results. Here's the code:
struct addrinfo hints, *info;
int status;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
if(status = getaddrinfo(address, port, &hints, &info)) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
}
char ip4[INET_ADDRSTRLEN];
inet_ntop(AF_INET, info->ai_addr, ip4, INET_ADDRSTRLEN);
std::cout<<ip4<<std::endl;
No matter what address I use, it always gives me an IP of the form
16.2.x.y
where 256*x + y is equal to the port number. Has anyone ever seen this happen, or can anyone guess why it's giving me this?
Shouldn't you be passing
((sockaddr_in const *)info->ai_addr)->sin_addr
to inet_ntop?
Related
Trying to get a program to return an IP address along with a port number so I can create an effective TCP Client/Server program. Struggling with the function getaddrinfo() at the moment and understand that the 2nd argument in the function is what designates the port number. I can get it to return an IP but can't get it to return a port number. I'm inputting the host name and port designation (ex. http or telnet) in string form and trying to get back an IP address and port number associated with it.
I've tried inputting AI_NUMERICSERV into ai.flags in order to input the numeric value of the port number besides specifying "http" and "telnet". Just trying to understand network programming for the first time.
int main(int argc, char **argv){
struct addrinfo hints, *res, *p;
int status;
char ipstr[INET_ADDRSTRLEN];
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
// hints.ai_flags = AI_NUMERICSERV;//leaving this off for now
if((status = getaddrinfo(argv[1], argv[2], &hints, &res)) != 0)
{
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
return 2;
}
`for(p = res; p != NULL; p = p->ai_next)
{
void *addr;
struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
addr = &(ipv4->sin_addr);
inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr);
printf("%s\n", ipstr);
}
printf("IP addresses for %s:\n\n", argv[1]); //displays IP correctly
printf("Port for %s: ", argv[2]); // doesn't display port number
freeaddrinfo(res);
return 0;
}
I keep expecting a port number output next to IP address output but I always get just the IP address and not the port number.
You need to read the port(s) returned by res->ai_addr...
printf("port=%h\n", ntohs(((struct sockaddr_in*)(res->ai_addr)) ->sin_port));
If you are just trying to figure out what port(s) are associated with specific services, and you are on a *nix host, you can also just grep /etc/services.
Context: My C++ application needs to know on which computer it is running in order to do specific behavior. So my application gets the IP address of the computer and then check that address in a configuration file with an IP list in order to determine the computer's role. All computers have a fixed IP address. I am using gethostname, getaddrinfo and inet_ntop in order to do that.
Problem: On some target platform's computers, getaddrinfo returns the old IP address (the address before I set the fixed value). But if I am doing "ipconfig" in the cmd, the expected fixed value is shown. It is also pingable by other computers. All computers have only 1 network card, IPv6 is disabled.
Platform: Windows 7 x64.
IDE: Visual Studio 2015.
I would like to have the actual fixed IP address.
Thank you for your help!
Code sample:
// [Some stuff...]
addrinfo hints;
addrinfo *pResults;
int returnedCode;
char hostName[1024];
if (0 != (returnedCode = gethostname(hostName, sizeof hostName)))
{
// Error handling stuff.
}
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET; // Only want IPv4.
hints.ai_socktype = SOCK_DGRAM; // UDP stream sockets.
hints.ai_flags = AI_PASSIVE; // Fill in my IP for me.
if (0 != (returnedCode = getaddrinfo(hostName, NULL, &hints, &pResults)))
{
// Error handling.
}
struct addrinfo* res;
char buffer[INET_ADDRSTRLEN];
std::string localIP;
for (res = pResults; res != NULL; res = res->ai_next)
{
if (res->ai_family == AF_INET)
{
const char* ip = inet_ntop(AF_INET,
&((struct sockaddr_in *)res->ai_addr)->sin_addr, buffer, INET_ADDRSTRLEN);
if ((NULL == ip) || (nullptr == ip))
{
// Error handling.
}
else
{
localIP = std::string(ip);
}
}
}
freeaddrinfo(pResults); // free the linked-list
WSACleanup();
// [More stuff...]
I am currently learning about the internet. I am trying to set up a simple proxy server that just forwards a request from the server side to its client side. Im currently following this tutorial. This is how far I have gotten:
#define MYPORT "3490" // the port users will be connecting to
#define BACKLOG 10 // how many pending connections queue will hold
int main(int argc, const char* argv[]) {
struct addrinfo hints;
struct addrinfo *res;
int sockIn;
int sockOut;
memset(&hints, 0, sizeof hints); // make sure its empty
hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever
hints.ai_socktype = SOCK_STREAM; // what kind of socket
hints.ai_flags = AI_PASSIVE; // fill in my IP for me
//listens on the hosts ip address:
getaddrinfo(NULL, MYPORT, &hints, &res);
// make a socket, bind it, and listen on it:
sockIn = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
bind(sockIn, res->ai_addr, res->ai_addrlen);
listen(sockIn, BACKLOG);
freeaddrinfo(res); // free the linked-list
struct sockaddr_storage their_addr;
socklen_t addr_size;
char buf[512];
while(1) {
addr_size = sizeof their_addr;
struct sockaddr *addr = (struct sockaddr *)&their_addr;
sockOut = accept(sockIn, addr, &addr_size);
recv(sockOut, buf, sizeof buf, 0);
for (auto ch : buf) {
cout << ch;
}
close(sockOut);
}
}
Right now im just displaying "hi" on every page I visit.
Before I implement the client side of the proxy id like to instead display the HTTP Get Request that my browser sends to the server side of the proxy. My issue is that I dont know how to retrieve it. The guide I'm using is not adressering this.
Edit: I added a recv call that is suppose to read everything from the socket in to a buffer. Unfortunately it does not cout anything
download and install wireshark (packet sniffer), or else Fiddler Fiddler(HTTP proxy). You will easily be able to inspect HTTP traffic. I recommend you start with fiddler. Install on computer where your browser is located.
I wrote server and client code client can connect with server normally but only on local address i don't know how to connect over internet
int main()
{
struct addrinfo host_info;
struct addrinfo * host_list;
struct sockaddr sa;
struct sockaddr_in ip4addr;
memset(&host_info, 0, sizeof host_info);
host_info.ai_family = AF_INET; // IP version not specified. Can be both.
host_info.ai_socktype = SOCK_STREAM;
getaddrinfo(NULL, "5555", &host_info, &host_list);
int s;
s=socket(host_list->ai_family,host_list->ai_socktype,host_list->ai_protocol);
if(s==-1) printf("error\n");
int status = connect(s, host_list->ai_addr, host_list->ai_addrlen);
if (status == -1) printf("connect error\n");
char *message="Hi there!";
send(s, message, 10, 0);
return 0;
}
I tried to change NULL in getaddrinfo to ip address but it always fail to connect
Which TCP/IP address are you trying to connect to, over the internet?
getaddrinfo() should have an IP address of some sort, or it won't know where to connect. It's like trying to send a letter in the mail without an address on it.
Furthermore, there are a LOT of reasons you might not be able to connect. Your firewall could be blocking something... there could be a firewall on the other end that's blocking something... AV software could even be detecting a connection that it thinks is "weird," and blocking it... the IP address could be wrong.
It'd be helpful for you to talk about the troubleshooting that you've done and what you're seeing.
I don't normally go to stackoverflow for sigsegv errors, but I have done all I can with my debugger at the moment.
The segmentation fault error is thrown following the completion of the function. Any ideas what I'm overlooking? I suspect that it is due to the casting of the sockaddr to the sockaddr_in, but I am unable to find any mistakes there. (Removing that line gets rid of the seg fault -- but I know that may not be the root cause here).
// basic setup
int sockfd;
char str[INET_ADDRSTRLEN];
sockaddr* sa;
socklen_t* sl;
struct addrinfo hints, *servinfo, *p;
int rv;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
// return string
string foundIP;
// setup the struct for a connection with selected IP
if ((rv = getaddrinfo("4.2.2.1", NULL, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return "1";
}
// loop through all the results and make a socket
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("talker: socket");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "talker: failed to bind socket\n");
return "2";
}
// connect the UDP socket to something
connect(sockfd, p->ai_addr, p->ai_addrlen); // we need to connect to get the systems local IP
// get information on the local IP from the socket we created
getsockname(sockfd, sa, sl);
// convert the sockaddr to a sockaddr_in via casting
struct sockaddr_in *sa_ipv4 = (struct sockaddr_in *)sa;
// get the IP from the sockaddr_in and print it
inet_ntop(AF_INET, &(sa_ipv4->sin_addr), str, INET_ADDRSTRLEN);
printf("%s\n", str);
// return the IP
return foundIP;
}
It doesn't look like you ever initialize the pointer sa to point at a valid sockaddr (or sockaddr_in) object.
If you replace
sockaddr* sa;
with
sockaddr addr;
and replace all uses of sa with &addr you should be in better shape.
The same is also true of sl. At least according to the documentation for my getsockname the socklen_t* parameter needs to point at a valid socklen_t object initialized to the size in bytes of the address buffer.
E.g.
socklen_t slen = sizeof addr;
and use &slen instead of sl.
It looks to me like you don't ever set up the sa pointer to actually point at anything. Commenting out the line "struct sockaddr_in *sa_ipv4 = (struct sockaddr_in *)sa;" should cause a compile error, so I guess I can see how not being able to compile your program would also cause it to not segfault - hard for a non-existent binary to crash :)
just to add, valgrind is pretty useful in detecting uninitialized pointers or for that matter any pointer related errors.
You did not allocate sa before passing it to getsockname, so you effectively passed in some garbage pointer value there. It needs to be:
struct sockaddr_in sa;
socklen_t sl;
...
getsockname(sockfd, (struct sockaddr*)&sa, &sl);
...