Fix some issues in b_print.c code
[openssl.git] / crypto / bio / bss_sock.c
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 <stdio.h>
11 #include <errno.h>
12 #define USE_SOCKETS
13 #include "bio_lcl.h"
14 #include "internal/cryptlib.h"
15
16 #ifndef OPENSSL_NO_SOCK
17
18 # include <openssl/bio.h>
19
20 # ifdef WATT32
21 /* Watt-32 uses same names */
22 #  undef sock_write
23 #  undef sock_read
24 #  undef sock_puts
25 #  define sock_write SockWrite
26 #  define sock_read  SockRead
27 #  define sock_puts  SockPuts
28 # endif
29
30 static int sock_write(BIO *h, const char *buf, int num);
31 static int sock_read(BIO *h, char *buf, int size);
32 static int sock_puts(BIO *h, const char *str);
33 static long sock_ctrl(BIO *h, int cmd, long arg1, void *arg2);
34 static int sock_new(BIO *h);
35 static int sock_free(BIO *data);
36 int BIO_sock_should_retry(int s);
37
38 static const BIO_METHOD methods_sockp = {
39     BIO_TYPE_SOCKET,
40     "socket",
41     sock_write,
42     sock_read,
43     sock_puts,
44     NULL,                       /* sock_gets, */
45     sock_ctrl,
46     sock_new,
47     sock_free,
48     NULL,
49 };
50
51 const BIO_METHOD *BIO_s_socket(void)
52 {
53     return (&methods_sockp);
54 }
55
56 BIO *BIO_new_socket(int fd, int close_flag)
57 {
58     BIO *ret;
59
60     ret = BIO_new(BIO_s_socket());
61     if (ret == NULL)
62         return (NULL);
63     BIO_set_fd(ret, fd, close_flag);
64     return (ret);
65 }
66
67 static int sock_new(BIO *bi)
68 {
69     bi->init = 0;
70     bi->num = 0;
71     bi->ptr = NULL;
72     bi->flags = 0;
73     return (1);
74 }
75
76 static int sock_free(BIO *a)
77 {
78     if (a == NULL)
79         return (0);
80     if (a->shutdown) {
81         if (a->init) {
82             BIO_closesocket(a->num);
83         }
84         a->init = 0;
85         a->flags = 0;
86     }
87     return (1);
88 }
89
90 static int sock_read(BIO *b, char *out, int outl)
91 {
92     int ret = 0;
93
94     if (out != NULL) {
95         clear_socket_error();
96         ret = readsocket(b->num, out, outl);
97         BIO_clear_retry_flags(b);
98         if (ret <= 0) {
99             if (BIO_sock_should_retry(ret))
100                 BIO_set_retry_read(b);
101         }
102     }
103     return (ret);
104 }
105
106 static int sock_write(BIO *b, const char *in, int inl)
107 {
108     int ret;
109
110     clear_socket_error();
111     ret = writesocket(b->num, in, inl);
112     BIO_clear_retry_flags(b);
113     if (ret <= 0) {
114         if (BIO_sock_should_retry(ret))
115             BIO_set_retry_write(b);
116     }
117     return (ret);
118 }
119
120 static long sock_ctrl(BIO *b, int cmd, long num, void *ptr)
121 {
122     long ret = 1;
123     int *ip;
124
125     switch (cmd) {
126     case BIO_C_SET_FD:
127         sock_free(b);
128         b->num = *((int *)ptr);
129         b->shutdown = (int)num;
130         b->init = 1;
131         break;
132     case BIO_C_GET_FD:
133         if (b->init) {
134             ip = (int *)ptr;
135             if (ip != NULL)
136                 *ip = b->num;
137             ret = b->num;
138         } else
139             ret = -1;
140         break;
141     case BIO_CTRL_GET_CLOSE:
142         ret = b->shutdown;
143         break;
144     case BIO_CTRL_SET_CLOSE:
145         b->shutdown = (int)num;
146         break;
147     case BIO_CTRL_DUP:
148     case BIO_CTRL_FLUSH:
149         ret = 1;
150         break;
151     default:
152         ret = 0;
153         break;
154     }
155     return (ret);
156 }
157
158 static int sock_puts(BIO *bp, const char *str)
159 {
160     int n, ret;
161
162     n = strlen(str);
163     ret = sock_write(bp, str, n);
164     return (ret);
165 }
166
167 int BIO_sock_should_retry(int i)
168 {
169     int err;
170
171     if ((i == 0) || (i == -1)) {
172         err = get_last_socket_error();
173
174         return (BIO_sock_non_fatal_error(err));
175     }
176     return (0);
177 }
178
179 int BIO_sock_non_fatal_error(int err)
180 {
181     switch (err) {
182 # if defined(OPENSSL_SYS_WINDOWS)
183 #  if defined(WSAEWOULDBLOCK)
184     case WSAEWOULDBLOCK:
185 #  endif
186 # endif
187
188 # ifdef EWOULDBLOCK
189 #  ifdef WSAEWOULDBLOCK
190 #   if WSAEWOULDBLOCK != EWOULDBLOCK
191     case EWOULDBLOCK:
192 #   endif
193 #  else
194     case EWOULDBLOCK:
195 #  endif
196 # endif
197
198 # if defined(ENOTCONN)
199     case ENOTCONN:
200 # endif
201
202 # ifdef EINTR
203     case EINTR:
204 # endif
205
206 # ifdef EAGAIN
207 #  if EWOULDBLOCK != EAGAIN
208     case EAGAIN:
209 #  endif
210 # endif
211
212 # ifdef EPROTO
213     case EPROTO:
214 # endif
215
216 # ifdef EINPROGRESS
217     case EINPROGRESS:
218 # endif
219
220 # ifdef EALREADY
221     case EALREADY:
222 # endif
223         return (1);
224         /* break; */
225     default:
226         break;
227     }
228     return (0);
229 }
230
231 #endif                          /* #ifndef OPENSSL_NO_SOCK */