Branch data Line data Source code
1 : : /* crypto/bio/b_sock.c */
2 : : /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 : : * All rights reserved.
4 : : *
5 : : * This package is an SSL implementation written
6 : : * by Eric Young (eay@cryptsoft.com).
7 : : * The implementation was written so as to conform with Netscapes SSL.
8 : : *
9 : : * This library is free for commercial and non-commercial use as long as
10 : : * the following conditions are aheared to. The following conditions
11 : : * apply to all code found in this distribution, be it the RC4, RSA,
12 : : * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13 : : * included with this distribution is covered by the same copyright terms
14 : : * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15 : : *
16 : : * Copyright remains Eric Young's, and as such any Copyright notices in
17 : : * the code are not to be removed.
18 : : * If this package is used in a product, Eric Young should be given attribution
19 : : * as the author of the parts of the library used.
20 : : * This can be in the form of a textual message at program startup or
21 : : * in documentation (online or textual) provided with the package.
22 : : *
23 : : * Redistribution and use in source and binary forms, with or without
24 : : * modification, are permitted provided that the following conditions
25 : : * are met:
26 : : * 1. Redistributions of source code must retain the copyright
27 : : * notice, this list of conditions and the following disclaimer.
28 : : * 2. Redistributions in binary form must reproduce the above copyright
29 : : * notice, this list of conditions and the following disclaimer in the
30 : : * documentation and/or other materials provided with the distribution.
31 : : * 3. All advertising materials mentioning features or use of this software
32 : : * must display the following acknowledgement:
33 : : * "This product includes cryptographic software written by
34 : : * Eric Young (eay@cryptsoft.com)"
35 : : * The word 'cryptographic' can be left out if the rouines from the library
36 : : * being used are not cryptographic related :-).
37 : : * 4. If you include any Windows specific code (or a derivative thereof) from
38 : : * the apps directory (application code) you must include an acknowledgement:
39 : : * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40 : : *
41 : : * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 : : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 : : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 : : * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 : : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 : : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 : : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 : : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 : : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 : : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 : : * SUCH DAMAGE.
52 : : *
53 : : * The licence and distribution terms for any publically available version or
54 : : * derivative of this code cannot be changed. i.e. this code cannot simply be
55 : : * copied and put under another distribution licence
56 : : * [including the GNU Public Licence.]
57 : : */
58 : :
59 : : #include <stdio.h>
60 : : #include <stdlib.h>
61 : : #include <errno.h>
62 : : #define USE_SOCKETS
63 : : #include "cryptlib.h"
64 : : #include <openssl/bio.h>
65 : : #if defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_BSDSOCK)
66 : : #include <netdb.h>
67 : : #if defined(NETWARE_CLIB)
68 : : #include <sys/ioctl.h>
69 : : NETDB_DEFINE_CONTEXT
70 : : #endif
71 : : #endif
72 : :
73 : : #ifndef OPENSSL_NO_SOCK
74 : :
75 : : #include <openssl/dso.h>
76 : :
77 : : #define SOCKET_PROTOCOL IPPROTO_TCP
78 : :
79 : : #ifdef SO_MAXCONN
80 : : #define MAX_LISTEN SO_MAXCONN
81 : : #elif defined(SOMAXCONN)
82 : : #define MAX_LISTEN SOMAXCONN
83 : : #else
84 : : #define MAX_LISTEN 32
85 : : #endif
86 : :
87 : : #if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK))
88 : : static int wsa_init_done=0;
89 : : #endif
90 : :
91 : : /*
92 : : * WSAAPI specifier is required to make indirect calls to run-time
93 : : * linked WinSock 2 functions used in this module, to be specific
94 : : * [get|free]addrinfo and getnameinfo. This is because WinSock uses
95 : : * uses non-C calling convention, __stdcall vs. __cdecl, on x86
96 : : * Windows. On non-WinSock platforms WSAAPI needs to be void.
97 : : */
98 : : #ifndef WSAAPI
99 : : #define WSAAPI
100 : : #endif
101 : :
102 : : #if 0
103 : : static unsigned long BIO_ghbn_hits=0L;
104 : : static unsigned long BIO_ghbn_miss=0L;
105 : :
106 : : #define GHBN_NUM 4
107 : : static struct ghbn_cache_st
108 : : {
109 : : char name[129];
110 : : struct hostent *ent;
111 : : unsigned long order;
112 : : } ghbn_cache[GHBN_NUM];
113 : : #endif
114 : :
115 : : static int get_ip(const char *str,unsigned char *ip);
116 : : #if 0
117 : : static void ghbn_free(struct hostent *a);
118 : : static struct hostent *ghbn_dup(struct hostent *a);
119 : : #endif
120 : 0 : int BIO_get_host_ip(const char *str, unsigned char *ip)
121 : : {
122 : : int i;
123 : 0 : int err = 1;
124 : 0 : int locked = 0;
125 : : struct hostent *he;
126 : :
127 : 0 : i=get_ip(str,ip);
128 [ # # ]: 0 : if (i < 0)
129 : : {
130 : 0 : BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_INVALID_IP_ADDRESS);
131 : 0 : goto err;
132 : : }
133 : :
134 : : /* At this point, we have something that is most probably correct
135 : : in some way, so let's init the socket. */
136 [ # # ]: 0 : if (BIO_sock_init() != 1)
137 : : return 0; /* don't generate another error code here */
138 : :
139 : : /* If the string actually contained an IP address, we need not do
140 : : anything more */
141 [ # # ]: 0 : if (i > 0) return(1);
142 : :
143 : : /* do a gethostbyname */
144 : 0 : CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME);
145 : 0 : locked = 1;
146 : 0 : he=BIO_gethostbyname(str);
147 [ # # ]: 0 : if (he == NULL)
148 : : {
149 : 0 : BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_BAD_HOSTNAME_LOOKUP);
150 : 0 : goto err;
151 : : }
152 : :
153 : : /* cast to short because of win16 winsock definition */
154 [ # # ]: 0 : if ((short)he->h_addrtype != AF_INET)
155 : : {
156 : 0 : BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET);
157 : 0 : goto err;
158 : : }
159 [ # # ]: 0 : for (i=0; i<4; i++)
160 : 0 : ip[i]=he->h_addr_list[0][i];
161 : : err = 0;
162 : :
163 : : err:
164 [ # # ]: 0 : if (locked)
165 : 0 : CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME);
166 [ # # ]: 0 : if (err)
167 : : {
168 : 0 : ERR_add_error_data(2,"host=",str);
169 : 0 : return 0;
170 : : }
171 : : else
172 : : return 1;
173 : : }
174 : :
175 : 0 : int BIO_get_port(const char *str, unsigned short *port_ptr)
176 : : {
177 : : int i;
178 : : struct servent *s;
179 : :
180 [ # # ]: 0 : if (str == NULL)
181 : : {
182 : 0 : BIOerr(BIO_F_BIO_GET_PORT,BIO_R_NO_PORT_DEFINED);
183 : 0 : return(0);
184 : : }
185 : 0 : i=atoi(str);
186 [ # # ]: 0 : if (i != 0)
187 : 0 : *port_ptr=(unsigned short)i;
188 : : else
189 : : {
190 : 0 : CRYPTO_w_lock(CRYPTO_LOCK_GETSERVBYNAME);
191 : : /* Note: under VMS with SOCKETSHR, it seems like the first
192 : : * parameter is 'char *', instead of 'const char *'
193 : : */
194 : : #ifndef CONST_STRICT
195 : 0 : s=getservbyname((char *)str,"tcp");
196 : : #else
197 : : s=getservbyname(str,"tcp");
198 : : #endif
199 [ # # ]: 0 : if(s != NULL)
200 [ # # ]: 0 : *port_ptr=ntohs((unsigned short)s->s_port);
201 : 0 : CRYPTO_w_unlock(CRYPTO_LOCK_GETSERVBYNAME);
202 [ # # ]: 0 : if(s == NULL)
203 : : {
204 [ # # ]: 0 : if (strcmp(str,"http") == 0)
205 : 0 : *port_ptr=80;
206 [ # # ]: 0 : else if (strcmp(str,"telnet") == 0)
207 : 0 : *port_ptr=23;
208 [ # # ]: 0 : else if (strcmp(str,"socks") == 0)
209 : 0 : *port_ptr=1080;
210 [ # # ]: 0 : else if (strcmp(str,"https") == 0)
211 : 0 : *port_ptr=443;
212 [ # # ]: 0 : else if (strcmp(str,"ssl") == 0)
213 : 0 : *port_ptr=443;
214 [ # # ]: 0 : else if (strcmp(str,"ftp") == 0)
215 : 0 : *port_ptr=21;
216 [ # # ]: 0 : else if (strcmp(str,"gopher") == 0)
217 : 0 : *port_ptr=70;
218 : : #if 0
219 : : else if (strcmp(str,"wais") == 0)
220 : : *port_ptr=21;
221 : : #endif
222 : : else
223 : : {
224 : 0 : SYSerr(SYS_F_GETSERVBYNAME,get_last_socket_error());
225 : 0 : ERR_add_error_data(3,"service='",str,"'");
226 : 0 : return(0);
227 : : }
228 : : }
229 : : }
230 : : return(1);
231 : : }
232 : :
233 : 0 : int BIO_sock_error(int sock)
234 : : {
235 : : int j,i;
236 : : union { size_t s; int i; } size;
237 : :
238 : : #if defined(OPENSSL_SYS_BEOS_R5)
239 : : return 0;
240 : : #endif
241 : :
242 : : /* heuristic way to adapt for platforms that expect 64-bit optlen */
243 : 0 : size.s=0, size.i=sizeof(j);
244 : : /* Note: under Windows the third parameter is of type (char *)
245 : : * whereas under other systems it is (void *) if you don't have
246 : : * a cast it will choke the compiler: if you do have a cast then
247 : : * you can either go for (char *) or (void *).
248 : : */
249 : 0 : i=getsockopt(sock,SOL_SOCKET,SO_ERROR,(void *)&j,(void *)&size);
250 [ # # ]: 0 : if (i < 0)
251 : : return(1);
252 : : else
253 : 0 : return(j);
254 : : }
255 : :
256 : : #if 0
257 : : long BIO_ghbn_ctrl(int cmd, int iarg, char *parg)
258 : : {
259 : : int i;
260 : : char **p;
261 : :
262 : : switch (cmd)
263 : : {
264 : : case BIO_GHBN_CTRL_HITS:
265 : : return(BIO_ghbn_hits);
266 : : /* break; */
267 : : case BIO_GHBN_CTRL_MISSES:
268 : : return(BIO_ghbn_miss);
269 : : /* break; */
270 : : case BIO_GHBN_CTRL_CACHE_SIZE:
271 : : return(GHBN_NUM);
272 : : /* break; */
273 : : case BIO_GHBN_CTRL_GET_ENTRY:
274 : : if ((iarg >= 0) && (iarg <GHBN_NUM) &&
275 : : (ghbn_cache[iarg].order > 0))
276 : : {
277 : : p=(char **)parg;
278 : : if (p == NULL) return(0);
279 : : *p=ghbn_cache[iarg].name;
280 : : ghbn_cache[iarg].name[128]='\0';
281 : : return(1);
282 : : }
283 : : return(0);
284 : : /* break; */
285 : : case BIO_GHBN_CTRL_FLUSH:
286 : : for (i=0; i<GHBN_NUM; i++)
287 : : ghbn_cache[i].order=0;
288 : : break;
289 : : default:
290 : : return(0);
291 : : }
292 : : return(1);
293 : : }
294 : : #endif
295 : :
296 : : #if 0
297 : : static struct hostent *ghbn_dup(struct hostent *a)
298 : : {
299 : : struct hostent *ret;
300 : : int i,j;
301 : :
302 : : MemCheck_off();
303 : : ret=(struct hostent *)OPENSSL_malloc(sizeof(struct hostent));
304 : : if (ret == NULL) return(NULL);
305 : : memset(ret,0,sizeof(struct hostent));
306 : :
307 : : for (i=0; a->h_aliases[i] != NULL; i++)
308 : : ;
309 : : i++;
310 : : ret->h_aliases = (char **)OPENSSL_malloc(i*sizeof(char *));
311 : : if (ret->h_aliases == NULL)
312 : : goto err;
313 : : memset(ret->h_aliases, 0, i*sizeof(char *));
314 : :
315 : : for (i=0; a->h_addr_list[i] != NULL; i++)
316 : : ;
317 : : i++;
318 : : ret->h_addr_list=(char **)OPENSSL_malloc(i*sizeof(char *));
319 : : if (ret->h_addr_list == NULL)
320 : : goto err;
321 : : memset(ret->h_addr_list, 0, i*sizeof(char *));
322 : :
323 : : j=strlen(a->h_name)+1;
324 : : if ((ret->h_name=OPENSSL_malloc(j)) == NULL) goto err;
325 : : memcpy((char *)ret->h_name,a->h_name,j);
326 : : for (i=0; a->h_aliases[i] != NULL; i++)
327 : : {
328 : : j=strlen(a->h_aliases[i])+1;
329 : : if ((ret->h_aliases[i]=OPENSSL_malloc(j)) == NULL) goto err;
330 : : memcpy(ret->h_aliases[i],a->h_aliases[i],j);
331 : : }
332 : : ret->h_length=a->h_length;
333 : : ret->h_addrtype=a->h_addrtype;
334 : : for (i=0; a->h_addr_list[i] != NULL; i++)
335 : : {
336 : : if ((ret->h_addr_list[i]=OPENSSL_malloc(a->h_length)) == NULL)
337 : : goto err;
338 : : memcpy(ret->h_addr_list[i],a->h_addr_list[i],a->h_length);
339 : : }
340 : : if (0)
341 : : {
342 : : err:
343 : : if (ret != NULL)
344 : : ghbn_free(ret);
345 : : ret=NULL;
346 : : }
347 : : MemCheck_on();
348 : : return(ret);
349 : : }
350 : :
351 : : static void ghbn_free(struct hostent *a)
352 : : {
353 : : int i;
354 : :
355 : : if(a == NULL)
356 : : return;
357 : :
358 : : if (a->h_aliases != NULL)
359 : : {
360 : : for (i=0; a->h_aliases[i] != NULL; i++)
361 : : OPENSSL_free(a->h_aliases[i]);
362 : : OPENSSL_free(a->h_aliases);
363 : : }
364 : : if (a->h_addr_list != NULL)
365 : : {
366 : : for (i=0; a->h_addr_list[i] != NULL; i++)
367 : : OPENSSL_free(a->h_addr_list[i]);
368 : : OPENSSL_free(a->h_addr_list);
369 : : }
370 : : if (a->h_name != NULL) OPENSSL_free(a->h_name);
371 : : OPENSSL_free(a);
372 : : }
373 : :
374 : : #endif
375 : :
376 : 0 : struct hostent *BIO_gethostbyname(const char *name)
377 : : {
378 : : #if 1
379 : : /* Caching gethostbyname() results forever is wrong,
380 : : * so we have to let the true gethostbyname() worry about this */
381 : : #if (defined(NETWARE_BSDSOCK) && !defined(__NOVELL_LIBC__))
382 : : return gethostbyname((char*)name);
383 : : #else
384 : 0 : return gethostbyname(name);
385 : : #endif
386 : : #else
387 : : struct hostent *ret;
388 : : int i,lowi=0,j;
389 : : unsigned long low= (unsigned long)-1;
390 : :
391 : :
392 : : # if 0
393 : : /* It doesn't make sense to use locking here: The function interface
394 : : * is not thread-safe, because threads can never be sure when
395 : : * some other thread destroys the data they were given a pointer to.
396 : : */
397 : : CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME);
398 : : # endif
399 : : j=strlen(name);
400 : : if (j < 128)
401 : : {
402 : : for (i=0; i<GHBN_NUM; i++)
403 : : {
404 : : if (low > ghbn_cache[i].order)
405 : : {
406 : : low=ghbn_cache[i].order;
407 : : lowi=i;
408 : : }
409 : : if (ghbn_cache[i].order > 0)
410 : : {
411 : : if (strncmp(name,ghbn_cache[i].name,128) == 0)
412 : : break;
413 : : }
414 : : }
415 : : }
416 : : else
417 : : i=GHBN_NUM;
418 : :
419 : : if (i == GHBN_NUM) /* no hit*/
420 : : {
421 : : BIO_ghbn_miss++;
422 : : /* Note: under VMS with SOCKETSHR, it seems like the first
423 : : * parameter is 'char *', instead of 'const char *'
424 : : */
425 : : # ifndef CONST_STRICT
426 : : ret=gethostbyname((char *)name);
427 : : # else
428 : : ret=gethostbyname(name);
429 : : # endif
430 : :
431 : : if (ret == NULL)
432 : : goto end;
433 : : if (j > 128) /* too big to cache */
434 : : {
435 : : # if 0
436 : : /* If we were trying to make this function thread-safe (which
437 : : * is bound to fail), we'd have to give up in this case
438 : : * (or allocate more memory). */
439 : : ret = NULL;
440 : : # endif
441 : : goto end;
442 : : }
443 : :
444 : : /* else add to cache */
445 : : if (ghbn_cache[lowi].ent != NULL)
446 : : ghbn_free(ghbn_cache[lowi].ent); /* XXX not thread-safe */
447 : : ghbn_cache[lowi].name[0] = '\0';
448 : :
449 : : if((ret=ghbn_cache[lowi].ent=ghbn_dup(ret)) == NULL)
450 : : {
451 : : BIOerr(BIO_F_BIO_GETHOSTBYNAME,ERR_R_MALLOC_FAILURE);
452 : : goto end;
453 : : }
454 : : strncpy(ghbn_cache[lowi].name,name,128);
455 : : ghbn_cache[lowi].order=BIO_ghbn_miss+BIO_ghbn_hits;
456 : : }
457 : : else
458 : : {
459 : : BIO_ghbn_hits++;
460 : : ret= ghbn_cache[i].ent;
461 : : ghbn_cache[i].order=BIO_ghbn_miss+BIO_ghbn_hits;
462 : : }
463 : : end:
464 : : # if 0
465 : : CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME);
466 : : # endif
467 : : return(ret);
468 : : #endif
469 : : }
470 : :
471 : :
472 : 0 : int BIO_sock_init(void)
473 : : {
474 : : #ifdef OPENSSL_SYS_WINDOWS
475 : : static struct WSAData wsa_state;
476 : :
477 : : if (!wsa_init_done)
478 : : {
479 : : int err;
480 : :
481 : : wsa_init_done=1;
482 : : memset(&wsa_state,0,sizeof(wsa_state));
483 : : /* Not making wsa_state available to the rest of the
484 : : * code is formally wrong. But the structures we use
485 : : * are [beleived to be] invariable among Winsock DLLs,
486 : : * while API availability is [expected to be] probed
487 : : * at run-time with DSO_global_lookup. */
488 : : if (WSAStartup(0x0202,&wsa_state)!=0)
489 : : {
490 : : err=WSAGetLastError();
491 : : SYSerr(SYS_F_WSASTARTUP,err);
492 : : BIOerr(BIO_F_BIO_SOCK_INIT,BIO_R_WSASTARTUP);
493 : : return(-1);
494 : : }
495 : : }
496 : : #endif /* OPENSSL_SYS_WINDOWS */
497 : : #ifdef WATT32
498 : : extern int _watt_do_exit;
499 : : _watt_do_exit = 0; /* don't make sock_init() call exit() */
500 : : if (sock_init())
501 : : return (-1);
502 : : #endif
503 : :
504 : : #if defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)
505 : : WORD wVerReq;
506 : : WSADATA wsaData;
507 : : int err;
508 : :
509 : : if (!wsa_init_done)
510 : : {
511 : : wsa_init_done=1;
512 : : wVerReq = MAKEWORD( 2, 0 );
513 : : err = WSAStartup(wVerReq,&wsaData);
514 : : if (err != 0)
515 : : {
516 : : SYSerr(SYS_F_WSASTARTUP,err);
517 : : BIOerr(BIO_F_BIO_SOCK_INIT,BIO_R_WSASTARTUP);
518 : : return(-1);
519 : : }
520 : : }
521 : : #endif
522 : :
523 : 0 : return(1);
524 : : }
525 : :
526 : 0 : void BIO_sock_cleanup(void)
527 : : {
528 : : #ifdef OPENSSL_SYS_WINDOWS
529 : : if (wsa_init_done)
530 : : {
531 : : wsa_init_done=0;
532 : : #if 0 /* this call is claimed to be non-present in Winsock2 */
533 : : WSACancelBlockingCall();
534 : : #endif
535 : : WSACleanup();
536 : : }
537 : : #elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)
538 : : if (wsa_init_done)
539 : : {
540 : : wsa_init_done=0;
541 : : WSACleanup();
542 : : }
543 : : #endif
544 : 0 : }
545 : :
546 : : #if !defined(OPENSSL_SYS_VMS) || __VMS_VER >= 70000000
547 : :
548 : 0 : int BIO_socket_ioctl(int fd, long type, void *arg)
549 : : {
550 : : int i;
551 : :
552 : : #ifdef __DJGPP__
553 : : i=ioctlsocket(fd,type,(char *)arg);
554 : : #else
555 : : # if defined(OPENSSL_SYS_VMS)
556 : : /* 2011-02-18 SMS.
557 : : * VMS ioctl() can't tolerate a 64-bit "void *arg", but we
558 : : * observe that all the consumers pass in an "unsigned long *",
559 : : * so we arrange a local copy with a short pointer, and use
560 : : * that, instead.
561 : : */
562 : : # if __INITIAL_POINTER_SIZE == 64
563 : : # define ARG arg_32p
564 : : # pragma pointer_size save
565 : : # pragma pointer_size 32
566 : : unsigned long arg_32;
567 : : unsigned long *arg_32p;
568 : : # pragma pointer_size restore
569 : : arg_32p = &arg_32;
570 : : arg_32 = *((unsigned long *) arg);
571 : : # else /* __INITIAL_POINTER_SIZE == 64 */
572 : : # define ARG arg
573 : : # endif /* __INITIAL_POINTER_SIZE == 64 [else] */
574 : : # else /* defined(OPENSSL_SYS_VMS) */
575 : : # define ARG arg
576 : : # endif /* defined(OPENSSL_SYS_VMS) [else] */
577 : :
578 : 0 : i=ioctlsocket(fd,type,ARG);
579 : : #endif /* __DJGPP__ */
580 [ # # ]: 0 : if (i < 0)
581 : 0 : SYSerr(SYS_F_IOCTLSOCKET,get_last_socket_error());
582 : 0 : return(i);
583 : : }
584 : : #endif /* __VMS_VER */
585 : :
586 : : /* The reason I have implemented this instead of using sscanf is because
587 : : * Visual C 1.52c gives an unresolved external when linking a DLL :-( */
588 : 0 : static int get_ip(const char *str, unsigned char ip[4])
589 : : {
590 : : unsigned int tmp[4];
591 : 0 : int num=0,c,ok=0;
592 : :
593 : 0 : tmp[0]=tmp[1]=tmp[2]=tmp[3]=0;
594 : :
595 : : for (;;)
596 : : {
597 : 0 : c= *(str++);
598 [ # # ]: 0 : if ((c >= '0') && (c <= '9'))
599 : : {
600 : 0 : ok=1;
601 : 0 : tmp[num]=tmp[num]*10+c-'0';
602 [ # # ]: 0 : if (tmp[num] > 255) return(0);
603 : : }
604 [ # # ]: 0 : else if (c == '.')
605 : : {
606 [ # # ]: 0 : if (!ok) return(-1);
607 [ # # ]: 0 : if (num == 3) return(0);
608 : 0 : num++;
609 : 0 : ok=0;
610 : : }
611 [ # # ][ # # ]: 0 : else if (c == '\0' && (num == 3) && ok)
612 : : break;
613 : : else
614 : : return(0);
615 : : }
616 : 0 : ip[0]=tmp[0];
617 : 0 : ip[1]=tmp[1];
618 : 0 : ip[2]=tmp[2];
619 : 0 : ip[3]=tmp[3];
620 : 0 : return(1);
621 : : }
622 : :
623 : 0 : int BIO_get_accept_socket(char *host, int bind_mode)
624 : : {
625 : 0 : int ret=0;
626 : : union {
627 : : struct sockaddr sa;
628 : : struct sockaddr_in sa_in;
629 : : #if OPENSSL_USE_IPV6
630 : : struct sockaddr_in6 sa_in6;
631 : : #endif
632 : : } server,client;
633 : 0 : int s=INVALID_SOCKET,cs,addrlen;
634 : : unsigned char ip[4];
635 : : unsigned short port;
636 : 0 : char *str=NULL,*e;
637 : : char *h,*p;
638 : : unsigned long l;
639 : : int err_num;
640 : :
641 [ # # ]: 0 : if (BIO_sock_init() != 1) return(INVALID_SOCKET);
642 : :
643 [ # # ]: 0 : if ((str=BUF_strdup(host)) == NULL) return(INVALID_SOCKET);
644 : :
645 : : h=p=NULL;
646 : : h=str;
647 [ # # ]: 0 : for (e=str; *e; e++)
648 : : {
649 [ # # ]: 0 : if (*e == ':')
650 : : {
651 : : p=e;
652 : : }
653 [ # # ]: 0 : else if (*e == '/')
654 : : {
655 : 0 : *e='\0';
656 : 0 : break;
657 : : }
658 : : }
659 [ # # ]: 0 : if (p) *p++='\0'; /* points at last ':', '::port' is special [see below] */
660 : : else p=h,h=NULL;
661 : :
662 : : #ifdef EAI_FAMILY
663 : : do {
664 : : static union { void *p;
665 : : int (WSAAPI *f)(const char *,const char *,
666 : : const struct addrinfo *,
667 : : struct addrinfo **);
668 : : } p_getaddrinfo = {NULL};
669 : : static union { void *p;
670 : : void (WSAAPI *f)(struct addrinfo *);
671 : : } p_freeaddrinfo = {NULL};
672 : : struct addrinfo *res,hint;
673 : :
674 [ # # ]: 0 : if (p_getaddrinfo.p==NULL)
675 : : {
676 [ # # # # ]: 0 : if ((p_getaddrinfo.p=DSO_global_lookup("getaddrinfo"))==NULL ||
677 : 0 : (p_freeaddrinfo.p=DSO_global_lookup("freeaddrinfo"))==NULL)
678 : 0 : p_getaddrinfo.p=(void*)-1;
679 : : }
680 [ # # ]: 0 : if (p_getaddrinfo.p==(void *)-1) break;
681 : :
682 : : /* '::port' enforces IPv6 wildcard listener. Some OSes,
683 : : * e.g. Solaris, default to IPv6 without any hint. Also
684 : : * note that commonly IPv6 wildchard socket can service
685 : : * IPv4 connections just as well... */
686 : : memset(&hint,0,sizeof(hint));
687 : 0 : hint.ai_flags = AI_PASSIVE;
688 [ # # ]: 0 : if (h)
689 : : {
690 [ # # ]: 0 : if (strchr(h,':'))
691 : : {
692 [ # # ]: 0 : if (h[1]=='\0') h=NULL;
693 : : #if OPENSSL_USE_IPV6
694 : 0 : hint.ai_family = AF_INET6;
695 : : #else
696 : : h=NULL;
697 : : #endif
698 : : }
699 [ # # ][ # # ]: 0 : else if (h[0]=='*' && h[1]=='\0')
700 : : {
701 : 0 : hint.ai_family = AF_INET;
702 : 0 : h=NULL;
703 : : }
704 : : }
705 : :
706 [ # # ]: 0 : if ((*p_getaddrinfo.f)(h,p,&hint,&res)) break;
707 : :
708 : 0 : addrlen = res->ai_addrlen<=sizeof(server) ?
709 : : res->ai_addrlen :
710 : : sizeof(server);
711 : 0 : memcpy(&server, res->ai_addr, addrlen);
712 : :
713 : 0 : (*p_freeaddrinfo.f)(res);
714 : 0 : goto again;
715 : : } while (0);
716 : : #endif
717 : :
718 [ # # ]: 0 : if (!BIO_get_port(p,&port)) goto err;
719 : :
720 : : memset((char *)&server,0,sizeof(server));
721 : 0 : server.sa_in.sin_family=AF_INET;
722 [ # # ]: 0 : server.sa_in.sin_port=htons(port);
723 : 0 : addrlen = sizeof(server.sa_in);
724 : :
725 [ # # ][ # # ]: 0 : if (h == NULL || strcmp(h,"*") == 0)
726 : : server.sa_in.sin_addr.s_addr=INADDR_ANY;
727 : : else
728 : : {
729 [ # # ]: 0 : if (!BIO_get_host_ip(h,&(ip[0]))) goto err;
730 : 0 : l=(unsigned long)
731 : 0 : ((unsigned long)ip[0]<<24L)|
732 : 0 : ((unsigned long)ip[1]<<16L)|
733 : 0 : ((unsigned long)ip[2]<< 8L)|
734 : 0 : ((unsigned long)ip[3]);
735 : 0 : server.sa_in.sin_addr.s_addr=htonl(l);
736 : : }
737 : :
738 : : again:
739 : 0 : s=socket(server.sa.sa_family,SOCK_STREAM,SOCKET_PROTOCOL);
740 [ # # ]: 0 : if (s == INVALID_SOCKET)
741 : : {
742 : 0 : SYSerr(SYS_F_SOCKET,get_last_socket_error());
743 : 0 : ERR_add_error_data(3,"port='",host,"'");
744 : 0 : BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_CREATE_SOCKET);
745 : 0 : goto err;
746 : : }
747 : :
748 : : #ifdef SO_REUSEADDR
749 [ # # ]: 0 : if (bind_mode == BIO_BIND_REUSEADDR)
750 : : {
751 : 0 : int i=1;
752 : :
753 : 0 : ret=setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&i,sizeof(i));
754 : 0 : bind_mode=BIO_BIND_NORMAL;
755 : : }
756 : : #endif
757 [ # # ]: 0 : if (bind(s,&server.sa,addrlen) == -1)
758 : : {
759 : : #ifdef SO_REUSEADDR
760 : 0 : err_num=get_last_socket_error();
761 [ # # ]: 0 : if ((bind_mode == BIO_BIND_REUSEADDR_IF_UNUSED) &&
762 : : #ifdef OPENSSL_SYS_WINDOWS
763 : : /* Some versions of Windows define EADDRINUSE to
764 : : * a dummy value.
765 : : */
766 : : (err_num == WSAEADDRINUSE))
767 : : #else
768 : 0 : (err_num == EADDRINUSE))
769 : : #endif
770 : : {
771 : 0 : client = server;
772 [ # # ][ # # ]: 0 : if (h == NULL || strcmp(h,"*") == 0)
773 : : {
774 : : #if OPENSSL_USE_IPV6
775 [ # # ]: 0 : if (client.sa.sa_family == AF_INET6)
776 : : {
777 : : memset(&client.sa_in6.sin6_addr,0,sizeof(client.sa_in6.sin6_addr));
778 : 0 : client.sa_in6.sin6_addr.s6_addr[15]=1;
779 : : }
780 : : else
781 : : #endif
782 [ # # ]: 0 : if (client.sa.sa_family == AF_INET)
783 : : {
784 : 0 : client.sa_in.sin_addr.s_addr=htonl(0x7F000001);
785 : : }
786 : : else goto err;
787 : : }
788 : 0 : cs=socket(client.sa.sa_family,SOCK_STREAM,SOCKET_PROTOCOL);
789 [ # # ]: 0 : if (cs != INVALID_SOCKET)
790 : : {
791 : : int ii;
792 : 0 : ii=connect(cs,&client.sa,addrlen);
793 : 0 : closesocket(cs);
794 [ # # ]: 0 : if (ii == INVALID_SOCKET)
795 : : {
796 : 0 : bind_mode=BIO_BIND_REUSEADDR;
797 : 0 : closesocket(s);
798 : 0 : goto again;
799 : : }
800 : : /* else error */
801 : : }
802 : : /* else error */
803 : : }
804 : : #endif
805 : 0 : SYSerr(SYS_F_BIND,err_num);
806 : 0 : ERR_add_error_data(3,"port='",host,"'");
807 : 0 : BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_BIND_SOCKET);
808 : 0 : goto err;
809 : : }
810 [ # # ]: 0 : if (listen(s,MAX_LISTEN) == -1)
811 : : {
812 : 0 : SYSerr(SYS_F_BIND,get_last_socket_error());
813 : 0 : ERR_add_error_data(3,"port='",host,"'");
814 : 0 : BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_LISTEN_SOCKET);
815 : 0 : goto err;
816 : : }
817 : : ret=1;
818 : : err:
819 [ # # ]: 0 : if (str != NULL) OPENSSL_free(str);
820 [ # # ]: 0 : if ((ret == 0) && (s != INVALID_SOCKET))
821 : : {
822 : 0 : closesocket(s);
823 : 0 : s= INVALID_SOCKET;
824 : : }
825 : 0 : return(s);
826 : : }
827 : :
828 : 0 : int BIO_accept(int sock, char **addr)
829 : : {
830 : 0 : int ret=INVALID_SOCKET;
831 : : unsigned long l;
832 : : unsigned short port;
833 : : char *p;
834 : :
835 : : struct {
836 : : /*
837 : : * As for following union. Trouble is that there are platforms
838 : : * that have socklen_t and there are platforms that don't, on
839 : : * some platforms socklen_t is int and on some size_t. So what
840 : : * one can do? One can cook #ifdef spaghetti, which is nothing
841 : : * but masochistic. Or one can do union between int and size_t.
842 : : * One naturally does it primarily for 64-bit platforms where
843 : : * sizeof(int) != sizeof(size_t). But would it work? Note that
844 : : * if size_t member is initialized to 0, then later int member
845 : : * assignment naturally does the job on little-endian platforms
846 : : * regardless accept's expectations! What about big-endians?
847 : : * If accept expects int*, then it works, and if size_t*, then
848 : : * length value would appear as unreasonably large. But this
849 : : * won't prevent it from filling in the address structure. The
850 : : * trouble of course would be if accept returns more data than
851 : : * actual buffer can accomodate and overwrite stack... That's
852 : : * where early OPENSSL_assert comes into picture. Besides, the
853 : : * only 64-bit big-endian platform found so far that expects
854 : : * size_t* is HP-UX, where stack grows towards higher address.
855 : : * <appro>
856 : : */
857 : : union { size_t s; int i; } len;
858 : : union {
859 : : struct sockaddr sa;
860 : : struct sockaddr_in sa_in;
861 : : #if OPENSSL_USE_IPV6
862 : : struct sockaddr_in6 sa_in6;
863 : : #endif
864 : : } from;
865 : : } sa;
866 : :
867 : 0 : sa.len.s=0;
868 : 0 : sa.len.i=sizeof(sa.from);
869 : : memset(&sa.from,0,sizeof(sa.from));
870 : 0 : ret=accept(sock,&sa.from.sa,(void *)&sa.len);
871 [ # # ]: 0 : if (sizeof(sa.len.i)!=sizeof(sa.len.s) && sa.len.i==0)
872 : : {
873 [ # # ]: 0 : OPENSSL_assert(sa.len.s<=sizeof(sa.from));
874 : 0 : sa.len.i = (int)sa.len.s;
875 : : /* use sa.len.i from this point */
876 : : }
877 [ # # ]: 0 : if (ret == INVALID_SOCKET)
878 : : {
879 [ # # ]: 0 : if(BIO_sock_should_retry(ret)) return -2;
880 : 0 : SYSerr(SYS_F_ACCEPT,get_last_socket_error());
881 : 0 : BIOerr(BIO_F_BIO_ACCEPT,BIO_R_ACCEPT_ERROR);
882 : 0 : goto end;
883 : : }
884 : :
885 [ # # ]: 0 : if (addr == NULL) goto end;
886 : :
887 : : #ifdef EAI_FAMILY
888 : : do {
889 : : char h[NI_MAXHOST],s[NI_MAXSERV];
890 : : size_t nl;
891 : : static union { void *p;
892 : : int (WSAAPI *f)(const struct sockaddr *,size_t/*socklen_t*/,
893 : : char *,size_t,char *,size_t,int);
894 : : } p_getnameinfo = {NULL};
895 : : /* 2nd argument to getnameinfo is specified to
896 : : * be socklen_t. Unfortunately there is a number
897 : : * of environments where socklen_t is not defined.
898 : : * As it's passed by value, it's safe to pass it
899 : : * as size_t... <appro> */
900 : :
901 [ # # ]: 0 : if (p_getnameinfo.p==NULL)
902 : : {
903 [ # # ]: 0 : if ((p_getnameinfo.p=DSO_global_lookup("getnameinfo"))==NULL)
904 : 0 : p_getnameinfo.p=(void*)-1;
905 : : }
906 [ # # ]: 0 : if (p_getnameinfo.p==(void *)-1) break;
907 : :
908 [ # # ]: 0 : if ((*p_getnameinfo.f)(&sa.from.sa,sa.len.i,h,sizeof(h),s,sizeof(s),
909 : : NI_NUMERICHOST|NI_NUMERICSERV)) break;
910 : 0 : nl = strlen(h)+strlen(s)+2;
911 : 0 : p = *addr;
912 [ # # ]: 0 : if (p) { *p = '\0'; p = OPENSSL_realloc(p,nl); }
913 : 0 : else { p = OPENSSL_malloc(nl); }
914 [ # # ]: 0 : if (p==NULL)
915 : : {
916 : 0 : BIOerr(BIO_F_BIO_ACCEPT,ERR_R_MALLOC_FAILURE);
917 : 0 : goto end;
918 : : }
919 : 0 : *addr = p;
920 : 0 : BIO_snprintf(*addr,nl,"%s:%s",h,s);
921 : 0 : goto end;
922 : : } while(0);
923 : : #endif
924 [ # # ]: 0 : if (sa.from.sa.sa_family != AF_INET) goto end;
925 : 0 : l=ntohl(sa.from.sa_in.sin_addr.s_addr);
926 [ # # ]: 0 : port=ntohs(sa.from.sa_in.sin_port);
927 [ # # ]: 0 : if (*addr == NULL)
928 : : {
929 [ # # ]: 0 : if ((p=OPENSSL_malloc(24)) == NULL)
930 : : {
931 : 0 : BIOerr(BIO_F_BIO_ACCEPT,ERR_R_MALLOC_FAILURE);
932 : 0 : goto end;
933 : : }
934 : 0 : *addr=p;
935 : : }
936 : 0 : BIO_snprintf(*addr,24,"%d.%d.%d.%d:%d",
937 : 0 : (unsigned char)(l>>24L)&0xff,
938 : 0 : (unsigned char)(l>>16L)&0xff,
939 : 0 : (unsigned char)(l>> 8L)&0xff,
940 : : (unsigned char)(l )&0xff,
941 : : port);
942 : : end:
943 : 0 : return(ret);
944 : : }
945 : :
946 : 0 : int BIO_set_tcp_ndelay(int s, int on)
947 : : {
948 : 0 : int ret=0;
949 : : #if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP))
950 : : int opt;
951 : :
952 : : #ifdef SOL_TCP
953 : : opt=SOL_TCP;
954 : : #else
955 : : #ifdef IPPROTO_TCP
956 : : opt=IPPROTO_TCP;
957 : : #endif
958 : : #endif
959 : :
960 : : ret=setsockopt(s,opt,TCP_NODELAY,(char *)&on,sizeof(on));
961 : : #endif
962 : 0 : return(ret == 0);
963 : : }
964 : :
965 : 0 : int BIO_socket_nbio(int s, int mode)
966 : : {
967 : 0 : int ret= -1;
968 : : int l;
969 : :
970 : 0 : l=mode;
971 : : #ifdef FIONBIO
972 : 0 : ret=BIO_socket_ioctl(s,FIONBIO,&l);
973 : : #endif
974 : 0 : return(ret == 0);
975 : : }
976 : : #endif
|