Reputation: 320
I want to make a server that accepts both IPv4 and IPv6 on all interfaces.
It does not seems to work for any address including localhost, 127.0.0.1, ::1, 192.168.1.26. What am I missing?
According to getaddrinfo(3) since ai_family is set to the AI_PASSIVE flag. 'The returned socket address will contain the "wildcard address"'
Here is my code so far.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/times.h>
#include <errno.h>
#define MAXBUF 1024
const char* PORTNUM = "687";
int init_address(struct addrinfo* hints)
{
hints->ai_flags= AI_PASSIVE;
hints->ai_family= AF_UNSPEC;
hints->ai_socktype= SOCK_DGRAM;
hints->ai_protocol= IPPROTO_UDP;
return 1;
}
socklen_t init_socket(struct addrinfo* res, int* sockfd)
{
struct addrinfo* ressave;
struct sockaddr_in* all_interface;
socklen_t addrlength;
ressave=res;
all_interface = (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));
do {/* each of the returned IP address is tried*/
(*sockfd) = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if ((*sockfd)<0)
continue; /* fail, try next one*/
if (bind((*sockfd), (struct sockaddr*)all_interface, sizeof(all_interface)) == 0)
break; /*success*/
close(*sockfd);
}while(res->ai_next != NULL && (res = res->ai_next)!= NULL);
if(&addrlength)
addrlength = res->ai_addrlen;
freeaddrinfo(ressave);
free(all_interface);
return addrlength;
}
int doprocessing(char* buffer, size_t buff_size)
{
return 0;
}
int peak_data(char* buffer, size_t buff_size)
{
return 0;
}
int main(int argc, char const *argv[])
{
int sockfd, newsockfd;
int bytes_read;
char* port;
char buffer[MAXBUF];
pid_t pid;
socklen_t addrlen, len;
struct addrinfo* socket_info;
struct addrinfo* res;
struct addrinfo* backup_res;
struct sockaddr* cliaddr;
int n;
socket_info = (struct addrinfo*)malloc(sizeof(struct addrinfo));
res = (struct addrinfo*)malloc(sizeof(struct addrinfo));
memset(socket_info, 0, sizeof(struct addrinfo));
init_address(socket_info);
if((n = getaddrinfo(NULL, PORTNUM, socket_info, &res)) !=0)
{
printf("multi_server: error for %s: %s", PORTNUM, gai_strerror(n));
exit(0);
}
if ((addrlen = init_socket(res, &sockfd)) < 0)
{
printf("multi_server: Socket or Bind error");
exit(0);
}
free(socket_info);
cliaddr=malloc(addrlen);
len=addrlen;
printf("\nUDP Server: waiting for connection...");
while (1) {
bytes_read = recvfrom(sockfd, buffer, MAXBUF-1, MSG_PEEK, cliaddr, &len);
if (bytes_read > 0) {
// a connection has been established
buffer[MAXBUF] = '\0';
printf("\nUDP Server: received %d bytes ", bytes_read);
pid = fork();
if (pid < 0) {
perror("UDP Server: ERROR while forking new process.\n");
exit(1);
}
// check if the process ID is zero
if (pid == 0) {
// we are now inside the new forked process
if(peak_data(buffer, bytes_read))
{
doprocessing(buffer, bytes_read);
}
printf("Now in %d\n", pid);
close(sockfd);
exit(0);
}
}
}
}
Upvotes: 0
Views: 179
Reputation: 2842
You're not missing anything. It is accepting connections to ::1 you said? Then it will accept ipv6 connections. And since IPv6 is backwards compatible, if you've created the correct ipv6 socket, it should be able to send and receive ipv4 packets as well.
Upvotes: 1