diff --git a/src/chat_system.c b/src/chat_system.c index 8fe0aa5..87e7506 100644 --- a/src/chat_system.c +++ b/src/chat_system.c @@ -88,25 +88,58 @@ void raw(char *fmt, ...) { write(chat_socket, sbuf, strlen(sbuf)); } -int hostname_to_ip(char * hostname , char* ip) { - struct hostent *he; - struct in_addr **addr_list; - int i; +int hostname_to_ip6(char * hostname , char* ip) { + struct addrinfo hints, *res, *p; + int status; + struct sockaddr_in6 *ipv6; - if ( (he = gethostbyname( hostname ) ) == NULL) - { - // get the host info - return 1; - } + memset(&hints, 0, sizeof(hints)); - addr_list = (struct in_addr **) he->h_addr_list; + hints.ai_family = AF_INET6; + hints.ai_socktype = SOCK_STREAM; - for(i = 0; addr_list[i] != NULL; i++) { - strcpy(ip , inet_ntoa(*addr_list[i]) ); - return 0; + if ((status = getaddrinfo(hostname, NULL, &hints, &res)) != 0) { + dolog("getaddrinfo: %s\n", gai_strerror(status)); + return 1; } - return 1; + for (p=res; p!= NULL; p=p->ai_next) { + if (p->ai_family == AF_INET6) { + ipv6 = (struct sockaddr_in6 *)p->ai_addr; + inet_ntop(p->ai_family, &(ipv6->sin6_addr), ip, INET6_ADDRSTRLEN); + freeaddrinfo(res); + return 0; + } + } + freeaddrinfo(res); + return 1; +} + +int hostname_to_ip(char * hostname , char* ip) { + struct addrinfo hints, *res, *p; + int status; + struct sockaddr_in *ipv4; + + memset(&hints, 0, sizeof(hints)); + + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + + if ((status = getaddrinfo(hostname, NULL, &hints, &res)) != 0) { + dolog("getaddrinfo: %s\n", gai_strerror(status)); + return 1; + } + + for (p=res; p!= NULL; p=p->ai_next) { + if (p->ai_family == AF_INET) { + ipv4 = (struct sockaddr_in *)p->ai_addr; + inet_ntop(p->ai_family, &(ipv4->sin_addr), ip, INET_ADDRSTRLEN); + freeaddrinfo(res); + return 0; + } + } + freeaddrinfo(res); + return 1; } void append_screenbuffer(char *buffer) { @@ -209,6 +242,7 @@ void append_screenbuffer(char *buffer) { void chat_system(struct user_record *user) { struct sockaddr_in servaddr; + struct sockaddr_in6 servaddr6; fd_set fds; int t; int ret; @@ -236,6 +270,8 @@ void chat_system(struct user_record *user) { int z; int y; int last_color = 7; + int chat_connected = 0; + if (sshBBS) { chat_in = STDIN_FILENO; } else { @@ -256,23 +292,75 @@ void chat_system(struct user_record *user) { s_putstring(get_string(50)); s_putstring("\e[24;1H"); - memset(&servaddr, 0, sizeof(struct sockaddr_in)); - servaddr.sin_family = AF_INET; - servaddr.sin_port = htons(conf.mgchat_port); - - - if ( (chat_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - return; - } - if (inet_pton(AF_INET, conf.mgchat_server, &servaddr.sin_addr) != 1) { - hostname_to_ip(conf.mgchat_server, buffer); - if (!inet_pton(AF_INET, buffer, &servaddr.sin_addr)) { - return; + if (conf.ipv6) { + memset(&servaddr6, 0, sizeof(struct sockaddr_in6)); + if (inet_pton(AF_INET6, conf.mgchat_server, &servaddr6.sin6_addr) != 1) { + if (!hostname_to_ip6(conf.mgchat_server, buffer)) { + if (!inet_pton(AF_INET6, buffer, &servaddr6.sin6_addr)) { + chat_connected = 0; + } else { + servaddr6.sin6_family = AF_INET6; + servaddr6.sin6_port = htons(conf.mgchat_port); + if ( (chat_socket = socket(AF_INET6, SOCK_STREAM, 0)) < 0) { + chat_connected = 0; + } else { + if (connect(chat_socket, (struct sockaddr*)&servaddr6, sizeof(servaddr6)) < 0 ) { + chat_connected = 0; + } else { + chat_connected = 1; + } + } + } + } else { + chat_connected = 0; + } + } else { + servaddr6.sin6_family = AF_INET6; + servaddr6.sin6_port = htons(conf.mgchat_port); + if ( (chat_socket = socket(AF_INET6, SOCK_STREAM, 0)) < 0) { + chat_connected = 0; + } else { + if (connect(chat_socket, (struct sockaddr*)&servaddr6, sizeof(servaddr6)) < 0 ) { + chat_connected = 0; + } else { + chat_connected = 1; + } + } } - } - if (connect(chat_socket, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0 ) { - return; - } + } + + if (!chat_connected) { + memset(&servaddr, 0, sizeof(struct sockaddr_in)); + if (inet_pton(AF_INET, conf.mgchat_server, &servaddr.sin_addr) != 1) { + if (!hostname_to_ip(conf.mgchat_server, buffer)) { + if (!inet_pton(AF_INET, buffer, &servaddr.sin_addr)) { + return; + } else { + servaddr.sin_family = AF_INET; + servaddr.sin_port = htons(conf.mgchat_port); + if ( (chat_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + return; + } + if (connect(chat_socket, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0 ) { + return; + } + } + } else { + return; + } + } else { + servaddr.sin_family = AF_INET; + servaddr.sin_port = htons(conf.mgchat_port); + if ( (chat_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + return; + } + if (connect(chat_socket, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0 ) { + return; + } + } + } + + memset(buffer, 0, 513); diff --git a/utils/magichat/main.c b/utils/magichat/main.c index c046858..8646f86 100644 --- a/utils/magichat/main.c +++ b/utils/magichat/main.c @@ -39,8 +39,9 @@ static int jsoneq(const char *json, jsmntok_t *tok, const char *s) { int main(int argc, char **argv) { int port; - int server_socket; + int server_socket, server_socket6; struct sockaddr_in server, client; + struct sockaddr_in6 server6, client6; fd_set master, read_fds; int fdmax; int c; @@ -55,12 +56,18 @@ int main(int argc, char **argv) { int r; int nbytes; FILE *fptr; - + int ipv6 = 0; + int on = 1; + if (argc < 2) { - printf("Usage: magichat [port]\n"); + printf("Usage: magichat [port] [ipv6(true/false)]\n"); return 0; } + if (argc > 2 && strcasecmp(argv[2], "true") == 0) { + ipv6 = 1; + } + port = atoi(argv[1]); if (port <= 1024 && port > 65535) { @@ -68,12 +75,44 @@ int main(int argc, char **argv) { return 0; } + FD_ZERO(&master); + + if (ipv6) { + server_socket6 = socket(AF_INET6, SOCK_STREAM, 0); + if (server_socket6 == -1) { + fprintf(stderr, "Couldn't create socket (ipv6)..\n"); + exit(1); + } + + if (setsockopt(server_socket6, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) { + fprintf(stderr, "setsockopt(SO_REUSEADDR) failed"); + exit(1); + } + if (setsockopt(server_socket6, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&on, sizeof(on)) < 0) { + fprintf(stderr, "setsockopt(IPV6_V6ONLY) failed"); + } + + server6.sin6_family = AF_INET6; + server6.sin6_addr = in6addr_any; + server6.sin6_port = htons(port); + + if (bind(server_socket6, (struct sockaddr *)&server6, sizeof(server6)) < 0) { + perror("Bind Failed, Error\n"); + exit(1); + } + + listen(server_socket6, 3); + FD_SET(server_socket6, &master); + } server_socket = socket(AF_INET, SOCK_STREAM, 0); if (server_socket == -1) { fprintf(stderr, "Couldn't create socket..\n"); exit(1); } - + if (setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) { + fprintf(stderr, "setsockopt(SO_REUSEADDR) failed"); + exit(1); + } server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons(port); @@ -84,12 +123,19 @@ int main(int argc, char **argv) { } listen(server_socket, 3); - FD_ZERO(&master); - FD_SET(server_socket, &master); - fdmax = server_socket; - c = sizeof(struct sockaddr_in); + if (ipv6) { + if (server_socket6 > server_socket) { + fdmax = server_socket6; + } else { + fdmax = server_socket; + } + } else { + fdmax = server_socket; + } + + while (1) { @@ -102,6 +148,7 @@ int main(int argc, char **argv) { for(i = 0; i <= fdmax; i++) { if (FD_ISSET(i, &read_fds)) { if (i == server_socket) { + c = sizeof(struct sockaddr_in); new_fd = accept(server_socket, (struct sockaddr *)&client, (socklen_t *)&c); if (new_fd == -1) { perror("accept"); @@ -134,7 +181,42 @@ int main(int argc, char **argv) { if (new_fd > fdmax) { fdmax = new_fd; } - } + } + } else if (ipv6 && i == server_socket6) { + c = sizeof(struct sockaddr_in6); + new_fd = accept(server_socket6, (struct sockaddr *)&client6, (socklen_t *)&c); + if (new_fd == -1) { + perror("accept"); + } else { + if (client_count == 0) { + clients = (struct client **)malloc(sizeof(struct client *)); + } else { + clients = (struct client **)realloc(clients, sizeof(struct client *) * (client_count + 1)); + } + + if (!clients) { + fprintf(stderr, "Out of memory!\n"); + return -1; + } + + clients[client_count] = (struct client *)malloc(sizeof(struct client)); + + if (!clients[client_count]) { + fprintf(stderr, "Out of memory!\n"); + return -1; + } + + sprintf(clients[client_count]->bbstag, "UNKNOWN"); + sprintf(clients[client_count]->nick, "UNKNOWN"); + clients[client_count]->fd = new_fd; + + client_count++; + + FD_SET(new_fd, &master); + if (new_fd > fdmax) { + fdmax = new_fd; + } + } } else { if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) { for (k=0;knick, clients[k]->bbstag); for (j=0;j<=fdmax;j++) { if (FD_ISSET(j, &master)) { - if (j != server_socket && j != clients[k]->fd) { - if (send(j, buffer, strlen(buffer), 0) == -1) { - perror("send"); + if (ipv6) { + if (j != server_socket && j != server_socket6 && j != clients[k]->fd) { + if (send(j, buffer, strlen(buffer), 0) == -1) { + perror("send"); + } } + } else { + if (j != server_socket && j != clients[k]->fd) { + if (send(j, buffer, strlen(buffer), 0) == -1) { + perror("send"); + } + } } } }