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