|  | #include "tunala.h" | 
|  |  | 
|  | #ifndef NO_IP | 
|  |  | 
|  | #define IP_LISTENER_BACKLOG 511 /* So if it gets masked by 256 or some other | 
|  | such value it'll still be respectable */ | 
|  |  | 
|  | /* Any IP-related initialisations. For now, this means blocking SIGPIPE */ | 
|  | int ip_initialise(void) | 
|  | { | 
|  | struct sigaction sa; | 
|  |  | 
|  | sa.sa_handler = SIG_IGN; | 
|  | sa.sa_flags = 0; | 
|  | sigemptyset(&sa.sa_mask); | 
|  | if(sigaction(SIGPIPE, &sa, NULL) != 0) | 
|  | return 0; | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | int ip_create_listener_split(const char *ip, unsigned short port) | 
|  | { | 
|  | struct sockaddr_in in_addr; | 
|  | int fd = -1; | 
|  | int reuseVal = 1; | 
|  |  | 
|  | /* Create the socket */ | 
|  | if((fd = socket(PF_INET, SOCK_STREAM, 0)) == -1) | 
|  | goto err; | 
|  | /* Set the SO_REUSEADDR flag - servers act weird without it */ | 
|  | if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)(&reuseVal), | 
|  | sizeof(reuseVal)) != 0) | 
|  | goto err; | 
|  | /* Prepare the listen address stuff */ | 
|  | in_addr.sin_family = AF_INET; | 
|  | memcpy(&in_addr.sin_addr.s_addr, ip, 4); | 
|  | in_addr.sin_port = htons(port); | 
|  | /* Bind to the required port/address/interface */ | 
|  | if(bind(fd, (struct sockaddr *)&in_addr, sizeof(struct sockaddr_in)) != 0) | 
|  | goto err; | 
|  | /* Start "listening" */ | 
|  | if(listen(fd, IP_LISTENER_BACKLOG) != 0) | 
|  | goto err; | 
|  | return fd; | 
|  | err: | 
|  | if(fd != -1) | 
|  | close(fd); | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | int ip_create_connection_split(const char *ip, unsigned short port) | 
|  | { | 
|  | struct sockaddr_in in_addr; | 
|  | int flags, fd = -1; | 
|  |  | 
|  | /* Create the socket */ | 
|  | if((fd = socket(PF_INET, SOCK_STREAM, 0)) == -1) | 
|  | goto err; | 
|  | /* Make it non-blocking */ | 
|  | if(((flags = fcntl(fd, F_GETFL, 0)) < 0) || | 
|  | (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0)) | 
|  | goto err; | 
|  | /* Prepare the connection address stuff */ | 
|  | in_addr.sin_family = AF_INET; | 
|  | memcpy(&in_addr.sin_addr.s_addr, ip, 4); | 
|  | in_addr.sin_port = htons(port); | 
|  | /* Start a connect (non-blocking, in all likelihood) */ | 
|  | if((connect(fd, (struct sockaddr *)&in_addr, | 
|  | sizeof(struct sockaddr_in)) != 0) && | 
|  | (errno != EINPROGRESS)) | 
|  | goto err; | 
|  | return fd; | 
|  | err: | 
|  | if(fd != -1) | 
|  | close(fd); | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | static char all_local_ip[] = {0x00,0x00,0x00,0x00}; | 
|  |  | 
|  | int ip_parse_address(const char *address, const char **parsed_ip, | 
|  | unsigned short *parsed_port, int accept_all_ip) | 
|  | { | 
|  | char buf[256]; | 
|  | struct hostent *lookup; | 
|  | unsigned long port; | 
|  | const char *ptr = strstr(address, ":"); | 
|  | const char *ip = all_local_ip; | 
|  |  | 
|  | if(!ptr) { | 
|  | /* We assume we're listening on all local interfaces and have | 
|  | * only specified a port. */ | 
|  | if(!accept_all_ip) | 
|  | return 0; | 
|  | ptr = address; | 
|  | goto determine_port; | 
|  | } | 
|  | if((ptr - address) > 255) | 
|  | return 0; | 
|  | memset(buf, 0, 256); | 
|  | memcpy(buf, address, ptr - address); | 
|  | ptr++; | 
|  | if((lookup = gethostbyname(buf)) == NULL) { | 
|  | /* Spit a message to differentiate between lookup failures and | 
|  | * bad strings. */ | 
|  | fprintf(stderr, "hostname lookup for '%s' failed\n", buf); | 
|  | return 0; | 
|  | } | 
|  | ip = lookup->h_addr_list[0]; | 
|  | determine_port: | 
|  | if(strlen(ptr) < 1) | 
|  | return 0; | 
|  | if(!int_strtoul(ptr, &port) || (port > 65535)) | 
|  | return 0; | 
|  | *parsed_ip = ip; | 
|  | *parsed_port = (unsigned short)port; | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | int ip_create_listener(const char *address) | 
|  | { | 
|  | const char *ip; | 
|  | unsigned short port; | 
|  |  | 
|  | if(!ip_parse_address(address, &ip, &port, 1)) | 
|  | return -1; | 
|  | return ip_create_listener_split(ip, port); | 
|  | } | 
|  |  | 
|  | int ip_create_connection(const char *address) | 
|  | { | 
|  | const char *ip; | 
|  | unsigned short port; | 
|  |  | 
|  | if(!ip_parse_address(address, &ip, &port, 0)) | 
|  | return -1; | 
|  | return ip_create_connection_split(ip, port); | 
|  | } | 
|  |  | 
|  | int ip_accept_connection(int listen_fd) | 
|  | { | 
|  | return accept(listen_fd, NULL, NULL); | 
|  | } | 
|  |  | 
|  | #endif /* !defined(NO_IP) */ | 
|  |  |