- if (!BIO_get_port(p,&port)) goto err;
-
- memset((char *)&server,0,sizeof(server));
- sin = (struct sockaddr_in *)&server;
- sin->sin_family=AF_INET;
- sin->sin_port=htons(port);
-
- if (h == NULL || strcmp(h,"*") == 0)
- sin->sin_addr.s_addr=INADDR_ANY;
- else
- {
- if (!BIO_get_host_ip(h,&(ip[0]))) goto err;
- l=(unsigned long)
- ((unsigned long)ip[0]<<24L)|
- ((unsigned long)ip[1]<<16L)|
- ((unsigned long)ip[2]<< 8L)|
- ((unsigned long)ip[3]);
- sin->sin_addr.s_addr=htonl(l);
- }
-
-again:
- s=socket(server.sa_family,SOCK_STREAM,SOCKET_PROTOCOL);
- if (s == INVALID_SOCKET)
- {
- SYSerr(SYS_F_SOCKET,get_last_socket_error());
- ERR_add_error_data(3,"port='",host,"'");
- BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_CREATE_SOCKET);
- goto err;
- }
-
-#ifdef SO_REUSEADDR
- if (bind_mode == BIO_BIND_REUSEADDR)
- {
- int i=1;
-
- ret=setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&i,sizeof(i));
- bind_mode=BIO_BIND_NORMAL;
- }
-#endif
- if (bind(s,&server,sizeof(server)) == -1)
- {
-#ifdef SO_REUSEADDR
- err_num=get_last_socket_error();
- if ((bind_mode == BIO_BIND_REUSEADDR_IF_UNUSED) &&
- (err_num == EADDRINUSE))
- {
- client = server;
- if (h == NULL || strcmp(h,"*") == 0)
- {
-#ifdef AF_INET6
- if (client.sa_family == AF_INET6)
- {
- struct sockaddr_in6 *sin =
- (struct sockaddr_in6 *)&client;
- memset(&sin->sin6_addr,0,sizeof(sin->sin6_addr));
- sin->sin6_addr.s6_addr[15]=1;
- }
- else
-#endif
- if (client.sa_family == AF_INET)
- {
- struct sockaddr_in *sin =
- (struct sockaddr_in *)&client;
- sin->sin_addr.s_addr=htonl(0x7F000001);
- }
- else goto err;
- }
- cs=socket(client.sa_family,SOCK_STREAM,SOCKET_PROTOCOL);
- if (cs != INVALID_SOCKET)
- {
- int ii;
- ii=connect(cs,(struct sockaddr *)&client,
- sizeof(client));
- closesocket(cs);
- if (ii == INVALID_SOCKET)
- {
- bind_mode=BIO_BIND_REUSEADDR;
- closesocket(s);
- goto again;
- }
- /* else error */
- }
- /* else error */
- }
-#endif
- SYSerr(SYS_F_BIND,err_num);
- ERR_add_error_data(3,"port='",host,"'");
- BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_BIND_SOCKET);
- goto err;
- }
- if (listen(s,MAX_LISTEN) == -1)
- {
- SYSerr(SYS_F_BIND,get_last_socket_error());
- ERR_add_error_data(3,"port='",host,"'");
- BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_LISTEN_SOCKET);
- goto err;
- }
- ret=1;
-err:
- if (str != NULL) OPENSSL_free(str);
- if ((ret == 0) && (s != INVALID_SOCKET))
- {
- closesocket(s);
- s= INVALID_SOCKET;
- }
- return(s);
- }
-
-int BIO_accept(int sock, char **addr)
- {
- int ret=INVALID_SOCKET;
- struct sockaddr from;
- struct sockaddr_in *sin;
- unsigned long l;
- unsigned short port;
- int len;
- char *p;
-
- memset(&from,0,sizeof(from));
- len=sizeof(from);
- /* 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,&from,(void *)&len);
- if (ret == INVALID_SOCKET)
- {
- if(BIO_sock_should_retry(ret)) return -2;
- SYSerr(SYS_F_ACCEPT,get_last_socket_error());
- BIOerr(BIO_F_BIO_ACCEPT,BIO_R_ACCEPT_ERROR);
- goto end;
- }
-
- if (addr == NULL) goto end;
-
-#ifdef EAI_FAMILY
- do {
- char h[NI_MAXHOST],s[NI_MAXSERV];
- size_t l;
- static union { void *p;
- int (*f)(const struct sockaddr *,socklen_t,
- char *,size_t,char *,size_t,int);
- } getnameinfo = {NULL};
-
- if (getnameinfo.p==NULL)
- {
- if ((getnameinfo.p=DSO_global_lookup("getnameinfo"))==NULL)
- getnameinfo.p=(void*)-1;
- }
- if (getnameinfo.p==(void *)-1) break;
-
- if ((*getnameinfo.f)(&from,sizeof(from),h,sizeof(h),s,sizeof(s),
- NI_NUMERICHOST|NI_NUMERICSERV)) break;
- l = strlen(h)+strlen(s)+2; if (len<24) len=24;
- p = *addr;
- if (p) { *p = '\0'; p = OPENSSL_realloc(p,l); }
- else { p = OPENSSL_malloc(l); }
- if (p==NULL)
- {
- BIOerr(BIO_F_BIO_ACCEPT,ERR_R_MALLOC_FAILURE);
- goto end;
- }
- *addr = p;
- BIO_snprintf(*addr,l,"%s:%s",h,s);
- goto end;
- } while(0);
-#endif
- if (from.sa_family != AF_INET) goto end;
- sin = (struct sockaddr_in *)&from;
- l=ntohl(sin->sin_addr.s_addr);
- port=ntohs(sin->sin_port);
- if (*addr == NULL)
- {
- if ((p=OPENSSL_malloc(24)) == NULL)
- {
- BIOerr(BIO_F_BIO_ACCEPT,ERR_R_MALLOC_FAILURE);
- goto end;
- }
- *addr=p;
- }
- BIO_snprintf(*addr,24,"%d.%d.%d.%d:%d",
- (unsigned char)(l>>24L)&0xff,
- (unsigned char)(l>>16L)&0xff,
- (unsigned char)(l>> 8L)&0xff,
- (unsigned char)(l )&0xff,
- port);
-end:
- return(ret);
- }
+ if (!BIO_parse_hostserv(host, &h, &p, BIO_PARSE_PRIO_SERV))
+ return INVALID_SOCKET;
+
+ if (BIO_sock_init() != 1)
+ return INVALID_SOCKET;
+
+ if (BIO_lookup(h, p, BIO_LOOKUP_SERVER, AF_UNSPEC, SOCK_STREAM, &res) != 0)
+ goto err;
+
+ if ((s = BIO_socket(BIO_ADDRINFO_family(res), BIO_ADDRINFO_socktype(res),
+ BIO_ADDRINFO_protocol(res), 0)) == INVALID_SOCKET) {
+ s = INVALID_SOCKET;
+ goto err;
+ }
+
+ if (!BIO_listen(s, BIO_ADDRINFO_address(res),
+ bind_mode ? BIO_SOCK_REUSEADDR : 0)) {
+ BIO_closesocket(s);
+ s = INVALID_SOCKET;
+ }
+
+ err:
+ BIO_ADDRINFO_free(res);
+ OPENSSL_free(h);
+ OPENSSL_free(p);
+
+ return s;
+}
+
+int BIO_accept(int sock, char **ip_port)
+{
+ BIO_ADDR *res = BIO_ADDR_new();
+ int ret = -1;
+
+ if (res == NULL) {
+ BIOerr(BIO_F_BIO_ACCEPT, ERR_R_MALLOC_FAILURE);
+ return ret;
+ }
+
+ ret = BIO_accept_ex(sock, res, 0);
+
+ if (ret == (int)INVALID_SOCKET) {
+ if (BIO_sock_should_retry(ret)) {
+ ret = -2;
+ goto end;
+ }
+ SYSerr(SYS_F_ACCEPT, get_last_socket_error());
+ BIOerr(BIO_F_BIO_ACCEPT, BIO_R_ACCEPT_ERROR);
+ goto end;
+ }
+
+ if (ip_port != NULL) {
+ char *host = BIO_ADDR_hostname_string(res, 1);
+ char *port = BIO_ADDR_service_string(res, 1);
+ *ip_port = OPENSSL_zalloc(strlen(host) + strlen(port) + 2);
+ strcpy(*ip_port, host);
+ strcat(*ip_port, ":");
+ strcat(*ip_port, port);
+ OPENSSL_free(host);
+ OPENSSL_free(port);
+ }
+
+ end:
+ BIO_ADDR_free(res);
+ return ret;
+}
+# endif