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)) != 40 0) 41 goto err; 42 /* Start "listening" */ 43 if (listen(fd, IP_LISTENER_BACKLOG) != 0) 44 goto err; 45 return fd; 46 err: 47 if (fd != -1) 48 close(fd); 49 return -1; 50} 51 52int ip_create_connection_split(const char *ip, unsigned short port) 53{ 54 struct sockaddr_in in_addr; 55 int flags, fd = -1; 56 57 /* Create the socket */ 58 if ((fd = socket(PF_INET, SOCK_STREAM, 0)) == -1) 59 goto err; 60 /* Make it non-blocking */ 61 if (((flags = fcntl(fd, F_GETFL, 0)) < 0) || 62 (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0)) 63 goto err; 64 /* Prepare the connection address stuff */ 65 in_addr.sin_family = AF_INET; 66 memcpy(&in_addr.sin_addr.s_addr, ip, 4); 67 in_addr.sin_port = htons(port); 68 /* Start a connect (non-blocking, in all likelihood) */ 69 if ((connect(fd, (struct sockaddr *)&in_addr, 70 sizeof(struct sockaddr_in)) != 0) && (errno != EINPROGRESS)) 71 goto err; 72 return fd; 73 err: 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 /* 92 * We assume we're listening on all local interfaces and have only 93 * specified a port. 94 */ 95 if (!accept_all_ip) 96 return 0; 97 ptr = address; 98 goto determine_port; 99 } 100 if ((ptr - address) > 255) 101 return 0; 102 memset(buf, 0, 256); 103 memcpy(buf, address, ptr - address); 104 ptr++; 105 if ((lookup = gethostbyname(buf)) == NULL) { 106 /* 107 * Spit a message to differentiate between lookup failures and bad 108 * strings. 109 */ 110 fprintf(stderr, "hostname lookup for '%s' failed\n", buf); 111 return 0; 112 } 113 ip = lookup->h_addr_list[0]; 114 determine_port: 115 if (strlen(ptr) < 1) 116 return 0; 117 if (!int_strtoul(ptr, &port) || (port > 65535)) 118 return 0; 119 *parsed_ip = ip; 120 *parsed_port = (unsigned short)port; 121 return 1; 122} 123 124int ip_create_listener(const char *address) 125{ 126 const char *ip; 127 unsigned short port; 128 129 if (!ip_parse_address(address, &ip, &port, 1)) 130 return -1; 131 return ip_create_listener_split(ip, port); 132} 133 134int ip_create_connection(const char *address) 135{ 136 const char *ip; 137 unsigned short port; 138 139 if (!ip_parse_address(address, &ip, &port, 0)) 140 return -1; 141 return ip_create_connection_split(ip, port); 142} 143 144int ip_accept_connection(int listen_fd) 145{ 146 return accept(listen_fd, NULL, NULL); 147} 148 149#endif /* !defined(NO_IP) */ 150