libutil++  1.9.3
 All Classes Functions Variables
Socket.cpp
1 /*
2 ** libutil++
3 ** $Id: Socket.cpp 1653 2016-02-28 19:54:59Z sella $
4 ** Copyright (c) 2011-2016 Digital Genesis, LLC. All Rights Reserved.
5 ** Released under the LGPL Version 2.1 License.
6 ** http://www.digitalgenesis.com
7 */
8 
9 static const char rcsid[] __attribute__((used)) = "$Id: Socket.cpp 1653 2016-02-28 19:54:59Z sella $";
10 
11 #include "Socket.h"
12 
13 #include <stdio.h>
14 #include <netdb.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <unistd.h>
18 #include <fcntl.h>
19 #include <net/if.h>
20 #include <arpa/inet.h>
21 #include <sys/ioctl.h>
22 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <sys/un.h>
25 #include <netinet/in.h>
26 #include <errno.h>
27 #include <sys/mman.h>
28 
29 using namespace sella::net;
30 
31 /* Global Variables */
32 extern int errno;
33 
34 union __sockaddr_union {
35  struct sockaddr_storage *ss;
36  struct sockaddr *sa;
37  struct sockaddr_in *sa_in;
38  struct sockaddr_in6 *sa_in6;
39  struct sockaddr_un *sa_un;
40 };
41 
42 Socket::Socket(int s) throw (SocketException) : usable(false), mux(false), read(false), write(false), except(false) {
43  sockaddr_storage addr;
44  socklen_t addrlen = sizeof(sockaddr_storage);
45 
46  if (s < 0 || s > FD_SETSIZE) {
47  THROW(SocketException, "Passed invalid socket (%d)", s);
48  }
49 
50  if (getsockname(s, (sockaddr *) &addr, &addrlen) < 0) {
51  THROW2(SocketException, "getsockname()");
52  }
53 
54  if (addr.ss_family < 1 || addr.ss_family >= AF_MAX) {
55  THROW(SocketException, "Family (%d) is invalid", addr.ss_family);
56  }
57 
58  if (addr.ss_family != AF_INET && addr.ss_family != AF_INET6 && addr.ss_family != AF_PACKET && addr.ss_family != AF_UNIX) {
59  THROW(SocketException, "Only addr.ss_family AF_INET, AF_INET6, AF_PACKET and AF_UNIX are implemented");
60  }
61 
62  this->family = addr.ss_family;
63  this->s = s;
64 }
65 
66 Socket::Socket(int family, int type, int protocol) throw (SocketException) : s(-1), family(family), usable(false), mux(false), read(false), write(false), except(false) {
67  if (family < 1 || family >= AF_MAX) {
68  THROW(SocketException, "Family (%d) is invalid", family);
69  }
70 
71  if (family != AF_INET && family != AF_INET6 && family != AF_PACKET && family != AF_UNIX) {
72  THROW(SocketException, "Only family AF_INET, AF_INET6, AF_PACKET and AF_UNIX are implemented");
73  }
74 
75  if (type < 0) {
76  THROW(SocketException, "Socket type (%d) is invalid", type);
77  }
78 
79  if (protocol < 0) {
80  THROW(SocketException, "Protocol (%d) is invalid", protocol);
81  }
82 
83  if ((this->s = ::socket(family, type, protocol)) < 0) {
84  THROW2(SocketException, "socket()");
85  }
86 }
87 
88 Socket::~Socket() {
89  try {
90  read = write = except = false;
91  close();
92  } catch (...) { };
93 }
94 
95 void Socket::bind(const IPAddressPort &addressport) throw (SocketException) {
96  bind(addressport.getIPAddress().str(), addressport.getPort().get());
97 }
98 
99 void Socket::bind(const IPAddress &address, const Port &port) throw (SocketException) {
100  bind(address.str(), port.get());
101 }
102 
103 void Socket::bind(const std::string &address, const unsigned short port) throw (SocketException) {
104  sockaddr_storage addr;
105  socklen_t addrlen = sizeof(sockaddr_storage);
106 
107  initAddr(family, address, port, addr, addrlen);
108 
109  addr.ss_family = family;
110 
111  if (::bind(s, (sockaddr *) &addr, addrlen) < 0) {
112  THROW2(SocketException, "bind()");
113  }
114 
115  usable = true;
116 }
117 
118 void Socket::connect(const IPAddressPort &addressport) throw (SocketException) {
119  connect(addressport.getIPAddress().str(), addressport.getPort().get());
120 }
121 
122 void Socket::connect(const IPAddress &address, const Port &port) throw (SocketException) {
123  connect(address.str(), port.get());
124 }
125 
126 void Socket::connect(const std::string &address, const unsigned short port) throw (SocketException) {
127  sockaddr_storage addr;
128  socklen_t addrlen = sizeof(sockaddr_storage);
129 
130  initAddr(family, address, port, addr, addrlen);
131 
132  if (::connect(s, (sockaddr *) &addr, addrlen) < 0) {
133  usable = false;
134 
135  THROW2(SocketException, "connect()");
136  }
137 
138  usable = true;
139 }
140 
141 void Socket::close(void) throw (SocketException) {
142  usable = false;
143 
144  if (s >= 0) {
145  if (::close(s) < 0) {
146  THROW2(SocketException, "close()");
147  }
148 
149  s = -1;
150  }
151 }
152 
153 ssize_t Socket::send(const void *data, size_t len, int flags) throw (SocketException) {
154  ssize_t c, r = len;
155  int flg;
156 
157  do {
158  if ((c = ::send(s, data, len, flags)) < 0) {
159  switch (errno) {
160  case EINTR:
161  case EMSGSIZE:
162  case ENOBUFS:
163  break;
164 
165 #if ((EAGAIN) != (EWOULDBLOCK)) /* Same value in Linux, but both are checked for completeness. */
166  case EAGAIN:
167 #endif
168  case EWOULDBLOCK:
169  if ((flags & MSG_DONTWAIT) || ((flg = fcntl(s, F_GETFL)) != -1 && (flg & O_NONBLOCK))) {
170  THROW_CODE(SocketException, EWOULDBLOCK, "Nonblocking socket would have blocked");
171  }
172 
173  THROW_CODE(SocketException, EWOULDBLOCK, "Send timed out");
174 
175  default:
176  usable = false;
177  }
178 
179  THROW2(SocketException, "send()");
180  } else if (c == 0) {
181  usable = false;
182  }
183  } while ((r -= c) > 0);
184 
185  write = false;
186 
187  return len;
188 }
189 
190 ssize_t Socket::send(const std::string &data, int flags) throw (SocketException) {
191  return send((const void*) data.c_str(), data.size(), flags);
192 }
193 
194 ssize_t Socket::send(const std::vector<uint8_t> &data, int flags) throw (SocketException) {
195  return send((const void*) data.data(), data.size(), flags);
196 }
197 
198 ssize_t Socket::recv(void *buf, size_t len, int flags) throw (SocketException) {
199  ssize_t c;
200  int flg;
201 
202  if ((c = ::recv(s, buf, len, flags)) < 0) {
203  switch (errno) {
204  case EINTR:
205  break;
206 
207 #if ((EAGAIN) != (EWOULDBLOCK)) /* Same value in Linux, but both are checked for completeness. */
208  case EAGAIN:
209 #endif
210  case EWOULDBLOCK:
211  read = except = false;
212 
213  if ((flags & MSG_DONTWAIT) || ((flg = fcntl(s, F_GETFL)) != -1 && (flg & O_NONBLOCK))) {
214  THROW_CODE(SocketException, EWOULDBLOCK, "Nonblocking socket would have blocked");
215  }
216 
217  THROW_CODE(SocketException, EWOULDBLOCK, "Receive timed out");
218 
219  default:
220  usable = false;
221  }
222 
223  THROW2(SocketException, "recv()");
224  } else if (c == 0) { /* Orderly socket shutdown detected */
225  usable = false;
226  }
227 
228  read = except = false;
229 
230  return c;
231 }
232 
233 ssize_t Socket::recv(std::string &data, size_t len, int flags) throw (SocketException) {
234  uint8_t buf[len];
235  ssize_t size = recv(buf, len, flags);
236 
237  std::string(buf, buf + size).swap(data);
238 
239  return size;
240 }
241 
242 ssize_t Socket::recv(std::vector<uint8_t> &data, size_t len, int flags) throw (SocketException) {
243  uint8_t buf[len];
244  ssize_t size = recv(buf, len, flags);
245 
246  std::vector<uint8_t>(buf, buf + size).swap(data);
247 
248  return size;
249 }
250 
251 int Socket::getFD(void) const {
252  return s;
253 }
254 
255 bool Socket::isRead(void) const {
256  return read;
257 }
258 
259 bool Socket::isWrite(void) const {
260  return write;
261 }
262 
263 bool Socket::isExcept(void) const {
264  return except;
265 }
266 
267 bool Socket::hasData(void) const throw (SocketException) {
268  return (getQueuedBytes() > 0);
269 }
270 
271 int Socket::getQueuedBytes(void) const throw (SocketException) {
272  int count;
273 
274  if (ioctl(s, FIONREAD, &count) == -1) {
275  THROW2(SocketException, "ioctl()");
276  }
277 
278  return count;
279 }
280 
281 IPAddressPort Socket::getLocalIPAddressPort(void) const throw (SocketException) {
282  sockaddr_storage addr;
283  socklen_t addrlen = sizeof(sockaddr_storage);
284 
285  if (getsockname(s, (sockaddr *) &addr, &addrlen) < 0) {
286  THROW2(SocketException, "getsockname()");
287  }
288 
289  return IPAddressPort(&addr);
290 }
291 
292 IPAddress Socket::getLocalIPAddress(void) const throw (SocketException) {
293  sockaddr_storage addr;
294  socklen_t addrlen = sizeof(sockaddr_storage);
295 
296  if (getsockname(s, (sockaddr *) &addr, &addrlen) < 0) {
297  THROW2(SocketException, "getsockname()");
298  }
299 
300  return IPAddress(&addr);
301 }
302 
303 Port Socket::getLocalPort(void) const throw (SocketException) {
304  sockaddr_storage addr;
305  socklen_t addrlen = sizeof(sockaddr_storage);
306 
307  if (getsockname(s, (sockaddr *) &addr, &addrlen) < 0) {
308  THROW2(SocketException, "getsockname()");
309  }
310 
311  return Port(&addr);
312 }
313 
314 IPAddressPort Socket::getRemoteIPAddressPort(void) const throw (SocketException) {
315  sockaddr_storage addr;
316  socklen_t addrlen = sizeof(sockaddr_storage);
317 
318  if (getpeername(s, (sockaddr *) &addr, &addrlen) < 0) {
319  THROW2(SocketException, "getpeername()");
320  }
321 
322  return IPAddressPort(&addr);
323 }
324 
325 IPAddress Socket::getRemoteIPAddress(void) const throw (SocketException) {
326  sockaddr_storage addr;
327  socklen_t addrlen = sizeof(sockaddr_storage);
328 
329  if (getpeername(s, (sockaddr *) &addr, &addrlen) < 0) {
330  THROW2(SocketException, "getpeername()");
331  }
332 
333  return IPAddress(&addr);
334 }
335 
336 Port Socket::getRemotePort(void) const throw (SocketException) {
337  sockaddr_storage addr;
338  socklen_t addrlen = sizeof(sockaddr_storage);
339 
340  if (getpeername(s, (sockaddr *) &addr, &addrlen) < 0) {
341  THROW2(SocketException, "getpeername()");
342  }
343 
344  return Port(&addr);
345 }
346 
347 int Socket::getFamily(void) const throw () {
348  return family;
349 }
350 
351 bool Socket::isUsable(void) const throw () {
352  if (s < 0 || !(fcntl(s, F_GETFD) != -1 || errno != EBADF)) {
353  return false;
354  }
355 
356  return usable;
357 }
358 
359 bool Socket::hasMux(void) const throw () {
360  return mux;
361 }
362 
363 bool Socket::isSecure(void) const throw () {
364  return false;
365 }
366 
367 void Socket::setBlock(bool on) throw (SocketException) {
368  int flags;
369 
370  if ((flags = fcntl(s, F_GETFL)) < 0) {
371  THROW2(SocketException, "fcntl()");
372  }
373 
374  if (on) {
375  flags &= ~O_NONBLOCK;
376  } else {
377  flags |= O_NONBLOCK;
378  }
379 
380  if (fcntl(s, F_SETFL, flags) < 0) {
381  THROW2(SocketException, "fcntl()");
382  }
383 }
384 
385 bool Socket::isBlock(void) throw (SocketException) {
386  int flags;
387 
388  if ((flags = fcntl(s, F_GETFL)) < 0) {
389  THROW2(SocketException, "fcntl()");
390  }
391 
392  return (flags & O_NONBLOCK);
393 }
394 
395 void Socket::setIpOptions(const void *optval, socklen_t len) throw (SocketException) {
396 #ifdef IP_OPTIONS
397  if (setsockopt(s, IPPROTO_IP, IP_OPTIONS, (void*) optval, len) < 0) {
398  THROW2(SocketException, "setsockopt()");
399  }
400 #else
401  THROW(SocketException, "IP_OPTIONS not defined");
402 #endif
403 }
404 
405 void Socket::setIpPktInfo(bool on) throw (SocketException) {
406 #ifdef IP_PKTINFO
407  int optval = (on) ? 1 : 0;
408 
409  if (setsockopt(s, IPPROTO_IP, IP_PKTINFO, (void*) &optval, sizeof(optval)) < 0) {
410  THROW2(SocketException, "setsockopt()");
411  }
412 #else
413  THROW(SocketException, "IP_PKTINFO not defined");
414 #endif
415 }
416 
417 void Socket::setIpRecvTOS(bool on) throw (SocketException) {
418 #ifdef IP_RECVTOS
419  int optval = (on) ? 1 : 0;
420 
421  if (setsockopt(s, IPPROTO_IP, IP_RECVTOS, (void*) &optval, sizeof(optval)) < 0) {
422  THROW2(SocketException, "setsockopt()");
423  }
424 #else
425  THROW(SocketException, "IP_RECVTOS not defined");
426 #endif
427 }
428 
429 void Socket::setIpRecvTTL(bool on) throw (SocketException) {
430 #ifdef IP_RECVTTL
431  int optval = (on) ? 1 : 0;
432 
433  if (setsockopt(s, IPPROTO_IP, IP_RECVTTL, (void*) &optval, sizeof(optval)) < 0) {
434  THROW2(SocketException, "setsockopt()");
435  }
436 #else
437  THROW(SocketException, "IP_RECVTTL not defined");
438 #endif
439 }
440 
441 void Socket::setIpRecvOpts(bool on) throw (SocketException) {
442 #ifdef IP_RECVOPTS
443  int optval = (on) ? 1 : 0;
444 
445  if (setsockopt(s, IPPROTO_IP, IP_RECVOPTS, (void*) &optval, sizeof(optval)) < 0) {
446  THROW2(SocketException, "setsockopt()");
447  }
448 #else
449  THROW(SocketException, "IP_RECVOPTS not defined");
450 #endif
451 }
452 
453 void Socket::setIpRetOpts(bool on) throw (SocketException) {
454 #ifdef IP_RETOPTS
455  int optval = (on) ? 1 : 0;
456 
457  if (setsockopt(s, IPPROTO_IP, IP_RETOPTS, (void*) &optval, sizeof(optval)) < 0) {
458  THROW2(SocketException, "setsockopt()");
459  }
460 #else
461  THROW(SocketException, "IP_RETOPTS not defined");
462 #endif
463 }
464 
465 void Socket::setIpTOS(unsigned char tos) throw (SocketException) {
466 #ifdef IP_TOS
467  if (setsockopt(s, IPPROTO_IP, IP_TOS, (void*) &tos, sizeof(tos)) < 0) {
468  THROW2(SocketException, "setsockopt()");
469  }
470 #else
471  THROW(SocketException, "IP_TOS not defined");
472 #endif
473 }
474 
475 unsigned char Socket::getIpTOS(void) const throw (SocketException) {
476  unsigned char tos = 0;
477 
478 #ifdef IP_TOS
479  socklen_t len = sizeof(tos);
480 
481  if (getsockopt(s, IPPROTO_IP, IP_TOS, (void*) &tos, &len) < 0) {
482  THROW2(SocketException, "getsockopt()");
483  }
484 #else
485  THROW(SocketException, "IP_TOS not defined");
486 #endif
487 
488  return tos;
489 }
490 
491 void Socket::setIpTTL(int ttl) throw (SocketException) {
492 #ifdef IP_TTL
493  if (setsockopt(s, IPPROTO_IP, IP_TTL, (void*) &ttl, sizeof(ttl)) < 0) {
494  THROW2(SocketException, "setsockopt()");
495  }
496 #else
497  THROW(SocketException, "IP_TTL not defined");
498 #endif
499 }
500 
501 int Socket::getIpTTL(void) const throw (SocketException) {
502  int ttl = 0;
503 #ifdef IP_TTL
504  socklen_t len = sizeof(ttl);
505 
506  if (getsockopt(s, IPPROTO_IP, IP_TTL, (void*) &ttl, &len) < 0) {
507  THROW2(SocketException, "getsockopt()");
508  }
509 #else
510  THROW(SocketException, "IP_TTL not defined");
511 #endif
512 
513  return ttl;
514 }
515 
516 void Socket::setIpHdrIncl(bool on) throw (SocketException) {
517 #ifdef IP_HDRINCL
518  int optval = (on) ? 1 : 0;
519 
520  if (setsockopt(s, IPPROTO_IP, IP_HDRINCL, (void*) &optval, sizeof(optval)) < 0) {
521  THROW2(SocketException, "setsockopt()");
522  }
523 #else
524  THROW(SocketException, "IP_HDRINCL not defined");
525 #endif
526 }
527 
528 void Socket::setIpRecvErr(bool on) throw (SocketException) {
529 #ifdef IP_RECVERR
530  int optval = (on) ? 1 : 0;
531 
532  if (setsockopt(s, IPPROTO_IP, IP_RECVERR, (void*) &optval, sizeof(optval)) < 0) {
533  THROW2(SocketException, "setsockopt()");
534  }
535 #else
536  THROW(SocketException, "IP_RECVERR not defined");
537 #endif
538 }
539 
540 void Socket::setIpMtuDiscover(bool on) throw (SocketException) {
541 #ifdef IP_MTU_DISCOVER
542  int optval = (on) ? 1 : 0;
543 
544  if (setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, (void*) &optval, sizeof(optval)) < 0) {
545  THROW2(SocketException, "setsockopt()");
546  }
547 #else
548  THROW(SocketException, "IP_MTU_DISCOVER not defined");
549 #endif
550 }
551 
552 int Socket::getIpMtu(void) const throw (SocketException) {
553  int mtu = 0;
554 
555 #ifdef IP_MTU
556  socklen_t len = sizeof(mtu);
557 
558  if (getsockopt(s, IPPROTO_IP, IP_MTU, (void*) &mtu, &len) < 0) {
559  THROW2(SocketException, "getsockopt()");
560  }
561 #else
562  THROW(SocketException, "IP_MTU not defined");
563 #endif
564 
565  return mtu;
566 }
567 
568 void Socket::setIpRouterAlert(bool on) throw (SocketException) {
569 #ifdef IP_ROUTER_ALERT
570  int optval = (on) ? 1 : 0;
571 
572  if (setsockopt(s, IPPROTO_IP, IP_ROUTER_ALERT, (void*) &optval, sizeof(optval)) < 0) {
573  THROW2(SocketException, "setsockopt()");
574  }
575 #else
576  THROW(SocketException, "IP_ROUTER_ALERT not defined");
577 #endif
578 }
579 
580 void Socket::setIpMulticastTTL(int ttl) throw (SocketException) {
581 #ifdef IP_MULTICAST_TTL
582  if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, (void*) &ttl, sizeof(ttl)) < 0) {
583  THROW2(SocketException, "setsockopt()");
584  }
585 #else
586  THROW(SocketException, "IP_MULTICAST_TTL not defined");
587 #endif
588 }
589 
590 int Socket::getIpMulticastTTL(void) const throw (SocketException) {
591  int ttl = 0;
592 
593 #ifdef MULTICAST_TTL
594  socklen_t len = sizeof(ttl);
595 
596  if (getsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, (void*) &ttl, &len) < 0) {
597  THROW2(SocketException, "getsockopt()");
598  }
599 #else
600  THROW(SocketException, "IP_MULTICAST_TTL not defined");
601 #endif
602 
603  return ttl;
604 }
605 
606 void Socket::setIpMulticastLoop(bool on) throw (SocketException) {
607 #ifdef IP_MULTICAST_LOOP
608  int optval = (on) ? 1 : 0;
609 
610  if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, (void*) &optval, sizeof(optval)) < 0) {
611  THROW2(SocketException, "setsockopt()");
612  }
613 #else
614  THROW(SocketException, "IP_MULTICAST_LOOP not defined");
615 #endif
616 }
617 
618 void Socket::setIpAddMembership(struct ip_mreqn& m) throw (SocketException) {
619 #ifdef IP_ADD_MEMBERSHIP
620  if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void*) &m, sizeof(struct ip_mreqn)) < 0) {
621  THROW2(SocketException, "setsockopt()");
622  }
623 #else
624  THROW(SocketException, "IP_ADD_MEMBERSHIP not defined");
625 #endif
626 }
627 
628 void Socket::setIpDropMembership(struct ip_mreqn& m) throw (SocketException) {
629 #ifdef IP_DROP_MEMBERSHIP
630  if (setsockopt(s, IPPROTO_IP, IP_DROP_MEMBERSHIP, (void*) &m, sizeof(struct ip_mreqn)) < 0) {
631  THROW2(SocketException, "setsockopt()");
632  }
633 #else
634  THROW(SocketException, "IP_DROP_MEMBERSHIP not defined");
635 #endif
636 }
637 
638 void Socket::setSoReuseAddr(bool on) throw (SocketException) {
639 #ifdef SO_REUSEADDR
640  int optval = (on) ? 1 : 0;
641 
642  if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*) &optval, sizeof(optval)) < 0) {
643  THROW2(SocketException, "setsockopt()");
644  }
645 #else
646  THROW(SocketException, "SO_REUSEADDR not defined");
647 #endif
648 }
649 
650 void Socket::setSoKeepAlive(bool on) throw (SocketException) {
651 #ifdef SO_KEEPALIVE
652  int optval = (on) ? 1 : 0;
653 
654  if (setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (void*) &optval, sizeof(optval)) < 0) {
655  THROW2(SocketException, "setsockopt()");
656  }
657 #else
658  THROW(SocketException, "SO_KEEPALIVE not defined");
659 #endif
660 }
661 
662 void Socket::setSoNoSigPipe(bool on) throw (SocketException) {
663 #ifdef SO_NOSIGPIPE
664  int optval = (on) ? 1 : 0;
665 
666  if (setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (void*) &optval, sizeof(optval)) < 0) {
667  THROW2(SocketException, "setsockopt()");
668  }
669 #else
670  THROW(SocketException, "SO_NOSIGPIPE not defined");
671 #endif
672 }
673 
674 bool Socket::getSoAcceptConn(void) const throw (SocketException) {
675  int accept = 0;
676 #ifdef SO_ACCEPTCONN
677  socklen_t len = sizeof(accept);
678 
679  if (getsockopt(s, SOL_SOCKET, SO_ACCEPTCONN, (void*) &accept, &len) < 0) {
680  THROW2(SocketException, "getsockopt()");
681  }
682 #else
683  THROW(SocketException, "SO_ACCEPTCONN not defined");
684 #endif
685 
686  return (accept) ? true : false;
687 }
688 
689 void Socket::setSoBindToDevice(const std::string &interface) throw (SocketException) {
690 #ifdef SO_BINDTODEVICE
691 #if 0
692  struct ifreq ifr;
693 
694  memset(&ifr, 0, sizeof(ifr));
695  strncpy(ifr.ifr_name, interface.c_str(), sizeof(ifr.ifr_name));
696 
697  if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, (void*) &ifr, sizeof(ifr)) < 0) {
698  THROW2(SocketException, "setsockopt()");
699  }
700 #else
701  size_t len = (interface.size() > IFNAMSIZ - 1) ? IFNAMSIZ - 1 : interface.size();
702 
703  if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, interface.c_str(), len) < 0) {
704  THROW2(SocketException, "setsockopt()");
705  }
706 #endif
707 #else
708  THROW(SocketException, "SO_BINDTODEVICE not defined");
709 #endif
710 }
711 
712 void Socket::setSoBroadcast(bool on) throw (SocketException) {
713 #ifdef SO_BROADCAST
714  int optval = (on) ? 1 : 0;
715 
716  if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, (void*) &optval, sizeof(optval)) < 0) {
717  THROW2(SocketException, "setsockopt()");
718  }
719 #else
720  THROW(SocketException, "SO_BROADCAST not defined");
721 #endif
722 }
723 
724 void Socket::setSoDebug(bool on) throw (SocketException) {
725 #ifdef SO_DEBUG
726  int optval = (on) ? 1 : 0;
727 
728  if (setsockopt(s, SOL_SOCKET, SO_DEBUG, (void*) &optval, sizeof(optval)) < 0) {
729  THROW2(SocketException, "setsockopt()");
730  }
731 #else
732  THROW(SocketException, "SO_DEBUG not defined");
733 #endif
734 }
735 
736 int Socket::getSoError(void) const throw (SocketException) {
737  int error = 0;
738 #ifdef SO_ERROR
739  socklen_t len = sizeof(error);
740 
741  if (getsockopt(s, SOL_SOCKET, SO_ERROR, (void*) &error, &len) < 0) {
742  THROW2(SocketException, "getsockopt()");
743  }
744 #else
745  THROW(SocketException, "SO_ERROR not defined");
746 #endif
747 
748  return error;
749 }
750 
751 void Socket::setSoDontRoute(bool on) throw (SocketException) {
752 #ifdef SO_DONTROUTE
753  int optval = (on) ? 1 : 0;
754 
755  if (setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (void*) &optval, sizeof(optval)) < 0) {
756  THROW2(SocketException, "setsockopt()");
757  }
758 #else
759  THROW(SocketException, "SO_DONTROUTE not defined");
760 #endif
761 }
762 
763 void Socket::setSoLinger(int onoff, int linger) throw (SocketException) {
764 #ifdef SO_LINGER
765  struct linger l;
766  l.l_onoff = onoff;
767  l.l_linger = linger;
768 
769  if (setsockopt(s, SOL_SOCKET, SO_LINGER, (void*) &l, sizeof(struct linger)) < 0) {
770  THROW2(SocketException, "setsockopt()");
771  }
772 #else
773  THROW(SocketException, "SO_LINGER not defined");
774 #endif
775 }
776 
777 void Socket::setSoPriority(int pri) throw (SocketException) {
778 #ifdef SO_PRIORITY
779  if (setsockopt(s, SOL_SOCKET, SO_PRIORITY, (void*) &pri, sizeof(pri)) < 0) {
780  THROW2(SocketException, "setsockopt()");
781  }
782 #else
783  THROW(SocketException, "SO_DONTROUTE not defined");
784 #endif
785 }
786 
787 void Socket::setSoRcvTimeo(struct timeval &tv) throw (SocketException) {
788 #ifdef SO_RCVTIMEO
789  if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (void*) &tv, sizeof(struct timeval)) < 0) {
790  THROW2(SocketException, "setsockopt()");
791  }
792 #else
793  THROW(SocketException, "SO_RCVTIMEO not defined");
794 #endif
795 }
796 
797 void Socket::setSoSndTimeo(struct timeval &tv) throw (SocketException) {
798 #ifdef SO_SNDTIMEO
799  if (setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (void*) &tv, sizeof(struct timeval)) < 0) {
800  THROW2(SocketException, "setsockopt()");
801  }
802 #else
803  THROW(SocketException, "SO_SNDTIMEO not defined");
804 #endif
805 }
806 
807 void Socket::setSoRcvBuf(int bytes) throw (SocketException) {
808 #ifdef SO_RCVBUF
809  if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*) &bytes, sizeof(bytes)) < 0) {
810  THROW2(SocketException, "setsockopt()");
811  }
812 #else
813  THROW(SocketException, "SO_RCVBUF not defined");
814 #endif
815 }
816 
817 void Socket::setSoRcvBufForce(int bytes) throw (SocketException) {
818 #ifdef SO_RCVBUFFORCE
819  if (setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, (void*) &bytes, sizeof(bytes)) < 0) {
820  THROW2(SocketException, "setsockopt()");
821  }
822 #else
823  THROW(SocketException, "SO_RCVBUFFORCE not defined");
824 #endif
825 }
826 
827 int Socket::getSoRcvBuf(void) const throw (SocketException) {
828  int bytes = 0;
829 #ifdef SO_RCVBUF
830  socklen_t len = sizeof(bytes);
831 
832  if (getsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*) &bytes, &len) < 0) {
833  THROW2(SocketException, "getsockopt()");
834  }
835 #else
836  THROW(SocketException, "SO_RCVBUF not defined");
837 #endif
838 
839  return bytes;
840 }
841 
842 void Socket::setSoSndBuf(int bytes) throw (SocketException) {
843 #ifdef SO_SNDBUF
844  if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*) &bytes, sizeof(bytes)) < 0) {
845  THROW2(SocketException, "setsockopt()");
846  }
847 #else
848  THROW(SocketException, "SO_SNDBUF not defined");
849 #endif
850 }
851 
852 void Socket::setSoSndBufForce(int bytes) throw (SocketException) {
853 #ifdef SO_SNDBUFFORCE
854  if (setsockopt(s, SOL_SOCKET, SO_SNDBUFFORCE, (void*) &bytes, sizeof(bytes)) < 0) {
855  THROW2(SocketException, "setsockopt()");
856  }
857 #else
858  THROW(SocketException, "SO_SNDBUFFORCE not defined");
859 #endif
860 }
861 
862 int Socket::getSoSndBuf(void) const throw (SocketException) {
863  int bytes = 0;
864 #ifdef SO_SNDBUF
865  socklen_t len = sizeof(bytes);
866 
867  if (getsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*) &bytes, &len) < 0) {
868  THROW2(SocketException, "getsockopt()");
869  }
870 #else
871  THROW(SocketException, "SO_SNDBUF not defined");
872 #endif
873 
874  return bytes;
875 }
876 
877 void Socket::setSoTimestamp(bool on) throw (SocketException) {
878 #ifdef SO_TIMESTAMP
879  int optval = (on) ? 1 : 0;
880 
881  if (setsockopt(s, SOL_SOCKET, SO_TIMESTAMP, (void*) &optval, (socklen_t) sizeof(optval)) < 0) {
882  THROW2(SocketException, "setsockopt()");
883  }
884 #else
885  THROW(SocketException, "SO_TIMESTAMP not defined");
886 #endif
887 }
888 
889 int Socket::getSoType(void) throw (SocketException) {
890  int type = 0;
891 #ifdef SO_TYPE
892  socklen_t len = sizeof(type);
893 
894  if (getsockopt(s, SOL_SOCKET, SO_TYPE, (void*) &type, &len) < 0) {
895  THROW2(SocketException, "getsockopt()");
896  }
897 #else
898  THROW(SocketException, "SO_TYPE not defined");
899 #endif
900 
901  return type;
902 }
903 
904 /* Socket Options (IPv6) - man 7 ipv6 */
905 void Socket::setIpv6V6Only(bool on) throw (SocketException) {
906 #ifdef IPV6_V6ONLY
907  int optval = (on) ? 1 : 0;
908 
909  if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (void*) &optval, sizeof(optval)) < 0) {
910  THROW2(SocketException, "setsockopt()");
911  }
912 #else
913  THROW(SocketException, "IPV6_V6ONLY not defined");
914 #endif
915 }
916 
917 bool Socket::getIpv6V6Only(void) const throw (SocketException) {
918  int optval = 0;
919 #ifdef IPV6_V6ONLY
920  socklen_t len = sizeof(optval);
921 
922  if (getsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (void*) &optval, &len) < 0) {
923  THROW2(SocketException, "getsockopt()");
924  }
925 #else
926  THROW(SocketException, "IPV6_V6ONLY not defined");
927 #endif
928 
929  return (optval) ? true : false;
930 }
931 
932 /* Packet Options - man 7 packet */
933 void Socket::mmapRingBuffer(unsigned char **ring, struct tpacket_req &req) throw (SocketException) {
934  if ((*ring = (unsigned char*) mmap(0, req.tp_block_size * req.tp_block_nr, PROT_READ | PROT_WRITE, MAP_SHARED, s, 0)) == NULL) {
935  THROW2(SocketException, "mmap()");
936  }
937 }
938 
939 void Socket::munmapRingBuffer(unsigned char **ring, struct tpacket_req &req) throw (SocketException) {
940  if (munmap(*ring, req.tp_block_size) > 0) {
941  THROW2(SocketException, "munmap()");
942  }
943 
944  ring = NULL;
945 }
946 
947 void Socket::setPacketRxRing(struct tpacket_req &req, int version) throw (SocketException) {
948 #ifdef PACKET_VERSION
949  if (setsockopt(s, SOL_PACKET, PACKET_VERSION, (void*) &version, sizeof(version)) < 0) {
950  THROW2(SocketException, "setsockopt()");
951  }
952 #else
953  THROW(SocketException, "PACKET_VERSION not defined");
954 #endif
955 
956 #ifdef PACKET_RX_RING
957  if (setsockopt(s, SOL_PACKET, PACKET_RX_RING, (void*) &req, sizeof(req)) < 0) {
958  THROW2(SocketException, "setsockopt()");
959  }
960 #else
961  THROW(SocketException, "PACKET_RX_RING not defined");
962 #endif
963 }
964 
965 void Socket::setPacketTxRing(struct tpacket_req &req, int version) throw (SocketException) {
966 #ifdef PACKET_VERSION
967  if (setsockopt(s, SOL_PACKET, PACKET_VERSION, (void*) &version, sizeof(version)) < 0) {
968  THROW2(SocketException, "setsockopt()");
969  }
970 #else
971  THROW(SocketException, "PACKET_VERSION not defined");
972 #endif
973 
974 #ifdef PACKET_TX_RING
975  if (setsockopt(s, SOL_PACKET, PACKET_TX_RING, (void*) &req, sizeof(req)) < 0) {
976  THROW2(SocketException, "setsockopt()");
977  }
978 #else
979  THROW(SocketException, "PACKET_TX_RING not defined");
980 #endif
981 }
982 
983 void Socket::setPacketLoss(bool drop) throw (SocketException) {
984  int optval = (drop) ? 1 : 0;
985 
986 #ifdef PACKET_LOSS
987  if (setsockopt(s, SOL_PACKET, PACKET_LOSS, (void*) &optval, sizeof(optval)) < 0) {
988  THROW2(SocketException, "setsockopt()");
989  }
990 #else
991  THROW(SocketException, "PACKET_LOSS not defined");
992 #endif
993 }
994 
995 int Socket::getPacketHdrLen(int version) throw (SocketException) {
996  int ret;
997  socklen_t len = sizeof(version);
998 
999 #ifdef PACKET_LOSS
1000  if ((ret = getsockopt(s, SOL_PACKET, PACKET_HDRLEN, (void*) &version, &len)) < 0) {
1001  THROW2(SocketException, "getsockopt()");
1002  }
1003 #else
1004  THROW(SocketException, "PACKET_HDRLEN not defined");
1005 #endif
1006 
1007  return ret;
1008 }
1009 
1010 void Socket::initAddr(int family, const std::string &address, unsigned short port, sockaddr_storage &addr, socklen_t addrlen) throw (SocketException) {
1011  union __sockaddr_union u;
1012  u.ss = (struct sockaddr_storage*) &addr;
1013 
1014  memset(&addr, 0, addrlen);
1015  u.ss->ss_family = family;
1016 
1017  if (family != AF_INET && family != AF_INET6) {
1018  THROW(SocketException, "Only family AF_INET and AF_INET6 and AF_PACKET are implemented");
1019  }
1020 
1021  if (address.empty()) {
1022  if (family == AF_INET) {
1023  u.sa_in->sin_addr.s_addr = htonl(INADDR_ANY);
1024  } else {
1025  u.sa_in6->sin6_addr = in6addr_any;
1026  }
1027  } else {
1028  int s;
1029  struct addrinfo hints, *result, *rp;
1030 
1031  memset(&hints, 0, sizeof(struct addrinfo));
1032  hints.ai_family = family;
1033  hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
1034  hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */
1035  hints.ai_protocol = 0; /* Any protocol */
1036  hints.ai_canonname = NULL;
1037  hints.ai_addr = NULL;
1038  hints.ai_next = NULL;
1039 
1040  if ((s = getaddrinfo(address.c_str(), NULL, &hints, &result)) != 0) {
1041  THROW(SocketException, "getaddrinfo() failed: %s", gai_strerror(s));
1042  }
1043 
1044  for (rp = result; rp != NULL; rp = rp->ai_next) {
1045  if (family == rp->ai_family) {
1046  if (rp->ai_family == AF_INET) {
1047  memcpy(u.sa_in, rp->ai_addr, rp->ai_addrlen);
1048  } else if (rp->ai_family == AF_INET6) {
1049  memcpy(u.sa_in6, rp->ai_addr, rp->ai_addrlen);
1050  }
1051 
1052  break;
1053  }
1054 
1055  if (rp->ai_next == NULL) {
1056  THROW(SocketException, "Failed to locate an IPv4 or IPv6 address for %s", address.c_str());
1057  }
1058  }
1059  }
1060 
1061  IPAddress x(u.ss);
1062 
1063  if (family == AF_INET) {
1064  u.sa_in->sin_port = htons(port);
1065  } else {
1066  u.sa_in6->sin6_port = htons(port);
1067  }
1068 }
1069 
1070 unsigned short Socket::resolveService(const std::string &service, const std::string &protocol) throw (SocketException) {
1071  struct servent serv, *result = NULL;
1072  char buf[1024];
1073  long int ret;
1074 
1075  if (getservbyname_r(service.c_str(), protocol.c_str(), &serv, buf, sizeof(buf), &result) != 0) {
1076  THROW2(SocketException, "getservbyname()");
1077  }
1078 
1079  if (result != NULL) {
1080  return ntohs(result->s_port);
1081  } else if (!isdigit(service.c_str()[0])) {
1082  THROW(SocketException, "unresolveable service");
1083  }
1084 
1085  ret = strtol(service.c_str(), (char **) NULL, 10);
1086  if (ret < 1 || ret > 65535) {
1087  THROW2(SocketException, "port out of range");
1088  }
1089 
1090  return ret;
1091 }
1092 
1093 /*
1094 ** vim: noet ts=3 sw=3
1095 */