Identifying the problems with connect( ) - c

I have been working on a proxy server. It has to connect to another "monitor" program and get connection address information from that program. That program in running on a known ip and port. If I use the following to connect it works fine:
struct hostent *serv;
int sockfd;
struct sockaddr_in serv_addr;
serv = gethostbyname("localhost");
sockfd = socket(AF)INET, SOCK_STREAM, 0);
if (sockfd < 0)
/* Error handling */
bzero((char *) &serv_addr, sizeof (serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *) server->h_addr, (char *) &serv_addr.sin_addr.s_addr, server->h_length);
serv_addr.sin_port = htons(portno); // portno is an int holding the port number
if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
/* error handling */
However I wanted to use the exact ip address instead of local host, they may not alway be on the same machine, and gethostbyname () is obsolete. I attempted to use getaddrinfo() like this:
struct addrinfo hints, *server;
int sockfd, i;
char *host = "192.168.2.4";
char *port = "4044";
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = 0;
hints.ai_protocol = IPPROTO_TCP; // have also tried it with 0
i = getaddrinfo(host, port, &hints, &server);
if (i != 0)
/* Error handling */
sockfd = socket(server->ai_family, server->ai_socktype, server->ai_protocol);
freeaddrinfo (server); // have also tried without this line
if (sockfd < 0)
/* Error handling */
printf("Attempting to connect\n");
if (connect(sockfd, server->ai_addr, server->ai_addrlen) != -1)
/* Error handling */
printf("Connection attempt complete\n");
This second attempt hangs for a long time on the connect() command and finally returns in error. I have gone over the examples in several places and searched previous questions here on stackoverflow but can't find the problem, or why one works and the other doesn't. I think it has something to do with the server->ai_addr value but have not been able to verify it yet.
Any help would be appreciated, am I doing something obviously wrong? I don't know where else to look for more ideas to check.
EDIT UPDATE:
I have figured out one problem. In the line if (connect (/* */) != -1)
it should have been != 0. One of the samples I was looking at used a bind() statement instead. If I use the local host address with the second may it will work with that change. However I still can't connect to a specific ip address node. I am beginning to suspect that the ip address I was given isn't one that this computer can receive network traffic on. I am not sure how to check that though. I will see If I can figure out any more info on the error with using the specific ip address and edit again with the information.
EDIT UPDATE: I added #include and tried to print out the error code after the system call returns. I also printed out the return. It returns a -1 which according to the documentation I found just means an error occurred when I try to print out the errno it seg faults.
fprintf(stderr, "Error Code %s\n", errno); // seg faults
However changing it to:
fprintf(stderr, "Error Code %d\n", errno); // returns Error Code 60

Try to replace
hints.ai_flags = 0;
with
hints.ai_flags = AI_NUMERICHOST;
and see what happens.

The ip address that I was given is not the ip on the computer I am using. I finally decided that the ip address had to be the problem. I found the ip address on my computer and got the server program to bind to it. I also put it in as the ip address for the code included above instead of local host and it was able to connect regardless of rather the server was on that specific ip address or simply connected to INADDR_ANY.

Related

Bind C language for windows

I'm having trouble to use bind method on Windows (C language). Well. My code is supposed to do the following things:
get 2 addresses from the user: One must be an ip address from the local machine and another a remote address ( a google address for example).
The application i'm writing will bind to the local address
The application will connect to the second address.
I got some code from the Internet. You can see all the sources i had consulted on the comments.
This application will only accepts a string from the client (which specifies the local
address which the application will bind), then, the app will connect to a remote service
google, youtube or whatever. The main purpose that this app serves is to know if, when
binded to a local address, the operative system (in this case Windows Based system) gives priority to:
- SA/DA rule
- Forwarding table
SOURCES:
http://stackoverflow.com/questions/2065495/using-a-specific-network-interface-for-a-socket-in-windows
http://stackoverflow.com/questions/2605182/when-binding-a-client-tcp-socket-to-a-specific-local-port-with-winsock-so-reuse
http://www.delta-search.com/?q=error+on+binding+to+local+address%2Cwindows&s=web&as=0&rlz=0&babsrc=HP_ss
http://social.msdn.microsoft.com/Forums/zh/vcgeneral/thread/763a00ab-0e7f-44c6-9794-840fc6cb2e07
http://www.delta-search.com/?q=add+ws2_32.lib+visual+studio+2010&babsrc=HP_ss&s=web&rlz=0&as=3&ac=0%2C331
http://stackoverflow.com/questions/5220309/why-am-i-getting-linker-errors-for-ws2-32-dll-in-my-c-program
http://msdn.microsoft.com/en-US/windows/desktop/aa904949
http://msdn.microsoft.com/en-us/library/windows/desktop/ms737550(v=vs.85).aspx
#pragma once
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#include <Ws2tcpip.h>
#include <stdio.h>
void Abort(char *msg);
void main(int argc,char*argv[]){
int ret, fd;
struct sockaddr_in sa_dst;
struct sockaddr_in sa_loc;
if(argc < 3)
Abort("Syntax: SourceIpAddress(to bind) DestinationIpAddress(to connect)");
fd = socket(AF_INET, SOCK_STREAM, 0);
// Local
memset(&sa_loc, 0, sizeof(struct sockaddr_in));
sa_loc.sin_family = AF_INET;
sa_loc.sin_port = htons(0);
sa_loc.sin_addr.s_addr = inet_addr(argv[1]);
if((ret = bind(fd, (struct sockaddr *)&sa_loc, sizeof(struct sockaddr))) < 0)
Abort("Binding to local address");
// Remote
memset(&sa_dst, 0, sizeof(struct sockaddr_in));
sa_dst.sin_family = AF_INET;
sa_dst.sin_port = htons(80);
sa_dst.sin_addr.s_addr = inet_addr(argv[2]); // google :)
if((ret = connect(fd, (struct sockaddr *)&sa_dst, sizeof(struct sockaddr))) < 0)
Abort("Connect to remote address");
printf("\n\nConnection Successfully made!!\n\n"); }
void Abort(char *msg){
fprintf(stderr,"\n\n<ERROR>: <%s>\n",msg);
perror("\n\nExiting...");
exit(EXIT_FAILURE); }
The problem is that bind returns -1. I've tested already.
Can anyone help me on this?
Thanks in advance
When a Winsock function fails, you can call WSAGetLastError() to find out why.
In this case, you are not calling WSAStartup(), so socket() fails with a WSANOTINITIALISED error that you are ignoring, so you end up passing an invalid socket to bind().

Unix C socket server not accepting connections

Here's the deal, I'm writing a simple tcp socket server in C (with unix system calls) that I'm not able to get to accept connections.
From what I can tell, I get through the server initialization just fine, but when I try to connect to the port that I print out (see code below) it refuses as if nothing is there.
More to the point, when I netstat that port isn't even in use. I'm not throwing any errors with my current set up, I'm all dried up for ideas.
int main(){
int sock_fd;
int conn_fd;
struct sockaddr_in serv_addr;
struct sockaddr_in cli_addr;
socklen_t* serlen;
socklen_t* clilen;
clilen = malloc(sizeof(socklen_t));
serlen = malloc(sizeof(socklen_t));
*serlen = sizeof(serv_addr);
*clilen = sizeof(cli_addr);
/*=============================Create Socket=============================*/
//Create Socket
sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if(sock_fd<0){
fprintf(stderr,"error creating socket\n");
exit(1);}
//Initialize Server Address Struct
bzero((char *) &serv_addr, *serlen);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = 0;
/*=============================Bind Address==============================*/
//Bind socket to an address
if(bind(sock_fd,(struct sockaddr*)&serv_addr,*serlen)<0){
fprintf(stderr,"error binding\n");
exit(1);}
//Get socket data
if(getsockname(sock_fd,(struct sockaddr*)&serv_addr, serlen)<0){
fprintf(stderr,"error with socket name");
exit(1);}
/*=============================Server Started============================*/
//Listen for connections
listen(sock_fd,32);
//Print port
printf("%i", serv_addr.sin_port);
conn_fd = accept(sock_fd,(struct sockaddr*)&cli_addr,clilen);
/**Do something exciting with my new connection**/
}
Are you really trying to listen on port zero? Try a high port number, preferably > 1024. /etc/services will give a hint about free ports - but it only a set of comments, those port numbers are not enforced.
Edit: another hint. The port number should be in network order, so the assignment should use htons(). It could be that the "random numbers" you are getting are simple numbers that appear garbled because you might be on a little-endian machine (like Intel). When you print them, convert them back using ntohs().
props to #askmish for inspiring this one
//Print port
printf("%i", serv_addr.sin_port);
becomes
//Print port
printf("%i", htons(serv_addr.sin_port));
In your code:
Instead of:
serv_addr.sin_port = 0;
try this:
serv_addr.sin_port=htons(2056);//Any port no.
Instead of:
listen(sock_fd,32);
try this:
if(listen(sock_fd,SOMAXCONN)<0)//Just to be sure that you are considering max. no. of requests
{ fprintf(stderr,"error with listen");
exit(1);}
Also for:
conn_fd = accept(sock_fd,(struct sockaddr*)&cli_addr,clilen);
Add this:
if(conn_fd <0)
{
//handle the error here
}
If none of these solve your issues, then, there might be problem with the client code or your server environment.

how to connect to a bit torrent tracker in c

I am tying to connect to a bit torrent tracker, http://tracker.thepiratebay.org. The gethostbyname() keeps returning null, how should I fix this? Also do you see anything else wrong with this code?
int sock;
struct sockaddr_in servAddr;
int portNum = 80;
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0){
printf("fail create socket");
return 0;
}
char *path = "http://tracker.thepiratebay.org/";
struct hostent *hp = gethostbyname(path);
if(hp==NULL){
printf("null");
else{
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
memcpy( (char *) &servAddr.sin_addr.s_addr, (char *) hp->h_addr, hp->h_length );
servAddr.sin_port = htons(portNum);
}
//send request to tracker server
if (send(sock, requestToSend, strlen(requestToSend), 0) != strlen(requestToSend)){
printf("fail send");
return 0;
}
The problem here is that http://tracker.thepiratebay.org/ is a URL, but gethostbyname() expects just the host name. The host name is tracker.thepiratebay.org.
It would make it much easier if you just use libcurl, which will handle all of that HTTP stuff for you. It is extremely common to use libcurl in applications that connect to HTTP servers; it is an excellent library. It's certainly easier than socket programming.
Use getaddrinfo()
The modern alternative to gethostbyname() is getaddrinfo(). It's not that gethostbyname() doesn't do what you want, rather, getaddrinfo() is simply better in every conceivable way.
struct addrinfo hint, *ap;
memset(&hint, 0, sizeof(hint));
hint.ai_family = AF_UNSPEC;
hint.ai_socktype = SOCK_STREAM;
int r = getaddrinfo("tracker.thepiratebay.org", "http", &hint, &ap);
This will not only get you the address for the host you want, but it will also fill in the port number. You can use "http" as the port, or you can use "80" for the port, they are the same thing (as long as /etc/services has the right entry).
Other problems
This line is wrong.
memcpy( (char *) &servAddr.sin_addr.s_addr, (char *) hp->h_addr, hp->h_length );
You don't know that gethostbyname() returned an IPv4 address, and it is foolish to try and copy it into a struct sockaddr_in. If gethostbyname() returned an IPv6 address, you have just smashed your stack and your program will crash -- or worse, it might not crash.
Either check that it returns an IPv4 address, or simply copy hp->h_addr into a generic struct sockaddr that was returned from malloc(hp->h_length). This is a bit ugly but it's the way it goes.
Finally, it is wrong to cast the arguments to memcpy(). It's not an error, but it's wrong. Don't do it, it can cause otherwise legitimate compiler errors to be suppressed, e.g., if you accidentally cast an int to char *.

How to re bind a udp socket in Linux

I am an experienced Linux socket programmer and am writing a server application which has many outgoing interfaces. Now server socket binds to a random source port in the start of the process along with INADDR_ANY.
Later at some point when submitting response to a specific node, i need to assign a fixed source ip address. The standard way to do this is calling bind. However, bind is called once for the port number, successive calls fail with invalid argument error.
Creating a new socket is not really a good choice since i will have to be doing this very often upon responding to some clients.
I have also explored SO and a lot of socket options such as IP_FREEBIND, but it doesn't quite suite my scenario.
Perhaps using IP_PKT_INFO and setting source address might work unless it suffers the same problem i.e. not allowing a socket once bound to INADDRANY to rebind to a fixed source ip latter.
Is there a way to unbind an existing socket or an alternate way to setting source ip address in outgoing packet?
int sock = socket(AF_INET, SOCK_DGRAM, 0);
if(sock < 0)
printf("Failed creating socket\n");
struct sockaddr_in addr;
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons(1500);
addr.sin_addr.s_addr = INADDR_ANY;
// first bind succeeds
if ( (status = bind(sock, (struct sockaddr *) &addr, sizeof(addr))) < 0)
printf("bind error with port %s\n", strerror(errno));
struct sockaddr_in src_addr;
memset(&src_addr, 0, sizeof(struct sockaddr_in));
src_addr.sin_family = AF_INET;
if (inet_aton("10.0.2.17", &(src_addr.sin_addr)) == 0)
printf("Failed copying address\n");
// second bind fails
if((status = bind(sock, (struct sockaddr *)&src_addr, sizeof(src_addr))) < 0)
printf("re bind error with ip %s\n", strerror(errno));
Any ideas in this regard will be highly appreciated. I have gone through considerable material on sockets, SO etc. but no success yet.
I finally found the solution myself so accepting my own answer (shameless but correct plugin), supplemented with code sample.
I originally wanted to rewrite source address of an outgoing packet without creating the socket again where the socket was already bound. Calling bind multiple times fail for this case, and (in my particular situation), i was not able to just have separate sockets for each source ip and use it.
I found some references in IP_PACKET_INFO but it was a pain to get it to work correctly. Following reference was helpful.
Setting source of udp socket
Sample Code
Here is a trivial application which creates a udp socket, binds it to a local port, then before sending a particular message, it appends the outgoing source ip address. Keeping in mind that in my case, i created a sudo interface and assigned it another ip. The send call will fail if this is not the case.
int status=-1;
int sock = socket(AF_INET, SOCK_DGRAM, 0);
if(sock < 0)
printf("Failed creating socket\n");
int opt = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
struct sockaddr_in bind_addr;
memset(&bind_addr, 0, sizeof(struct sockaddr_in));
bind_addr.sin_family = AF_INET;
bind_addr.sin_port = htons(44000); // locally bound port
if((status = bind(sock, (struct sockaddr *)&bind_addr, sizeof(bind_addr))) < 0)
printf("bind error with port %s\n", strerror(errno));
// currently using addr as destination
struct sockaddr_in addr;
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons(80); // destination port
if (inet_aton("74.125.236.35", &(addr.sin_addr)) == 0)
printf("Failed copying remote address\n");
else
printf("Success copying remote address\n");
struct sockaddr_in src_addr;
memset(&src_addr, 0, sizeof(struct sockaddr_in));
src_addr.sin_family = AF_INET;
if (inet_aton("10.0.2.17", &(src_addr.sin_addr)) == 0)
printf("Failed copying src address\n");
else
printf("Success copying src address\n");
char cmbuf[CMSG_SPACE(sizeof(struct in_pktinfo))];
char msg[10] = "hello";
int len = strlen(msg);
struct msghdr mh;
memset(&mh, 0, sizeof(mh));
struct cmsghdr *cmsg;
struct in_pktinfo *pktinfo;
struct iovec iov[1];
iov[0].iov_base = msg;
iov[0].iov_len = len;
mh.msg_name = &addr; // destination address of packet
mh.msg_namelen = sizeof(addr);
mh.msg_control = cmbuf;
mh.msg_controllen = sizeof(cmbuf);
mh.msg_flags = 0;
mh.msg_iov = iov;
mh.msg_iovlen = 1;
// after initializing msghdr & control data to
// CMSG_SPACE(sizeof(struct in_pktinfo))
cmsg = CMSG_FIRSTHDR(&mh);
cmsg->cmsg_level = IPPROTO_IP;
cmsg->cmsg_type = IP_PKTINFO;
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
pktinfo = (struct in_pktinfo*) CMSG_DATA(cmsg);
//src_interface_index 0 allows choosing interface of the source ip specified
pktinfo->ipi_ifindex = 0;
pktinfo->ipi_spec_dst = src_addr.sin_addr;
int rc = sendmsg(sock, &mh, 0);
printf("Result %d\n", rc);
The key statement is
pktinfo->ipi_spec_dst = src_addr.sin_addr;
where we are specifying the source ip address to be used. The rest of things like cmsg struct etc. are merely used in order to be able to write ipoktinfo struct ourselves
There is no way to unbind and rebind an existing socket.
Why don't you create a socket for each interface instead? Since the UDP/IP protocol is connectionless, you can choose the source IP address by choosing which socket you use to send the reply with; there is no need to use the same socket the incoming datagram was received on.
The downsides are that you can no longer bind to the wildcard address, and you must use select(), poll(), multiple threads, or some other mechanism to receive datagrams from multiple sources concurrently. You'll also need some logic to efficiently pick the socket based on the client IP address.
In most cases, I suspect that adding a few route entries to route each remote IP address to the desired host IP address, and using a separate socket for each host IP address and port combination, solves the issues perfectly -- and using the very efficient kernel functionality to do so. While the behaviour may be an application requirement, I suspect it is better solved using the network interface configuration instead. Unfortunately, often the requirements are written by semi-functional idiots better suited for manual labor, and your hands are tied.. if so, I commiserate.
If you have a test network with workstations having multiple physical network interfaces, I can provide a simple example C99 test program you can use to verify the design works.

Execute two local socket servers simultaneously in C

I'm trying to simulate a DHCP server as a university task. It's required to execute at least 2 servers (or more up to 255) since several clients will be sending messages to these servers using BROADCAST (that's where the limit of 'only' 255 servers comes from).
But when I'm trying to execute 2 servers in 2 different terminals in Ubuntu, the second server executed is rejected. I guess it's due to IP at the same localhost or whatever (I'm sorry but I don't know too much about communication protocols)
How can I run several servers on the same machine? Our teacher told us about using VMWare to run another Linux OS, and try to run both, but for me this solution is far away from my thoughts... I will post the server and client connection statements, although I don't know if there's a problem with the C statements, or the OS configuration, etc.
Server:
int sockfd, newsockfd, clilen, n;
struct sockaddr_in cli_addr, serv_addr ;
char host_name[200];
int size = sizeof(struct DHCP);
char buffer[size];
struct MACIP *macip;
if ((sockfd = socket(AF_INET, SOCK_DGRAM,0)) < 0) {
printf("server: can't open datagram socket\n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(0);
serv_addr.sin_port = htons(SERV_UDP_PORT);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) <0) {
printf("server: can't bind local address\n");
return -1;
}
Client:
int sockfd, n, clilen;
struct sockaddr_in serv_addr, cli_addr;
char serv_host_addr[30];
int size = sizeof(struct DHCP);
char buffer[size];
printf("Dirección IP del servidor (a.b.c.d) => ");
gets(serv_host_addr);
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("client: can't open datagram socket");
return -1;
}
int opt=1;
if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST,&opt, sizeof(opt))<0) {
perror("Error opcion socket");
close(sockfd);
return 1;
}
bzero((char *)&cli_addr,sizeof(cli_addr));
cli_addr.sin_family = AF_INET;
if (bind(sockfd, (struct sockaddr *) &cli_addr,sizeof(cli_addr)) < 0) {
perror("client: can't bind a port");
return -1;
}
serv_addr.sin_family = AF_INET;
inet_pton(AF_INET, serv_host_addr,&serv_addr.sin_addr);
//serv_addr.sin_addr.s_addr = inet_addr(serv_host_addr);
serv_addr.sin_port = htons(SERV_UDP_PORT);
Thank you very much in advance.
Every instance of your UDP server must listen on another port. Key line in your code is this:
serv_addr.sin_port = htons(SERV_UDP_PORT);
Looks like you have the port number as a constant (SERV_UDP_PORT). To make multiple servers run at the same time you need another port for each one.
Probably best solution in your case is to have a command line argument that would define the port on which you start your server.
Each client needs to know which port (and address of course) to connect to as well. So make your client to accept similar command line argument.
To run multiple servers, they should listen on different ports on same network interface. You may get away by using two network interfaces (say wifi and ethernet) on same network with different ips.
You might try to set up alias interfaces on an existing interface. Such alias interfaces then get their own ip address each.
Using the loopback interface (lo), which typical has 127.0.0.1 assigned, such aliases to this interface could then be called lo:0, lo:1 ... and would carry the ip addresses 127.0.0.2, 127.0.0.3, ....
For details on how to achieve this see man ifconfig.

Resources