X-Git-Url: https://git.openssl.org/?a=blobdiff_plain;f=crypto%2Fbio%2Fb_sock.c;h=d29b29ff8b324a24bfa3c9d4045ef085a98d754b;hb=ba9f28088597f103f0a058ecf3772c521663add5;hp=d3c1345d0b5eb28a71d4bc00080d3cd8e120ccc5;hpb=95dc05bc6d0dfe0f3f3681f5e27afbc3f7a35eea;p=openssl.git diff --git a/crypto/bio/b_sock.c b/crypto/bio/b_sock.c index d3c1345d0b..d29b29ff8b 100644 --- a/crypto/bio/b_sock.c +++ b/crypto/bio/b_sock.c @@ -63,9 +63,7 @@ #include #define USE_SOCKETS #include "cryptlib.h" -#include "bio.h" - -/* BIOerr(BIO_F_WSASTARTUP,BIO_R_WSASTARTUP ); */ +#include #ifdef WIN16 #define SOCKET_PROTOCOL 0 /* more microsoft stupidity */ @@ -96,19 +94,14 @@ static struct ghbn_cache_st unsigned long order; } ghbn_cache[GHBN_NUM]; -#ifndef NOPROTO static int get_ip(const char *str,unsigned char *ip); static void ghbn_free(struct hostent *a); static struct hostent *ghbn_dup(struct hostent *a); -#else -static int get_ip(); -static void ghbn_free(); -static struct hostent *ghbn_dup(); -#endif - int BIO_get_host_ip(const char *str, unsigned char *ip) { int i; + int err = 1; + int locked = 0; struct hostent *he; i=get_ip(str,ip); @@ -116,32 +109,42 @@ int BIO_get_host_ip(const char *str, unsigned char *ip) if (i < 0) { BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_INVALID_IP_ADDRESS); - ERR_add_error_data(2,"host=",str); - return(0); + goto err; } - else - { /* do a gethostbyname */ - if (!BIO_sock_init()) return(0); - he=BIO_gethostbyname(str); - if (he == NULL) - { - BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_BAD_HOSTNAME_LOOKUP); - ERR_add_error_data(2,"host=",str); - return(0); - } + /* do a gethostbyname */ + if (!BIO_sock_init()) + return(0); /* don't generate another error code here */ - /* cast to short because of win16 winsock definition */ - if ((short)he->h_addrtype != AF_INET) - { - BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET); - ERR_add_error_data(2,"host=",str); - return(0); - } - for (i=0; i<4; i++) - ip[i]=he->h_addr_list[0][i]; + CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME); + locked = 1; + he=BIO_gethostbyname(str); + if (he == NULL) + { + BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_BAD_HOSTNAME_LOOKUP); + goto err; } - return(1); + + /* cast to short because of win16 winsock definition */ + if ((short)he->h_addrtype != AF_INET) + { + BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET); + goto err; + } + for (i=0; i<4; i++) + ip[i]=he->h_addr_list[0][i]; + err = 0; + + err: + if (locked) + CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME); + if (err) + { + ERR_add_error_data(2,"host=",str); + return 0; + } + else + return 1; } int BIO_get_port(const char *str, unsigned short *port_ptr) @@ -159,8 +162,12 @@ int BIO_get_port(const char *str, unsigned short *port_ptr) *port_ptr=(unsigned short)i; else { - s=getservbyname(str,"tcp"); - if (s == NULL) + CRYPTO_w_lock(CRYPTO_LOCK_GETSERVBYNAME); + s=getservbyname(str,"tcp"); + if(s != NULL) + *port_ptr=ntohs((unsigned short)s->s_port); + CRYPTO_w_unlock(CRYPTO_LOCK_GETSERVBYNAME); + if(s == NULL) { if (strcmp(str,"http") == 0) *port_ptr=80; @@ -186,9 +193,7 @@ int BIO_get_port(const char *str, unsigned short *port_ptr) ERR_add_error_data(3,"service='",str,"'"); return(0); } - return(1); } - *port_ptr=htons((unsigned short)s->s_port); } return(1); } @@ -196,11 +201,15 @@ int BIO_get_port(const char *str, unsigned short *port_ptr) int BIO_sock_error(int sock) { int j,i; - unsigned int size; + int size; size=sizeof(int); - - i=getsockopt(sock,SOL_SOCKET,SO_ERROR,(char *)&j,&size); + /* Note: under Windows the third parameter is of type (char *) + * whereas under other systems it is (void *) if you don't have + * a cast it will choke the compiler: if you do have a cast then + * you can either go for (char *) or (void *). + */ + i=getsockopt(sock,SOL_SOCKET,SO_ERROR,(void *)&j,(void *)&size); if (i < 0) return(1); else @@ -258,16 +267,18 @@ static struct hostent *ghbn_dup(struct hostent *a) for (i=0; a->h_aliases[i] != NULL; i++) ; i++; - ret->h_aliases=(char **)Malloc(sizeof(char *)*i); - memset(ret->h_aliases,0,sizeof(char *)*i); - if (ret == NULL) goto err; + ret->h_aliases = (char **)Malloc(i*sizeof(char *)); + if (ret->h_aliases == NULL) + goto err; + memset(ret->h_aliases, 0, i*sizeof(char *)); for (i=0; a->h_addr_list[i] != NULL; i++) ; i++; - ret->h_addr_list=(char **)Malloc(sizeof(char *)*i); - memset(ret->h_addr_list,0,sizeof(char *)*i); - if (ret->h_addr_list == NULL) goto err; + ret->h_addr_list=(char **)Malloc(i*sizeof(char *)); + if (ret->h_addr_list == NULL) + goto err; + memset(ret->h_addr_list, 0, i*sizeof(char *)); j=strlen(a->h_name)+1; if ((ret->h_name=Malloc(j)) == NULL) goto err; @@ -328,7 +339,12 @@ struct hostent *BIO_gethostbyname(const char *name) /* return(gethostbyname(name)); */ - CRYPTO_w_lock(CRYPTO_LOCK_BIO_GETHOSTBYNAME); +#if 0 /* It doesn't make sense to use locking here: The function interface + * is not thread-safe, because threads can never be sure when + * some other thread destroys the data they were given a pointer to. + */ + CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME); +#endif j=strlen(name); if (j < 128) { @@ -354,15 +370,29 @@ struct hostent *BIO_gethostbyname(const char *name) BIO_ghbn_miss++; ret=gethostbyname(name); - if (ret == NULL) return(NULL); - if (j > 128) return(ret); /* too big to cache */ + if (ret == NULL) + goto end; + if (j > 128) /* too big to cache */ + { +#if 0 /* If we were trying to make this function thread-safe (which + * is bound to fail), we'd have to give up in this case + * (or allocate more memory). */ + ret = NULL; +#endif + goto end; + } /* else add to cache */ if (ghbn_cache[lowi].ent != NULL) - ghbn_free(ghbn_cache[lowi].ent); + ghbn_free(ghbn_cache[lowi].ent); /* XXX not thread-safe */ + ghbn_cache[lowi].name[0] = '\0'; + if((ret=ghbn_cache[lowi].ent=ghbn_dup(ret)) == NULL) + { + BIOerr(BIO_F_BIO_GETHOSTBYNAME,ERR_R_MALLOC_FAILURE); + goto end; + } strncpy(ghbn_cache[lowi].name,name,128); - ghbn_cache[lowi].ent=ghbn_dup(ret); ghbn_cache[lowi].order=BIO_ghbn_miss+BIO_ghbn_hits; } else @@ -371,7 +401,10 @@ struct hostent *BIO_gethostbyname(const char *name) ret= ghbn_cache[i].ent; ghbn_cache[i].order=BIO_ghbn_miss+BIO_ghbn_hits; } - CRYPTO_w_unlock(CRYPTO_LOCK_BIO_GETHOSTBYNAME); +end: +#if 0 + CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME); +#endif return(ret); } @@ -413,6 +446,8 @@ void BIO_sock_cleanup(void) #endif } +#if !defined(VMS) || __VMS_VER >= 70000000 + int BIO_socket_ioctl(int fd, long type, unsigned long *arg) { int i; @@ -422,6 +457,7 @@ int BIO_socket_ioctl(int fd, long type, unsigned long *arg) SYSerr(SYS_F_IOCTLSOCKET,get_last_socket_error()); return(i); } +#endif /* __VMS_VER */ /* The reason I have implemented this instead of using sscanf is because * Visual C 1.52c gives an unresolved external when linking a DLL :-( */ @@ -593,12 +629,17 @@ int BIO_accept(int sock, char **addr) static struct sockaddr_in from; unsigned long l; unsigned short port; - unsigned int len; + int len; char *p; memset((char *)&from,0,sizeof(from)); len=sizeof(from); - ret=accept(sock,(struct sockaddr *)&from,&len); + /* Note: under VMS with SOCKETSHR the fourth parameter is currently + * of type (int *) whereas under other systems it is (void *) if + * you don't have a cast it will choke the compiler: if you do + * have a cast then you can either go for (int *) or (void *). + */ + ret=accept(sock,(struct sockaddr *)&from,(void *)&len); if (ret == INVALID_SOCKET) { SYSerr(SYS_F_ACCEPT,get_last_socket_error());