1 /*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 */
24
25 #include "private-lib-core.h"
26 #include <errno.h>
27 #if defined(LWS_WITH_MBEDTLS)
28 #if defined(LWS_HAVE_MBEDTLS_NET_SOCKETS)
29 #include "mbedtls/net_sockets.h"
30 #else
31 #include "mbedtls/net.h"
32 #endif
33 #endif
34
35 int
lws_send_pipe_choked(struct lws * wsi)36 lws_send_pipe_choked(struct lws *wsi)
37 {
38 struct lws *wsi_eff = wsi;
39 fd_set writefds;
40 struct timeval tv = { 0, 0 };
41 int n;
42 #if defined(LWS_WITH_HTTP2)
43 wsi_eff = lws_get_network_wsi(wsi);
44 #endif
45
46 /* the fact we checked implies we avoided back-to-back writes */
47 wsi_eff->could_have_pending = 0;
48
49 /* treat the fact we got a truncated send pending as if we're choked */
50 if (lws_has_buffered_out(wsi)
51 #if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
52 || wsi->http.comp_ctx.buflist_comp ||
53 wsi->http.comp_ctx.may_have_more
54 #endif
55 )
56 return 1;
57
58 FD_ZERO(&writefds);
59 FD_SET(wsi_eff->desc.sockfd, &writefds);
60
61 n = select(wsi_eff->desc.sockfd + 1, NULL, &writefds, NULL, &tv);
62 if (n < 0)
63 return 1; /* choked */
64
65 return !n; /* n = 0 = not writable = choked */
66 }
67
68 int
lws_poll_listen_fd(struct lws_pollfd * fd)69 lws_poll_listen_fd(struct lws_pollfd *fd)
70 {
71 fd_set readfds;
72 struct timeval tv = { 0, 0 };
73
74 FD_ZERO(&readfds);
75 FD_SET(fd->fd, &readfds);
76
77 return select(fd->fd + 1, &readfds, NULL, NULL, &tv);
78 }
79
80 int
lws_plat_set_nonblocking(lws_sockfd_type fd)81 lws_plat_set_nonblocking(lws_sockfd_type fd)
82 {
83 return fcntl(fd, F_SETFL, O_NONBLOCK) < 0;
84 }
85
86 int
lws_plat_set_socket_options(struct lws_vhost * vhost,int fd,int unix_skt)87 lws_plat_set_socket_options(struct lws_vhost *vhost, int fd, int unix_skt)
88 {
89 int optval = 1;
90 socklen_t optlen = sizeof(optval);
91
92 #if defined(__APPLE__) || \
93 defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
94 defined(__NetBSD__) || \
95 defined(__OpenBSD__)
96 struct protoent *tcp_proto;
97 #endif
98
99 if (vhost->ka_time) {
100 /* enable keepalive on this socket */
101 optval = 1;
102 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
103 (const void *)&optval, optlen) < 0)
104 return 1;
105
106 #if defined(__APPLE__) || \
107 defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
108 defined(__NetBSD__) || \
109 defined(__CYGWIN__) || defined(__OpenBSD__) || defined (__sun)
110
111 /*
112 * didn't find a way to set these per-socket, need to
113 * tune kernel systemwide values
114 */
115 #else
116 /* set the keepalive conditions we want on it too */
117 optval = vhost->ka_time;
118 if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE,
119 (const void *)&optval, optlen) < 0)
120 return 1;
121
122 optval = vhost->ka_interval;
123 if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL,
124 (const void *)&optval, optlen) < 0)
125 return 1;
126
127 optval = vhost->ka_probes;
128 if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT,
129 (const void *)&optval, optlen) < 0)
130 return 1;
131 #endif
132 }
133
134 /* Disable Nagle */
135 optval = 1;
136 if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &optval, optlen) < 0)
137 return 1;
138
139 return lws_plat_set_nonblocking(fd);
140 }
141
142 static const int ip_opt_lws_flags[] = {
143 LCCSCF_IP_LOW_LATENCY, LCCSCF_IP_HIGH_THROUGHPUT,
144 LCCSCF_IP_HIGH_RELIABILITY, LCCSCF_IP_LOW_COST
145 }, ip_opt_val[] = {
146 IPTOS_LOWDELAY, IPTOS_THROUGHPUT, IPTOS_RELIABILITY, IPTOS_MINCOST
147 };
148 #if !defined(LWS_WITH_NO_LOGS)
149 static const char *ip_opt_names[] = {
150 "LOWDELAY", "THROUGHPUT", "RELIABILITY", "MINCOST"
151 };
152 #endif
153
154 int
lws_plat_set_socket_options_ip(lws_sockfd_type fd,uint8_t pri,int lws_flags)155 lws_plat_set_socket_options_ip(lws_sockfd_type fd, uint8_t pri, int lws_flags)
156 {
157 int optval = (int)pri, ret = 0, n;
158 socklen_t optlen = sizeof(optval);
159 #if !defined(LWS_WITH_NO_LOGS)
160 int en;
161 #endif
162
163 #if defined(SO_PRIORITY)
164 if (pri) { /* 0 is the default already */
165 if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY,
166 (const void *)&optval, optlen) < 0) {
167 #if !defined(LWS_WITH_NO_LOGS)
168 en = errno;
169 lwsl_warn("%s: unable to set socket pri %d: errno %d\n",
170 __func__, (int)pri, en);
171 #endif
172 ret = 1;
173 } else
174 lwsl_notice("%s: set pri %u\n", __func__, pri);
175 }
176 #endif
177
178 for (n = 0; n < 4; n++) {
179 if (!(lws_flags & ip_opt_lws_flags[n]))
180 continue;
181
182 optval = (int)ip_opt_val[n];
183 if (setsockopt(fd, IPPROTO_IP, IP_TOS, (const void *)&optval,
184 optlen) < 0) {
185 #if !defined(LWS_WITH_NO_LOGS)
186 en = errno;
187 lwsl_warn("%s: unable to set %s: errno %d\n", __func__,
188 ip_opt_names[n], en);
189 #endif
190 ret = 1;
191 } else
192 lwsl_notice("%s: set ip flag %s\n", __func__,
193 ip_opt_names[n]);
194 }
195
196 return ret;
197 }
198
199 /* cast a struct sockaddr_in6 * into addr for ipv6 */
200
201 int
lws_interface_to_sa(int ipv6,const char * ifname,struct sockaddr_in * addr,size_t addrlen)202 lws_interface_to_sa(int ipv6, const char *ifname, struct sockaddr_in *addr,
203 size_t addrlen)
204 {
205 #if 0
206 int rc = LWS_ITOSA_NOT_EXIST;
207
208 struct ifaddrs *ifr;
209 struct ifaddrs *ifc;
210 #ifdef LWS_WITH_IPV6
211 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
212 #endif
213
214 getifaddrs(&ifr);
215 for (ifc = ifr; ifc != NULL && rc; ifc = ifc->ifa_next) {
216 if (!ifc->ifa_addr)
217 continue;
218
219 lwsl_info(" interface %s vs %s\n", ifc->ifa_name, ifname);
220
221 if (strcmp(ifc->ifa_name, ifname))
222 continue;
223
224 switch (ifc->ifa_addr->sa_family) {
225 case AF_INET:
226 #ifdef LWS_WITH_IPV6
227 if (ipv6) {
228 /* map IPv4 to IPv6 */
229 memset((char *)&addr6->sin6_addr, 0,
230 sizeof(struct in6_addr));
231 addr6->sin6_addr.s6_addr[10] = 0xff;
232 addr6->sin6_addr.s6_addr[11] = 0xff;
233 memcpy(&addr6->sin6_addr.s6_addr[12],
234 &((struct sockaddr_in *)ifc->ifa_addr)->sin_addr,
235 sizeof(struct in_addr));
236 } else
237 #endif
238 memcpy(addr,
239 (struct sockaddr_in *)ifc->ifa_addr,
240 sizeof(struct sockaddr_in));
241 break;
242 #ifdef LWS_WITH_IPV6
243 case AF_INET6:
244 memcpy(&addr6->sin6_addr,
245 &((struct sockaddr_in6 *)ifc->ifa_addr)->sin6_addr,
246 sizeof(struct in6_addr));
247 break;
248 #endif
249 default:
250 continue;
251 }
252 rc = LWS_ITOSA_USABLE;
253 }
254
255 freeifaddrs(ifr);
256
257 if (rc == LWS_ITOSA_NOT_EXIST) {
258 /* check if bind to IP address */
259 #ifdef LWS_WITH_IPV6
260 if (inet_pton(AF_INET6, ifname, &addr6->sin6_addr) == 1)
261 rc = LWS_ITOSA_USABLE;
262 else
263 #endif
264 if (inet_pton(AF_INET, ifname, &addr->sin_addr) == 1)
265 rc = LWS_ITOSA_USABLE;
266 }
267
268 return rc;
269 #endif
270
271 return LWS_ITOSA_NOT_EXIST;
272 }
273
274 const char *
lws_plat_inet_ntop(int af,const void * src,char * dst,socklen_t cnt)275 lws_plat_inet_ntop(int af, const void *src, char *dst, socklen_t cnt)
276 {
277 return inet_ntop(af, src, dst, cnt);
278 }
279
280 int
lws_plat_inet_pton(int af,const char * src,void * dst)281 lws_plat_inet_pton(int af, const char *src, void *dst)
282 {
283 return 1; // inet_pton(af, src, dst);
284 }
285
286 int
lws_plat_ifname_to_hwaddr(int fd,const char * ifname,uint8_t * hwaddr,int len)287 lws_plat_ifname_to_hwaddr(int fd, const char *ifname, uint8_t *hwaddr, int len)
288 {
289 lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__);
290
291 return -1;
292 }
293
294 int
lws_plat_rawudp_broadcast(uint8_t * p,const uint8_t * canned,size_t canned_len,size_t n,int fd,const char * iface)295 lws_plat_rawudp_broadcast(uint8_t *p, const uint8_t *canned, size_t canned_len,
296 size_t n, int fd, const char *iface)
297 {
298 lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__);
299
300 return -1;
301 }
302
303 int
lws_plat_if_up(const char * ifname,int fd,int up)304 lws_plat_if_up(const char *ifname, int fd, int up)
305 {
306 lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__);
307
308 return -1;
309 }
310
311 int
lws_plat_BINDTODEVICE(lws_sockfd_type fd,const char * ifname)312 lws_plat_BINDTODEVICE(lws_sockfd_type fd, const char *ifname)
313 {
314 lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__);
315
316 return -1;
317 }
318
319 int
lws_plat_ifconfig(int fd,lws_dhcpc_ifstate_t * is)320 lws_plat_ifconfig(int fd, lws_dhcpc_ifstate_t *is)
321 {
322 lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__);
323
324 return -1;
325 }
326
327 int
lws_plat_vhost_tls_client_ctx_init(struct lws_vhost * vhost)328 lws_plat_vhost_tls_client_ctx_init(struct lws_vhost *vhost)
329 {
330 return 0;
331 }
332
333 #if defined(LWS_WITH_MBEDTLS)
334 int
lws_plat_mbedtls_net_send(void * ctx,const uint8_t * buf,size_t len)335 lws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len)
336 {
337 int fd = ((mbedtls_net_context *) ctx)->fd;
338 int ret;
339
340 if (fd < 0)
341 return MBEDTLS_ERR_NET_INVALID_CONTEXT;
342
343 ret = write(fd, buf, len);
344 if (ret >= 0)
345 return ret;
346
347 if (errno == EAGAIN || errno == EWOULDBLOCK)
348 return MBEDTLS_ERR_SSL_WANT_WRITE;
349
350 if (errno == EPIPE || errno == ECONNRESET)
351 return MBEDTLS_ERR_NET_CONN_RESET;
352
353 if( errno == EINTR )
354 return MBEDTLS_ERR_SSL_WANT_WRITE;
355
356 return MBEDTLS_ERR_NET_SEND_FAILED;
357 }
358
359 int
lws_plat_mbedtls_net_recv(void * ctx,unsigned char * buf,size_t len)360 lws_plat_mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len)
361 {
362 int fd = ((mbedtls_net_context *) ctx)->fd;
363 int ret;
364
365 if (fd < 0)
366 return MBEDTLS_ERR_NET_INVALID_CONTEXT;
367
368 ret = (int)read(fd, buf, len);
369 if (ret >= 0)
370 return ret;
371
372 if (errno == EAGAIN || errno == EWOULDBLOCK)
373 return MBEDTLS_ERR_SSL_WANT_READ;
374
375 if (errno == EPIPE || errno == ECONNRESET)
376 return MBEDTLS_ERR_NET_CONN_RESET;
377
378 if (errno == EINTR || !errno)
379 return MBEDTLS_ERR_SSL_WANT_READ;
380
381 return MBEDTLS_ERR_NET_RECV_FAILED;
382 }
383 #endif
384
385