1 /* -*- c-basic-offset: 4; -*- */
2 /* sock.c: General Socket Functions
3  *
4  * Copyright (C) 2014 Michael Smith <msmith@icecast.org>,
5  *                    Brendan Cully <brendan@xiph.org>,
6  *                    Karl Heyes <karl@xiph.org>,
7  *                    Jack Moffitt <jack@icecast.org>,
8  *                    Ed "oddsock" Zaleski <oddsock@xiph.org>
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public
21  * License along with this library; if not, write to the
22  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
23  * Boston, MA  02110-1301, USA.
24  *
25  */
26 
27 #ifdef HAVE_CONFIG_H
28  #include <config.h>
29 #endif
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <stdarg.h>
34 #include <sys/types.h>
35 #include <ctype.h>
36 #include <string.h>
37 #include <fcntl.h>
38 #include <errno.h>
39 #ifdef HAVE_POLL
40 #include <poll.h>
41 #endif
42 #ifdef HAVE_SYS_SELECT_H
43 #include <sys/select.h>
44 #endif
45 
46 #ifndef _WIN32
47 #include <unistd.h>
48 #include <sys/socket.h>
49 #include <netinet/in.h>
50 #include <netinet/tcp.h>
51 #include <arpa/inet.h>
52 #include <sys/time.h>
53 #include <netdb.h>
54 #else
55 #include <winsock2.h>
56 #endif
57 
58 #include "sock.h"
59 #include "resolver.h"
60 
61 /* for older C libraries */
62 #ifndef AI_NUMERICSERV
63 # define AI_NUMERICSERV 0
64 #endif
65 #ifndef AI_ADDRCONFIG
66 # define AI_ADDRCONFIG 0
67 #endif
68 
69 /* sock_initialize
70 **
71 ** initializes the socket library.  you must call this
72 ** before using the library!
73 */
sock_initialize(void)74 void sock_initialize(void)
75 {
76 #ifdef _WIN32
77     WSADATA wsad;
78     WSAStartup(0x0101, &wsad);
79 #endif
80 
81     resolver_initialize();
82 }
83 
84 /* sock_shutdown
85 **
86 ** shutdown the socket library.  remember to call this when you're
87 ** through using the lib
88 */
sock_shutdown(void)89 void sock_shutdown(void)
90 {
91 #ifdef _WIN32
92     WSACleanup();
93 #endif
94 
95     resolver_shutdown();
96 }
97 
98 /* sock_get_localip
99 **
100 ** gets the local ip address for the machine
101 ** the ip it returns *should* be on the internet.
102 ** in any case, it's as close as we can hope to get
103 ** unless someone has better ideas on how to do this
104 */
sock_get_localip(char * buff,int len)105 char *sock_get_localip(char *buff, int len)
106 {
107     char temp[1024];
108 
109     if (gethostname(temp, sizeof(temp)) != 0)
110         return NULL;
111 
112     if (resolver_getip(temp, buff, len))
113         return buff;
114 
115     return NULL;
116 }
117 
118 /* sock_error
119 **
120 ** returns the last socket error
121 */
sock_error(void)122 int sock_error(void)
123 {
124 #ifdef _WIN32
125     return WSAGetLastError();
126 #else
127     return errno;
128 #endif
129 }
130 
sock_set_error(int val)131 void sock_set_error(int val)
132 {
133 #ifdef _WIN32
134      WSASetLastError (val);
135 #else
136      errno = val;
137 #endif
138 }
139 
140 /* sock_recoverable
141 **
142 ** determines if the socket error is recoverable
143 ** in terms of non blocking sockets
144 */
sock_recoverable(int error)145 int sock_recoverable(int error)
146 {
147     switch (error)
148     {
149     case 0:
150     case EAGAIN:
151     case EINTR:
152     case EINPROGRESS:
153 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
154     case EWOULDBLOCK:
155 #endif
156 #if defined (WSAEWOULDBLOCK) && WSAEWOULDBLOCK != EWOULDBLOCK
157     case WSAEWOULDBLOCK:
158 #endif
159 #if defined (WSAEINPROGRESS) && WSAEINPROGRESS != EINPROGRESS
160     case WSAEINPROGRESS:
161 #endif
162 #ifdef ERESTART
163     case ERESTART:
164 #endif
165         return 1;
166     default:
167         return 0;
168     }
169 }
170 
sock_stalled(int error)171 int sock_stalled (int error)
172 {
173     switch (error)
174     {
175     case EAGAIN:
176     case EINPROGRESS:
177     case EALREADY:
178 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
179     case EWOULDBLOCK:
180 #endif
181 #if defined (WSAEWOULDBLOCK) && WSAEWOULDBLOCK != EWOULDBLOCK
182     case WSAEWOULDBLOCK:
183 #endif
184 #if defined (WSAEINPROGRESS) && WSAEINPROGRESS != EINPROGRESS
185     case WSAEINPROGRESS:
186 #endif
187 #ifdef ERESTART
188     case ERESTART:
189 #endif
190         return 1;
191     default:
192         return 0;
193     }
194 }
195 
196 
sock_connect_pending(int error)197 static int sock_connect_pending (int error)
198 {
199     return error == EINPROGRESS || error == EALREADY;
200 }
201 
202 /* sock_valid_socket
203 **
204 ** determines if a sock_t represents a valid socket
205 */
sock_valid_socket(sock_t sock)206 int sock_valid_socket(sock_t sock)
207 {
208     int ret;
209     int optval;
210     socklen_t optlen;
211 
212     optlen = sizeof(int);
213     /* apparently on windows getsockopt.optval is a char * */
214     ret = getsockopt(sock, SOL_SOCKET, SO_TYPE, (void*) &optval, &optlen);
215 
216     return (ret == 0);
217 }
218 
219 
220 /* determines if the passed socket is still connected */
sock_active(sock_t sock)221 int sock_active (sock_t sock)
222 {
223     char c;
224     int l;
225 
226     l = recv (sock, &c, 1, MSG_PEEK);
227     if (l == 0)
228         return 0;
229     if (l == SOCK_ERROR && sock_recoverable (sock_error()))
230         return 1;
231     return 0;
232 }
233 
234 /* inet_aton
235 **
236 ** turns an ascii ip address into a binary representation
237 */
238 #ifdef _WIN32
inet_aton(const char * s,struct in_addr * a)239 int inet_aton(const char *s, struct in_addr *a)
240 {
241     int lsb, b2, b3, msb;
242 
243     if (sscanf(s, "%d.%d.%d.%d", &lsb, &b2, &b3, &msb) < 4) {
244         return 0;
245     }
246 
247     a->s_addr = inet_addr(s);
248 
249     return (a->s_addr != INADDR_NONE);
250 }
251 #endif /* _WIN32 */
252 
253 /* sock_set_blocking
254  *
255  * set the sock blocking or nonblocking
256  * 1 for blocking
257  * 0 for nonblocking
258  */
sock_set_blocking(sock_t sock,int block)259 int sock_set_blocking(sock_t sock, int block)
260 {
261 #ifdef _WIN32
262 #ifdef __MINGW32__
263     u_long varblock = 1;
264 #else
265     int varblock = 1;
266 #endif
267 #endif
268 
269     if ((!sock_valid_socket(sock)) || (block < 0) || (block > 1))
270         return SOCK_ERROR;
271 
272 #ifdef _WIN32
273     if (block) varblock = 0;
274     return ioctlsocket(sock, FIONBIO, &varblock);
275 #else
276     return fcntl(sock, F_SETFL, (block) ? 0 : O_NONBLOCK);
277 #endif
278 }
279 
sock_set_nolinger(sock_t sock)280 int sock_set_nolinger(sock_t sock)
281 {
282     struct linger lin = { 0, 0 };
283     return setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *)&lin,
284             sizeof(struct linger));
285 }
286 
sock_set_nodelay(sock_t sock)287 int sock_set_nodelay(sock_t sock)
288 {
289     int nodelay = 1;
290 
291     return setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void *)&nodelay,
292             sizeof(int));
293 }
294 
sock_set_keepalive(sock_t sock)295 int sock_set_keepalive(sock_t sock)
296 {
297     int keepalive = 1;
298     return setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepalive,
299             sizeof(int));
300 }
301 
302 /* sock_close
303 **
304 ** close the socket
305 */
sock_close(sock_t sock)306 int sock_close(sock_t sock)
307 {
308 #ifdef _WIN32
309     return closesocket(sock);
310 #else
311     return close(sock);
312 #endif
313 }
314 
315 /* sock_writev
316  *
317  * write multiple buffers at once, return bytes actually written
318  */
319 #ifdef HAVE_WRITEV
320 
sock_writev(sock_t sock,const struct iovec * iov,size_t count)321 ssize_t sock_writev (sock_t sock, const struct iovec *iov, size_t count)
322 {
323     return writev (sock, iov, count);
324 }
325 
326 #else
327 
sock_writev(sock_t sock,const struct iovec * iov,size_t count)328 ssize_t sock_writev (sock_t sock, const struct iovec *iov, size_t count)
329 {
330     int i = count, accum = 0, ret;
331     const struct iovec *v = iov;
332 
333     while (i)
334     {
335         if (v->iov_base && v->iov_len)
336         {
337             ret = sock_write_bytes (sock, v->iov_base, v->iov_len);
338             if (ret == -1 && accum==0)
339                 return -1;
340             if (ret == -1)
341                 ret = 0;
342             accum += ret;
343             if (ret < (int)v->iov_len)
344                 break;
345         }
346         v++;
347         i--;
348     }
349     return accum;
350 }
351 
352 #endif
353 
354 /* sock_write_bytes
355 **
356 ** write bytes to the socket
357 ** this function will _NOT_ block
358 */
sock_write_bytes(sock_t sock,const void * buff,size_t len)359 int sock_write_bytes(sock_t sock, const void *buff, size_t len)
360 {
361     /* sanity check */
362     if (!buff) {
363         return SOCK_ERROR;
364     } else if (len <= 0) {
365         return SOCK_ERROR;
366     } /*else if (!sock_valid_socket(sock)) {
367         return SOCK_ERROR;
368     } */
369 
370     return send(sock, buff, len, 0);
371 }
372 
373 /* sock_write_string
374 **
375 ** writes a string to a socket
376 ** This function must only be called with a blocking socket.
377 */
sock_write_string(sock_t sock,const char * buff)378 int sock_write_string(sock_t sock, const char *buff)
379 {
380     return (sock_write_bytes(sock, buff, strlen(buff)) > 0);
381 }
382 
383 /* sock_write
384 **
385 ** write a formatted string to the socket
386 ** this function must only be called with a blocking socket.
387 ** will truncate the string if it's greater than 1024 chars.
388 */
sock_write(sock_t sock,const char * fmt,...)389 int sock_write(sock_t sock, const char *fmt, ...)
390 {
391     int rc;
392     va_list ap;
393 
394     va_start (ap, fmt);
395     rc = sock_write_fmt (sock, fmt, ap);
396     va_end (ap);
397 
398     return rc;
399 }
400 
401 #ifdef HAVE_OLD_VSNPRINTF
sock_write_fmt(sock_t sock,const char * fmt,va_list ap)402 int sock_write_fmt(sock_t sock, const char *fmt, va_list ap)
403 {
404     va_list ap_local;
405     unsigned int len = 1024;
406     char *buff = NULL;
407     int ret;
408 
409     /* don't go infinite, but stop at some huge limit */
410     while (len < 2*1024*1024)
411     {
412         char *tmp = realloc (buff, len);
413         ret = -1;
414         if (tmp == NULL)
415             break;
416         buff = tmp;
417         va_copy (ap_local, ap);
418         ret = vsnprintf (buff, len, fmt, ap_local);
419         if (ret > 0)
420         {
421             ret = sock_write_bytes (sock, buff, ret);
422             break;
423         }
424         len += 8192;
425     }
426     free (buff);
427     return ret;
428 }
429 #else
sock_write_fmt(sock_t sock,const char * fmt,va_list ap)430 int sock_write_fmt(sock_t sock, const char *fmt, va_list ap)
431 {
432     char buffer [1024], *buff = buffer;
433     int len;
434     int rc = SOCK_ERROR;
435     va_list ap_retry;
436 
437     va_copy (ap_retry, ap);
438 
439     len = vsnprintf (buff, sizeof (buffer), fmt, ap);
440 
441     if (len > 0)
442     {
443         if ((size_t)len < sizeof (buffer))   /* common case */
444             rc = sock_write_bytes(sock, buff, (size_t)len);
445         else
446         {
447             /* truncated */
448             buff = malloc (++len);
449             if (buff)
450             {
451                 len = vsnprintf (buff, len, fmt, ap_retry);
452                 if (len > 0)
453                     rc = sock_write_bytes (sock, buff, len);
454                 free (buff);
455             }
456         }
457     }
458     va_end (ap_retry);
459 
460     return rc;
461 }
462 #endif
463 
464 
sock_read_bytes(sock_t sock,char * buff,size_t len)465 int sock_read_bytes(sock_t sock, char *buff, size_t len)
466 {
467 
468     /*if (!sock_valid_socket(sock)) return 0; */
469     if (!buff) return 0;
470     if (len <= 0) return 0;
471 
472     return recv(sock, buff, len, 0);
473 }
474 
475 /* sock_read_line
476 **
477 ** Read one line of at max len bytes from sock into buff.
478 ** If ok, return 1 and nullterminate buff. Otherwize return 0.
479 ** Terminating \n is not put into the buffer.
480 **
481 ** this function will probably not work on sockets in nonblocking mode
482 */
sock_read_line(sock_t sock,char * buff,const int len)483 int sock_read_line(sock_t sock, char *buff, const int len)
484 {
485     char c = '\0';
486     int read_bytes, pos;
487 
488     /*if (!sock_valid_socket(sock)) {
489         return 0;
490     } else*/ if (!buff) {
491         return 0;
492     } else if (len <= 0) {
493         return 0;
494     }
495 
496     pos = 0;
497     read_bytes = recv(sock, &c, 1, 0);
498 
499     if (read_bytes < 0) {
500         return 0;
501     }
502 
503     while ((c != '\n') && (pos < len) && (read_bytes == 1)) {
504         if (c != '\r')
505             buff[pos++] = c;
506         read_bytes = recv(sock, &c, 1, 0);
507     }
508 
509     if (read_bytes == 1) {
510         buff[pos] = '\0';
511         return 1;
512     } else {
513         return 0;
514     }
515 }
516 
517 /* see if a connection has been established. If timeout is < 0 then wait
518  * indefinitely, else wait for the stated number of seconds.
519  * return SOCK_TIMEOUT for timeout
520  * return SOCK_ERROR for failure
521  * return 0 for try again, interrupted
522  * return 1 for ok
523  */
524 #ifdef HAVE_POLL
sock_connected(sock_t sock,int timeout)525 int sock_connected (sock_t sock, int timeout)
526 {
527     struct pollfd check;
528     int val = SOCK_ERROR;
529     socklen_t size = sizeof val;
530 
531     check.fd = sock;
532     check.events = POLLOUT;
533     switch (poll (&check, 1, timeout*1000))
534     {
535         case 0: return SOCK_TIMEOUT;
536         default:
537             /* on windows getsockopt.val is defined as char* */
538             if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*) &val, &size) == 0)
539             {
540                 if (val == 0)
541                     return 1;
542                 sock_set_error (val);
543             }
544             /* fall through */
545         case -1:
546             if (sock_recoverable (sock_error()))
547                 return 0;
548             return SOCK_ERROR;
549     }
550 }
551 
552 #else
553 
sock_connected(sock_t sock,int timeout)554 int sock_connected (sock_t sock, int timeout)
555 {
556     fd_set wfds;
557     int val = SOCK_ERROR;
558     socklen_t size = sizeof val;
559     struct timeval tv, *timeval = NULL;
560 
561     /* make a timeout of <0 be indefinite */
562     if (timeout >= 0)
563     {
564         tv.tv_sec = timeout;
565         tv.tv_usec = 0;
566         timeval = &tv;
567     }
568 
569     FD_ZERO(&wfds);
570     FD_SET(sock, &wfds);
571 
572     switch (select(sock + 1, NULL, &wfds, NULL, timeval))
573     {
574         case 0:
575             return SOCK_TIMEOUT;
576         default:
577             /* on windows getsockopt.val is defined as char* */
578             if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*) &val, &size) == 0)
579             {
580                 if (val == 0)
581                     return 1;
582                 sock_set_error (val);
583             }
584             /* fall through */
585         case -1:
586             if (sock_recoverable (sock_error()))
587                 return 0;
588             return SOCK_ERROR;
589     }
590 }
591 #endif
592 
sock_connect_wto(const char * hostname,int port,int timeout)593 sock_t sock_connect_wto (const char *hostname, int port, int timeout)
594 {
595     return sock_connect_wto_bind(hostname, port, NULL, timeout);
596 }
597 
598 #ifdef HAVE_GETADDRINFO
599 
sock_connect_non_blocking(const char * hostname,unsigned port)600 sock_t sock_connect_non_blocking (const char *hostname, unsigned port)
601 {
602     int sock = SOCK_ERROR;
603     struct addrinfo *ai, *head, hints;
604     char service[8];
605 
606     memset (&hints, 0, sizeof (hints));
607     hints.ai_family = AF_UNSPEC;
608     hints.ai_socktype = SOCK_STREAM;
609 
610     snprintf (service, sizeof (service), "%u", port);
611 
612     if (getaddrinfo (hostname, service, &hints, &head))
613         return SOCK_ERROR;
614 
615     ai = head;
616     while (ai)
617     {
618         if ((sock = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol))
619                 > -1)
620         {
621             sock_set_blocking (sock, 0);
622             if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0 &&
623                     !sock_connect_pending(sock_error()))
624             {
625                 sock_close (sock);
626                 sock = SOCK_ERROR;
627             }
628             else
629                 break;
630         }
631         ai = ai->ai_next;
632     }
633     if (head) freeaddrinfo (head);
634 
635     return sock;
636 }
637 
638 /* issue a connect, but return after the timeout (seconds) is reached. If
639  * timeout is 0 or less then we will wait until the OS gives up on the connect
640  * The socket is returned
641  */
sock_connect_wto_bind(const char * hostname,int port,const char * bnd,int timeout)642 sock_t sock_connect_wto_bind (const char *hostname, int port, const char *bnd, int timeout)
643 {
644     sock_t sock = SOCK_ERROR;
645     struct addrinfo *ai, *head, *b_head=NULL, hints;
646     char service[8];
647 
648     memset (&hints, 0, sizeof (hints));
649     hints.ai_family = AF_UNSPEC;
650     hints.ai_socktype = SOCK_STREAM;
651     snprintf (service, sizeof (service), "%u", port);
652 
653     if (getaddrinfo (hostname, service, &hints, &head))
654         return SOCK_ERROR;
655 
656     ai = head;
657     while (ai)
658     {
659         if ((sock = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol)) >= 0)
660         {
661             if (timeout > 0)
662                 sock_set_blocking (sock, 0);
663 
664             if (bnd)
665             {
666                 struct addrinfo b_hints;
667                 memset (&b_hints, 0, sizeof(b_hints));
668                 b_hints.ai_family = ai->ai_family;
669                 b_hints.ai_socktype = ai->ai_socktype;
670                 b_hints.ai_protocol = ai->ai_protocol;
671                 if (getaddrinfo (bnd, NULL, &b_hints, &b_head) ||
672                         bind (sock, b_head->ai_addr, b_head->ai_addrlen) < 0)
673                 {
674                     sock_close (sock);
675                     sock = SOCK_ERROR;
676                     break;
677                 }
678             }
679 
680             if (connect (sock, ai->ai_addr, ai->ai_addrlen) == 0)
681                 break;
682 
683             /* loop as the connect maybe async */
684             while (sock != SOCK_ERROR)
685             {
686                 if (sock_recoverable (sock_error()))
687                 {
688                     int connected = sock_connected (sock, timeout);
689                     if (connected == 0)  /* try again, interrupted */
690                         continue;
691                     if (connected == 1) /* connected */
692                     {
693                         if (timeout >= 0)
694                             sock_set_blocking(sock, 1);
695                         break;
696                     }
697                 }
698                 sock_close (sock);
699                 sock = SOCK_ERROR;
700             }
701             if (sock != SOCK_ERROR)
702                 break;
703         }
704         ai = ai->ai_next;
705     }
706     if (b_head)
707         freeaddrinfo (b_head);
708     freeaddrinfo (head);
709 
710     return sock;
711 }
712 
713 
sock_get_server_socket(int port,const char * sinterface)714 sock_t sock_get_server_socket (int port, const char *sinterface)
715 {
716     struct sockaddr_storage sa;
717     struct addrinfo hints, *res, *ai;
718     char service [12];
719     int sock;
720 
721     if (port < 0)
722         return SOCK_ERROR;
723 
724     memset (&sa, 0, sizeof(sa));
725     memset (&hints, 0, sizeof(hints));
726 
727     hints.ai_family = AF_UNSPEC;
728     hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG | AI_NUMERICSERV | AI_NUMERICHOST;
729     hints.ai_socktype = SOCK_STREAM;
730     snprintf (service, sizeof (service), "%d", port);
731 
732     if (getaddrinfo (sinterface, service, &hints, &res))
733         return SOCK_ERROR;
734     ai = res;
735     do
736     {
737         int on = 1;
738         sock = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol);
739         if (sock < 0)
740             continue;
741 
742         setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof(on));
743         on = 0;
744 #ifdef IPV6_V6ONLY
745         setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof on);
746 #endif
747 
748         if (bind (sock, ai->ai_addr, ai->ai_addrlen) < 0)
749         {
750             sock_close (sock);
751             continue;
752         }
753         freeaddrinfo (res);
754         return sock;
755 
756     } while ((ai = ai->ai_next));
757 
758     freeaddrinfo (res);
759     return SOCK_ERROR;
760 }
761 
762 
763 #else
764 
765 
sock_try_connection(sock_t sock,const char * hostname,unsigned int port)766 int sock_try_connection (sock_t sock, const char *hostname, unsigned int port)
767 {
768     struct sockaddr_in sin, server;
769     char ip[MAX_ADDR_LEN];
770 
771     if (!hostname || !hostname[0] || port == 0)
772         return -1;
773 
774     memset(&sin, 0, sizeof(struct sockaddr_in));
775     memset(&server, 0, sizeof(struct sockaddr_in));
776 
777     if (!resolver_getip(hostname, ip, MAX_ADDR_LEN))
778     {
779         sock_close (sock);
780         return -1;
781     }
782 
783     if (inet_aton(ip, (struct in_addr *)&sin.sin_addr) == 0)
784     {
785         sock_close(sock);
786         return -1;
787     }
788 
789     memcpy(&server.sin_addr, &sin.sin_addr, sizeof(struct sockaddr_in));
790 
791     server.sin_family = AF_INET;
792     server.sin_port = htons((short)port);
793 
794     return connect(sock, (struct sockaddr *)&server, sizeof(server));
795 }
796 
sock_connect_non_blocking(const char * hostname,unsigned port)797 sock_t sock_connect_non_blocking (const char *hostname, unsigned port)
798 {
799     sock_t sock;
800 
801     sock = socket(AF_INET, SOCK_STREAM, 0);
802     if (sock == SOCK_ERROR)
803         return SOCK_ERROR;
804 
805     sock_set_blocking (sock, 0);
806     sock_try_connection (sock, hostname, port);
807 
808     return sock;
809 }
810 
sock_connect_wto_bind(const char * hostname,int port,const char * bnd,int timeout)811 sock_t sock_connect_wto_bind (const char *hostname, int port, const char *bnd, int timeout)
812 {
813     sock_t sock;
814 
815     sock = socket(AF_INET, SOCK_STREAM, 0);
816     if (sock == SOCK_ERROR)
817         return SOCK_ERROR;
818 
819     if (bnd)
820     {
821         struct sockaddr_in sa;
822 
823         memset(&sa, 0, sizeof(sa));
824         sa.sin_family = AF_INET;
825 
826         if (inet_aton (bnd, &sa.sin_addr) == 0 ||
827             bind (sock, (struct sockaddr *)&sa, sizeof(sa)) < 0)
828         {
829             sock_close (sock);
830             return SOCK_ERROR;
831         }
832     }
833 
834     if (timeout)
835     {
836         sock_set_blocking (sock, 0);
837         if (sock_try_connection (sock, hostname, port) < 0)
838         {
839             int ret = sock_connected (sock, timeout);
840             if (ret <= 0)
841             {
842                 sock_close (sock);
843                 return SOCK_ERROR;
844             }
845         }
846         sock_set_blocking(sock, 1);
847     }
848     else
849     {
850         if (sock_try_connection (sock, hostname, port) < 0)
851         {
852             sock_close (sock);
853             sock = SOCK_ERROR;
854         }
855     }
856     return sock;
857 }
858 
859 
860 /* sock_get_server_socket
861 **
862 ** create a socket for incoming requests on a specified port and
863 ** interface.  if interface is null, listen on all interfaces.
864 ** returns the socket, or SOCK_ERROR on failure
865 */
sock_get_server_socket(int port,const char * sinterface)866 sock_t sock_get_server_socket(int port, const char *sinterface)
867 {
868     struct sockaddr_in sa;
869     int error, opt;
870     sock_t sock;
871     char ip[MAX_ADDR_LEN];
872 
873     if (port < 0)
874         return SOCK_ERROR;
875 
876     /* defaults */
877     memset(&sa, 0, sizeof(sa));
878 
879     /* set the interface to bind to if specified */
880     if (sinterface != NULL) {
881         if (!resolver_getip(sinterface, ip, sizeof (ip)))
882             return SOCK_ERROR;
883 
884         if (!inet_aton(ip, &sa.sin_addr)) {
885             return SOCK_ERROR;
886         } else {
887             sa.sin_family = AF_INET;
888             sa.sin_port = htons((short)port);
889         }
890     } else {
891         sa.sin_addr.s_addr = INADDR_ANY;
892         sa.sin_family = AF_INET;
893         sa.sin_port = htons((short)port);
894     }
895 
896     /* get a socket */
897     sock = socket (AF_INET, SOCK_STREAM, 0);
898     if (sock == -1)
899         return SOCK_ERROR;
900 
901     /* reuse it if we can */
902     opt = 1;
903     setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt, sizeof(int));
904 
905     /* bind socket to port */
906     error = bind(sock, (struct sockaddr *)&sa, sizeof (struct sockaddr_in));
907     if (error == -1)
908         return SOCK_ERROR;
909 
910     return sock;
911 }
912 
913 #endif
914 
sock_set_send_buffer(sock_t sock,int win_size)915 void sock_set_send_buffer (sock_t sock, int win_size)
916 {
917     setsockopt (sock, SOL_SOCKET, SO_SNDBUF, (char *) &win_size, sizeof(win_size));
918 }
919 
sock_listen(sock_t serversock,int backlog)920 int sock_listen(sock_t serversock, int backlog)
921 {
922     if (!sock_valid_socket(serversock))
923         return 0;
924 
925     if (backlog <= 0)
926         backlog = 10;
927 
928     return (listen(serversock, backlog) == 0);
929 }
930 
sock_accept(sock_t serversock,char * ip,size_t len)931 sock_t sock_accept(sock_t serversock, char *ip, size_t len)
932 {
933 #ifdef HAVE_GETNAMEINFO
934     struct sockaddr_storage sa;
935 #else
936     struct sockaddr_in sa;
937 #endif
938     sock_t ret;
939     socklen_t slen;
940 
941     if (ip == NULL || len == 0 || !sock_valid_socket(serversock))
942         return SOCK_ERROR;
943 
944     slen = sizeof(sa);
945     ret = accept(serversock, (struct sockaddr *)&sa, &slen);
946 
947     if (ret != SOCK_ERROR)
948     {
949 #ifdef HAVE_GETNAMEINFO
950         if (getnameinfo ((struct sockaddr *)&sa, slen, ip, len, NULL, 0, NI_NUMERICHOST))
951             snprintf (ip, len, "unknown");
952 #else
953         /* inet_ntoa is not reentrant, we should protect this */
954         strncpy(ip, inet_ntoa(sa.sin_addr), len);
955 #endif
956         sock_set_nolinger(ret);
957         sock_set_keepalive(ret);
958     }
959 
960     return ret;
961 }
962 
963