diff options
Diffstat (limited to 'src/lib/libcrypto/bio/b_sock.c')
-rw-r--r-- | src/lib/libcrypto/bio/b_sock.c | 319 |
1 files changed, 197 insertions, 122 deletions
diff --git a/src/lib/libcrypto/bio/b_sock.c b/src/lib/libcrypto/bio/b_sock.c index a45909527c..d29b29ff8b 100644 --- a/src/lib/libcrypto/bio/b_sock.c +++ b/src/lib/libcrypto/bio/b_sock.c | |||
@@ -63,9 +63,7 @@ | |||
63 | #include <errno.h> | 63 | #include <errno.h> |
64 | #define USE_SOCKETS | 64 | #define USE_SOCKETS |
65 | #include "cryptlib.h" | 65 | #include "cryptlib.h" |
66 | #include "bio.h" | 66 | #include <openssl/bio.h> |
67 | |||
68 | /* BIOerr(BIO_F_WSASTARTUP,BIO_R_WSASTARTUP ); */ | ||
69 | 67 | ||
70 | #ifdef WIN16 | 68 | #ifdef WIN16 |
71 | #define SOCKET_PROTOCOL 0 /* more microsoft stupidity */ | 69 | #define SOCKET_PROTOCOL 0 /* more microsoft stupidity */ |
@@ -96,21 +94,14 @@ static struct ghbn_cache_st | |||
96 | unsigned long order; | 94 | unsigned long order; |
97 | } ghbn_cache[GHBN_NUM]; | 95 | } ghbn_cache[GHBN_NUM]; |
98 | 96 | ||
99 | #ifndef NOPROTO | 97 | static int get_ip(const char *str,unsigned char *ip); |
100 | static int get_ip(char *str,unsigned char *ip); | ||
101 | static void ghbn_free(struct hostent *a); | 98 | static void ghbn_free(struct hostent *a); |
102 | static struct hostent *ghbn_dup(struct hostent *a); | 99 | static struct hostent *ghbn_dup(struct hostent *a); |
103 | #else | 100 | int BIO_get_host_ip(const char *str, unsigned char *ip) |
104 | static int get_ip(); | ||
105 | static void ghbn_free(); | ||
106 | static struct hostent *ghbn_dup(); | ||
107 | #endif | ||
108 | |||
109 | int BIO_get_host_ip(str,ip) | ||
110 | char *str; | ||
111 | unsigned char *ip; | ||
112 | { | 101 | { |
113 | int i; | 102 | int i; |
103 | int err = 1; | ||
104 | int locked = 0; | ||
114 | struct hostent *he; | 105 | struct hostent *he; |
115 | 106 | ||
116 | i=get_ip(str,ip); | 107 | i=get_ip(str,ip); |
@@ -118,37 +109,45 @@ unsigned char *ip; | |||
118 | if (i < 0) | 109 | if (i < 0) |
119 | { | 110 | { |
120 | BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_INVALID_IP_ADDRESS); | 111 | BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_INVALID_IP_ADDRESS); |
121 | ERR_add_error_data(2,"host=",str); | 112 | goto err; |
122 | return(0); | ||
123 | } | 113 | } |
124 | else | ||
125 | { /* do a gethostbyname */ | ||
126 | if (!BIO_sock_init()) return(0); | ||
127 | 114 | ||
128 | he=BIO_gethostbyname(str); | 115 | /* do a gethostbyname */ |
129 | if (he == NULL) | 116 | if (!BIO_sock_init()) |
130 | { | 117 | return(0); /* don't generate another error code here */ |
131 | BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_BAD_HOSTNAME_LOOKUP); | ||
132 | ERR_add_error_data(2,"host=",str); | ||
133 | return(0); | ||
134 | } | ||
135 | 118 | ||
136 | /* cast to short because of win16 winsock definition */ | 119 | CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME); |
137 | if ((short)he->h_addrtype != AF_INET) | 120 | locked = 1; |
138 | { | 121 | he=BIO_gethostbyname(str); |
139 | BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET); | 122 | if (he == NULL) |
140 | ERR_add_error_data(2,"host=",str); | 123 | { |
141 | return(0); | 124 | BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_BAD_HOSTNAME_LOOKUP); |
142 | } | 125 | goto err; |
143 | for (i=0; i<4; i++) | ||
144 | ip[i]=he->h_addr_list[0][i]; | ||
145 | } | 126 | } |
146 | return(1); | 127 | |
128 | /* cast to short because of win16 winsock definition */ | ||
129 | if ((short)he->h_addrtype != AF_INET) | ||
130 | { | ||
131 | BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET); | ||
132 | goto err; | ||
133 | } | ||
134 | for (i=0; i<4; i++) | ||
135 | ip[i]=he->h_addr_list[0][i]; | ||
136 | err = 0; | ||
137 | |||
138 | err: | ||
139 | if (locked) | ||
140 | CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME); | ||
141 | if (err) | ||
142 | { | ||
143 | ERR_add_error_data(2,"host=",str); | ||
144 | return 0; | ||
145 | } | ||
146 | else | ||
147 | return 1; | ||
147 | } | 148 | } |
148 | 149 | ||
149 | int BIO_get_port(str,port_ptr) | 150 | int BIO_get_port(const char *str, unsigned short *port_ptr) |
150 | char *str; | ||
151 | short *port_ptr; | ||
152 | { | 151 | { |
153 | int i; | 152 | int i; |
154 | struct servent *s; | 153 | struct servent *s; |
@@ -163,8 +162,12 @@ short *port_ptr; | |||
163 | *port_ptr=(unsigned short)i; | 162 | *port_ptr=(unsigned short)i; |
164 | else | 163 | else |
165 | { | 164 | { |
166 | s=getservbyname(str,"tcp"); | 165 | CRYPTO_w_lock(CRYPTO_LOCK_GETSERVBYNAME); |
167 | if (s == NULL) | 166 | s=getservbyname(str,"tcp"); |
167 | if(s != NULL) | ||
168 | *port_ptr=ntohs((unsigned short)s->s_port); | ||
169 | CRYPTO_w_unlock(CRYPTO_LOCK_GETSERVBYNAME); | ||
170 | if(s == NULL) | ||
168 | { | 171 | { |
169 | if (strcmp(str,"http") == 0) | 172 | if (strcmp(str,"http") == 0) |
170 | *port_ptr=80; | 173 | *port_ptr=80; |
@@ -190,31 +193,30 @@ short *port_ptr; | |||
190 | ERR_add_error_data(3,"service='",str,"'"); | 193 | ERR_add_error_data(3,"service='",str,"'"); |
191 | return(0); | 194 | return(0); |
192 | } | 195 | } |
193 | return(1); | ||
194 | } | 196 | } |
195 | *port_ptr=htons((unsigned short)s->s_port); | ||
196 | } | 197 | } |
197 | return(1); | 198 | return(1); |
198 | } | 199 | } |
199 | 200 | ||
200 | int BIO_sock_error(sock) | 201 | int BIO_sock_error(int sock) |
201 | int sock; | ||
202 | { | 202 | { |
203 | int j,i,size; | 203 | int j,i; |
204 | int size; | ||
204 | 205 | ||
205 | size=sizeof(int); | 206 | size=sizeof(int); |
206 | 207 | /* Note: under Windows the third parameter is of type (char *) | |
207 | i=getsockopt(sock,SOL_SOCKET,SO_ERROR,(char *)&j,&size); | 208 | * whereas under other systems it is (void *) if you don't have |
209 | * a cast it will choke the compiler: if you do have a cast then | ||
210 | * you can either go for (char *) or (void *). | ||
211 | */ | ||
212 | i=getsockopt(sock,SOL_SOCKET,SO_ERROR,(void *)&j,(void *)&size); | ||
208 | if (i < 0) | 213 | if (i < 0) |
209 | return(1); | 214 | return(1); |
210 | else | 215 | else |
211 | return(j); | 216 | return(j); |
212 | } | 217 | } |
213 | 218 | ||
214 | long BIO_ghbn_ctrl(cmd,iarg,parg) | 219 | long BIO_ghbn_ctrl(int cmd, int iarg, char *parg) |
215 | int cmd; | ||
216 | int iarg; | ||
217 | char *parg; | ||
218 | { | 220 | { |
219 | int i; | 221 | int i; |
220 | char **p; | 222 | char **p; |
@@ -223,13 +225,13 @@ char *parg; | |||
223 | { | 225 | { |
224 | case BIO_GHBN_CTRL_HITS: | 226 | case BIO_GHBN_CTRL_HITS: |
225 | return(BIO_ghbn_hits); | 227 | return(BIO_ghbn_hits); |
226 | break; | 228 | /* break; */ |
227 | case BIO_GHBN_CTRL_MISSES: | 229 | case BIO_GHBN_CTRL_MISSES: |
228 | return(BIO_ghbn_miss); | 230 | return(BIO_ghbn_miss); |
229 | break; | 231 | /* break; */ |
230 | case BIO_GHBN_CTRL_CACHE_SIZE: | 232 | case BIO_GHBN_CTRL_CACHE_SIZE: |
231 | return(GHBN_NUM); | 233 | return(GHBN_NUM); |
232 | break; | 234 | /* break; */ |
233 | case BIO_GHBN_CTRL_GET_ENTRY: | 235 | case BIO_GHBN_CTRL_GET_ENTRY: |
234 | if ((iarg >= 0) && (iarg <GHBN_NUM) && | 236 | if ((iarg >= 0) && (iarg <GHBN_NUM) && |
235 | (ghbn_cache[iarg].order > 0)) | 237 | (ghbn_cache[iarg].order > 0)) |
@@ -241,7 +243,7 @@ char *parg; | |||
241 | return(1); | 243 | return(1); |
242 | } | 244 | } |
243 | return(0); | 245 | return(0); |
244 | break; | 246 | /* break; */ |
245 | case BIO_GHBN_CTRL_FLUSH: | 247 | case BIO_GHBN_CTRL_FLUSH: |
246 | for (i=0; i<GHBN_NUM; i++) | 248 | for (i=0; i<GHBN_NUM; i++) |
247 | ghbn_cache[i].order=0; | 249 | ghbn_cache[i].order=0; |
@@ -252,77 +254,84 @@ char *parg; | |||
252 | return(1); | 254 | return(1); |
253 | } | 255 | } |
254 | 256 | ||
255 | static struct hostent *ghbn_dup(a) | 257 | static struct hostent *ghbn_dup(struct hostent *a) |
256 | struct hostent *a; | ||
257 | { | 258 | { |
258 | struct hostent *ret; | 259 | struct hostent *ret; |
259 | int i,j; | 260 | int i,j; |
260 | 261 | ||
261 | ret=(struct hostent *)malloc(sizeof(struct hostent)); | 262 | MemCheck_off(); |
263 | ret=(struct hostent *)Malloc(sizeof(struct hostent)); | ||
262 | if (ret == NULL) return(NULL); | 264 | if (ret == NULL) return(NULL); |
263 | memset(ret,0,sizeof(struct hostent)); | 265 | memset(ret,0,sizeof(struct hostent)); |
264 | 266 | ||
265 | for (i=0; a->h_aliases[i] != NULL; i++) | 267 | for (i=0; a->h_aliases[i] != NULL; i++) |
266 | ; | 268 | ; |
267 | i++; | 269 | i++; |
268 | ret->h_aliases=(char **)malloc(sizeof(char *)*i); | 270 | ret->h_aliases = (char **)Malloc(i*sizeof(char *)); |
269 | memset(ret->h_aliases,0,sizeof(char *)*i); | 271 | if (ret->h_aliases == NULL) |
270 | if (ret == NULL) goto err; | 272 | goto err; |
273 | memset(ret->h_aliases, 0, i*sizeof(char *)); | ||
271 | 274 | ||
272 | for (i=0; a->h_addr_list[i] != NULL; i++) | 275 | for (i=0; a->h_addr_list[i] != NULL; i++) |
273 | ; | 276 | ; |
274 | i++; | 277 | i++; |
275 | ret->h_addr_list=(char **)malloc(sizeof(char *)*i); | 278 | ret->h_addr_list=(char **)Malloc(i*sizeof(char *)); |
276 | memset(ret->h_addr_list,0,sizeof(char *)*i); | 279 | if (ret->h_addr_list == NULL) |
277 | if (ret->h_addr_list == NULL) goto err; | 280 | goto err; |
281 | memset(ret->h_addr_list, 0, i*sizeof(char *)); | ||
278 | 282 | ||
279 | j=strlen(a->h_name)+1; | 283 | j=strlen(a->h_name)+1; |
280 | if ((ret->h_name=malloc(j)) == NULL) goto err; | 284 | if ((ret->h_name=Malloc(j)) == NULL) goto err; |
281 | memcpy((char *)ret->h_name,a->h_name,j); | 285 | memcpy((char *)ret->h_name,a->h_name,j+1); |
282 | for (i=0; a->h_aliases[i] != NULL; i++) | 286 | for (i=0; a->h_aliases[i] != NULL; i++) |
283 | { | 287 | { |
284 | j=strlen(a->h_aliases[i])+1; | 288 | j=strlen(a->h_aliases[i])+1; |
285 | if ((ret->h_aliases[i]=malloc(j)) == NULL) goto err; | 289 | if ((ret->h_aliases[i]=Malloc(j)) == NULL) goto err; |
286 | memcpy(ret->h_aliases[i],a->h_aliases[i],j); | 290 | memcpy(ret->h_aliases[i],a->h_aliases[i],j+1); |
287 | } | 291 | } |
288 | ret->h_length=a->h_length; | 292 | ret->h_length=a->h_length; |
289 | ret->h_addrtype=a->h_addrtype; | 293 | ret->h_addrtype=a->h_addrtype; |
290 | for (i=0; a->h_addr_list[i] != NULL; i++) | 294 | for (i=0; a->h_addr_list[i] != NULL; i++) |
291 | { | 295 | { |
292 | if ((ret->h_addr_list[i]=malloc(a->h_length)) == NULL) | 296 | if ((ret->h_addr_list[i]=Malloc(a->h_length)) == NULL) |
293 | goto err; | 297 | goto err; |
294 | memcpy(ret->h_addr_list[i],a->h_addr_list[i],a->h_length); | 298 | memcpy(ret->h_addr_list[i],a->h_addr_list[i],a->h_length); |
295 | } | 299 | } |
296 | return(ret); | 300 | if (0) |
301 | { | ||
297 | err: | 302 | err: |
298 | if (ret != NULL) | 303 | if (ret != NULL) |
299 | ghbn_free(ret); | 304 | ghbn_free(ret); |
300 | return(NULL); | 305 | ret=NULL; |
306 | } | ||
307 | MemCheck_on(); | ||
308 | return(ret); | ||
301 | } | 309 | } |
302 | 310 | ||
303 | static void ghbn_free(a) | 311 | static void ghbn_free(struct hostent *a) |
304 | struct hostent *a; | ||
305 | { | 312 | { |
306 | int i; | 313 | int i; |
307 | 314 | ||
315 | if(a == NULL) | ||
316 | return; | ||
317 | |||
308 | if (a->h_aliases != NULL) | 318 | if (a->h_aliases != NULL) |
309 | { | 319 | { |
310 | for (i=0; a->h_aliases[i] != NULL; i++) | 320 | for (i=0; a->h_aliases[i] != NULL; i++) |
311 | free(a->h_aliases[i]); | 321 | Free(a->h_aliases[i]); |
312 | free(a->h_aliases); | 322 | Free(a->h_aliases); |
313 | } | 323 | } |
314 | if (a->h_addr_list != NULL) | 324 | if (a->h_addr_list != NULL) |
315 | { | 325 | { |
316 | for (i=0; a->h_addr_list[i] != NULL; i++) | 326 | for (i=0; a->h_addr_list[i] != NULL; i++) |
317 | free(a->h_addr_list[i]); | 327 | Free(a->h_addr_list[i]); |
318 | free(a->h_addr_list); | 328 | Free(a->h_addr_list); |
319 | } | 329 | } |
320 | if (a->h_name != NULL) free((char *)a->h_name); | 330 | if (a->h_name != NULL) Free((char *)a->h_name); |
321 | free(a); | 331 | Free(a); |
322 | } | 332 | } |
323 | 333 | ||
324 | struct hostent *BIO_gethostbyname(name) | 334 | struct hostent *BIO_gethostbyname(const char *name) |
325 | char *name; | ||
326 | { | 335 | { |
327 | struct hostent *ret; | 336 | struct hostent *ret; |
328 | int i,lowi=0,j; | 337 | int i,lowi=0,j; |
@@ -330,7 +339,12 @@ char *name; | |||
330 | 339 | ||
331 | /* return(gethostbyname(name)); */ | 340 | /* return(gethostbyname(name)); */ |
332 | 341 | ||
333 | CRYPTO_w_lock(CRYPTO_LOCK_BIO_GETHOSTBYNAME); | 342 | #if 0 /* It doesn't make sense to use locking here: The function interface |
343 | * is not thread-safe, because threads can never be sure when | ||
344 | * some other thread destroys the data they were given a pointer to. | ||
345 | */ | ||
346 | CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME); | ||
347 | #endif | ||
334 | j=strlen(name); | 348 | j=strlen(name); |
335 | if (j < 128) | 349 | if (j < 128) |
336 | { | 350 | { |
@@ -356,15 +370,29 @@ char *name; | |||
356 | BIO_ghbn_miss++; | 370 | BIO_ghbn_miss++; |
357 | ret=gethostbyname(name); | 371 | ret=gethostbyname(name); |
358 | 372 | ||
359 | if (ret == NULL) return(NULL); | 373 | if (ret == NULL) |
360 | if (j > 128) return(ret); /* too big to cache */ | 374 | goto end; |
375 | if (j > 128) /* too big to cache */ | ||
376 | { | ||
377 | #if 0 /* If we were trying to make this function thread-safe (which | ||
378 | * is bound to fail), we'd have to give up in this case | ||
379 | * (or allocate more memory). */ | ||
380 | ret = NULL; | ||
381 | #endif | ||
382 | goto end; | ||
383 | } | ||
361 | 384 | ||
362 | /* else add to cache */ | 385 | /* else add to cache */ |
363 | if (ghbn_cache[lowi].ent != NULL) | 386 | if (ghbn_cache[lowi].ent != NULL) |
364 | ghbn_free(ghbn_cache[lowi].ent); | 387 | ghbn_free(ghbn_cache[lowi].ent); /* XXX not thread-safe */ |
388 | ghbn_cache[lowi].name[0] = '\0'; | ||
365 | 389 | ||
390 | if((ret=ghbn_cache[lowi].ent=ghbn_dup(ret)) == NULL) | ||
391 | { | ||
392 | BIOerr(BIO_F_BIO_GETHOSTBYNAME,ERR_R_MALLOC_FAILURE); | ||
393 | goto end; | ||
394 | } | ||
366 | strncpy(ghbn_cache[lowi].name,name,128); | 395 | strncpy(ghbn_cache[lowi].name,name,128); |
367 | ghbn_cache[lowi].ent=ghbn_dup(ret); | ||
368 | ghbn_cache[lowi].order=BIO_ghbn_miss+BIO_ghbn_hits; | 396 | ghbn_cache[lowi].order=BIO_ghbn_miss+BIO_ghbn_hits; |
369 | } | 397 | } |
370 | else | 398 | else |
@@ -373,11 +401,14 @@ char *name; | |||
373 | ret= ghbn_cache[i].ent; | 401 | ret= ghbn_cache[i].ent; |
374 | ghbn_cache[i].order=BIO_ghbn_miss+BIO_ghbn_hits; | 402 | ghbn_cache[i].order=BIO_ghbn_miss+BIO_ghbn_hits; |
375 | } | 403 | } |
376 | CRYPTO_w_unlock(CRYPTO_LOCK_BIO_GETHOSTBYNAME); | 404 | end: |
405 | #if 0 | ||
406 | CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME); | ||
407 | #endif | ||
377 | return(ret); | 408 | return(ret); |
378 | } | 409 | } |
379 | 410 | ||
380 | int BIO_sock_init() | 411 | int BIO_sock_init(void) |
381 | { | 412 | { |
382 | #ifdef WINDOWS | 413 | #ifdef WINDOWS |
383 | static struct WSAData wsa_state; | 414 | static struct WSAData wsa_state; |
@@ -403,7 +434,7 @@ int BIO_sock_init() | |||
403 | return(1); | 434 | return(1); |
404 | } | 435 | } |
405 | 436 | ||
406 | void BIO_sock_cleanup() | 437 | void BIO_sock_cleanup(void) |
407 | { | 438 | { |
408 | #ifdef WINDOWS | 439 | #ifdef WINDOWS |
409 | if (wsa_init_done) | 440 | if (wsa_init_done) |
@@ -415,10 +446,9 @@ void BIO_sock_cleanup() | |||
415 | #endif | 446 | #endif |
416 | } | 447 | } |
417 | 448 | ||
418 | int BIO_socket_ioctl(fd,type,arg) | 449 | #if !defined(VMS) || __VMS_VER >= 70000000 |
419 | int fd; | 450 | |
420 | long type; | 451 | int BIO_socket_ioctl(int fd, long type, unsigned long *arg) |
421 | unsigned long *arg; | ||
422 | { | 452 | { |
423 | int i; | 453 | int i; |
424 | 454 | ||
@@ -427,12 +457,11 @@ unsigned long *arg; | |||
427 | SYSerr(SYS_F_IOCTLSOCKET,get_last_socket_error()); | 457 | SYSerr(SYS_F_IOCTLSOCKET,get_last_socket_error()); |
428 | return(i); | 458 | return(i); |
429 | } | 459 | } |
460 | #endif /* __VMS_VER */ | ||
430 | 461 | ||
431 | /* The reason I have implemented this instead of using sscanf is because | 462 | /* The reason I have implemented this instead of using sscanf is because |
432 | * Visual C 1.52c gives an unresolved external when linking a DLL :-( */ | 463 | * Visual C 1.52c gives an unresolved external when linking a DLL :-( */ |
433 | static int get_ip(str,ip) | 464 | static int get_ip(const char *str, unsigned char ip[4]) |
434 | char *str; | ||
435 | unsigned char ip[4]; | ||
436 | { | 465 | { |
437 | unsigned int tmp[4]; | 466 | unsigned int tmp[4]; |
438 | int num=0,c,ok=0; | 467 | int num=0,c,ok=0; |
@@ -467,16 +496,17 @@ unsigned char ip[4]; | |||
467 | return(1); | 496 | return(1); |
468 | } | 497 | } |
469 | 498 | ||
470 | int BIO_get_accept_socket(host) | 499 | int BIO_get_accept_socket(char *host, int bind_mode) |
471 | char *host; | ||
472 | { | 500 | { |
473 | int ret=0; | 501 | int ret=0; |
474 | struct sockaddr_in server; | 502 | struct sockaddr_in server,client; |
475 | int s= -1; | 503 | int s= -1,cs; |
476 | unsigned char ip[4]; | 504 | unsigned char ip[4]; |
477 | short port; | 505 | unsigned short port; |
478 | char *str,*h,*p,*e; | 506 | char *str,*e; |
507 | const char *h,*p; | ||
479 | unsigned long l; | 508 | unsigned long l; |
509 | int err_num; | ||
480 | 510 | ||
481 | if (!BIO_sock_init()) return(INVALID_SOCKET); | 511 | if (!BIO_sock_init()) return(INVALID_SOCKET); |
482 | 512 | ||
@@ -508,7 +538,7 @@ char *host; | |||
508 | 538 | ||
509 | memset((char *)&server,0,sizeof(server)); | 539 | memset((char *)&server,0,sizeof(server)); |
510 | server.sin_family=AF_INET; | 540 | server.sin_family=AF_INET; |
511 | server.sin_port=htons((unsigned short)port); | 541 | server.sin_port=htons(port); |
512 | 542 | ||
513 | if (strcmp(h,"*") == 0) | 543 | if (strcmp(h,"*") == 0) |
514 | server.sin_addr.s_addr=INADDR_ANY; | 544 | server.sin_addr.s_addr=INADDR_ANY; |
@@ -517,12 +547,13 @@ char *host; | |||
517 | if (!BIO_get_host_ip(h,&(ip[0]))) return(INVALID_SOCKET); | 547 | if (!BIO_get_host_ip(h,&(ip[0]))) return(INVALID_SOCKET); |
518 | l=(unsigned long) | 548 | l=(unsigned long) |
519 | ((unsigned long)ip[0]<<24L)| | 549 | ((unsigned long)ip[0]<<24L)| |
520 | ((unsigned long)ip[0]<<16L)| | 550 | ((unsigned long)ip[1]<<16L)| |
521 | ((unsigned long)ip[0]<< 8L)| | 551 | ((unsigned long)ip[2]<< 8L)| |
522 | ((unsigned long)ip[0]); | 552 | ((unsigned long)ip[3]); |
523 | server.sin_addr.s_addr=htonl(l); | 553 | server.sin_addr.s_addr=htonl(l); |
524 | } | 554 | } |
525 | 555 | ||
556 | again: | ||
526 | s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); | 557 | s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); |
527 | if (s == INVALID_SOCKET) | 558 | if (s == INVALID_SOCKET) |
528 | { | 559 | { |
@@ -531,9 +562,45 @@ char *host; | |||
531 | BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_CREATE_SOCKET); | 562 | BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_CREATE_SOCKET); |
532 | goto err; | 563 | goto err; |
533 | } | 564 | } |
565 | |||
566 | #ifdef SO_REUSEADDR | ||
567 | if (bind_mode == BIO_BIND_REUSEADDR) | ||
568 | { | ||
569 | int i=1; | ||
570 | |||
571 | ret=setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&i,sizeof(i)); | ||
572 | bind_mode=BIO_BIND_NORMAL; | ||
573 | } | ||
574 | #endif | ||
534 | if (bind(s,(struct sockaddr *)&server,sizeof(server)) == -1) | 575 | if (bind(s,(struct sockaddr *)&server,sizeof(server)) == -1) |
535 | { | 576 | { |
536 | SYSerr(SYS_F_BIND,get_last_socket_error()); | 577 | #ifdef SO_REUSEADDR |
578 | err_num=get_last_socket_error(); | ||
579 | if ((bind_mode == BIO_BIND_REUSEADDR_IF_UNUSED) && | ||
580 | (err_num == EADDRINUSE)) | ||
581 | { | ||
582 | memcpy((char *)&client,(char *)&server,sizeof(server)); | ||
583 | if (strcmp(h,"*") == 0) | ||
584 | client.sin_addr.s_addr=htonl(0x7F000001); | ||
585 | cs=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); | ||
586 | if (cs != INVALID_SOCKET) | ||
587 | { | ||
588 | int ii; | ||
589 | ii=connect(cs,(struct sockaddr *)&client, | ||
590 | sizeof(client)); | ||
591 | closesocket(cs); | ||
592 | if (ii == INVALID_SOCKET) | ||
593 | { | ||
594 | bind_mode=BIO_BIND_REUSEADDR; | ||
595 | closesocket(s); | ||
596 | goto again; | ||
597 | } | ||
598 | /* else error */ | ||
599 | } | ||
600 | /* else error */ | ||
601 | } | ||
602 | #endif | ||
603 | SYSerr(SYS_F_BIND,err_num); | ||
537 | ERR_add_error_data(3,"port='",host,"'"); | 604 | ERR_add_error_data(3,"port='",host,"'"); |
538 | BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_BIND_SOCKET); | 605 | BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_BIND_SOCKET); |
539 | goto err; | 606 | goto err; |
@@ -550,30 +617,29 @@ err: | |||
550 | if (str != NULL) Free(str); | 617 | if (str != NULL) Free(str); |
551 | if ((ret == 0) && (s != INVALID_SOCKET)) | 618 | if ((ret == 0) && (s != INVALID_SOCKET)) |
552 | { | 619 | { |
553 | #ifdef WINDOWS | ||
554 | closesocket(s); | 620 | closesocket(s); |
555 | #else | ||
556 | close(s); | ||
557 | #endif | ||
558 | s= INVALID_SOCKET; | 621 | s= INVALID_SOCKET; |
559 | } | 622 | } |
560 | return(s); | 623 | return(s); |
561 | } | 624 | } |
562 | 625 | ||
563 | int BIO_accept(sock,addr) | 626 | int BIO_accept(int sock, char **addr) |
564 | int sock; | ||
565 | char **addr; | ||
566 | { | 627 | { |
567 | int ret=INVALID_SOCKET; | 628 | int ret=INVALID_SOCKET; |
568 | static struct sockaddr_in from; | 629 | static struct sockaddr_in from; |
569 | unsigned long l; | 630 | unsigned long l; |
570 | short port; | 631 | unsigned short port; |
571 | int len; | 632 | int len; |
572 | char *p; | 633 | char *p; |
573 | 634 | ||
574 | memset((char *)&from,0,sizeof(from)); | 635 | memset((char *)&from,0,sizeof(from)); |
575 | len=sizeof(from); | 636 | len=sizeof(from); |
576 | ret=accept(sock,(struct sockaddr *)&from,&len); | 637 | /* Note: under VMS with SOCKETSHR the fourth parameter is currently |
638 | * of type (int *) whereas under other systems it is (void *) if | ||
639 | * you don't have a cast it will choke the compiler: if you do | ||
640 | * have a cast then you can either go for (int *) or (void *). | ||
641 | */ | ||
642 | ret=accept(sock,(struct sockaddr *)&from,(void *)&len); | ||
577 | if (ret == INVALID_SOCKET) | 643 | if (ret == INVALID_SOCKET) |
578 | { | 644 | { |
579 | SYSerr(SYS_F_ACCEPT,get_last_socket_error()); | 645 | SYSerr(SYS_F_ACCEPT,get_last_socket_error()); |
@@ -604,9 +670,7 @@ end: | |||
604 | return(ret); | 670 | return(ret); |
605 | } | 671 | } |
606 | 672 | ||
607 | int BIO_set_tcp_ndelay(s,on) | 673 | int BIO_set_tcp_ndelay(int s, int on) |
608 | int s; | ||
609 | int on; | ||
610 | { | 674 | { |
611 | int ret=0; | 675 | int ret=0; |
612 | #if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP)) | 676 | #if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP)) |
@@ -626,3 +690,14 @@ int on; | |||
626 | } | 690 | } |
627 | #endif | 691 | #endif |
628 | 692 | ||
693 | int BIO_socket_nbio(int s, int mode) | ||
694 | { | ||
695 | int ret= -1; | ||
696 | unsigned long l; | ||
697 | |||
698 | l=mode; | ||
699 | #ifdef FIONBIO | ||
700 | ret=BIO_socket_ioctl(s,FIONBIO,&l); | ||
701 | #endif | ||
702 | return(ret == 0); | ||
703 | } | ||