#include "sockets.h" // get sockaddr, IPv4 or IPv6: void *get_in_addr(struct sockaddr *sa) { if (sa->sa_family == AF_INET) { return &(((struct sockaddr_in*)sa)->sin_addr); } return &(((struct sockaddr_in6*)sa)->sin6_addr); } // Create socket to connect to real IRC server int createserversocket(char *host, char *port) { int sockfd; struct addrinfo hints, *servinfo, *p; int rv;// return value for getaddrinfo (for error message) char s[INET6_ADDRSTRLEN]; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; if ((rv = getaddrinfo(host, port, &hints, &servinfo)) != 0) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); return 1; } // loop through all the results and connect to the first we can for (p = servinfo; p != NULL; p = p->ai_next) { if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { perror("bouncer-server: socket"); continue; } if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) { close(sockfd); perror("bouncer-server: connect"); continue; } break; } if (p == NULL) { fprintf(stderr, "bouncer-server: failed to connect\n"); return 2; } inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr), s, sizeof s); printf("bouncer-server: connecting to %s\n", s); freeaddrinfo(servinfo); // all done with this structure return sockfd; } // Create listening socket to listen for bouncer client connections int createclientsocket(char *listenport) { listenport = BOUNCERLISTENPORT; int listener; // listening socket descriptor int rv; // return value for getaddrinfo (for error message) struct addrinfo hints, *ai, *p; int yes = 1; // for enabling socket options with setsockopt // get us a socket and bind it memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; if ((rv = getaddrinfo(NULL, listenport, &hints, &ai)) != 0) { fprintf(stderr, "bouncer-client: %s\n", gai_strerror(rv)); exit(1); } // Try for IPv6 for (p = ai; p != NULL; p = p->ai_next) { if (p->ai_family == AF_INET6) { listener = socket(p->ai_family, p->ai_socktype, p->ai_protocol); if (listener != -1) { // success, got IPv6! printf("success, got IPv6! ai_family: %d\n", p->ai_family); break; } } } // Try for IPv4 if IPv6 failed if (listener < 0) { for (p = ai; p != NULL; p = p->ai_next) { if (p->ai_family == AF_INET) { listener = socket(p->ai_family, p->ai_socktype, p->ai_protocol); if (listener != -1) { // moderate success, got IPv4! printf("moderate success, got IPv4! ai_family: %d\n", p->ai_family); break; } } } } // allow address re-use setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); // 1 as in non-zero as in enable if (bind(listener, p->ai_addr, p->ai_addrlen) < 0) { // failed to bind close(listener); printf("bouncer-client: failed to bind, exiting...\n"); exit(1); } // if we got here, it means we didn't get bound if (p == NULL) { fprintf(stderr, "bouncer-client: failed to bind\n"); exit(2); } freeaddrinfo(ai); // all done with this // listen if (listen(listener, BACKLOG) == -1) { perror("listen"); exit(1); } return listener; }