1#include "tunala.h" 2 3#ifndef NO_IP 4 5#define IP_LISTENER_BACKLOG 511 /* So if it gets masked by 256 or some other 6 such value it'll still be respectable */ 7 8/* Any IP-related initialisations. For now, this means blocking SIGPIPE */ 9int ip_initialise(void) 10{ 11 struct sigaction sa; 12 13 sa.sa_handler = SIG_IGN; 14 sa.sa_flags = 0; 15 sigemptyset(&sa.sa_mask); 16 if(sigaction(SIGPIPE, &sa, NULL) != 0) 17 return 0; 18 return 1; 19} 20 21int ip_create_listener_split(const char *ip, unsigned short port) 22{ 23 struct sockaddr_in in_addr; 24 int fd = -1; 25 int reuseVal = 1; 26 27 /* Create the socket */ 28 if((fd = socket(PF_INET, SOCK_STREAM, 0)) == -1) 29 goto err; 30 /* Set the SO_REUSEADDR flag - servers act weird without it */ 31 if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)(&reuseVal), 32 sizeof(reuseVal)) != 0) 33 goto err; 34 /* Prepare the listen address stuff */ 35 in_addr.sin_family = AF_INET; 36 memcpy(&in_addr.sin_addr.s_addr, ip, 4); 37 in_addr.sin_port = htons(port); 38 /* Bind to the required port/address/interface */ 39 if(bind(fd, (struct sockaddr *)&in_addr, sizeof(struct sockaddr_in)) != 0) 40 goto err; 41 /* Start "listening" */ 42 if(listen(fd, IP_LISTENER_BACKLOG) != 0) 43 goto err; 44 return fd; 45err: 46 if(fd != -1) 47 close(fd); 48 return -1; 49} 50 51int ip_create_connection_split(const char *ip, unsigned short port) 52{ 53 struct sockaddr_in in_addr; 54 int flags, fd = -1; 55 56 /* Create the socket */ 57 if((fd = socket(PF_INET, SOCK_STREAM, 0)) == -1) 58 goto err; 59 /* Make it non-blocking */ 60 if(((flags = fcntl(fd, F_GETFL, 0)) < 0) || 61 (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0)) 62 goto err; 63 /* Prepare the connection address stuff */ 64 in_addr.sin_family = AF_INET; 65 memcpy(&in_addr.sin_addr.s_addr, ip, 4); 66 in_addr.sin_port = htons(port); 67 /* Start a connect (non-blocking, in all likelihood) */ 68 if((connect(fd, (struct sockaddr *)&in_addr, 69 sizeof(struct sockaddr_in)) != 0) && 70 (errno != EINPROGRESS)) 71 goto err; 72 return fd; 73err: 74 if(fd != -1) 75 close(fd); 76 return -1; 77} 78 79static char all_local_ip[] = {0x00,0x00,0x00,0x00}; 80 81int ip_parse_address(const char *address, const char **parsed_ip, 82 unsigned short *parsed_port, int accept_all_ip) 83{ 84 char buf[256]; 85 struct hostent *lookup; 86 unsigned long port; 87 const char *ptr = strstr(address, ":"); 88 const char *ip = all_local_ip; 89 90 if(!ptr) { 91 /* We assume we're listening on all local interfaces and have 92 * only specified a port. */ 93 if(!accept_all_ip) 94 return 0; 95 ptr = address; 96 goto determine_port; 97 } 98 if((ptr - address) > 255) 99 return 0; 100 memset(buf, 0, 256); 101 memcpy(buf, address, ptr - address); 102 ptr++; 103 if((lookup = gethostbyname(buf)) == NULL) { 104 /* Spit a message to differentiate between lookup failures and 105 * bad strings. */ 106 fprintf(stderr, "hostname lookup for '%s' failed\n", buf); 107 return 0; 108 } 109 ip = lookup->h_addr_list[0]; 110determine_port: 111 if(strlen(ptr) < 1) 112 return 0; 113 if(!int_strtoul(ptr, &port) || (port > 65535)) 114 return 0; 115 *parsed_ip = ip; 116 *parsed_port = (unsigned short)port; 117 return 1; 118} 119 120int ip_create_listener(const char *address) 121{ 122 const char *ip; 123 unsigned short port; 124 125 if(!ip_parse_address(address, &ip, &port, 1)) 126 return -1; 127 return ip_create_listener_split(ip, port); 128} 129 130int ip_create_connection(const char *address) 131{ 132 const char *ip; 133 unsigned short port; 134 135 if(!ip_parse_address(address, &ip, &port, 0)) 136 return -1; 137 return ip_create_connection_split(ip, port); 138} 139 140int ip_accept_connection(int listen_fd) 141{ 142 return accept(listen_fd, NULL, NULL); 143} 144 145#endif /* !defined(NO_IP) */ 146 147