diff options
Diffstat (limited to 'src/lib/libssl/src/crypto/bio/b_sock.c')
-rw-r--r-- | src/lib/libssl/src/crypto/bio/b_sock.c | 386 |
1 files changed, 247 insertions, 139 deletions
diff --git a/src/lib/libssl/src/crypto/bio/b_sock.c b/src/lib/libssl/src/crypto/bio/b_sock.c index a45909527c..dcaef68ea7 100644 --- a/src/lib/libssl/src/crypto/bio/b_sock.c +++ b/src/lib/libssl/src/crypto/bio/b_sock.c | |||
@@ -56,32 +56,30 @@ | |||
56 | * [including the GNU Public Licence.] | 56 | * [including the GNU Public Licence.] |
57 | */ | 57 | */ |
58 | 58 | ||
59 | #ifndef NO_SOCK | 59 | #ifndef OPENSSL_NO_SOCK |
60 | 60 | ||
61 | #include <stdio.h> | 61 | #include <stdio.h> |
62 | #include <stdlib.h> | 62 | #include <stdlib.h> |
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 | 67 | ||
68 | /* BIOerr(BIO_F_WSASTARTUP,BIO_R_WSASTARTUP ); */ | 68 | #ifdef OPENSSL_SYS_WIN16 |
69 | |||
70 | #ifdef WIN16 | ||
71 | #define SOCKET_PROTOCOL 0 /* more microsoft stupidity */ | 69 | #define SOCKET_PROTOCOL 0 /* more microsoft stupidity */ |
72 | #else | 70 | #else |
73 | #define SOCKET_PROTOCOL IPPROTO_TCP | 71 | #define SOCKET_PROTOCOL IPPROTO_TCP |
74 | #endif | 72 | #endif |
75 | 73 | ||
76 | #ifdef SO_MAXCONN | 74 | #ifdef SO_MAXCONN |
77 | #define MAX_LISTEN SOMAXCONN | ||
78 | #elif defined(SO_MAXCONN) | ||
79 | #define MAX_LISTEN SO_MAXCONN | 75 | #define MAX_LISTEN SO_MAXCONN |
76 | #elif defined(SOMAXCONN) | ||
77 | #define MAX_LISTEN SOMAXCONN | ||
80 | #else | 78 | #else |
81 | #define MAX_LISTEN 32 | 79 | #define MAX_LISTEN 32 |
82 | #endif | 80 | #endif |
83 | 81 | ||
84 | #ifdef WINDOWS | 82 | #ifdef OPENSSL_SYS_WINDOWS |
85 | static int wsa_init_done=0; | 83 | static int wsa_init_done=0; |
86 | #endif | 84 | #endif |
87 | 85 | ||
@@ -96,59 +94,67 @@ 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); | 98 | #if 0 |
101 | static void ghbn_free(struct hostent *a); | 99 | static void ghbn_free(struct hostent *a); |
102 | static struct hostent *ghbn_dup(struct hostent *a); | 100 | static struct hostent *ghbn_dup(struct hostent *a); |
103 | #else | ||
104 | static int get_ip(); | ||
105 | static void ghbn_free(); | ||
106 | static struct hostent *ghbn_dup(); | ||
107 | #endif | 101 | #endif |
108 | 102 | int BIO_get_host_ip(const char *str, unsigned char *ip) | |
109 | int BIO_get_host_ip(str,ip) | ||
110 | char *str; | ||
111 | unsigned char *ip; | ||
112 | { | 103 | { |
113 | int i; | 104 | int i; |
105 | int err = 1; | ||
106 | int locked = 0; | ||
114 | struct hostent *he; | 107 | struct hostent *he; |
115 | 108 | ||
116 | i=get_ip(str,ip); | 109 | i=get_ip(str,ip); |
117 | if (i > 0) return(1); | ||
118 | if (i < 0) | 110 | if (i < 0) |
119 | { | 111 | { |
120 | BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_INVALID_IP_ADDRESS); | 112 | BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_INVALID_IP_ADDRESS); |
121 | ERR_add_error_data(2,"host=",str); | 113 | goto err; |
122 | return(0); | ||
123 | } | 114 | } |
124 | else | ||
125 | { /* do a gethostbyname */ | ||
126 | if (!BIO_sock_init()) return(0); | ||
127 | 115 | ||
128 | he=BIO_gethostbyname(str); | 116 | /* At this point, we have something that is most probably correct |
129 | if (he == NULL) | 117 | in some way, so let's init the socket. */ |
130 | { | 118 | if (BIO_sock_init() != 1) |
131 | BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_BAD_HOSTNAME_LOOKUP); | 119 | return 0; /* don't generate another error code here */ |
132 | ERR_add_error_data(2,"host=",str); | ||
133 | return(0); | ||
134 | } | ||
135 | 120 | ||
136 | /* cast to short because of win16 winsock definition */ | 121 | /* If the string actually contained an IP address, we need not do |
137 | if ((short)he->h_addrtype != AF_INET) | 122 | anything more */ |
138 | { | 123 | if (i > 0) return(1); |
139 | BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET); | 124 | |
140 | ERR_add_error_data(2,"host=",str); | 125 | /* do a gethostbyname */ |
141 | return(0); | 126 | CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME); |
142 | } | 127 | locked = 1; |
143 | for (i=0; i<4; i++) | 128 | he=BIO_gethostbyname(str); |
144 | ip[i]=he->h_addr_list[0][i]; | 129 | if (he == NULL) |
130 | { | ||
131 | BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_BAD_HOSTNAME_LOOKUP); | ||
132 | goto err; | ||
145 | } | 133 | } |
146 | return(1); | 134 | |
135 | /* cast to short because of win16 winsock definition */ | ||
136 | if ((short)he->h_addrtype != AF_INET) | ||
137 | { | ||
138 | BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET); | ||
139 | goto err; | ||
140 | } | ||
141 | for (i=0; i<4; i++) | ||
142 | ip[i]=he->h_addr_list[0][i]; | ||
143 | err = 0; | ||
144 | |||
145 | err: | ||
146 | if (locked) | ||
147 | CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME); | ||
148 | if (err) | ||
149 | { | ||
150 | ERR_add_error_data(2,"host=",str); | ||
151 | return 0; | ||
152 | } | ||
153 | else | ||
154 | return 1; | ||
147 | } | 155 | } |
148 | 156 | ||
149 | int BIO_get_port(str,port_ptr) | 157 | int BIO_get_port(const char *str, unsigned short *port_ptr) |
150 | char *str; | ||
151 | short *port_ptr; | ||
152 | { | 158 | { |
153 | int i; | 159 | int i; |
154 | struct servent *s; | 160 | struct servent *s; |
@@ -163,8 +169,19 @@ short *port_ptr; | |||
163 | *port_ptr=(unsigned short)i; | 169 | *port_ptr=(unsigned short)i; |
164 | else | 170 | else |
165 | { | 171 | { |
166 | s=getservbyname(str,"tcp"); | 172 | CRYPTO_w_lock(CRYPTO_LOCK_GETSERVBYNAME); |
167 | if (s == NULL) | 173 | /* Note: under VMS with SOCKETSHR, it seems like the first |
174 | * parameter is 'char *', instead of 'const char *' | ||
175 | */ | ||
176 | s=getservbyname( | ||
177 | #ifndef CONST_STRICT | ||
178 | (char *) | ||
179 | #endif | ||
180 | str,"tcp"); | ||
181 | if(s != NULL) | ||
182 | *port_ptr=ntohs((unsigned short)s->s_port); | ||
183 | CRYPTO_w_unlock(CRYPTO_LOCK_GETSERVBYNAME); | ||
184 | if(s == NULL) | ||
168 | { | 185 | { |
169 | if (strcmp(str,"http") == 0) | 186 | if (strcmp(str,"http") == 0) |
170 | *port_ptr=80; | 187 | *port_ptr=80; |
@@ -190,31 +207,30 @@ short *port_ptr; | |||
190 | ERR_add_error_data(3,"service='",str,"'"); | 207 | ERR_add_error_data(3,"service='",str,"'"); |
191 | return(0); | 208 | return(0); |
192 | } | 209 | } |
193 | return(1); | ||
194 | } | 210 | } |
195 | *port_ptr=htons((unsigned short)s->s_port); | ||
196 | } | 211 | } |
197 | return(1); | 212 | return(1); |
198 | } | 213 | } |
199 | 214 | ||
200 | int BIO_sock_error(sock) | 215 | int BIO_sock_error(int sock) |
201 | int sock; | ||
202 | { | 216 | { |
203 | int j,i,size; | 217 | int j,i; |
218 | int size; | ||
204 | 219 | ||
205 | size=sizeof(int); | 220 | size=sizeof(int); |
206 | 221 | /* Note: under Windows the third parameter is of type (char *) | |
207 | i=getsockopt(sock,SOL_SOCKET,SO_ERROR,(char *)&j,&size); | 222 | * whereas under other systems it is (void *) if you don't have |
223 | * a cast it will choke the compiler: if you do have a cast then | ||
224 | * you can either go for (char *) or (void *). | ||
225 | */ | ||
226 | i=getsockopt(sock,SOL_SOCKET,SO_ERROR,(void *)&j,(void *)&size); | ||
208 | if (i < 0) | 227 | if (i < 0) |
209 | return(1); | 228 | return(1); |
210 | else | 229 | else |
211 | return(j); | 230 | return(j); |
212 | } | 231 | } |
213 | 232 | ||
214 | long BIO_ghbn_ctrl(cmd,iarg,parg) | 233 | long BIO_ghbn_ctrl(int cmd, int iarg, char *parg) |
215 | int cmd; | ||
216 | int iarg; | ||
217 | char *parg; | ||
218 | { | 234 | { |
219 | int i; | 235 | int i; |
220 | char **p; | 236 | char **p; |
@@ -223,13 +239,13 @@ char *parg; | |||
223 | { | 239 | { |
224 | case BIO_GHBN_CTRL_HITS: | 240 | case BIO_GHBN_CTRL_HITS: |
225 | return(BIO_ghbn_hits); | 241 | return(BIO_ghbn_hits); |
226 | break; | 242 | /* break; */ |
227 | case BIO_GHBN_CTRL_MISSES: | 243 | case BIO_GHBN_CTRL_MISSES: |
228 | return(BIO_ghbn_miss); | 244 | return(BIO_ghbn_miss); |
229 | break; | 245 | /* break; */ |
230 | case BIO_GHBN_CTRL_CACHE_SIZE: | 246 | case BIO_GHBN_CTRL_CACHE_SIZE: |
231 | return(GHBN_NUM); | 247 | return(GHBN_NUM); |
232 | break; | 248 | /* break; */ |
233 | case BIO_GHBN_CTRL_GET_ENTRY: | 249 | case BIO_GHBN_CTRL_GET_ENTRY: |
234 | if ((iarg >= 0) && (iarg <GHBN_NUM) && | 250 | if ((iarg >= 0) && (iarg <GHBN_NUM) && |
235 | (ghbn_cache[iarg].order > 0)) | 251 | (ghbn_cache[iarg].order > 0)) |
@@ -241,7 +257,7 @@ char *parg; | |||
241 | return(1); | 257 | return(1); |
242 | } | 258 | } |
243 | return(0); | 259 | return(0); |
244 | break; | 260 | /* break; */ |
245 | case BIO_GHBN_CTRL_FLUSH: | 261 | case BIO_GHBN_CTRL_FLUSH: |
246 | for (i=0; i<GHBN_NUM; i++) | 262 | for (i=0; i<GHBN_NUM; i++) |
247 | ghbn_cache[i].order=0; | 263 | ghbn_cache[i].order=0; |
@@ -252,85 +268,105 @@ char *parg; | |||
252 | return(1); | 268 | return(1); |
253 | } | 269 | } |
254 | 270 | ||
255 | static struct hostent *ghbn_dup(a) | 271 | #if 0 |
256 | struct hostent *a; | 272 | static struct hostent *ghbn_dup(struct hostent *a) |
257 | { | 273 | { |
258 | struct hostent *ret; | 274 | struct hostent *ret; |
259 | int i,j; | 275 | int i,j; |
260 | 276 | ||
261 | ret=(struct hostent *)malloc(sizeof(struct hostent)); | 277 | MemCheck_off(); |
278 | ret=(struct hostent *)OPENSSL_malloc(sizeof(struct hostent)); | ||
262 | if (ret == NULL) return(NULL); | 279 | if (ret == NULL) return(NULL); |
263 | memset(ret,0,sizeof(struct hostent)); | 280 | memset(ret,0,sizeof(struct hostent)); |
264 | 281 | ||
265 | for (i=0; a->h_aliases[i] != NULL; i++) | 282 | for (i=0; a->h_aliases[i] != NULL; i++) |
266 | ; | 283 | ; |
267 | i++; | 284 | i++; |
268 | ret->h_aliases=(char **)malloc(sizeof(char *)*i); | 285 | ret->h_aliases = (char **)OPENSSL_malloc(i*sizeof(char *)); |
269 | memset(ret->h_aliases,0,sizeof(char *)*i); | 286 | if (ret->h_aliases == NULL) |
270 | if (ret == NULL) goto err; | 287 | goto err; |
288 | memset(ret->h_aliases, 0, i*sizeof(char *)); | ||
271 | 289 | ||
272 | for (i=0; a->h_addr_list[i] != NULL; i++) | 290 | for (i=0; a->h_addr_list[i] != NULL; i++) |
273 | ; | 291 | ; |
274 | i++; | 292 | i++; |
275 | ret->h_addr_list=(char **)malloc(sizeof(char *)*i); | 293 | ret->h_addr_list=(char **)OPENSSL_malloc(i*sizeof(char *)); |
276 | memset(ret->h_addr_list,0,sizeof(char *)*i); | 294 | if (ret->h_addr_list == NULL) |
277 | if (ret->h_addr_list == NULL) goto err; | 295 | goto err; |
296 | memset(ret->h_addr_list, 0, i*sizeof(char *)); | ||
278 | 297 | ||
279 | j=strlen(a->h_name)+1; | 298 | j=strlen(a->h_name)+1; |
280 | if ((ret->h_name=malloc(j)) == NULL) goto err; | 299 | if ((ret->h_name=OPENSSL_malloc(j)) == NULL) goto err; |
281 | memcpy((char *)ret->h_name,a->h_name,j); | 300 | memcpy((char *)ret->h_name,a->h_name,j); |
282 | for (i=0; a->h_aliases[i] != NULL; i++) | 301 | for (i=0; a->h_aliases[i] != NULL; i++) |
283 | { | 302 | { |
284 | j=strlen(a->h_aliases[i])+1; | 303 | j=strlen(a->h_aliases[i])+1; |
285 | if ((ret->h_aliases[i]=malloc(j)) == NULL) goto err; | 304 | if ((ret->h_aliases[i]=OPENSSL_malloc(j)) == NULL) goto err; |
286 | memcpy(ret->h_aliases[i],a->h_aliases[i],j); | 305 | memcpy(ret->h_aliases[i],a->h_aliases[i],j); |
287 | } | 306 | } |
288 | ret->h_length=a->h_length; | 307 | ret->h_length=a->h_length; |
289 | ret->h_addrtype=a->h_addrtype; | 308 | ret->h_addrtype=a->h_addrtype; |
290 | for (i=0; a->h_addr_list[i] != NULL; i++) | 309 | for (i=0; a->h_addr_list[i] != NULL; i++) |
291 | { | 310 | { |
292 | if ((ret->h_addr_list[i]=malloc(a->h_length)) == NULL) | 311 | if ((ret->h_addr_list[i]=OPENSSL_malloc(a->h_length)) == NULL) |
293 | goto err; | 312 | goto err; |
294 | memcpy(ret->h_addr_list[i],a->h_addr_list[i],a->h_length); | 313 | memcpy(ret->h_addr_list[i],a->h_addr_list[i],a->h_length); |
295 | } | 314 | } |
296 | return(ret); | 315 | if (0) |
316 | { | ||
297 | err: | 317 | err: |
298 | if (ret != NULL) | 318 | if (ret != NULL) |
299 | ghbn_free(ret); | 319 | ghbn_free(ret); |
300 | return(NULL); | 320 | ret=NULL; |
321 | } | ||
322 | MemCheck_on(); | ||
323 | return(ret); | ||
301 | } | 324 | } |
302 | 325 | ||
303 | static void ghbn_free(a) | 326 | static void ghbn_free(struct hostent *a) |
304 | struct hostent *a; | ||
305 | { | 327 | { |
306 | int i; | 328 | int i; |
307 | 329 | ||
330 | if(a == NULL) | ||
331 | return; | ||
332 | |||
308 | if (a->h_aliases != NULL) | 333 | if (a->h_aliases != NULL) |
309 | { | 334 | { |
310 | for (i=0; a->h_aliases[i] != NULL; i++) | 335 | for (i=0; a->h_aliases[i] != NULL; i++) |
311 | free(a->h_aliases[i]); | 336 | OPENSSL_free(a->h_aliases[i]); |
312 | free(a->h_aliases); | 337 | OPENSSL_free(a->h_aliases); |
313 | } | 338 | } |
314 | if (a->h_addr_list != NULL) | 339 | if (a->h_addr_list != NULL) |
315 | { | 340 | { |
316 | for (i=0; a->h_addr_list[i] != NULL; i++) | 341 | for (i=0; a->h_addr_list[i] != NULL; i++) |
317 | free(a->h_addr_list[i]); | 342 | OPENSSL_free(a->h_addr_list[i]); |
318 | free(a->h_addr_list); | 343 | OPENSSL_free(a->h_addr_list); |
319 | } | 344 | } |
320 | if (a->h_name != NULL) free((char *)a->h_name); | 345 | if (a->h_name != NULL) OPENSSL_free(a->h_name); |
321 | free(a); | 346 | OPENSSL_free(a); |
322 | } | 347 | } |
323 | 348 | ||
324 | struct hostent *BIO_gethostbyname(name) | 349 | #endif |
325 | char *name; | 350 | |
351 | struct hostent *BIO_gethostbyname(const char *name) | ||
326 | { | 352 | { |
353 | #if 1 | ||
354 | /* Caching gethostbyname() results forever is wrong, | ||
355 | * so we have to let the true gethostbyname() worry about this */ | ||
356 | return gethostbyname(name); | ||
357 | #else | ||
327 | struct hostent *ret; | 358 | struct hostent *ret; |
328 | int i,lowi=0,j; | 359 | int i,lowi=0,j; |
329 | unsigned long low= (unsigned long)-1; | 360 | unsigned long low= (unsigned long)-1; |
330 | 361 | ||
331 | /* return(gethostbyname(name)); */ | ||
332 | 362 | ||
333 | CRYPTO_w_lock(CRYPTO_LOCK_BIO_GETHOSTBYNAME); | 363 | # if 0 |
364 | /* It doesn't make sense to use locking here: The function interface | ||
365 | * is not thread-safe, because threads can never be sure when | ||
366 | * some other thread destroys the data they were given a pointer to. | ||
367 | */ | ||
368 | CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME); | ||
369 | # endif | ||
334 | j=strlen(name); | 370 | j=strlen(name); |
335 | if (j < 128) | 371 | if (j < 128) |
336 | { | 372 | { |
@@ -354,17 +390,39 @@ char *name; | |||
354 | if (i == GHBN_NUM) /* no hit*/ | 390 | if (i == GHBN_NUM) /* no hit*/ |
355 | { | 391 | { |
356 | BIO_ghbn_miss++; | 392 | BIO_ghbn_miss++; |
357 | ret=gethostbyname(name); | 393 | /* Note: under VMS with SOCKETSHR, it seems like the first |
358 | 394 | * parameter is 'char *', instead of 'const char *' | |
359 | if (ret == NULL) return(NULL); | 395 | */ |
360 | if (j > 128) return(ret); /* too big to cache */ | 396 | ret=gethostbyname( |
397 | # ifndef CONST_STRICT | ||
398 | (char *) | ||
399 | # endif | ||
400 | name); | ||
401 | |||
402 | if (ret == NULL) | ||
403 | goto end; | ||
404 | if (j > 128) /* too big to cache */ | ||
405 | { | ||
406 | # if 0 | ||
407 | /* If we were trying to make this function thread-safe (which | ||
408 | * is bound to fail), we'd have to give up in this case | ||
409 | * (or allocate more memory). */ | ||
410 | ret = NULL; | ||
411 | # endif | ||
412 | goto end; | ||
413 | } | ||
361 | 414 | ||
362 | /* else add to cache */ | 415 | /* else add to cache */ |
363 | if (ghbn_cache[lowi].ent != NULL) | 416 | if (ghbn_cache[lowi].ent != NULL) |
364 | ghbn_free(ghbn_cache[lowi].ent); | 417 | ghbn_free(ghbn_cache[lowi].ent); /* XXX not thread-safe */ |
418 | ghbn_cache[lowi].name[0] = '\0'; | ||
365 | 419 | ||
420 | if((ret=ghbn_cache[lowi].ent=ghbn_dup(ret)) == NULL) | ||
421 | { | ||
422 | BIOerr(BIO_F_BIO_GETHOSTBYNAME,ERR_R_MALLOC_FAILURE); | ||
423 | goto end; | ||
424 | } | ||
366 | strncpy(ghbn_cache[lowi].name,name,128); | 425 | 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; | 426 | ghbn_cache[lowi].order=BIO_ghbn_miss+BIO_ghbn_hits; |
369 | } | 427 | } |
370 | else | 428 | else |
@@ -373,13 +431,18 @@ char *name; | |||
373 | ret= ghbn_cache[i].ent; | 431 | ret= ghbn_cache[i].ent; |
374 | ghbn_cache[i].order=BIO_ghbn_miss+BIO_ghbn_hits; | 432 | ghbn_cache[i].order=BIO_ghbn_miss+BIO_ghbn_hits; |
375 | } | 433 | } |
376 | CRYPTO_w_unlock(CRYPTO_LOCK_BIO_GETHOSTBYNAME); | 434 | end: |
435 | # if 0 | ||
436 | CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME); | ||
437 | # endif | ||
377 | return(ret); | 438 | return(ret); |
439 | #endif | ||
378 | } | 440 | } |
379 | 441 | ||
380 | int BIO_sock_init() | 442 | |
443 | int BIO_sock_init(void) | ||
381 | { | 444 | { |
382 | #ifdef WINDOWS | 445 | #ifdef OPENSSL_SYS_WINDOWS |
383 | static struct WSAData wsa_state; | 446 | static struct WSAData wsa_state; |
384 | 447 | ||
385 | if (!wsa_init_done) | 448 | if (!wsa_init_done) |
@@ -399,13 +462,13 @@ int BIO_sock_init() | |||
399 | return(-1); | 462 | return(-1); |
400 | } | 463 | } |
401 | } | 464 | } |
402 | #endif /* WINDOWS */ | 465 | #endif /* OPENSSL_SYS_WINDOWS */ |
403 | return(1); | 466 | return(1); |
404 | } | 467 | } |
405 | 468 | ||
406 | void BIO_sock_cleanup() | 469 | void BIO_sock_cleanup(void) |
407 | { | 470 | { |
408 | #ifdef WINDOWS | 471 | #ifdef OPENSSL_SYS_WINDOWS |
409 | if (wsa_init_done) | 472 | if (wsa_init_done) |
410 | { | 473 | { |
411 | wsa_init_done=0; | 474 | wsa_init_done=0; |
@@ -415,10 +478,9 @@ void BIO_sock_cleanup() | |||
415 | #endif | 478 | #endif |
416 | } | 479 | } |
417 | 480 | ||
418 | int BIO_socket_ioctl(fd,type,arg) | 481 | #if !defined(OPENSSL_SYS_VMS) || __VMS_VER >= 70000000 |
419 | int fd; | 482 | |
420 | long type; | 483 | int BIO_socket_ioctl(int fd, long type, unsigned long *arg) |
421 | unsigned long *arg; | ||
422 | { | 484 | { |
423 | int i; | 485 | int i; |
424 | 486 | ||
@@ -427,12 +489,11 @@ unsigned long *arg; | |||
427 | SYSerr(SYS_F_IOCTLSOCKET,get_last_socket_error()); | 489 | SYSerr(SYS_F_IOCTLSOCKET,get_last_socket_error()); |
428 | return(i); | 490 | return(i); |
429 | } | 491 | } |
492 | #endif /* __VMS_VER */ | ||
430 | 493 | ||
431 | /* The reason I have implemented this instead of using sscanf is because | 494 | /* 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 :-( */ | 495 | * Visual C 1.52c gives an unresolved external when linking a DLL :-( */ |
433 | static int get_ip(str,ip) | 496 | static int get_ip(const char *str, unsigned char ip[4]) |
434 | char *str; | ||
435 | unsigned char ip[4]; | ||
436 | { | 497 | { |
437 | unsigned int tmp[4]; | 498 | unsigned int tmp[4]; |
438 | int num=0,c,ok=0; | 499 | int num=0,c,ok=0; |
@@ -446,16 +507,16 @@ unsigned char ip[4]; | |||
446 | { | 507 | { |
447 | ok=1; | 508 | ok=1; |
448 | tmp[num]=tmp[num]*10+c-'0'; | 509 | tmp[num]=tmp[num]*10+c-'0'; |
449 | if (tmp[num] > 255) return(-1); | 510 | if (tmp[num] > 255) return(0); |
450 | } | 511 | } |
451 | else if (c == '.') | 512 | else if (c == '.') |
452 | { | 513 | { |
453 | if (!ok) return(-1); | 514 | if (!ok) return(-1); |
454 | if (num == 3) break; | 515 | if (num == 3) return(0); |
455 | num++; | 516 | num++; |
456 | ok=0; | 517 | ok=0; |
457 | } | 518 | } |
458 | else if ((num == 3) && ok) | 519 | else if (c == '\0' && (num == 3) && ok) |
459 | break; | 520 | break; |
460 | else | 521 | else |
461 | return(0); | 522 | return(0); |
@@ -467,18 +528,19 @@ unsigned char ip[4]; | |||
467 | return(1); | 528 | return(1); |
468 | } | 529 | } |
469 | 530 | ||
470 | int BIO_get_accept_socket(host) | 531 | int BIO_get_accept_socket(char *host, int bind_mode) |
471 | char *host; | ||
472 | { | 532 | { |
473 | int ret=0; | 533 | int ret=0; |
474 | struct sockaddr_in server; | 534 | struct sockaddr_in server,client; |
475 | int s= -1; | 535 | int s=INVALID_SOCKET,cs; |
476 | unsigned char ip[4]; | 536 | unsigned char ip[4]; |
477 | short port; | 537 | unsigned short port; |
478 | char *str,*h,*p,*e; | 538 | char *str=NULL,*e; |
539 | const char *h,*p; | ||
479 | unsigned long l; | 540 | unsigned long l; |
541 | int err_num; | ||
480 | 542 | ||
481 | if (!BIO_sock_init()) return(INVALID_SOCKET); | 543 | if (BIO_sock_init() != 1) return(INVALID_SOCKET); |
482 | 544 | ||
483 | if ((str=BUF_strdup(host)) == NULL) return(INVALID_SOCKET); | 545 | if ((str=BUF_strdup(host)) == NULL) return(INVALID_SOCKET); |
484 | 546 | ||
@@ -504,25 +566,26 @@ char *host; | |||
504 | h="*"; | 566 | h="*"; |
505 | } | 567 | } |
506 | 568 | ||
507 | if (!BIO_get_port(p,&port)) return(INVALID_SOCKET); | 569 | if (!BIO_get_port(p,&port)) goto err; |
508 | 570 | ||
509 | memset((char *)&server,0,sizeof(server)); | 571 | memset((char *)&server,0,sizeof(server)); |
510 | server.sin_family=AF_INET; | 572 | server.sin_family=AF_INET; |
511 | server.sin_port=htons((unsigned short)port); | 573 | server.sin_port=htons(port); |
512 | 574 | ||
513 | if (strcmp(h,"*") == 0) | 575 | if (strcmp(h,"*") == 0) |
514 | server.sin_addr.s_addr=INADDR_ANY; | 576 | server.sin_addr.s_addr=INADDR_ANY; |
515 | else | 577 | else |
516 | { | 578 | { |
517 | if (!BIO_get_host_ip(h,&(ip[0]))) return(INVALID_SOCKET); | 579 | if (!BIO_get_host_ip(h,&(ip[0]))) goto err; |
518 | l=(unsigned long) | 580 | l=(unsigned long) |
519 | ((unsigned long)ip[0]<<24L)| | 581 | ((unsigned long)ip[0]<<24L)| |
520 | ((unsigned long)ip[0]<<16L)| | 582 | ((unsigned long)ip[1]<<16L)| |
521 | ((unsigned long)ip[0]<< 8L)| | 583 | ((unsigned long)ip[2]<< 8L)| |
522 | ((unsigned long)ip[0]); | 584 | ((unsigned long)ip[3]); |
523 | server.sin_addr.s_addr=htonl(l); | 585 | server.sin_addr.s_addr=htonl(l); |
524 | } | 586 | } |
525 | 587 | ||
588 | again: | ||
526 | s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); | 589 | s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); |
527 | if (s == INVALID_SOCKET) | 590 | if (s == INVALID_SOCKET) |
528 | { | 591 | { |
@@ -531,9 +594,45 @@ char *host; | |||
531 | BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_CREATE_SOCKET); | 594 | BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_CREATE_SOCKET); |
532 | goto err; | 595 | goto err; |
533 | } | 596 | } |
597 | |||
598 | #ifdef SO_REUSEADDR | ||
599 | if (bind_mode == BIO_BIND_REUSEADDR) | ||
600 | { | ||
601 | int i=1; | ||
602 | |||
603 | ret=setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&i,sizeof(i)); | ||
604 | bind_mode=BIO_BIND_NORMAL; | ||
605 | } | ||
606 | #endif | ||
534 | if (bind(s,(struct sockaddr *)&server,sizeof(server)) == -1) | 607 | if (bind(s,(struct sockaddr *)&server,sizeof(server)) == -1) |
535 | { | 608 | { |
536 | SYSerr(SYS_F_BIND,get_last_socket_error()); | 609 | #ifdef SO_REUSEADDR |
610 | err_num=get_last_socket_error(); | ||
611 | if ((bind_mode == BIO_BIND_REUSEADDR_IF_UNUSED) && | ||
612 | (err_num == EADDRINUSE)) | ||
613 | { | ||
614 | memcpy((char *)&client,(char *)&server,sizeof(server)); | ||
615 | if (strcmp(h,"*") == 0) | ||
616 | client.sin_addr.s_addr=htonl(0x7F000001); | ||
617 | cs=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); | ||
618 | if (cs != INVALID_SOCKET) | ||
619 | { | ||
620 | int ii; | ||
621 | ii=connect(cs,(struct sockaddr *)&client, | ||
622 | sizeof(client)); | ||
623 | closesocket(cs); | ||
624 | if (ii == INVALID_SOCKET) | ||
625 | { | ||
626 | bind_mode=BIO_BIND_REUSEADDR; | ||
627 | closesocket(s); | ||
628 | goto again; | ||
629 | } | ||
630 | /* else error */ | ||
631 | } | ||
632 | /* else error */ | ||
633 | } | ||
634 | #endif | ||
635 | SYSerr(SYS_F_BIND,err_num); | ||
537 | ERR_add_error_data(3,"port='",host,"'"); | 636 | ERR_add_error_data(3,"port='",host,"'"); |
538 | BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_BIND_SOCKET); | 637 | BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_BIND_SOCKET); |
539 | goto err; | 638 | goto err; |
@@ -547,35 +646,35 @@ char *host; | |||
547 | } | 646 | } |
548 | ret=1; | 647 | ret=1; |
549 | err: | 648 | err: |
550 | if (str != NULL) Free(str); | 649 | if (str != NULL) OPENSSL_free(str); |
551 | if ((ret == 0) && (s != INVALID_SOCKET)) | 650 | if ((ret == 0) && (s != INVALID_SOCKET)) |
552 | { | 651 | { |
553 | #ifdef WINDOWS | ||
554 | closesocket(s); | 652 | closesocket(s); |
555 | #else | ||
556 | close(s); | ||
557 | #endif | ||
558 | s= INVALID_SOCKET; | 653 | s= INVALID_SOCKET; |
559 | } | 654 | } |
560 | return(s); | 655 | return(s); |
561 | } | 656 | } |
562 | 657 | ||
563 | int BIO_accept(sock,addr) | 658 | int BIO_accept(int sock, char **addr) |
564 | int sock; | ||
565 | char **addr; | ||
566 | { | 659 | { |
567 | int ret=INVALID_SOCKET; | 660 | int ret=INVALID_SOCKET; |
568 | static struct sockaddr_in from; | 661 | static struct sockaddr_in from; |
569 | unsigned long l; | 662 | unsigned long l; |
570 | short port; | 663 | unsigned short port; |
571 | int len; | 664 | int len; |
572 | char *p; | 665 | char *p; |
573 | 666 | ||
574 | memset((char *)&from,0,sizeof(from)); | 667 | memset((char *)&from,0,sizeof(from)); |
575 | len=sizeof(from); | 668 | len=sizeof(from); |
576 | ret=accept(sock,(struct sockaddr *)&from,&len); | 669 | /* Note: under VMS with SOCKETSHR the fourth parameter is currently |
670 | * of type (int *) whereas under other systems it is (void *) if | ||
671 | * you don't have a cast it will choke the compiler: if you do | ||
672 | * have a cast then you can either go for (int *) or (void *). | ||
673 | */ | ||
674 | ret=accept(sock,(struct sockaddr *)&from,(void *)&len); | ||
577 | if (ret == INVALID_SOCKET) | 675 | if (ret == INVALID_SOCKET) |
578 | { | 676 | { |
677 | if(BIO_sock_should_retry(ret)) return -2; | ||
579 | SYSerr(SYS_F_ACCEPT,get_last_socket_error()); | 678 | SYSerr(SYS_F_ACCEPT,get_last_socket_error()); |
580 | BIOerr(BIO_F_BIO_ACCEPT,BIO_R_ACCEPT_ERROR); | 679 | BIOerr(BIO_F_BIO_ACCEPT,BIO_R_ACCEPT_ERROR); |
581 | goto end; | 680 | goto end; |
@@ -587,7 +686,7 @@ char **addr; | |||
587 | port=ntohs(from.sin_port); | 686 | port=ntohs(from.sin_port); |
588 | if (*addr == NULL) | 687 | if (*addr == NULL) |
589 | { | 688 | { |
590 | if ((p=Malloc(24)) == NULL) | 689 | if ((p=OPENSSL_malloc(24)) == NULL) |
591 | { | 690 | { |
592 | BIOerr(BIO_F_BIO_ACCEPT,ERR_R_MALLOC_FAILURE); | 691 | BIOerr(BIO_F_BIO_ACCEPT,ERR_R_MALLOC_FAILURE); |
593 | goto end; | 692 | goto end; |
@@ -604,9 +703,7 @@ end: | |||
604 | return(ret); | 703 | return(ret); |
605 | } | 704 | } |
606 | 705 | ||
607 | int BIO_set_tcp_ndelay(s,on) | 706 | int BIO_set_tcp_ndelay(int s, int on) |
608 | int s; | ||
609 | int on; | ||
610 | { | 707 | { |
611 | int ret=0; | 708 | int ret=0; |
612 | #if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP)) | 709 | #if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP)) |
@@ -626,3 +723,14 @@ int on; | |||
626 | } | 723 | } |
627 | #endif | 724 | #endif |
628 | 725 | ||
726 | int BIO_socket_nbio(int s, int mode) | ||
727 | { | ||
728 | int ret= -1; | ||
729 | unsigned long l; | ||
730 | |||
731 | l=mode; | ||
732 | #ifdef FIONBIO | ||
733 | ret=BIO_socket_ioctl(s,FIONBIO,&l); | ||
734 | #endif | ||
735 | return(ret == 0); | ||
736 | } | ||