• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 
10 #include <openssl/bio.h>
11 
12 #if !defined(OPENSSL_NO_SOCK)
13 
14 #include <fcntl.h>
15 #include <string.h>
16 
17 #if !defined(OPENSSL_WINDOWS)
18 #include <unistd.h>
19 #else
20 OPENSSL_MSVC_PRAGMA(warning(push, 3))
21 #include <winsock2.h>
OPENSSL_MSVC_PRAGMA(warning (pop))22 OPENSSL_MSVC_PRAGMA(warning(pop))
23 
24 OPENSSL_MSVC_PRAGMA(comment(lib, "Ws2_32.lib"))
25 #endif
26 
27 #include "internal.h"
28 
29 
30 #if !defined(OPENSSL_WINDOWS)
31 static int closesocket(int sock) {
32   return close(sock);
33 }
34 #endif
35 
sock_free(BIO * bio)36 static int sock_free(BIO *bio) {
37   if (bio->shutdown) {
38     if (bio->init) {
39       closesocket(bio->num);
40     }
41     bio->init = 0;
42     bio->flags = 0;
43   }
44   return 1;
45 }
46 
sock_read(BIO * b,char * out,int outl)47 static int sock_read(BIO *b, char *out, int outl) {
48   if (out == NULL) {
49     return 0;
50   }
51 
52   bio_clear_socket_error();
53 #if defined(OPENSSL_WINDOWS)
54   int ret = recv(b->num, out, outl, 0);
55 #else
56   int ret = (int)read(b->num, out, outl);
57 #endif
58   BIO_clear_retry_flags(b);
59   if (ret <= 0) {
60     if (bio_socket_should_retry(ret)) {
61       BIO_set_retry_read(b);
62     }
63   }
64   return ret;
65 }
66 
sock_write(BIO * b,const char * in,int inl)67 static int sock_write(BIO *b, const char *in, int inl) {
68   bio_clear_socket_error();
69 #if defined(OPENSSL_WINDOWS)
70   int ret = send(b->num, in, inl, 0);
71 #else
72   int ret = (int)write(b->num, in, inl);
73 #endif
74   BIO_clear_retry_flags(b);
75   if (ret <= 0) {
76     if (bio_socket_should_retry(ret)) {
77       BIO_set_retry_write(b);
78     }
79   }
80   return ret;
81 }
82 
sock_ctrl(BIO * b,int cmd,long num,void * ptr)83 static long sock_ctrl(BIO *b, int cmd, long num, void *ptr) {
84   long ret = 1;
85   int *ip;
86 
87   switch (cmd) {
88     case BIO_C_SET_FD:
89       sock_free(b);
90       b->num = *((int *)ptr);
91       b->shutdown = (int)num;
92       b->init = 1;
93       break;
94     case BIO_C_GET_FD:
95       if (b->init) {
96         ip = (int *)ptr;
97         if (ip != NULL) {
98           *ip = b->num;
99         }
100         ret = b->num;
101       } else {
102         ret = -1;
103       }
104       break;
105     case BIO_CTRL_GET_CLOSE:
106       ret = b->shutdown;
107       break;
108     case BIO_CTRL_SET_CLOSE:
109       b->shutdown = (int)num;
110       break;
111     case BIO_CTRL_FLUSH:
112       ret = 1;
113       break;
114     default:
115       ret = 0;
116       break;
117   }
118   return ret;
119 }
120 
121 static const BIO_METHOD methods_sockp = {
122     BIO_TYPE_SOCKET, "socket",
123     sock_write,      sock_read,
124     NULL /* puts */, NULL /* gets, */,
125     sock_ctrl,       NULL /* create */,
126     sock_free,       NULL /* callback_ctrl */,
127 };
128 
BIO_s_socket(void)129 const BIO_METHOD *BIO_s_socket(void) { return &methods_sockp; }
130 
BIO_new_socket(int fd,int close_flag)131 BIO *BIO_new_socket(int fd, int close_flag) {
132   BIO *ret;
133 
134   ret = BIO_new(BIO_s_socket());
135   if (ret == NULL) {
136     return NULL;
137   }
138   BIO_set_fd(ret, fd, close_flag);
139   return ret;
140 }
141 
142 #endif  // OPENSSL_NO_SOCK
143