X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=apps%2Fs_socket.c;h=e83baf4e709279dee9a452c990fa276eadb073a7;hp=77908b638019df0cf0bbc92f266bd3a5e2cb00d0;hb=7ce79a5bfdbcd53ae75f85e94eed665a05b5dea3;hpb=19aa3705739cc8bde71916b02ab019bab7bb945c diff --git a/apps/s_socket.c b/apps/s_socket.c index 77908b6380..e83baf4e70 100644 --- a/apps/s_socket.c +++ b/apps/s_socket.c @@ -62,14 +62,6 @@ #include #include -#ifdef FLAT_INC -#include "e_os.h" -#else -#include "../e_os.h" -#endif - -#ifndef OPENSSL_NO_SOCK - /* With IPv6, it looks like Digital has mixed up the proper order of recursive header file inclusion, resulting in the compiler complaining that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which @@ -87,16 +79,33 @@ typedef unsigned int u_int; #include "s_apps.h" #include -static struct hostent *GetHostByName(char *name); -#ifdef OPENSSL_SYS_WINDOWS +#ifdef FLAT_INC +#include "e_os.h" +#else +#include "../e_os.h" +#endif + +#ifndef OPENSSL_NO_SOCK + +#if defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_BSDSOCK) +#include "netdb.h" +#endif + +static struct hostent *GetHostByName(const char *name); +#if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)) static void ssl_sock_cleanup(void); #endif static int ssl_sock_init(void); -static int init_client_ip(int *sock,unsigned char ip[4], int port); -static int init_server(int *sock, int port); -static int init_server_long(int *sock, int port,char *ip); +static int init_client_ip(int *sock, const unsigned char ip[4], int port, + int type); +static int init_server(int *sock, int port, int type); +static int init_server_long(int *sock, int port,char *ip, int type); static int do_accept(int acc_sock, int *sock, char **host); -static int host_ip(char *str, unsigned char ip[4]); +static int host_ip(const char *str, unsigned char ip[4]); +#ifndef NO_SYS_UN_H +static int init_server_unix(int *sock, const char *path); +static int do_accept_unix(int acc_sock, int *sock); +#endif #ifdef OPENSSL_SYS_WIN16 #define SOCKET_PROTOCOL 0 /* more microsoft stupidity */ @@ -104,6 +113,10 @@ static int host_ip(char *str, unsigned char ip[4]); #define SOCKET_PROTOCOL IPPROTO_TCP #endif +#if defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK) +static int wsa_init_done=0; +#endif + #ifdef OPENSSL_SYS_WINDOWS static struct WSAData wsa_state; static int wsa_init_done=0; @@ -152,6 +165,15 @@ static void ssl_sock_cleanup(void) WSACleanup(); } } +#elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK) +static void sock_cleanup(void) + { + if (wsa_init_done) + { + wsa_init_done=0; + WSACleanup(); + } + } #endif static int ssl_sock_init(void) @@ -159,7 +181,6 @@ static int ssl_sock_init(void) #ifdef WATT32 extern int _watt_do_exit; _watt_do_exit = 0; - dbug_init(); if (sock_init()) return (0); #elif defined(OPENSSL_SYS_WINDOWS) @@ -187,24 +208,43 @@ static int ssl_sock_init(void) SetWindowLong(topWnd,GWL_WNDPROC,(LONG)lpTopHookProc); #endif /* OPENSSL_SYS_WIN16 */ } +#elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK) + WORD wVerReq; + WSADATA wsaData; + int err; + + if (!wsa_init_done) + { + +# ifdef SIGINT + signal(SIGINT,(void (*)(int))sock_cleanup); +# endif + + wsa_init_done=1; + wVerReq = MAKEWORD( 2, 0 ); + err = WSAStartup(wVerReq,&wsaData); + if (err != 0) + { + BIO_printf(bio_err,"unable to start WINSOCK2, error code=%d\n",err); + return(0); + } + } #endif /* OPENSSL_SYS_WINDOWS */ return(1); } -int init_client(int *sock, char *host, int port) +int init_client(int *sock, const char *host, int port, int type) { unsigned char ip[4]; - short p=0; + ip[0] = ip[1] = ip[2] = ip[3] = 0; if (!host_ip(host,&(ip[0]))) - { - return(0); - } - if (p != 0) port=p; - return(init_client_ip(sock,ip,port)); + return 0; + return init_client_ip(sock,ip,port,type); } -static int init_client_ip(int *sock, unsigned char ip[4], int port) +static int init_client_ip(int *sock, const unsigned char ip[4], int port, + int type) { unsigned long addr; struct sockaddr_in them; @@ -222,58 +262,139 @@ static int init_client_ip(int *sock, unsigned char ip[4], int port) ((unsigned long)ip[3]); them.sin_addr.s_addr=htonl(addr); - s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); + if (type == SOCK_STREAM) + s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); + else /* ( type == SOCK_DGRAM) */ + s=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); + if (s == INVALID_SOCKET) { perror("socket"); return(0); } -#ifndef OPENSSL_SYS_MPE - i=0; - i=setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i)); - if (i < 0) { perror("keepalive"); return(0); } +#if defined(SO_KEEPALIVE) && !defined(OPENSSL_SYS_MPE) + if (type == SOCK_STREAM) + { + i=0; + i=setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i)); + if (i < 0) { closesocket(s); perror("keepalive"); return(0); } + } #endif if (connect(s,(struct sockaddr *)&them,sizeof(them)) == -1) - { close(s); perror("connect"); return(0); } + { closesocket(s); perror("connect"); return(0); } + *sock=s; + return(1); + } + +#ifndef NO_SYS_UN_H +int init_client_unix(int *sock, const char *server) + { + struct sockaddr_un them; + int s; + + if (strlen(server) > (UNIX_PATH_MAX + 1)) return(0); + if (!ssl_sock_init()) return(0); + + s=socket(AF_UNIX, SOCK_STREAM, 0); + if (s == INVALID_SOCKET) { perror("socket"); return(0); } + + memset((char *)&them,0,sizeof(them)); + them.sun_family=AF_UNIX; + strcpy(them.sun_path, server); + + if (connect(s, (struct sockaddr *)&them, sizeof(them)) == -1) + { closesocket(s); perror("connect"); return(0); } *sock=s; return(1); } +#endif -int do_server(int port, int *ret, int (*cb)(), char *context) +int do_server(int port, int type, int *ret, + int (*cb)(char *hostname, int s, int stype, unsigned char *context), + unsigned char *context, int naccept) { int sock; - char *name; - int accept_socket; + char *name = NULL; + int accept_socket = 0; int i; - if (!init_server(&accept_socket,port)) return(0); + if (!init_server(&accept_socket,port,type)) return(0); if (ret != NULL) { *ret=accept_socket; /* return(1);*/ } + for (;;) + { + if (type==SOCK_STREAM) + { +#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL + if (do_accept(accept_socket,&sock,NULL) == 0) +#else + if (do_accept(accept_socket,&sock,&name) == 0) +#endif + { + SHUTDOWN(accept_socket); + return(0); + } + } + else + sock = accept_socket; + i=(*cb)(name,sock, type, context); + if (name != NULL) OPENSSL_free(name); + if (type==SOCK_STREAM) + SHUTDOWN2(sock); + if (naccept != -1) + naccept--; + if (i < 0 || naccept == 0) + { + SHUTDOWN2(accept_socket); + return(i); + } + } + } + +#ifndef NO_SYS_UN_H +int do_server_unix(const char *path, int *ret, + int (*cb)(char *hostname, int s, int stype, unsigned char *context), + unsigned char *context, int naccept) + { + int sock; + int accept_socket = 0; + int i; + + if (!init_server_unix(&accept_socket, path)) return(0); + + if (ret != NULL) + *ret=accept_socket; for (;;) { - if (do_accept(accept_socket,&sock,&name) == 0) + if (do_accept_unix(accept_socket, &sock) == 0) { SHUTDOWN(accept_socket); - return(0); + i = 0; + goto out; } - i=(*cb)(name,sock, context); - if (name != NULL) OPENSSL_free(name); + i=(*cb)(NULL, sock, 0, context); SHUTDOWN2(sock); - if (i < 0) + if (naccept != -1) + naccept--; + if (i < 0 || naccept == 0) { SHUTDOWN2(accept_socket); - return(i); + goto out; } } +out: + unlink(path); + return(i); } +#endif -static int init_server_long(int *sock, int port, char *ip) +static int init_server_long(int *sock, int port, char *ip, int type) { int ret=0; struct sockaddr_in server; - int s= -1,i; + int s= -1; if (!ssl_sock_init()) return(0); @@ -289,7 +410,11 @@ static int init_server_long(int *sock, int port, char *ip) #else memcpy(&server.sin_addr,ip,4); #endif - s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); + + if (type == SOCK_STREAM) + s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); + else /* type == SOCK_DGRAM */ + s=socket(AF_INET, SOCK_DGRAM,IPPROTO_UDP); if (s == INVALID_SOCKET) goto err; #if defined SOL_SOCKET && defined SO_REUSEADDR @@ -307,8 +432,7 @@ static int init_server_long(int *sock, int port, char *ip) goto err; } /* Make it 128 for linux */ - if (listen(s,128) == -1) goto err; - i=0; + if (type==SOCK_STREAM && listen(s,128) == -1) goto err; *sock=s; ret=1; err: @@ -319,14 +443,58 @@ err: return(ret); } -static int init_server(int *sock, int port) +static int init_server(int *sock, int port, int type) + { + return(init_server_long(sock, port, NULL, type)); + } + +#ifndef NO_SYS_UN_H +static int init_server_unix(int *sock, const char *path) { - return(init_server_long(sock, port, NULL)); + int ret = 0; + struct sockaddr_un server; + int s = -1; + + if (strlen(path) > (UNIX_PATH_MAX + 1)) return(0); + if (!ssl_sock_init()) return(0); + + s=socket(AF_UNIX, SOCK_STREAM, 0); + if (s == INVALID_SOCKET) goto err; + + memset((char *)&server,0,sizeof(server)); + server.sun_family=AF_UNIX; + strcpy(server.sun_path, path); + + if (bind(s, (struct sockaddr *)&server, sizeof(server)) == -1) + { +#ifndef OPENSSL_SYS_WINDOWS + perror("bind"); +#endif + goto err; + } + /* Make it 128 for linux */ + if (listen(s,128) == -1) + { +#ifndef OPENSSL_SYS_WINDOWS + perror("listen"); +#endif + unlink(path); + goto err; + } + *sock=s; + ret=1; +err: + if ((ret == 0) && (s != -1)) + { + SHUTDOWN(s); + } + return(ret); } +#endif static int do_accept(int acc_sock, int *sock, char **host) { - int ret,i; + int ret; struct hostent *h1,*h2; static struct sockaddr_in from; int len; @@ -348,7 +516,8 @@ redoit: ret=accept(acc_sock,(struct sockaddr *)&from,(void *)&len); if (ret == INVALID_SOCKET) { -#ifdef OPENSSL_SYS_WINDOWS +#if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)) + int i; i=WSAGetLastError(); BIO_printf(bio_err,"accept error %d\n",i); #else @@ -393,20 +562,22 @@ redoit: if ((*host=(char *)OPENSSL_malloc(strlen(h1->h_name)+1)) == NULL) { perror("OPENSSL_malloc"); + closesocket(ret); return(0); } - strcpy(*host,h1->h_name); + BUF_strlcpy(*host,h1->h_name,strlen(h1->h_name)+1); h2=GetHostByName(*host); if (h2 == NULL) { BIO_printf(bio_err,"gethostbyname failure\n"); + closesocket(ret); return(0); } - i=0; if (h2->h_addrtype != AF_INET) { BIO_printf(bio_err,"gethostbyname addr is not AF_INET\n"); + closesocket(ret); return(0); } } @@ -415,6 +586,32 @@ end: return(1); } +#ifndef NO_SYS_UN_H +static int do_accept_unix(int acc_sock, int *sock) + { + int ret; + + if (!ssl_sock_init()) return(0); + +redoit: + ret=accept(acc_sock, NULL, NULL); + if (ret == INVALID_SOCKET) + { + if (errno == EINTR) + { + /*check_timeout(); */ + goto redoit; + } + fprintf(stderr,"errno=%d ",errno); + perror("accept"); + return(0); + } + + *sock=ret; + return(1); + } +#endif + int extract_host_port(char *str, char **host_ptr, unsigned char *ip, short *port_ptr) { @@ -440,7 +637,7 @@ err: return(0); } -static int host_ip(char *str, unsigned char ip[4]) +static int host_ip(const char *str, unsigned char ip[4]) { unsigned int in[4]; int i; @@ -486,7 +683,7 @@ err: return(0); } -int extract_port(char *str, short *port_ptr) +int extract_port(const char *str, short *port_ptr) { int i; struct servent *s; @@ -518,7 +715,7 @@ static struct ghbn_cache_st static unsigned long ghbn_hits=0L; static unsigned long ghbn_miss=0L; -static struct hostent *GetHostByName(char *name) +static struct hostent *GetHostByName(const char *name) { struct hostent *ret; int i,lowi=0;