Reputation: 501
Im trying to use sockets with C. Now Im writing server side software. My new connection handler:
int handle_new_connection(SOCKET *server_socket_descriptor, unsigned int *max_known_socket_descriptor, fd_set *main_socket_set)
{
const int yes = 1;
struct sockaddr_in remote_address;
SOCKET new_connection_socket_descriptor;
int address_size;
char buffer[1000] = {0};
struct hostent *host_entry;
address_size = sizeof(struct sockaddr_in);
if (SOCKET_ERROR == (new_connection_socket_descriptor = accept((*server_socket_descriptor), (struct sockaddr *)&remote_address, (socklen_t *)&address_size)))
{
return SOCKET_ERROR;
}
if ( SOCKET_ERROR == setsockopt(new_connection_socket_descriptor, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)))
{
return SOCKET_ERROR;
}
printf ("Server: new connection from \'%s\' accepted successfully.\n", inet_ntoa(remote_address.sin_addr));
unsigned long remote_address_size = sizeof(remote_address.sin_addr);
if (NULL == (host_entry = gethostbyaddr((void *)&(remote_address.sin_addr), (socklen_t)&(remote_address_size), AF_INET)))
{
closesocket (new_connection_socket_descriptor);
printf ("Server: new connection from \'%s\' was immediately closed because of gethostbyaddr() failure.\n", host_entry -> h_addr);
return SOCKET_ERROR;
}
printf("Been here!\n");
return 1;
}
When new user connects (via telnet) if
sentence if (NULL == (host_entry = gethostbyaddr((void *)&(remote_address.sin_addr), (socklen_t)&(remote_address_size), AF_INET)))
brings error: Segmentation fault: 11
. Also, this code works perfectly on Linux. My operating system is Mac OS X. How to solve this issue?
Upvotes: 0
Views: 4163
Reputation: 90531
You are passing the address of remote_address_size
as the len
parameter of gethostbyaddr()
. That parameter should not be an address, just a length value, directly.
Update:
Also, you may not be getting a struct sockaddr_in
from accept()
. For example, if the connection is an IPv6 connection, you would get a struct sockaddr_in6
. The safest approach would be to use a struct sockaddr_storage
.
Ideally, you should switch from gethostbyaddr()
to getnameinfo()
. The latter takes a struct sockaddr*
argument, to which you can supply the pointer to your struct sockaddr_storage
without having to care about what address family it actually contains. The man page has sample code.
If you want to keep using gethostbyaddr()
, you will need to examine the sa_family
field of the struct sockaddr_storage
. If it's AF_INET
, you should use &((struct sockaddr_in*)&remote_address)->sin_addr
as the first argument. If it's AF_INET6
, you should use &((struct sockaddr_in6*)&remote_address)->sin6_addr
. The second argument would be the size of the same field.
If the family is something else, you'll need to either look up how to handle that or return failure for a case not understood by your code.
Upvotes: 2