• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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