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