1 //
2 // Copyright (C) 2012 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #include "shill/net/sockets.h"
18 
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <net/if.h>
22 #include <stdio.h>
23 #include <sys/ioctl.h>
24 #include <sys/socket.h>
25 #include <unistd.h>
26 
27 #include <base/logging.h>
28 #include <base/posix/eintr_wrapper.h>
29 
30 namespace shill {
31 
Sockets()32 Sockets::Sockets() {}
33 
~Sockets()34 Sockets::~Sockets() {}
35 
36 // Some system calls can be interrupted and return EINTR, but will succeed on
37 // retry.  The HANDLE_EINTR macro retries a call if it returns EINTR.  For a
38 // list of system calls that can return EINTR, see 'man 7 signal' under the
39 // heading "Interruption of System Calls and Library Functions by Signal
40 // Handlers".
41 
Accept(int sockfd,struct sockaddr * addr,socklen_t * addrlen) const42 int Sockets::Accept(int sockfd,
43                     struct sockaddr* addr,
44                     socklen_t* addrlen) const {
45   return HANDLE_EINTR(accept(sockfd, addr, addrlen));
46 }
47 
AttachFilter(int sockfd,struct sock_fprog * pf) const48 int Sockets::AttachFilter(int sockfd, struct sock_fprog* pf) const {
49   return setsockopt(sockfd, SOL_SOCKET, SO_ATTACH_FILTER, pf, sizeof(*pf));
50 }
51 
Bind(int sockfd,const struct sockaddr * addr,socklen_t addrlen) const52 int Sockets::Bind(int sockfd,
53                   const struct sockaddr* addr,
54                   socklen_t addrlen) const {
55   return bind(sockfd, addr, addrlen);
56 }
57 
BindToDevice(int sockfd,const std::string & device) const58 int Sockets::BindToDevice(int sockfd, const std::string& device) const {
59   char dev_name[IFNAMSIZ];
60   CHECK_GT(sizeof(dev_name), device.length());
61   memset(&dev_name, 0, sizeof(dev_name));
62   snprintf(dev_name, sizeof(dev_name), "%s", device.c_str());
63   return setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, &dev_name,
64                     sizeof(dev_name));
65 }
66 
ReuseAddress(int sockfd) const67 int Sockets::ReuseAddress(int sockfd) const {
68   int value = 1;
69   return setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value));
70 }
71 
AddMulticastMembership(int sockfd,in_addr_t addr) const72 int Sockets::AddMulticastMembership(int sockfd, in_addr_t addr) const {
73   ip_mreq mreq;
74   mreq.imr_multiaddr.s_addr = addr;
75   mreq.imr_interface.s_addr = htonl(INADDR_ANY);
76   return setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
77 }
78 
Close(int fd) const79 int Sockets::Close(int fd) const {
80   return IGNORE_EINTR(close(fd));
81 }
82 
Connect(int sockfd,const struct sockaddr * addr,socklen_t addrlen) const83 int Sockets::Connect(int sockfd,
84                      const struct sockaddr* addr,
85                      socklen_t addrlen) const {
86   return HANDLE_EINTR(connect(sockfd, addr, addrlen));
87 }
88 
Error() const89 int Sockets::Error() const {
90   return errno;
91 }
92 
ErrorString() const93 std::string Sockets::ErrorString() const {
94   return std::string(strerror(Error()));
95 }
96 
GetSockName(int sockfd,struct sockaddr * addr,socklen_t * addrlen) const97 int Sockets::GetSockName(int sockfd,
98                          struct sockaddr* addr,
99                          socklen_t* addrlen) const {
100   return getsockname(sockfd, addr, addrlen);
101 }
102 
103 
GetSocketError(int sockfd) const104 int Sockets::GetSocketError(int sockfd) const {
105   int error;
106   socklen_t optlen = sizeof(error);
107   if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &optlen) == 0) {
108     return error;
109   }
110   return -1;
111 }
112 
113 
Ioctl(int d,int request,void * argp) const114 int Sockets::Ioctl(int d, int request, void* argp) const {
115   return HANDLE_EINTR(ioctl(d, request, argp));
116 }
117 
Listen(int sockfd,int backlog) const118 int Sockets::Listen(int sockfd, int backlog) const {
119   return listen(sockfd, backlog);
120 }
121 
RecvFrom(int sockfd,void * buf,size_t len,int flags,struct sockaddr * src_addr,socklen_t * addrlen) const122 ssize_t Sockets::RecvFrom(int sockfd,
123                           void* buf,
124                           size_t len,
125                           int flags,
126                           struct sockaddr* src_addr,
127                           socklen_t* addrlen) const {
128   return HANDLE_EINTR(recvfrom(sockfd, buf, len, flags, src_addr, addrlen));
129 }
130 
Select(int nfds,fd_set * readfds,fd_set * writefds,fd_set * exceptfds,struct timeval * timeout) const131 int Sockets::Select(int nfds,
132                     fd_set* readfds,
133                     fd_set* writefds,
134                     fd_set* exceptfds,
135                     struct timeval* timeout) const {
136   return HANDLE_EINTR(select(nfds, readfds, writefds, exceptfds, timeout));
137 }
138 
Send(int sockfd,const void * buf,size_t len,int flags) const139 ssize_t Sockets::Send(int sockfd,
140                       const void* buf,
141                       size_t len,
142                       int flags) const {
143   return HANDLE_EINTR(send(sockfd, buf, len, flags));
144 }
145 
SendTo(int sockfd,const void * buf,size_t len,int flags,const struct sockaddr * dest_addr,socklen_t addrlen) const146 ssize_t Sockets::SendTo(int sockfd,
147                         const void* buf,
148                         size_t len,
149                         int flags,
150                         const struct sockaddr* dest_addr,
151                         socklen_t addrlen) const {
152   return HANDLE_EINTR(sendto(sockfd, buf, len, flags, dest_addr, addrlen));
153 }
154 
SetNonBlocking(int sockfd) const155 int Sockets::SetNonBlocking(int sockfd) const {
156   return HANDLE_EINTR(
157       fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK));
158 }
159 
SetReceiveBuffer(int sockfd,int size) const160 int Sockets::SetReceiveBuffer(int sockfd, int size) const {
161   // Note: kernel will set buffer to 2*size to allow for struct skbuff overhead
162   return setsockopt(sockfd, SOL_SOCKET, SO_RCVBUFFORCE, &size, sizeof(size));
163 }
164 
ShutDown(int sockfd,int how) const165 int Sockets::ShutDown(int sockfd, int how) const {
166   return HANDLE_EINTR(shutdown(sockfd, how));
167 }
168 
Socket(int domain,int type,int protocol) const169 int Sockets::Socket(int domain, int type, int protocol) const {
170   return socket(domain, type, protocol);
171 }
172 
ScopedSocketCloser(Sockets * sockets,int fd)173 ScopedSocketCloser::ScopedSocketCloser(Sockets* sockets, int fd)
174     : sockets_(sockets),
175       fd_(fd) {}
176 
~ScopedSocketCloser()177 ScopedSocketCloser::~ScopedSocketCloser() {
178   sockets_->Close(fd_);
179   fd_ = Sockets::kInvalidFileDescriptor;
180 }
181 
Release()182 int ScopedSocketCloser::Release() {
183   int fd = fd_;
184   fd_ = Sockets::kInvalidFileDescriptor;
185   return fd;
186 }
187 
188 }  // namespace shill
189