I'm trying to run a simple C program which uses the bind() function to bind a IPv4/IPv6 address to a socket.
Below is the code:
int main(int argc, char *argv[])
{
int socket_fd = -1, addrlen = 0, af;
struct sockaddr_storage addr = {0};
unsigned connections = 0;
pthread_t workers[WORKER_NUM] = { 0 };
int client_sock_fds[WORKER_NUM] = { 0 };
char ip_string[64];
if (argc > 1 && strcmp(argv[1], "inet6") == 0) {
af = AF_INET6;
init_sockaddr_inet6((struct sockaddr_in6 *)&addr);
}
else {
af = AF_INET;
init_sockaddr_inet((struct sockaddr_in *)&addr);
}
printf("[Server] Create socket\n");
socket_fd = socket(af, SOCK_STREAM, 0);
if (socket_fd < 0) {
perror("Create socket failed");
goto fail;
}
printf("[Server] Bind socket\n");
addrlen = sizeof(addr);
if (bind(socket_fd, (struct sockaddr *)&addr, addrlen) < 0) {
perror("Bind failed");
goto fail;
}
printf("[Server] Listening on socket\n");
if (listen(socket_fd, 3) < 0) {
perror("Listen failed");
goto fail;
}
printf("[Server] Wait for clients to connect ..\n");
while (connections < WORKER_NUM) {
client_sock_fds[connections] =
accept(socket_fd, (struct sockaddr *)&addr, (socklen_t *)&addrlen);
if (client_sock_fds[connections] < 0) {
perror("Accept failed");
break;
}
if (sockaddr_to_string((struct sockaddr *)&addr, ip_string,
sizeof(ip_string) / sizeof(ip_string[0]))
!= 0) {
printf("[Server] failed to parse client address\n");
goto fail;
}
printf("[Server] Client connected (%s)\n", ip_string);
if (pthread_create(&workers[connections], NULL, run,
&client_sock_fds[connections])) {
perror("Create a worker thread failed");
shutdown(client_sock_fds[connections], SHUT_RDWR);
break;
}
connections++;
}
if (connections == WORKER_NUM) {
printf("[Server] Achieve maximum amount of connections\n");
}
for (int i = 0; i < WORKER_NUM; i++) {
pthread_join(workers[i], NULL);
}
printf("[Server] Shuting down ..\n");
shutdown(socket_fd, SHUT_RDWR);
sleep(3);
printf("[Server] BYE \n");
return EXIT_SUCCESS;
fail:
printf("[Server] Shuting down ..\n");
if (socket_fd >= 0)
close(socket_fd);
sleep(3);
return EXIT_FAILURE;
}
static void
init_sockaddr_inet(struct sockaddr_in *addr)
{
/* 0.0.0.0:1234 */
addr->sin_family = AF_INET;
addr->sin_port = htons(1234);
addr->sin_addr.s_addr = htonl(INADDR_ANY);
}
static void
init_sockaddr_inet6(struct sockaddr_in6 *addr)
{
/* [::]:1234 */
addr->sin6_family = AF_INET6;
addr->sin6_port = htons(1234);
addr->sin6_addr = in6addr_any;
}
When this program is compiled and run on Linux it works without any errors. But when the same program is compiled and run on MacOS, the bind() function returns an "Invalid Argument" error.
I checked the man page for the bind() function to see what the possible reasons for this error could be. The three possible reasons were:
- The socket was already bound to another address
- The
addrlenvalue passed to the function is incorrect - The
addris not a valid address for this socket's domain
I was able to verify that it wasn't due to the first and third reason.
My question would be as to why does the addrlen value passed to the bind() function throw an "Incorrect argument" error when ran on a Unix system but works perfectly fine when ran on a Linux system?