1 /*
2  * Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31 
32 #include <errno.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <unistd.h>
36 #include <poll.h>
37 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <netdb.h>
40 #include <netinet/in.h>
41 #include <netinet/tcp.h>
42 
43 #include "istgt.h"
44 #include "istgt_log.h"
45 #include "istgt_sock.h"
46 #include "istgt_misc.h"
47 
48 //#define USE_POLLWAIT
49 #undef USE_POLLWAIT
50 #define TIMEOUT_RW 60
51 #define POLLWAIT 1000
52 #define PORTNUMLEN 32
53 
54 #ifndef AI_NUMERICSERV
55 #define AI_NUMERICSERV 0
56 #endif
57 
58 #if !defined(__GNUC__)
59 #undef __attribute__
60 #define __attribute__(x)
61 #endif
62 
63 int
istgt_getaddr(int sock,char * saddr,int slen,char * caddr,int clen)64 istgt_getaddr(int sock, char *saddr, int slen, char *caddr, int clen)
65 {
66 	struct sockaddr_storage sa;
67 	socklen_t salen;
68 	int rc;
69 
70 	memset(&sa, 0, sizeof sa);
71 	salen = sizeof sa;
72 	rc = getsockname(sock, (struct sockaddr *) &sa, &salen);
73 	if (rc != 0) {
74 		ISTGT_ERRLOG("getsockname() failed (errno=%d)\n", errno);
75 		return -1;
76 	}
77 	rc = getnameinfo((struct sockaddr *) &sa, salen,
78 	    saddr, slen, NULL, 0, NI_NUMERICHOST);
79 	if (rc != 0) {
80 		ISTGT_ERRLOG("getnameinfo() failed (errno=%d)\n", errno);
81 		return -1;
82 	}
83 
84 	memset(&sa, 0, sizeof sa);
85 	salen = sizeof sa;
86 	rc = getpeername(sock, (struct sockaddr *) &sa, &salen);
87 	if (rc != 0) {
88 		ISTGT_ERRLOG("getpeername() failed (errno=%d)\n", errno);
89 		return -1;
90 	}
91 	rc = getnameinfo((struct sockaddr *) &sa, salen,
92 	    caddr, clen, NULL, 0, NI_NUMERICHOST);
93 	if (rc != 0) {
94 		ISTGT_ERRLOG("getnameinfo() failed (errno=%d)\n", errno);
95 		return -1;
96 	}
97 
98 	return 0;
99 }
100 
101 int
istgt_listen(const char * ip,int port)102 istgt_listen(const char *ip, int port)
103 {
104 	char buf[MAX_TMPBUF];
105 	char portnum[PORTNUMLEN];
106 	char *p;
107 	struct addrinfo hints, *res, *res0;
108 	int sock;
109 	int val = 1;
110 	int rc;
111 
112 	if (ip == NULL)
113 		return -1;
114 	if (ip[0] == '[') {
115 		strlcpy(buf, ip + 1, sizeof buf);
116 		p = strchr(buf, ']');
117 		if (p != NULL)
118 			*p = '\0';
119 		ip = (const char *) &buf[0];
120 		if (strcasecmp(ip, "*") == 0) {
121 			strlcpy(buf, "::", sizeof buf);
122 			ip = (const char *) &buf[0];
123 		}
124 	} else {
125 		if (strcasecmp(ip, "*") == 0) {
126 			strlcpy(buf, "0.0.0.0", sizeof buf);
127 			ip = (const char *) &buf[0];
128 		}
129 	}
130 	snprintf(portnum, sizeof portnum, "%d", port);
131 	memset(&hints, 0, sizeof hints);
132 	hints.ai_family = PF_UNSPEC;
133 	hints.ai_socktype = SOCK_STREAM;
134 	hints.ai_flags = AI_NUMERICSERV;
135 	hints.ai_flags |= AI_PASSIVE;
136 	hints.ai_flags |= AI_NUMERICHOST;
137 	rc = getaddrinfo(ip, portnum, &hints, &res0);
138 	if (rc != 0) {
139 		ISTGT_ERRLOG("getaddrinfo() failed (errno=%d)\n", errno);
140 		return -1;
141 	}
142 
143 	/* try listen */
144 	sock = -1;
145 	for (res = res0; res != NULL; res = res->ai_next) {
146 	retry:
147 		sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
148 		if (sock < 0) {
149 			/* error */
150 			continue;
151 		}
152 		rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof val);
153 		if (rc != 0) {
154 			/* error */
155 			continue;
156 		}
157 		rc = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &val, sizeof val);
158 		if (rc != 0) {
159 			/* error */
160 			continue;
161 		}
162 		rc = bind(sock, res->ai_addr, res->ai_addrlen);
163 		if (rc == -1 && errno == EINTR) {
164 			/* interrupted? */
165 			close(sock);
166 			sock = -1;
167 			goto retry;
168 		}
169 		if (rc != 0) {
170 			/* try next family */
171 			close(sock);
172 			sock = -1;
173 			continue;
174 		}
175 		/* bind OK */
176 		rc = listen(sock, 1);
177 		if (rc != 0) {
178 			close(sock);
179 			sock = -1;
180 			break;
181 		}
182 		break;
183 	}
184 	freeaddrinfo(res0);
185 
186 	if (sock < 0) {
187 		return -1;
188 	}
189 	return sock;
190 }
191 
192 int
istgt_connect(const char * host,int port)193 istgt_connect(const char *host, int port)
194 {
195 	char buf[MAX_TMPBUF];
196 	char portnum[PORTNUMLEN];
197 	char *p;
198 	struct addrinfo hints, *res, *res0;
199 	int sock;
200 	int val = 1;
201 	int rc;
202 
203 	if (host == NULL)
204 		return -1;
205 	if (host[0] == '[') {
206 		strlcpy(buf, host + 1, sizeof buf);
207 		p = strchr(buf, ']');
208 		if (p != NULL)
209 			*p = '\0';
210 		host = (const char *) &buf[0];
211 		if (strcasecmp(host, "*") == 0) {
212 			strlcpy(buf, "::", sizeof buf);
213 			host = (const char *) &buf[0];
214 		}
215 	} else {
216 		if (strcasecmp(host, "*") == 0) {
217 			strlcpy(buf, "0.0.0.0", sizeof buf);
218 			host = (const char *) &buf[0];
219 		}
220 	}
221 	snprintf(portnum, sizeof portnum, "%d", port);
222 	memset(&hints, 0, sizeof hints);
223 	hints.ai_family = PF_UNSPEC;
224 	hints.ai_socktype = SOCK_STREAM;
225 	hints.ai_flags = AI_NUMERICSERV;
226 	rc = getaddrinfo(host, portnum, &hints, &res0);
227 	if (rc != 0) {
228 		ISTGT_ERRLOG("getaddrinfo() failed (errno=%d)\n", errno);
229 		return -1;
230 	}
231 
232 	/* try connect */
233 	sock = -1;
234 	for (res = res0; res != NULL; res = res->ai_next) {
235 	retry:
236 		sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
237 		if (sock < 0) {
238 			/* error */
239 			continue;
240 		}
241 		rc = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &val, sizeof val);
242 		if (rc != 0) {
243 			/* error */
244 			continue;
245 		}
246 		rc = connect(sock, res->ai_addr, res->ai_addrlen);
247 		if (rc == -1 && errno == EINTR) {
248 			/* interrupted? */
249 			close(sock);
250 			sock = -1;
251 			goto retry;
252 		}
253 		if (rc != 0) {
254 			/* try next family */
255 			close(sock);
256 			sock = -1;
257 			continue;
258 		}
259 		/* connect OK */
260 		break;
261 	}
262 	freeaddrinfo(res0);
263 
264 	if (sock < 0) {
265 		return -1;
266 	}
267 	return sock;
268 }
269 
270 int
istgt_set_recvtimeout(int s,int msec)271 istgt_set_recvtimeout(int s, int msec)
272 {
273 	struct timeval tv;
274 	int rc;
275 
276 	memset(&tv, 0, sizeof tv);
277 	tv.tv_sec = msec / 1000;
278 	tv.tv_usec = (msec % 1000) * 1000;
279 	rc = setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof tv);
280 	if (rc != 0)
281 		return -1;
282 	return 0;
283 }
284 
285 int
istgt_set_sendtimeout(int s,int msec)286 istgt_set_sendtimeout(int s, int msec)
287 {
288 	struct timeval tv;
289 	int rc;
290 
291 	memset(&tv, 0, sizeof tv);
292 	tv.tv_sec = msec / 1000;
293 	tv.tv_usec = (msec % 1000) * 1000;
294 	rc = setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof tv);
295 	if (rc != 0)
296 		return -1;
297 	return 0;
298 }
299 
300 int
istgt_set_recvlowat(int s,int nbytes)301 istgt_set_recvlowat(int s, int nbytes)
302 {
303 	int val;
304 	int rc;
305 
306 	val = nbytes;
307 	rc = setsockopt(s, SOL_SOCKET, SO_RCVLOWAT, &val, sizeof val);
308 	if (rc != 0)
309 		return -1;
310 	return 0;
311 }
312 
313 #ifdef USE_POLLWAIT
314 static int
can_read_socket(int s,int msec)315 can_read_socket(int s, int msec)
316 {
317 	struct pollfd fds[1];
318 	int rc;
319 
320 	fds[0].fd = s;
321 	fds[0].events = POLLIN;
322  retry:
323 	do {
324 		rc = poll(fds, 1, msec);
325 	} while (rc == -1 && errno == EINTR);
326 	if (rc == -1 && errno == EAGAIN) {
327 		goto retry;
328 	}
329 	if (rc < 0) {
330 		/* error */
331 		return -1;
332 	}
333 	if (fds[0].revents & POLLIN) {
334 		/* read OK */
335 		return 1;
336 	}
337 	return 0;
338 }
339 
340 static int
can_write_socket(int s,int msec)341 can_write_socket(int s, int msec)
342 {
343 	struct pollfd fds[1];
344 	int rc;
345 
346 	fds[0].fd = s;
347 	fds[0].events = POLLOUT;
348  retry:
349 	do {
350 		rc = poll(fds, 1, msec);
351 	} while (rc == -1 && errno == EINTR);
352 	if (rc == -1 && errno == EAGAIN) {
353 		goto retry;
354 	}
355 	if (rc < 0) {
356 		/* error */
357 		return -1;
358 	}
359 	if (fds[0].revents & POLLOUT) {
360 		/* write OK */
361 		return 1;
362 	}
363 	return 0;
364 }
365 #endif /* USE_POLLWAIT */
366 
367 #ifdef USE_POLLWAIT
368 #define UNUSED_POLLWAIT(x) x
369 #else
370 #define UNUSED_POLLWAIT(x) x __attribute__((__unused__))
371 #endif
372 
373 ssize_t
istgt_read_socket(int s,void * buf,size_t nbytes,int UNUSED_POLLWAIT (timeout))374 istgt_read_socket(int s, void *buf, size_t nbytes, int UNUSED_POLLWAIT(timeout))
375 {
376 	ssize_t n;
377 #ifdef USE_POLLWAIT
378 	int msec = POLLWAIT;
379 	int rc;
380 #endif /* USE_POLLWAIT */
381 
382 	if (nbytes == 0)
383 		return 0;
384 
385 #ifdef USE_POLLWAIT
386 	msec = timeout * 1000;
387 	rc = can_read_socket(s, msec);
388 	if (rc < 0) {
389 		return -1;
390 	}
391 	if (rc == 0) {
392 		/* TIMEOUT */
393 		return -2;
394 	}
395  retry:
396 	do {
397 		n = read(s, buf, nbytes);
398 	} while (n == -1 && errno == EINTR);
399 	if (n == -1 && errno == EAGAIN) {
400 		goto retry;
401 	}
402 	if (n < 0) {
403 		return -1;
404 	}
405 #else
406 	do {
407 		n = recv(s, buf, nbytes, 0);
408 	} while (n == -1 && errno == EINTR);
409 	if (n == -1 && errno == EAGAIN) {
410 		/* TIMEOUT */
411 		return -2;
412 	}
413 	if (n == -1) {
414 		return -1;
415 	}
416 #endif /* USE_POLLWAIT */
417 	return n;
418 }
419 
420 ssize_t
istgt_write_socket(int s,const void * buf,size_t nbytes,int UNUSED_POLLWAIT (timeout))421 istgt_write_socket(int s, const void *buf, size_t nbytes, int UNUSED_POLLWAIT(timeout))
422 {
423 	ssize_t n;
424 #ifdef USE_POLLWAIT
425 	int msec = POLLWAIT;
426 	int rc;
427 #endif /* USE_POLLWAIT */
428 
429 	if (nbytes == 0)
430 		return 0;
431 
432 #ifdef USE_POLLWAIT
433 	msec = timeout * 1000;
434 	rc = can_write_socket(s, msec);
435 	if (rc < 0) {
436 		return -1;
437 	}
438 	if (rc == 0) {
439 		/* TIMEOUT */
440 		return -2;
441 	}
442  retry:
443 	do {
444 		n = write(s, buf, nbytes);
445 	} while (n == -1 && errno == EINTR);
446 	if (n == -1 && errno == EAGAIN) {
447 		goto retry;
448 	}
449 	if (n < 0) {
450 		return -1;
451 	}
452 #else
453 	do {
454 		n = send(s, buf, nbytes, 0);
455 	} while (n == -1 && (errno == EINTR || errno == EAGAIN));
456 	if (n == -1) {
457 		return -1;
458 	}
459 #endif /* USE_POLLWAIT */
460 	return n;
461 }
462 
463 ssize_t
istgt_readline_socket(int sock,char * buf,size_t size,char * tmp,size_t tmpsize,int * tmpidx,int * tmpcnt,int timeout)464 istgt_readline_socket(int sock, char *buf, size_t size, char *tmp, size_t tmpsize, int *tmpidx, int *tmpcnt, int timeout)
465 {
466 	unsigned char *up, *utp;
467 	ssize_t maxsize;
468 	ssize_t total;
469 	ssize_t n;
470 	int got_cr;
471 	int idx, cnt;
472 	int ch;
473 
474 	if (size < 2) {
475 		return -1;
476 	}
477 
478 	up = (unsigned char *) buf;
479 	utp = (unsigned char *) tmp;
480 	maxsize = size - 2; /* LF + NUL */
481 	total = 0;
482 	idx = *tmpidx;
483 	cnt = *tmpcnt;
484 	got_cr = 0;
485 
486 	/* receive with LF */
487 	while (total < maxsize) {
488 		/* fill temporary buffer */
489 		if (idx == cnt) {
490 			*tmpidx = idx;
491 			up[total] = '\0';
492 			n = istgt_read_socket(sock, tmp, tmpsize, timeout);
493 			if (n < 0) {
494 				if (total != 0) {
495 					up[total] = '\0';
496 					return total;
497 				}
498 				return -1;
499 			}
500 			if (n == 0) {
501 				/* EOF */
502 				up[total] = '\0';
503 				return total;
504 			}
505 			/* got n bytes */
506 			cnt = *tmpcnt = n;
507 			idx = 0;
508 		}
509 
510 		/* copy from temporary until LF */
511 		ch = utp[idx++];
512 		if (got_cr && ch != '\n') {
513 			/* CR only */
514 			/* back to temporary */
515 			idx--;
516 			/* remove CR */
517 			total--;
518 			break;
519 		} else if (ch == '\n') {
520 			if (got_cr) {
521 				/* CRLF */
522 				/* remove CR */
523 				total--;
524 			} else {
525 				/* LF only */
526 			}
527 			break;
528 		} else if (ch == '\r') {
529 			got_cr = 1;
530 		}
531 		up[total++] = ch;
532 	}
533 	*tmpidx = idx;
534 	/* always append LF + NUL */
535 	up[total++] = '\n';
536 	up[total] = '\0';
537 	return total;
538 }
539 
540 static ssize_t
istgt_allwrite_socket(int s,const void * buf,size_t nbytes,int timeout)541 istgt_allwrite_socket(int s, const void *buf, size_t nbytes, int timeout)
542 {
543 	const uint8_t *cp;
544 	size_t total;
545 	ssize_t n;
546 
547 	total = 0;
548 	cp = (const uint8_t *) buf;
549 	do {
550 		n = istgt_write_socket(s, cp + total, (nbytes - total), timeout);
551 		if (n < 0) {
552 			return n;
553 		}
554 		total += n;
555 	} while (total < nbytes);
556 	return total;
557 }
558 
559 ssize_t
istgt_writeline_socket(int sock,const char * buf,int timeout)560 istgt_writeline_socket(int sock, const char *buf, int timeout)
561 {
562 	const unsigned char *up;
563 	ssize_t total;
564 	ssize_t n;
565 	int idx;
566 	int ch;
567 
568 	up = (const unsigned char *) buf;
569 	total = 0;
570 	idx = 0;
571 
572 	if (up[0] == '\0') {
573 		/* empty string */
574 		n = istgt_allwrite_socket(sock, "\r\n", 2, timeout);
575 		if (n < 0) {
576 			return -1;
577 		}
578 		if (n != 2) {
579 			return -1;
580 		}
581 		total = n;
582 		return total;
583 	}
584 
585 	/* send with CRLF */
586 	while ((ch = up[idx]) != '\0') {
587 		if (ch == '\r') {
588 			if (up[idx + 1] == '\n') {
589 				/* CRLF */
590 				n = istgt_allwrite_socket(sock, up, idx + 2, timeout);
591 				if (n < 0) {
592 					return -1;
593 				}
594 				if (n != idx + 2) {
595 					return -1;
596 				}
597 				idx += 2;
598 			} else {
599 				/* CR Only */
600 				n = istgt_allwrite_socket(sock, up, idx, timeout);
601 				if (n < 0) {
602 					return -1;
603 				}
604 				if (n != idx) {
605 					return -1;
606 				}
607 				idx += 1;
608 				n = istgt_allwrite_socket(sock, "\r\n", 2, timeout);
609 				if (n < 0) {
610 					return -1;
611 				}
612 				if (n != 2) {
613 					return -1;
614 				}
615 			}
616 		} else if (ch == '\n') {
617 			/* LF Only */
618 			n = istgt_allwrite_socket(sock, up, idx, timeout);
619 			if (n < 0) {
620 				return -1;
621 			}
622 			if (n != idx) {
623 				return -1;
624 			}
625 			idx += 1;
626 			n = istgt_allwrite_socket(sock, "\r\n", 2, timeout);
627 			if (n < 0) {
628 				return -1;
629 			}
630 			if (n != 2) {
631 				return -1;
632 			}
633 		} else {
634 			idx++;
635 			continue;
636 		}
637 		up += idx;
638 		total += idx;
639 		idx = 0;
640 	}
641 
642 	if (idx != 0) {
643 		/* no CRLF string */
644 		n = istgt_allwrite_socket(sock, up, idx, timeout);
645 		if (n < 0) {
646 			return -1;
647 		}
648 		if (n != idx) {
649 			return -1;
650 		}
651 		n = istgt_allwrite_socket(sock, "\r\n", 2, timeout);
652 		if (n < 0) {
653 			return -1;
654 		}
655 		if (n != 2) {
656 			return -1;
657 		}
658 		up += idx;
659 		total += idx + 2;
660 		idx = 0;
661 	}
662 
663 	return total;
664 }
665