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