10Sstevel@tonic-gate /* apps/s_socket.c - socket-related functions used by s_client and s_server */
20Sstevel@tonic-gate /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
30Sstevel@tonic-gate * All rights reserved.
40Sstevel@tonic-gate *
50Sstevel@tonic-gate * This package is an SSL implementation written
60Sstevel@tonic-gate * by Eric Young (eay@cryptsoft.com).
70Sstevel@tonic-gate * The implementation was written so as to conform with Netscapes SSL.
80Sstevel@tonic-gate *
90Sstevel@tonic-gate * This library is free for commercial and non-commercial use as long as
100Sstevel@tonic-gate * the following conditions are aheared to. The following conditions
110Sstevel@tonic-gate * apply to all code found in this distribution, be it the RC4, RSA,
120Sstevel@tonic-gate * lhash, DES, etc., code; not just the SSL code. The SSL documentation
130Sstevel@tonic-gate * included with this distribution is covered by the same copyright terms
140Sstevel@tonic-gate * except that the holder is Tim Hudson (tjh@cryptsoft.com).
150Sstevel@tonic-gate *
160Sstevel@tonic-gate * Copyright remains Eric Young's, and as such any Copyright notices in
170Sstevel@tonic-gate * the code are not to be removed.
180Sstevel@tonic-gate * If this package is used in a product, Eric Young should be given attribution
190Sstevel@tonic-gate * as the author of the parts of the library used.
200Sstevel@tonic-gate * This can be in the form of a textual message at program startup or
210Sstevel@tonic-gate * in documentation (online or textual) provided with the package.
220Sstevel@tonic-gate *
230Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without
240Sstevel@tonic-gate * modification, are permitted provided that the following conditions
250Sstevel@tonic-gate * are met:
260Sstevel@tonic-gate * 1. Redistributions of source code must retain the copyright
270Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer.
280Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright
290Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the
300Sstevel@tonic-gate * documentation and/or other materials provided with the distribution.
310Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software
320Sstevel@tonic-gate * must display the following acknowledgement:
330Sstevel@tonic-gate * "This product includes cryptographic software written by
340Sstevel@tonic-gate * Eric Young (eay@cryptsoft.com)"
350Sstevel@tonic-gate * The word 'cryptographic' can be left out if the rouines from the library
360Sstevel@tonic-gate * being used are not cryptographic related :-).
370Sstevel@tonic-gate * 4. If you include any Windows specific code (or a derivative thereof) from
380Sstevel@tonic-gate * the apps directory (application code) you must include an acknowledgement:
390Sstevel@tonic-gate * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
400Sstevel@tonic-gate *
410Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
420Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
430Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
440Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
450Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
460Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
470Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
480Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
490Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
500Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
510Sstevel@tonic-gate * SUCH DAMAGE.
520Sstevel@tonic-gate *
530Sstevel@tonic-gate * The licence and distribution terms for any publically available version or
540Sstevel@tonic-gate * derivative of this code cannot be changed. i.e. this code cannot simply be
550Sstevel@tonic-gate * copied and put under another distribution licence
560Sstevel@tonic-gate * [including the GNU Public Licence.]
570Sstevel@tonic-gate */
580Sstevel@tonic-gate
590Sstevel@tonic-gate #include <stdio.h>
600Sstevel@tonic-gate #include <stdlib.h>
610Sstevel@tonic-gate #include <string.h>
620Sstevel@tonic-gate #include <errno.h>
630Sstevel@tonic-gate #include <signal.h>
640Sstevel@tonic-gate
650Sstevel@tonic-gate /* With IPv6, it looks like Digital has mixed up the proper order of
660Sstevel@tonic-gate recursive header file inclusion, resulting in the compiler complaining
670Sstevel@tonic-gate that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which
680Sstevel@tonic-gate is needed to have fileno() declared correctly... So let's define u_int */
690Sstevel@tonic-gate #if defined(OPENSSL_SYS_VMS_DECC) && !defined(__U_INT)
700Sstevel@tonic-gate #define __U_INT
710Sstevel@tonic-gate typedef unsigned int u_int;
720Sstevel@tonic-gate #endif
730Sstevel@tonic-gate
740Sstevel@tonic-gate #define USE_SOCKETS
750Sstevel@tonic-gate #define NON_MAIN
760Sstevel@tonic-gate #include "apps.h"
770Sstevel@tonic-gate #undef USE_SOCKETS
780Sstevel@tonic-gate #undef NON_MAIN
790Sstevel@tonic-gate #include "s_apps.h"
800Sstevel@tonic-gate #include <openssl/ssl.h>
810Sstevel@tonic-gate
82*2139Sjp161948 #ifdef FLAT_INC
83*2139Sjp161948 #include "e_os.h"
84*2139Sjp161948 #else
85*2139Sjp161948 #include "../e_os.h"
86*2139Sjp161948 #endif
87*2139Sjp161948
88*2139Sjp161948 #ifndef OPENSSL_NO_SOCK
89*2139Sjp161948
90*2139Sjp161948 #if defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_BSDSOCK)
91*2139Sjp161948 #include "netdb.h"
92*2139Sjp161948 #endif
93*2139Sjp161948
940Sstevel@tonic-gate static struct hostent *GetHostByName(char *name);
95*2139Sjp161948 #if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK))
960Sstevel@tonic-gate static void ssl_sock_cleanup(void);
970Sstevel@tonic-gate #endif
980Sstevel@tonic-gate static int ssl_sock_init(void);
99*2139Sjp161948 static int init_client_ip(int *sock,unsigned char ip[4], int port, int type);
100*2139Sjp161948 static int init_server(int *sock, int port, int type);
101*2139Sjp161948 static int init_server_long(int *sock, int port,char *ip, int type);
1020Sstevel@tonic-gate static int do_accept(int acc_sock, int *sock, char **host);
1030Sstevel@tonic-gate static int host_ip(char *str, unsigned char ip[4]);
1040Sstevel@tonic-gate
1050Sstevel@tonic-gate #ifdef OPENSSL_SYS_WIN16
1060Sstevel@tonic-gate #define SOCKET_PROTOCOL 0 /* more microsoft stupidity */
1070Sstevel@tonic-gate #else
1080Sstevel@tonic-gate #define SOCKET_PROTOCOL IPPROTO_TCP
1090Sstevel@tonic-gate #endif
1100Sstevel@tonic-gate
111*2139Sjp161948 #if defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)
112*2139Sjp161948 static int wsa_init_done=0;
113*2139Sjp161948 #endif
114*2139Sjp161948
1150Sstevel@tonic-gate #ifdef OPENSSL_SYS_WINDOWS
1160Sstevel@tonic-gate static struct WSAData wsa_state;
1170Sstevel@tonic-gate static int wsa_init_done=0;
1180Sstevel@tonic-gate
1190Sstevel@tonic-gate #ifdef OPENSSL_SYS_WIN16
1200Sstevel@tonic-gate static HWND topWnd=0;
1210Sstevel@tonic-gate static FARPROC lpTopWndProc=NULL;
1220Sstevel@tonic-gate static FARPROC lpTopHookProc=NULL;
1230Sstevel@tonic-gate extern HINSTANCE _hInstance; /* nice global CRT provides */
1240Sstevel@tonic-gate
topHookProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)1250Sstevel@tonic-gate static LONG FAR PASCAL topHookProc(HWND hwnd, UINT message, WPARAM wParam,
1260Sstevel@tonic-gate LPARAM lParam)
1270Sstevel@tonic-gate {
1280Sstevel@tonic-gate if (hwnd == topWnd)
1290Sstevel@tonic-gate {
1300Sstevel@tonic-gate switch(message)
1310Sstevel@tonic-gate {
1320Sstevel@tonic-gate case WM_DESTROY:
1330Sstevel@tonic-gate case WM_CLOSE:
1340Sstevel@tonic-gate SetWindowLong(topWnd,GWL_WNDPROC,(LONG)lpTopWndProc);
1350Sstevel@tonic-gate ssl_sock_cleanup();
1360Sstevel@tonic-gate break;
1370Sstevel@tonic-gate }
1380Sstevel@tonic-gate }
1390Sstevel@tonic-gate return CallWindowProc(lpTopWndProc,hwnd,message,wParam,lParam);
1400Sstevel@tonic-gate }
1410Sstevel@tonic-gate
enumproc(HWND hwnd,LPARAM lParam)1420Sstevel@tonic-gate static BOOL CALLBACK enumproc(HWND hwnd,LPARAM lParam)
1430Sstevel@tonic-gate {
1440Sstevel@tonic-gate topWnd=hwnd;
1450Sstevel@tonic-gate return(FALSE);
1460Sstevel@tonic-gate }
1470Sstevel@tonic-gate
1480Sstevel@tonic-gate #endif /* OPENSSL_SYS_WIN32 */
1490Sstevel@tonic-gate #endif /* OPENSSL_SYS_WINDOWS */
1500Sstevel@tonic-gate
1510Sstevel@tonic-gate #ifdef OPENSSL_SYS_WINDOWS
ssl_sock_cleanup(void)1520Sstevel@tonic-gate static void ssl_sock_cleanup(void)
1530Sstevel@tonic-gate {
1540Sstevel@tonic-gate if (wsa_init_done)
1550Sstevel@tonic-gate {
1560Sstevel@tonic-gate wsa_init_done=0;
1570Sstevel@tonic-gate #ifndef OPENSSL_SYS_WINCE
1580Sstevel@tonic-gate WSACancelBlockingCall();
1590Sstevel@tonic-gate #endif
1600Sstevel@tonic-gate WSACleanup();
1610Sstevel@tonic-gate }
1620Sstevel@tonic-gate }
163*2139Sjp161948 #elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)
sock_cleanup(void)164*2139Sjp161948 static void sock_cleanup(void)
165*2139Sjp161948 {
166*2139Sjp161948 if (wsa_init_done)
167*2139Sjp161948 {
168*2139Sjp161948 wsa_init_done=0;
169*2139Sjp161948 WSACleanup();
170*2139Sjp161948 }
171*2139Sjp161948 }
1720Sstevel@tonic-gate #endif
1730Sstevel@tonic-gate
ssl_sock_init(void)1740Sstevel@tonic-gate static int ssl_sock_init(void)
1750Sstevel@tonic-gate {
1760Sstevel@tonic-gate #ifdef WATT32
1770Sstevel@tonic-gate extern int _watt_do_exit;
1780Sstevel@tonic-gate _watt_do_exit = 0;
1790Sstevel@tonic-gate if (sock_init())
1800Sstevel@tonic-gate return (0);
1810Sstevel@tonic-gate #elif defined(OPENSSL_SYS_WINDOWS)
1820Sstevel@tonic-gate if (!wsa_init_done)
1830Sstevel@tonic-gate {
1840Sstevel@tonic-gate int err;
1850Sstevel@tonic-gate
1860Sstevel@tonic-gate #ifdef SIGINT
1870Sstevel@tonic-gate signal(SIGINT,(void (*)(int))ssl_sock_cleanup);
1880Sstevel@tonic-gate #endif
1890Sstevel@tonic-gate wsa_init_done=1;
1900Sstevel@tonic-gate memset(&wsa_state,0,sizeof(wsa_state));
1910Sstevel@tonic-gate if (WSAStartup(0x0101,&wsa_state)!=0)
1920Sstevel@tonic-gate {
1930Sstevel@tonic-gate err=WSAGetLastError();
1940Sstevel@tonic-gate BIO_printf(bio_err,"unable to start WINSOCK, error code=%d\n",err);
1950Sstevel@tonic-gate return(0);
1960Sstevel@tonic-gate }
1970Sstevel@tonic-gate
1980Sstevel@tonic-gate #ifdef OPENSSL_SYS_WIN16
1990Sstevel@tonic-gate EnumTaskWindows(GetCurrentTask(),enumproc,0L);
2000Sstevel@tonic-gate lpTopWndProc=(FARPROC)GetWindowLong(topWnd,GWL_WNDPROC);
2010Sstevel@tonic-gate lpTopHookProc=MakeProcInstance((FARPROC)topHookProc,_hInstance);
2020Sstevel@tonic-gate
2030Sstevel@tonic-gate SetWindowLong(topWnd,GWL_WNDPROC,(LONG)lpTopHookProc);
2040Sstevel@tonic-gate #endif /* OPENSSL_SYS_WIN16 */
2050Sstevel@tonic-gate }
206*2139Sjp161948 #elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)
207*2139Sjp161948 WORD wVerReq;
208*2139Sjp161948 WSADATA wsaData;
209*2139Sjp161948 int err;
210*2139Sjp161948
211*2139Sjp161948 if (!wsa_init_done)
212*2139Sjp161948 {
213*2139Sjp161948
214*2139Sjp161948 # ifdef SIGINT
215*2139Sjp161948 signal(SIGINT,(void (*)(int))sock_cleanup);
216*2139Sjp161948 # endif
217*2139Sjp161948
218*2139Sjp161948 wsa_init_done=1;
219*2139Sjp161948 wVerReq = MAKEWORD( 2, 0 );
220*2139Sjp161948 err = WSAStartup(wVerReq,&wsaData);
221*2139Sjp161948 if (err != 0)
222*2139Sjp161948 {
223*2139Sjp161948 BIO_printf(bio_err,"unable to start WINSOCK2, error code=%d\n",err);
224*2139Sjp161948 return(0);
225*2139Sjp161948 }
226*2139Sjp161948 }
2270Sstevel@tonic-gate #endif /* OPENSSL_SYS_WINDOWS */
2280Sstevel@tonic-gate return(1);
2290Sstevel@tonic-gate }
2300Sstevel@tonic-gate
init_client(int * sock,char * host,int port,int type)231*2139Sjp161948 int init_client(int *sock, char *host, int port, int type)
2320Sstevel@tonic-gate {
2330Sstevel@tonic-gate unsigned char ip[4];
2340Sstevel@tonic-gate short p=0;
2350Sstevel@tonic-gate
2360Sstevel@tonic-gate if (!host_ip(host,&(ip[0])))
2370Sstevel@tonic-gate {
2380Sstevel@tonic-gate return(0);
2390Sstevel@tonic-gate }
2400Sstevel@tonic-gate if (p != 0) port=p;
241*2139Sjp161948 return(init_client_ip(sock,ip,port,type));
2420Sstevel@tonic-gate }
2430Sstevel@tonic-gate
init_client_ip(int * sock,unsigned char ip[4],int port,int type)244*2139Sjp161948 static int init_client_ip(int *sock, unsigned char ip[4], int port, int type)
2450Sstevel@tonic-gate {
2460Sstevel@tonic-gate unsigned long addr;
2470Sstevel@tonic-gate struct sockaddr_in them;
2480Sstevel@tonic-gate int s,i;
2490Sstevel@tonic-gate
2500Sstevel@tonic-gate if (!ssl_sock_init()) return(0);
2510Sstevel@tonic-gate
2520Sstevel@tonic-gate memset((char *)&them,0,sizeof(them));
2530Sstevel@tonic-gate them.sin_family=AF_INET;
2540Sstevel@tonic-gate them.sin_port=htons((unsigned short)port);
2550Sstevel@tonic-gate addr=(unsigned long)
2560Sstevel@tonic-gate ((unsigned long)ip[0]<<24L)|
2570Sstevel@tonic-gate ((unsigned long)ip[1]<<16L)|
2580Sstevel@tonic-gate ((unsigned long)ip[2]<< 8L)|
2590Sstevel@tonic-gate ((unsigned long)ip[3]);
2600Sstevel@tonic-gate them.sin_addr.s_addr=htonl(addr);
2610Sstevel@tonic-gate
262*2139Sjp161948 if (type == SOCK_STREAM)
263*2139Sjp161948 s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
264*2139Sjp161948 else /* ( type == SOCK_DGRAM) */
265*2139Sjp161948 s=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
266*2139Sjp161948
2670Sstevel@tonic-gate if (s == INVALID_SOCKET) { perror("socket"); return(0); }
2680Sstevel@tonic-gate
2690Sstevel@tonic-gate #ifndef OPENSSL_SYS_MPE
270*2139Sjp161948 if (type == SOCK_STREAM)
271*2139Sjp161948 {
272*2139Sjp161948 i=0;
273*2139Sjp161948 i=setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i));
274*2139Sjp161948 if (i < 0) { perror("keepalive"); return(0); }
275*2139Sjp161948 }
2760Sstevel@tonic-gate #endif
2770Sstevel@tonic-gate
2780Sstevel@tonic-gate if (connect(s,(struct sockaddr *)&them,sizeof(them)) == -1)
2790Sstevel@tonic-gate { close(s); perror("connect"); return(0); }
2800Sstevel@tonic-gate *sock=s;
2810Sstevel@tonic-gate return(1);
2820Sstevel@tonic-gate }
2830Sstevel@tonic-gate
do_server(int port,int type,int * ret,int (* cb)(char * hostname,int s,unsigned char * context),unsigned char * context)284*2139Sjp161948 int do_server(int port, int type, int *ret, int (*cb)(char *hostname, int s, unsigned char *context), unsigned char *context)
2850Sstevel@tonic-gate {
2860Sstevel@tonic-gate int sock;
287*2139Sjp161948 char *name = NULL;
2880Sstevel@tonic-gate int accept_socket;
2890Sstevel@tonic-gate int i;
2900Sstevel@tonic-gate
291*2139Sjp161948 if (!init_server(&accept_socket,port,type)) return(0);
2920Sstevel@tonic-gate
2930Sstevel@tonic-gate if (ret != NULL)
2940Sstevel@tonic-gate {
2950Sstevel@tonic-gate *ret=accept_socket;
2960Sstevel@tonic-gate /* return(1);*/
2970Sstevel@tonic-gate }
298*2139Sjp161948 for (;;)
299*2139Sjp161948 {
300*2139Sjp161948 if (type==SOCK_STREAM)
3010Sstevel@tonic-gate {
302*2139Sjp161948 if (do_accept(accept_socket,&sock,&name) == 0)
303*2139Sjp161948 {
304*2139Sjp161948 SHUTDOWN(accept_socket);
305*2139Sjp161948 return(0);
306*2139Sjp161948 }
3070Sstevel@tonic-gate }
308*2139Sjp161948 else
309*2139Sjp161948 sock = accept_socket;
3100Sstevel@tonic-gate i=(*cb)(name,sock, context);
3110Sstevel@tonic-gate if (name != NULL) OPENSSL_free(name);
312*2139Sjp161948 if (type==SOCK_STREAM)
313*2139Sjp161948 SHUTDOWN2(sock);
3140Sstevel@tonic-gate if (i < 0)
3150Sstevel@tonic-gate {
3160Sstevel@tonic-gate SHUTDOWN2(accept_socket);
3170Sstevel@tonic-gate return(i);
3180Sstevel@tonic-gate }
3190Sstevel@tonic-gate }
3200Sstevel@tonic-gate }
3210Sstevel@tonic-gate
init_server_long(int * sock,int port,char * ip,int type)322*2139Sjp161948 static int init_server_long(int *sock, int port, char *ip, int type)
3230Sstevel@tonic-gate {
3240Sstevel@tonic-gate int ret=0;
3250Sstevel@tonic-gate struct sockaddr_in server;
3260Sstevel@tonic-gate int s= -1,i;
3270Sstevel@tonic-gate
3280Sstevel@tonic-gate if (!ssl_sock_init()) return(0);
3290Sstevel@tonic-gate
3300Sstevel@tonic-gate memset((char *)&server,0,sizeof(server));
3310Sstevel@tonic-gate server.sin_family=AF_INET;
3320Sstevel@tonic-gate server.sin_port=htons((unsigned short)port);
3330Sstevel@tonic-gate if (ip == NULL)
3340Sstevel@tonic-gate server.sin_addr.s_addr=INADDR_ANY;
3350Sstevel@tonic-gate else
3360Sstevel@tonic-gate /* Added for T3E, address-of fails on bit field (beckman@acl.lanl.gov) */
3370Sstevel@tonic-gate #ifndef BIT_FIELD_LIMITS
3380Sstevel@tonic-gate memcpy(&server.sin_addr.s_addr,ip,4);
3390Sstevel@tonic-gate #else
3400Sstevel@tonic-gate memcpy(&server.sin_addr,ip,4);
3410Sstevel@tonic-gate #endif
342*2139Sjp161948
343*2139Sjp161948 if (type == SOCK_STREAM)
344*2139Sjp161948 s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
345*2139Sjp161948 else /* type == SOCK_DGRAM */
346*2139Sjp161948 s=socket(AF_INET, SOCK_DGRAM,IPPROTO_UDP);
3470Sstevel@tonic-gate
3480Sstevel@tonic-gate if (s == INVALID_SOCKET) goto err;
3490Sstevel@tonic-gate #if defined SOL_SOCKET && defined SO_REUSEADDR
3500Sstevel@tonic-gate {
3510Sstevel@tonic-gate int j = 1;
3520Sstevel@tonic-gate setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
3530Sstevel@tonic-gate (void *) &j, sizeof j);
3540Sstevel@tonic-gate }
3550Sstevel@tonic-gate #endif
3560Sstevel@tonic-gate if (bind(s,(struct sockaddr *)&server,sizeof(server)) == -1)
3570Sstevel@tonic-gate {
3580Sstevel@tonic-gate #ifndef OPENSSL_SYS_WINDOWS
3590Sstevel@tonic-gate perror("bind");
3600Sstevel@tonic-gate #endif
3610Sstevel@tonic-gate goto err;
3620Sstevel@tonic-gate }
3630Sstevel@tonic-gate /* Make it 128 for linux */
364*2139Sjp161948 if (type==SOCK_STREAM && listen(s,128) == -1) goto err;
3650Sstevel@tonic-gate i=0;
3660Sstevel@tonic-gate *sock=s;
3670Sstevel@tonic-gate ret=1;
3680Sstevel@tonic-gate err:
3690Sstevel@tonic-gate if ((ret == 0) && (s != -1))
3700Sstevel@tonic-gate {
3710Sstevel@tonic-gate SHUTDOWN(s);
3720Sstevel@tonic-gate }
3730Sstevel@tonic-gate return(ret);
3740Sstevel@tonic-gate }
3750Sstevel@tonic-gate
init_server(int * sock,int port,int type)376*2139Sjp161948 static int init_server(int *sock, int port, int type)
3770Sstevel@tonic-gate {
378*2139Sjp161948 return(init_server_long(sock, port, NULL, type));
3790Sstevel@tonic-gate }
3800Sstevel@tonic-gate
do_accept(int acc_sock,int * sock,char ** host)3810Sstevel@tonic-gate static int do_accept(int acc_sock, int *sock, char **host)
3820Sstevel@tonic-gate {
3830Sstevel@tonic-gate int ret,i;
3840Sstevel@tonic-gate struct hostent *h1,*h2;
3850Sstevel@tonic-gate static struct sockaddr_in from;
3860Sstevel@tonic-gate int len;
3870Sstevel@tonic-gate /* struct linger ling; */
3880Sstevel@tonic-gate
3890Sstevel@tonic-gate if (!ssl_sock_init()) return(0);
3900Sstevel@tonic-gate
3910Sstevel@tonic-gate #ifndef OPENSSL_SYS_WINDOWS
3920Sstevel@tonic-gate redoit:
3930Sstevel@tonic-gate #endif
3940Sstevel@tonic-gate
3950Sstevel@tonic-gate memset((char *)&from,0,sizeof(from));
3960Sstevel@tonic-gate len=sizeof(from);
3970Sstevel@tonic-gate /* Note: under VMS with SOCKETSHR the fourth parameter is currently
3980Sstevel@tonic-gate * of type (int *) whereas under other systems it is (void *) if
3990Sstevel@tonic-gate * you don't have a cast it will choke the compiler: if you do
4000Sstevel@tonic-gate * have a cast then you can either go for (int *) or (void *).
4010Sstevel@tonic-gate */
4020Sstevel@tonic-gate ret=accept(acc_sock,(struct sockaddr *)&from,(void *)&len);
4030Sstevel@tonic-gate if (ret == INVALID_SOCKET)
4040Sstevel@tonic-gate {
405*2139Sjp161948 #if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK))
4060Sstevel@tonic-gate i=WSAGetLastError();
4070Sstevel@tonic-gate BIO_printf(bio_err,"accept error %d\n",i);
4080Sstevel@tonic-gate #else
4090Sstevel@tonic-gate if (errno == EINTR)
4100Sstevel@tonic-gate {
4110Sstevel@tonic-gate /*check_timeout(); */
4120Sstevel@tonic-gate goto redoit;
4130Sstevel@tonic-gate }
4140Sstevel@tonic-gate fprintf(stderr,"errno=%d ",errno);
4150Sstevel@tonic-gate perror("accept");
4160Sstevel@tonic-gate #endif
4170Sstevel@tonic-gate return(0);
4180Sstevel@tonic-gate }
4190Sstevel@tonic-gate
4200Sstevel@tonic-gate /*
4210Sstevel@tonic-gate ling.l_onoff=1;
4220Sstevel@tonic-gate ling.l_linger=0;
4230Sstevel@tonic-gate i=setsockopt(ret,SOL_SOCKET,SO_LINGER,(char *)&ling,sizeof(ling));
4240Sstevel@tonic-gate if (i < 0) { perror("linger"); return(0); }
4250Sstevel@tonic-gate i=0;
4260Sstevel@tonic-gate i=setsockopt(ret,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i));
4270Sstevel@tonic-gate if (i < 0) { perror("keepalive"); return(0); }
4280Sstevel@tonic-gate */
4290Sstevel@tonic-gate
4300Sstevel@tonic-gate if (host == NULL) goto end;
4310Sstevel@tonic-gate #ifndef BIT_FIELD_LIMITS
4320Sstevel@tonic-gate /* I should use WSAAsyncGetHostByName() under windows */
4330Sstevel@tonic-gate h1=gethostbyaddr((char *)&from.sin_addr.s_addr,
4340Sstevel@tonic-gate sizeof(from.sin_addr.s_addr),AF_INET);
4350Sstevel@tonic-gate #else
4360Sstevel@tonic-gate h1=gethostbyaddr((char *)&from.sin_addr,
4370Sstevel@tonic-gate sizeof(struct in_addr),AF_INET);
4380Sstevel@tonic-gate #endif
4390Sstevel@tonic-gate if (h1 == NULL)
4400Sstevel@tonic-gate {
4410Sstevel@tonic-gate BIO_printf(bio_err,"bad gethostbyaddr\n");
4420Sstevel@tonic-gate *host=NULL;
4430Sstevel@tonic-gate /* return(0); */
4440Sstevel@tonic-gate }
4450Sstevel@tonic-gate else
4460Sstevel@tonic-gate {
4470Sstevel@tonic-gate if ((*host=(char *)OPENSSL_malloc(strlen(h1->h_name)+1)) == NULL)
4480Sstevel@tonic-gate {
4490Sstevel@tonic-gate perror("OPENSSL_malloc");
4500Sstevel@tonic-gate return(0);
4510Sstevel@tonic-gate }
4520Sstevel@tonic-gate BUF_strlcpy(*host,h1->h_name,strlen(h1->h_name)+1);
4530Sstevel@tonic-gate
4540Sstevel@tonic-gate h2=GetHostByName(*host);
4550Sstevel@tonic-gate if (h2 == NULL)
4560Sstevel@tonic-gate {
4570Sstevel@tonic-gate BIO_printf(bio_err,"gethostbyname failure\n");
4580Sstevel@tonic-gate return(0);
4590Sstevel@tonic-gate }
4600Sstevel@tonic-gate i=0;
4610Sstevel@tonic-gate if (h2->h_addrtype != AF_INET)
4620Sstevel@tonic-gate {
4630Sstevel@tonic-gate BIO_printf(bio_err,"gethostbyname addr is not AF_INET\n");
4640Sstevel@tonic-gate return(0);
4650Sstevel@tonic-gate }
4660Sstevel@tonic-gate }
4670Sstevel@tonic-gate end:
4680Sstevel@tonic-gate *sock=ret;
4690Sstevel@tonic-gate return(1);
4700Sstevel@tonic-gate }
4710Sstevel@tonic-gate
extract_host_port(char * str,char ** host_ptr,unsigned char * ip,short * port_ptr)4720Sstevel@tonic-gate int extract_host_port(char *str, char **host_ptr, unsigned char *ip,
4730Sstevel@tonic-gate short *port_ptr)
4740Sstevel@tonic-gate {
4750Sstevel@tonic-gate char *h,*p;
4760Sstevel@tonic-gate
4770Sstevel@tonic-gate h=str;
4780Sstevel@tonic-gate p=strchr(str,':');
4790Sstevel@tonic-gate if (p == NULL)
4800Sstevel@tonic-gate {
4810Sstevel@tonic-gate BIO_printf(bio_err,"no port defined\n");
4820Sstevel@tonic-gate return(0);
4830Sstevel@tonic-gate }
4840Sstevel@tonic-gate *(p++)='\0';
4850Sstevel@tonic-gate
4860Sstevel@tonic-gate if ((ip != NULL) && !host_ip(str,ip))
4870Sstevel@tonic-gate goto err;
4880Sstevel@tonic-gate if (host_ptr != NULL) *host_ptr=h;
4890Sstevel@tonic-gate
4900Sstevel@tonic-gate if (!extract_port(p,port_ptr))
4910Sstevel@tonic-gate goto err;
4920Sstevel@tonic-gate return(1);
4930Sstevel@tonic-gate err:
4940Sstevel@tonic-gate return(0);
4950Sstevel@tonic-gate }
4960Sstevel@tonic-gate
host_ip(char * str,unsigned char ip[4])4970Sstevel@tonic-gate static int host_ip(char *str, unsigned char ip[4])
4980Sstevel@tonic-gate {
4990Sstevel@tonic-gate unsigned int in[4];
5000Sstevel@tonic-gate int i;
5010Sstevel@tonic-gate
5020Sstevel@tonic-gate if (sscanf(str,"%u.%u.%u.%u",&(in[0]),&(in[1]),&(in[2]),&(in[3])) == 4)
5030Sstevel@tonic-gate {
5040Sstevel@tonic-gate for (i=0; i<4; i++)
5050Sstevel@tonic-gate if (in[i] > 255)
5060Sstevel@tonic-gate {
5070Sstevel@tonic-gate BIO_printf(bio_err,"invalid IP address\n");
5080Sstevel@tonic-gate goto err;
5090Sstevel@tonic-gate }
5100Sstevel@tonic-gate ip[0]=in[0];
5110Sstevel@tonic-gate ip[1]=in[1];
5120Sstevel@tonic-gate ip[2]=in[2];
5130Sstevel@tonic-gate ip[3]=in[3];
5140Sstevel@tonic-gate }
5150Sstevel@tonic-gate else
5160Sstevel@tonic-gate { /* do a gethostbyname */
5170Sstevel@tonic-gate struct hostent *he;
5180Sstevel@tonic-gate
5190Sstevel@tonic-gate if (!ssl_sock_init()) return(0);
5200Sstevel@tonic-gate
5210Sstevel@tonic-gate he=GetHostByName(str);
5220Sstevel@tonic-gate if (he == NULL)
5230Sstevel@tonic-gate {
5240Sstevel@tonic-gate BIO_printf(bio_err,"gethostbyname failure\n");
5250Sstevel@tonic-gate goto err;
5260Sstevel@tonic-gate }
5270Sstevel@tonic-gate /* cast to short because of win16 winsock definition */
5280Sstevel@tonic-gate if ((short)he->h_addrtype != AF_INET)
5290Sstevel@tonic-gate {
5300Sstevel@tonic-gate BIO_printf(bio_err,"gethostbyname addr is not AF_INET\n");
5310Sstevel@tonic-gate return(0);
5320Sstevel@tonic-gate }
5330Sstevel@tonic-gate ip[0]=he->h_addr_list[0][0];
5340Sstevel@tonic-gate ip[1]=he->h_addr_list[0][1];
5350Sstevel@tonic-gate ip[2]=he->h_addr_list[0][2];
5360Sstevel@tonic-gate ip[3]=he->h_addr_list[0][3];
5370Sstevel@tonic-gate }
5380Sstevel@tonic-gate return(1);
5390Sstevel@tonic-gate err:
5400Sstevel@tonic-gate return(0);
5410Sstevel@tonic-gate }
5420Sstevel@tonic-gate
extract_port(char * str,short * port_ptr)5430Sstevel@tonic-gate int extract_port(char *str, short *port_ptr)
5440Sstevel@tonic-gate {
5450Sstevel@tonic-gate int i;
5460Sstevel@tonic-gate struct servent *s;
5470Sstevel@tonic-gate
5480Sstevel@tonic-gate i=atoi(str);
5490Sstevel@tonic-gate if (i != 0)
5500Sstevel@tonic-gate *port_ptr=(unsigned short)i;
5510Sstevel@tonic-gate else
5520Sstevel@tonic-gate {
5530Sstevel@tonic-gate s=getservbyname(str,"tcp");
5540Sstevel@tonic-gate if (s == NULL)
5550Sstevel@tonic-gate {
5560Sstevel@tonic-gate BIO_printf(bio_err,"getservbyname failure for %s\n",str);
5570Sstevel@tonic-gate return(0);
5580Sstevel@tonic-gate }
5590Sstevel@tonic-gate *port_ptr=ntohs((unsigned short)s->s_port);
5600Sstevel@tonic-gate }
5610Sstevel@tonic-gate return(1);
5620Sstevel@tonic-gate }
5630Sstevel@tonic-gate
5640Sstevel@tonic-gate #define GHBN_NUM 4
5650Sstevel@tonic-gate static struct ghbn_cache_st
5660Sstevel@tonic-gate {
5670Sstevel@tonic-gate char name[128];
5680Sstevel@tonic-gate struct hostent ent;
5690Sstevel@tonic-gate unsigned long order;
5700Sstevel@tonic-gate } ghbn_cache[GHBN_NUM];
5710Sstevel@tonic-gate
5720Sstevel@tonic-gate static unsigned long ghbn_hits=0L;
5730Sstevel@tonic-gate static unsigned long ghbn_miss=0L;
5740Sstevel@tonic-gate
GetHostByName(char * name)5750Sstevel@tonic-gate static struct hostent *GetHostByName(char *name)
5760Sstevel@tonic-gate {
5770Sstevel@tonic-gate struct hostent *ret;
5780Sstevel@tonic-gate int i,lowi=0;
5790Sstevel@tonic-gate unsigned long low= (unsigned long)-1;
5800Sstevel@tonic-gate
5810Sstevel@tonic-gate for (i=0; i<GHBN_NUM; i++)
5820Sstevel@tonic-gate {
5830Sstevel@tonic-gate if (low > ghbn_cache[i].order)
5840Sstevel@tonic-gate {
5850Sstevel@tonic-gate low=ghbn_cache[i].order;
5860Sstevel@tonic-gate lowi=i;
5870Sstevel@tonic-gate }
5880Sstevel@tonic-gate if (ghbn_cache[i].order > 0)
5890Sstevel@tonic-gate {
5900Sstevel@tonic-gate if (strncmp(name,ghbn_cache[i].name,128) == 0)
5910Sstevel@tonic-gate break;
5920Sstevel@tonic-gate }
5930Sstevel@tonic-gate }
5940Sstevel@tonic-gate if (i == GHBN_NUM) /* no hit*/
5950Sstevel@tonic-gate {
5960Sstevel@tonic-gate ghbn_miss++;
5970Sstevel@tonic-gate ret=gethostbyname(name);
5980Sstevel@tonic-gate if (ret == NULL) return(NULL);
5990Sstevel@tonic-gate /* else add to cache */
6000Sstevel@tonic-gate if(strlen(name) < sizeof ghbn_cache[0].name)
6010Sstevel@tonic-gate {
6020Sstevel@tonic-gate strcpy(ghbn_cache[lowi].name,name);
6030Sstevel@tonic-gate memcpy((char *)&(ghbn_cache[lowi].ent),ret,sizeof(struct hostent));
6040Sstevel@tonic-gate ghbn_cache[lowi].order=ghbn_miss+ghbn_hits;
6050Sstevel@tonic-gate }
6060Sstevel@tonic-gate return(ret);
6070Sstevel@tonic-gate }
6080Sstevel@tonic-gate else
6090Sstevel@tonic-gate {
6100Sstevel@tonic-gate ghbn_hits++;
6110Sstevel@tonic-gate ret= &(ghbn_cache[i].ent);
6120Sstevel@tonic-gate ghbn_cache[i].order=ghbn_miss+ghbn_hits;
6130Sstevel@tonic-gate return(ret);
6140Sstevel@tonic-gate }
6150Sstevel@tonic-gate }
616*2139Sjp161948
617*2139Sjp161948 #endif
618