sockets.cc revision 8d6b59704591ba9fad57751858835dc332dbdd37
1// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "shill/net/sockets.h"
6
7#include <errno.h>
8#include <fcntl.h>
9#include <net/if.h>
10#include <stdio.h>
11#include <sys/ioctl.h>
12#include <sys/socket.h>
13#include <unistd.h>
14
15#include <base/logging.h>
16#include <base/posix/eintr_wrapper.h>
17
18namespace shill {
19
20Sockets::Sockets() {}
21
22Sockets::~Sockets() {}
23
24// Some system calls can be interrupted and return EINTR, but will succeed on
25// retry.  The HANDLE_EINTR macro retries a call if it returns EINTR.  For a
26// list of system calls that can return EINTR, see 'man 7 signal' under the
27// heading "Interruption of System Calls and Library Functions by Signal
28// Handlers".
29
30int Sockets::Accept(int sockfd,
31                    struct sockaddr *addr,
32                    socklen_t *addrlen) const {
33  return HANDLE_EINTR(accept(sockfd, addr, addrlen));
34}
35
36int Sockets::AttachFilter(int sockfd, struct sock_fprog *pf) const {
37  return setsockopt(sockfd, SOL_SOCKET, SO_ATTACH_FILTER, pf, sizeof(*pf));
38}
39
40int Sockets::Bind(int sockfd,
41                  const struct sockaddr *addr,
42                  socklen_t addrlen) const {
43  return bind(sockfd, addr, addrlen);
44}
45
46int Sockets::BindToDevice(int sockfd, const std::string &device) const {
47  char dev_name[IFNAMSIZ];
48  CHECK_GT(sizeof(dev_name), device.length());
49  memset(&dev_name, 0, sizeof(dev_name));
50  snprintf(dev_name, sizeof(dev_name), "%s", device.c_str());
51  return HANDLE_EINTR(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, &dev_name,
52                                 sizeof(dev_name)));
53}
54
55int Sockets::Close(int fd) const {
56  return IGNORE_EINTR(close(fd));
57}
58
59int Sockets::Connect(int sockfd,
60                     const struct sockaddr *addr,
61                     socklen_t addrlen) const {
62  return HANDLE_EINTR(connect(sockfd, addr, addrlen));
63}
64
65int Sockets::Error() const {
66  return errno;
67}
68
69std::string Sockets::ErrorString() const {
70  return std::string(strerror(Error()));
71}
72
73int Sockets::GetSockName(int sockfd,
74                         struct sockaddr *addr,
75                         socklen_t *addrlen) const {
76  return getsockname(sockfd, addr, addrlen);
77}
78
79
80int Sockets::GetSocketError(int sockfd) const {
81  int error;
82  socklen_t optlen = sizeof(error);
83  if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &optlen) == 0) {
84    return error;
85  }
86  return -1;
87}
88
89
90int Sockets::Ioctl(int d, int request, void *argp) const {
91  return HANDLE_EINTR(ioctl(d, request, argp));
92}
93
94int Sockets::Listen(int sockfd, int backlog) const {
95  return listen(sockfd, backlog);
96}
97
98ssize_t Sockets::RecvFrom(int sockfd,
99                          void *buf,
100                          size_t len,
101                          int flags,
102                          struct sockaddr *src_addr,
103                          socklen_t *addrlen) const {
104  return HANDLE_EINTR(recvfrom(sockfd, buf, len, flags, src_addr, addrlen));
105}
106
107int Sockets::Select(int nfds,
108                    fd_set *readfds,
109                    fd_set *writefds,
110                    fd_set *exceptfds,
111                    struct timeval *timeout) const {
112  return HANDLE_EINTR(select(nfds, readfds, writefds, exceptfds, timeout));
113}
114
115ssize_t Sockets::Send(int sockfd,
116                      const void *buf,
117                      size_t len,
118                      int flags) const {
119  return HANDLE_EINTR(send(sockfd, buf, len, flags));
120}
121
122ssize_t Sockets::SendTo(int sockfd,
123                        const void *buf,
124                        size_t len,
125                        int flags,
126                        const struct sockaddr *dest_addr,
127                        socklen_t addrlen) const {
128  return HANDLE_EINTR(sendto(sockfd, buf, len, flags, dest_addr, addrlen));
129}
130
131int Sockets::SetNonBlocking(int sockfd) const {
132  return HANDLE_EINTR(
133      fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK));
134}
135
136int Sockets::SetReceiveBuffer(int sockfd, int size) const {
137  // Note: kernel will set buffer to 2*size to allow for struct skbuff overhead
138  return setsockopt(sockfd, SOL_SOCKET, SO_RCVBUFFORCE, &size, sizeof(size));
139}
140
141int Sockets::ShutDown(int sockfd, int how) const {
142  return HANDLE_EINTR(shutdown(sockfd, how));
143}
144
145int Sockets::Socket(int domain, int type, int protocol) const {
146  return socket(domain, type, protocol);
147}
148
149ScopedSocketCloser::ScopedSocketCloser(Sockets *sockets, int fd)
150    : sockets_(sockets),
151      fd_(fd) {}
152
153ScopedSocketCloser::~ScopedSocketCloser() {
154  sockets_->Close(fd_);
155  fd_ = Sockets::kInvalidFileDescriptor;
156}
157
158}  // namespace shill
159