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