1 // ----------------------------------------------------------------------------
2 //
3 //  Copyright (C) 2011-2016 Fons Adriaensen <fons@linuxaudio.org>
4 //
5 //  This program is free software; you can redistribute it and/or modify
6 //  it under the terms of the GNU General Public License as published by
7 //  the Free Software Foundation; either version 3 of the License, or
8 //  (at your option) any later version.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 //
18 // ----------------------------------------------------------------------------
19 
20 
21 #include <stdlib.h>
22 #include <stddef.h>
23 #include <stdio.h> // for perror()
24 #include <string.h>
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <sys/ioctl.h>
28 #include <sys/un.h>
29 #include <netinet/tcp.h>
30 #if defined(__APPLE__) || defined(__FreeBSD__)
31 #include <netinet/in.h>
32 #endif
33 #include <net/if.h>
34 #include <arpa/inet.h>
35 #include <errno.h>
36 #include "zsockets.h"
37 
38 
Sockaddr(int family)39 Sockaddr::Sockaddr (int family)
40 {
41     reset (family);
42 }
43 
44 
reset(int family)45 void Sockaddr::reset (int family)
46 {
47     sockaddr *S = (sockaddr *) _data;
48     memset (_data, 0, sizeof (struct sockaddr_storage));
49     S->sa_family = family;
50 }
51 
52 
set_addr(int family,int socktype,int protocol,const char * address)53 int Sockaddr::set_addr (int family, int socktype, int protocol, const char *address)
54 {
55     struct addrinfo     H, *A;
56     struct sockaddr_un  *U;
57     int                 rv, len;
58 
59     if (family == AF_UNIX)
60     {
61 	U = (struct sockaddr_un *) _data;
62 	len = sizeof (struct sockaddr_un) - offsetof (struct sockaddr_un, sun_path);
63 	if ((int) strlen (address) > len - 1) return -1;
64 	U->sun_family = AF_UNIX;
65 	strcpy (U->sun_path, address);
66 	return 0;
67     }
68 
69     memset (&H, 0, sizeof (H));
70     H.ai_family = family;
71     H.ai_socktype = socktype;
72     H.ai_protocol = protocol;
73     rv = getaddrinfo (address, 0, &H, &A);
74     if (rv) return rv;
75     if (A == 0) return -1;
76     switch (A->ai_family)
77     {
78     case AF_INET:  len = sizeof (struct sockaddr_in);  break;
79     case AF_INET6: len = sizeof (struct sockaddr_in6); break;
80     default: len = 0;
81     }
82     if (len) memcpy (_data, (char *)(A->ai_addr), len);
83     freeaddrinfo (A);
84     return len ? 0 : -1;
85 }
86 
87 
set_port(int port)88 void Sockaddr::set_port (int port)
89 {
90     struct sockaddr *S = (struct sockaddr *) _data;
91     switch (S->sa_family)
92     {
93     case AF_INET:
94     {
95 	struct sockaddr_in *S4 = (struct sockaddr_in *) _data;
96 	S4->sin_port = htons (port);
97     }
98     case AF_INET6:
99     {
100 	struct sockaddr_in6 *S6 = (struct sockaddr_in6 *) _data;
101 	S6->sin6_port = htons (port);
102     }
103     }
104 }
105 
106 
get_addr(char * address,int len) const107 int Sockaddr::get_addr (char *address, int len) const
108 {
109     struct sockaddr *S = (struct sockaddr *) _data;
110     *address = 0;
111     switch (S->sa_family)
112     {
113     case AF_UNIX:
114     {
115 	struct sockaddr_un *U = (struct sockaddr_un *) _data;
116         strcpy (address, U->sun_path);
117 	return 0;
118     }
119     case AF_INET:
120     {
121 	struct sockaddr_in *S4 = (struct sockaddr_in *) _data;
122         return (inet_ntop (AF_INET, &(S4->sin_addr.s_addr), address, len) == 0) ? -1 : 0;
123     }
124     case AF_INET6:
125     {
126 	struct sockaddr_in6 *S6 = (struct sockaddr_in6 *) _data;
127         return (inet_ntop (AF_INET6, &(S6->sin6_addr.s6_addr), address, len) == 0) ? -1 : 0;
128     }
129     }
130     return 0;
131 }
132 
133 
get_port(void) const134 int Sockaddr::get_port (void) const
135 {
136     struct sockaddr *S = (struct sockaddr *) _data;
137     switch (S->sa_family)
138     {
139     case AF_INET:
140     {
141 	struct sockaddr_in *S4 = (struct sockaddr_in *) _data;
142 	return ntohs (S4->sin_port);
143     }
144     case AF_INET6:
145     {
146 	struct sockaddr_in6 *S6 = (struct sockaddr_in6 *) _data;
147 	return ntohs (S6->sin6_port);
148     }
149     }
150     return 0;
151 }
152 
153 
family(void) const154 int Sockaddr::family (void) const
155 {
156     struct sockaddr *S = (struct sockaddr *) _data;
157     return S->sa_family;
158 }
159 
160 
is_multicast(void) const161 bool Sockaddr::is_multicast (void) const
162 {
163     struct sockaddr *S = (struct sockaddr *) _data;
164     switch (S->sa_family)
165     {
166     case AF_INET:
167     {
168 	struct sockaddr_in *S4 = (struct sockaddr_in *) _data;
169         return IN_MULTICAST (ntohl (S4->sin_addr.s_addr)) ? true : false;
170     }
171     case AF_INET6:
172     {
173 	struct sockaddr_in6 *S6 = (struct sockaddr_in6 *) _data;
174         return IN6_IS_ADDR_MULTICAST (&(S6->sin6_addr)) ? true : false;
175     }
176     }
177     return false;
178 }
179 
180 
sa_len(void) const181 int Sockaddr::sa_len (void) const
182 {
183     struct sockaddr *S = (struct sockaddr *) _data;
184     switch (S->sa_family)
185     {
186     case AF_UNIX:
187         return sizeof (struct sockaddr_un);
188     case AF_INET:
189         return sizeof (struct sockaddr_in);
190     case AF_INET6:
191         return sizeof (struct sockaddr_in6);
192     }
193     return sizeof (struct sockaddr_storage);
194 }
195 
196 
sock_open_active(Sockaddr * remote,Sockaddr * local)197 int sock_open_active (Sockaddr *remote, Sockaddr *local)
198 {
199     int          fd, ipar;
200     socklen_t    len;
201     sa_family_t  fam;
202 
203     fam = remote->family ();
204     len = remote->sa_len ();
205     if (fam != AF_INET && fam != AF_INET6 && fam != AF_UNIX) return -1;
206 
207     fd = socket (fam, SOCK_STREAM, 0);
208     if (fd < 0) return -1;
209     if (fam != AF_UNIX)
210     {
211         ipar = 1;
212         if (setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (char*) &ipar, sizeof (int)))
213         {
214 	    close (fd);
215             return -1;
216 	}
217     }
218     if (local && (local->family () == fam))
219     {
220         if (bind (fd, local->sa_ptr (), len))
221         {
222   	    close (fd);
223 	    return -1;
224 	}
225     }
226     if (connect (fd, remote->sa_ptr (), len))
227     {
228         close (fd);
229         return -1;
230     }
231     if (local && local->family () == AF_UNSPEC)
232     {
233 	if (getsockname (fd, local->sa_ptr (), &len))
234 	{
235   	    close (fd);
236 	    return -1;
237 	}
238     }
239     return fd;
240 }
241 
242 
sock_open_passive(Sockaddr * local,int qlen)243 int sock_open_passive (Sockaddr *local, int qlen)
244 {
245     int          fd;
246     sa_family_t  fam;
247     socklen_t    len;
248 
249     fam = local->family ();
250     len = local->sa_len ();
251     if (fam != AF_INET && fam != AF_INET6 && fam != AF_UNIX) return -1;
252 
253     fd = socket (fam, SOCK_STREAM, 0);
254     if (fd < 0) return -1;
255     if (   bind (fd, local->sa_ptr (), len)
256         || (listen (fd, qlen) < 0))
257     {
258 	close (fd);
259         return -1;
260     }
261     return 0;
262 }
263 
264 
sock_accept(int fd,Sockaddr * remote,Sockaddr * local)265 int sock_accept (int fd, Sockaddr *remote, Sockaddr *local)
266 {
267     int          newfd;
268     sa_family_t  fam;
269     socklen_t    len;
270 
271     fam = remote->family ();
272     len = remote->sa_len ();
273     if (fam != AF_INET && fam != AF_INET6 && fam != AF_UNIX) return -1;
274 
275     newfd = accept (fd, remote->sa_ptr (), &len);
276     if (newfd < 0) return -1;
277     if (local && getsockname (newfd, local->sa_ptr (), &len))
278     {
279 	close (newfd);
280 	return -1;
281     }
282     return newfd;
283 }
284 
285 
sock_open_dgram(Sockaddr * remote,Sockaddr * local)286 int sock_open_dgram (Sockaddr *remote, Sockaddr *local)
287 {
288     int          fd;
289     sa_family_t  fam;
290     socklen_t    len;
291 
292     fam = AF_UNSPEC;
293     len = 0;
294     if (remote)
295     {
296         fam = remote->family ();
297 	len = remote->sa_len ();
298     }
299     else if (local)
300     {
301         fam = local->family ();
302         len = local->sa_len ();
303     }
304 
305     if (local && remote && local->family () != remote->family ()) return -1;
306 
307     fd = socket (fam, SOCK_DGRAM, 0);
308     if (fd < 0) return -1;
309 
310     if (local &&  bind (fd, local->sa_ptr (), len))
311     {
312         close (fd);
313 	return -1;
314     }
315     if (remote && connect (fd, remote->sa_ptr (), len))
316     {
317         close (fd);
318 	return -1;
319     }
320     return fd;
321 }
322 
323 
sock_open_mcsend(Sockaddr * addr,const char * iface,int loop,int hops)324 int sock_open_mcsend (Sockaddr *addr, const char *iface, int loop, int hops)
325 {
326     int            fd, ipar;
327     sa_family_t    fam;
328     socklen_t      len;
329     in_addr        ifa;
330     struct ifreq   ifr;
331 
332     fam = addr->family ();
333     len = addr->sa_len ();
334     if (fam != AF_INET && fam != AF_INET6) return -1;
335 
336     fd = socket (fam, SOCK_DGRAM, 0);
337     if (fd < 0) return -1;
338     ipar = 1;
339     if (fam == AF_INET6)
340     {
341 	ipar = if_nametoindex (iface);
342         if (   setsockopt (fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &loop, sizeof(loop))
343             || setsockopt (fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,  &hops, sizeof(hops))
344             || setsockopt (fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *) &ipar, sizeof(int)))
345         {
346 	    close (fd);
347             return -1;
348         }
349     }
350     else
351     {
352         strncpy (ifr.ifr_name, iface, 16);
353         ifr.ifr_name [15] = 0;
354         ifr.ifr_addr.sa_family = AF_INET;
355         if (ioctl (fd, SIOCGIFADDR, &ifr))
356 	{
357 	    close (fd);
358 	    return -1;
359 	}
360         ifa = ((struct sockaddr_in *)(&ifr.ifr_addr))->sin_addr;
361         if (   setsockopt (fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop))
362             || setsockopt (fd, IPPROTO_IP, IP_MULTICAST_TTL,  &hops, sizeof(hops))
363             || setsockopt (fd, IPPROTO_IP, IP_MULTICAST_IF, (char*) &ifa,  sizeof (ifa)))
364 	{
365 	    close (fd);
366 	    return -1;
367 	}
368     }
369     if (connect (fd, addr->sa_ptr (), len))
370     {
371         close (fd);
372         return -1;
373     }
374     return fd;
375 }
376 
377 
378 
sock_open_mcrecv(Sockaddr * addr,const char * iface)379 int sock_open_mcrecv (Sockaddr *addr, const char *iface)
380 {
381     int                  fd, ipar;
382     sa_family_t          fam;
383 
384     fam = addr->family ();
385     if (fam != AF_INET && fam != AF_INET6) return -1;
386 
387     fd = socket (fam, SOCK_DGRAM, 0);
388     if (fd < 0) return -1;
389     ipar = 1;
390     if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (char*) &ipar, sizeof (int)))
391     {
392 	close (fd);
393         return -1;
394     }
395     if (fam == AF_INET6)
396     {
397         struct ipv6_mreq  mcreq;
398 	struct sockaddr_in6 W6, *A6;
399 
400 	A6 = (struct sockaddr_in6 *) addr->sa_ptr ();
401 	memset (&W6, 0, sizeof (sockaddr_in6));
402 	W6.sin6_family = AF_INET6;
403 	W6.sin6_port = A6->sin6_port;
404 	if (bind (fd, (sockaddr *) &W6, sizeof (sockaddr_in6)))
405 	{
406             close (fd);
407 	    return -1;
408 	}
409         memcpy (&mcreq.ipv6mr_multiaddr, &(A6->sin6_addr), sizeof(struct in6_addr));
410         mcreq.ipv6mr_interface = if_nametoindex (iface);
411 #if defined(__APPLE__) || defined(__FreeBSD__)
412         if (setsockopt (fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char*) &mcreq, sizeof (mcreq)))
413 #else
414         if (setsockopt (fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char*) &mcreq, sizeof (mcreq)))
415 #endif
416 	{
417 	    close (fd);
418 	    return -1;
419 	}
420     }
421     else
422     {
423         struct ifreq     ifreq;
424         struct ip_mreq   mcreq;
425 	struct sockaddr_in W4, *A4;
426 
427         A4 = (struct sockaddr_in *) addr->sa_ptr ();
428 	memset (&W4, 0, sizeof (sockaddr_in));
429 	W4.sin_family = AF_INET;
430 	W4.sin_port = A4->sin_port;
431 	if (bind (fd, (sockaddr *) &W4, sizeof (sockaddr_in)))
432 	{
433             close (fd);
434 	    return -1;
435 	}
436         strncpy (ifreq.ifr_name, iface, 16);
437         ifreq.ifr_name [15] = 0;
438         ifreq.ifr_addr.sa_family = AF_INET;
439         if (ioctl (fd, SIOCGIFADDR, &ifreq))
440 	{
441 	    close (fd);
442 	    return -1;
443 	}
444         mcreq.imr_multiaddr.s_addr = A4->sin_addr.s_addr;
445         mcreq.imr_interface.s_addr = ((struct sockaddr_in *)(&ifreq.ifr_addr))->sin_addr.s_addr;
446         if (setsockopt (fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*) &mcreq, sizeof (mcreq)))
447 	{
448 	    close (fd);
449 	    return -1;
450 	}
451     }
452     return fd;
453 }
454 
455 
sock_close(int fd)456 int sock_close (int fd)
457 {
458     shutdown (fd, SHUT_RDWR);
459     return close (fd);
460 }
461 
462 
463 
sock_set_close_on_exec(int fd,bool flag)464 int sock_set_close_on_exec (int fd, bool flag)
465 {
466     return (fcntl (fd, F_SETFD, flag ? FD_CLOEXEC : 0) < 0) ? -1 : 0;
467 }
468 
469 
sock_set_no_delay(int fd,bool flag)470 int sock_set_no_delay (int fd, bool flag)
471 {
472     int ipar = flag ? 1 : 0;
473 
474     return setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (char*) &ipar, sizeof (ipar));
475 }
476 
477 
sock_set_write_buffer(int fd,size_t size)478 int sock_set_write_buffer (int fd, size_t size)
479 {
480     return setsockopt (fd, SOL_SOCKET, SO_SNDBUF, (char*) &size, sizeof (size));
481 }
482 
483 
sock_set_read_buffer(int fd,size_t size)484 int sock_set_read_buffer (int fd, size_t size)
485 {
486     return setsockopt (fd, SOL_SOCKET, SO_RCVBUF, (char*) &size, sizeof (size));
487 }
488 
489 
sock_write(int fd,void * data,size_t size,size_t min)490 int sock_write (int fd, void* data, size_t size, size_t min)
491 {
492     int    n;
493     size_t k;
494 
495     if (min > size) min = size;
496     for (k = 0; k < min; k += n)
497     {
498         n = write (fd, (char *) data + k, size - k);
499 	if (n <= 0) return n;
500     }
501     return k;
502 }
503 
504 
sock_read(int fd,void * data,size_t size,size_t min)505 int sock_read (int fd, void* data, size_t size, size_t min)
506 {
507     int    n;
508     size_t k;
509 
510     if (min > size) min = size;
511     for (k = 0; k < min; k += n)
512     {
513         n = read (fd, (char *) data + k, size - k);
514 	if (n <= 0) return n;
515     }
516     return k;
517 }
518 
519 
sock_sendto(int fd,void * data,size_t size,Sockaddr * addr)520 int sock_sendto (int fd, void* data, size_t size, Sockaddr *addr)
521 {
522     if (addr) return sendto (fd, (char *) data, size, 0, addr->sa_ptr (), addr->sa_len ());
523     return send (fd, (char *) data, size, 0);
524 }
525 
526 
sock_recvfm(int fd,void * data,size_t size,Sockaddr * addr)527 int sock_recvfm (int fd, void* data, size_t size, Sockaddr *addr)
528 {
529     socklen_t len = sizeof (struct sockaddr_storage);
530 
531     if (addr) return recvfrom (fd, (char *) data, size, 0, addr->sa_ptr (), &len);
532     return recv (fd, (char *) data, size, 0);
533 }
534 
535 
536 
537