net.c (5366B)
1 /* See LICENSE file for copyright and license details */ 2 3 #include <unistd.h> 4 #include <netdb.h> 5 6 #include <openssl/ssl.h> 7 #include <openssl/err.h> 8 9 #include "ind.h" 10 #include "net.h" 11 12 /* 13 * net format: 14 * net!addr!service 15 */ 16 enum { 17 NET_NET = 0x00, 18 NET_TCP, 19 NET_TCPS 20 }; 21 22 static char *netnames[] = { 23 [NET_NET] = "net", 24 [NET_TCP] = "tcp", 25 [NET_TCPS] = "tcps" 26 }; 27 28 int net_gettype(char *str) { 29 unsigned long int i; 30 31 for (i = 0; i < nelem(netnames); i++) 32 if (!strcmp(netnames[i], str)) 33 return i; 34 return -1; 35 } 36 37 net_t *net_new(char *desc) { 38 net_t *ret; 39 int state; 40 char *tok, *buf, *toks; 41 42 state = -1; 43 toks = NULL; 44 ret = NULL; 45 buf = memdup(desc, strlen(desc)+1); 46 47 tok = strtok_r(buf, "!", &toks); 48 if (tok == NULL) 49 goto netnewerror; 50 51 ret = mallocz(sizeof(net_t), 2); 52 do { 53 state++; 54 switch(state) { 55 case 0: 56 ret->net = memdup(tok, strlen(tok)+1); 57 ret->type = net_gettype(ret->net); 58 break; 59 case 1: 60 ret->addr = memdup(tok, strlen(tok)+1); 61 break; 62 case 2: 63 ret->service = memdup(tok, strlen(tok)+1); 64 break; 65 case 3: 66 ret->options = memdup(tok, strlen(tok)+1); 67 break; 68 default: 69 break; 70 } 71 } while ((tok = strtok_r(NULL, "!", &toks)) != NULL); 72 if (state < 2) 73 goto netnewerror; 74 free(buf); 75 76 return ret; 77 netnewerror: 78 if (buf != NULL) 79 free(buf); 80 81 switch (state) { 82 case 1: 83 free(ret->addr); 84 case 0: 85 free(ret->net); 86 default: 87 break; 88 } 89 if (ret != NULL) 90 free(ret); 91 92 return NULL; 93 } 94 95 void net_free(net_t *net) { 96 if (net->net != NULL) 97 free(net->net); 98 if (net->addr != NULL) 99 free(net->addr); 100 if (net->service != NULL) 101 free(net->service); 102 free(net); 103 } 104 105 int net_connecttcp(net_t *net) { 106 struct addrinfo hints, *ai, *rp; 107 108 memset(&hints, 0, sizeof(hints)); 109 110 hints.ai_family = AF_UNSPEC; 111 hints.ai_socktype = SOCK_STREAM; 112 hints.ai_protocol = IPPROTO_TCP; 113 if (getaddrinfo(net->addr, net->service, &hints, &ai)) 114 return 1; 115 if (ai == NULL) 116 return 1; 117 118 for (rp = ai; rp != NULL; rp = rp->ai_next) { 119 net->fd = socket(rp->ai_family, rp->ai_socktype, 120 rp->ai_protocol); 121 if (net->fd < 0) 122 continue; 123 if (!connect(net->fd, rp->ai_addr, rp->ai_addrlen)) 124 break; 125 close(net->fd); 126 } 127 if (rp == NULL) 128 return 1; 129 freeaddrinfo(ai); 130 131 return 0; 132 } 133 134 int net_addssl(net_t *net) { 135 SSL *sfd; 136 long opts; 137 138 SSL_library_init(); 139 OpenSSL_add_all_algorithms(); 140 net->data[1] = SSL_CTX_new(SSLv23_method()); 141 if (net->data[1] == NULL) 142 goto netaddsslerr; 143 144 opts = SSL_CTX_get_options(net->data[1]); 145 opts |= SSL_OP_NO_SSLv2; 146 opts |= SSL_OP_NO_SSLv3; 147 opts |= SSL_OP_NO_TLSv1; 148 opts |= SSL_OP_NO_TLSv1_1; 149 SSL_CTX_set_options((SSL_CTX *)net->data[1], opts); 150 151 if ((sfd = SSL_new((SSL_CTX *)net->data[1])) == NULL) 152 goto netaddsslerr; 153 SSL_set_fd(sfd, net->fd); 154 if (SSL_connect(sfd) < 1) 155 goto netaddsslerr; 156 157 switch (net->type) { 158 case NET_NET: 159 case NET_TCP: 160 free(net->net); 161 net->net = memdup("tcps", 5); 162 net->type = net_gettype(net->net); 163 case NET_TCPS: 164 default: 165 break; 166 } 167 168 net->data[0] = sfd; 169 170 return 0; 171 netaddsslerr: 172 SSL_load_error_strings(); 173 ERR_print_errors_fp(stderr); 174 ERR_free_strings(); 175 return 1; 176 } 177 178 int net_connecttcps(net_t *net) { 179 if (net_connecttcp(net)) 180 return 1; 181 if (net_addssl(net)) 182 return 1; 183 184 return 0; 185 } 186 187 int net_connect(net_t *net) { 188 switch (net->type) { 189 case NET_NET: 190 case NET_TCP: 191 return net_connecttcp(net); 192 case NET_TCPS: 193 return net_connecttcps(net); 194 default: 195 return 1; 196 } 197 198 return 0; 199 } 200 201 void net_closetcp(net_t *net) { 202 shutdown(net->fd, SHUT_RDWR); 203 close(net->fd); 204 } 205 206 void net_closetcps(net_t *net) { 207 SSL_CTX_free((SSL_CTX *)net->data[1]); 208 SSL_free((SSL *)net->data[0]); 209 EVP_cleanup(); 210 CRYPTO_cleanup_all_ex_data(); 211 } 212 213 void net_close(net_t *net) { 214 switch (net->type) { 215 case NET_NET: 216 case NET_TCP: 217 net_closetcp(net); 218 case NET_TCPS: 219 net_closetcps(net); 220 default: 221 break; 222 } 223 } 224 225 int net_writetcp(net_t *net, char *buf, int len) { 226 return send(net->fd, buf, len, MSG_NOSIGNAL); 227 } 228 229 int net_writetcps(net_t *net, char *buf, int len) { 230 return SSL_write((SSL *)net->data[0], buf, len); 231 } 232 233 int net_write(net_t *net, char *buf, int len) { 234 switch (net->type) { 235 case NET_NET: 236 case NET_TCP: 237 return net_writetcp(net, buf, len); 238 case NET_TCPS: 239 return net_writetcps(net, buf, len); 240 default: 241 return -1; 242 } 243 return -1; 244 } 245 246 247 int net_writeall(net_t *net, char *buf, int len) { 248 249 int olen, nlen; 250 251 for (olen = 0; 252 (nlen = net_write(net, &buf[olen], len-olen)) 253 && olen < len; olen += nlen); 254 255 return 0; 256 } 257 258 int net_printf(net_t *net, char *fmt, ...) { 259 va_list fmtargs; 260 char *buf; 261 int len; 262 263 va_start(fmtargs, fmt); 264 len = vsnprintf(NULL, 0, fmt, fmtargs); 265 va_end(fmtargs); 266 267 va_start(fmtargs, fmt); 268 buf = vsmprintf(fmt, fmtargs, len); 269 va_end(fmtargs); 270 271 len = net_writeall(net, buf, strlen(buf)); 272 free(buf); 273 return len; 274 } 275 276 int net_readtcp(net_t *net, char *buf, int len) { 277 return recv(net->fd, buf, len, 0); 278 } 279 280 int net_readtcps(net_t *net, char *buf, int len) { 281 return SSL_read((SSL *)net->data[0], buf, len); 282 } 283 284 int net_read(net_t *net, char *buf, int len) { 285 switch (net->type) { 286 case NET_NET: 287 case NET_TCP: 288 return net_readtcp(net, buf, len); 289 case NET_TCPS: 290 return net_readtcps(net, buf, len); 291 default: 292 return -1; 293 } 294 return -1; 295 } 296 297 int net_readall(net_t *net, char *buf, int len) { 298 int olen, nlen; 299 300 for (olen = 0; 301 (nlen = net_read(net, &buf[olen], len-olen)) 302 && olen < len; olen += nlen); 303 304 return 0; 305 }