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 32 Sockets::Sockets() {} 33 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 42 int Sockets::Accept(int sockfd, 43 struct sockaddr* addr, 44 socklen_t* addrlen) const { 45 return HANDLE_EINTR(accept(sockfd, addr, addrlen)); 46 } 47 48 int Sockets::AttachFilter(int sockfd, struct sock_fprog* pf) const { 49 return setsockopt(sockfd, SOL_SOCKET, SO_ATTACH_FILTER, pf, sizeof(*pf)); 50 } 51 52 int Sockets::Bind(int sockfd, 53 const struct sockaddr* addr, 54 socklen_t addrlen) const { 55 return bind(sockfd, addr, addrlen); 56 } 57 58 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 67 int Sockets::ReuseAddress(int sockfd) const { 68 int value = 1; 69 return setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value)); 70 } 71 72 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 79 int Sockets::Close(int fd) const { 80 return IGNORE_EINTR(close(fd)); 81 } 82 83 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 89 int Sockets::Error() const { 90 return errno; 91 } 92 93 std::string Sockets::ErrorString() const { 94 return std::string(strerror(Error())); 95 } 96 97 int Sockets::GetSockName(int sockfd, 98 struct sockaddr* addr, 99 socklen_t* addrlen) const { 100 return getsockname(sockfd, addr, addrlen); 101 } 102 103 104 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 114 int Sockets::Ioctl(int d, int request, void* argp) const { 115 return HANDLE_EINTR(ioctl(d, request, argp)); 116 } 117 118 int Sockets::Listen(int sockfd, int backlog) const { 119 return listen(sockfd, backlog); 120 } 121 122 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 131 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 139 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 146 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 155 int Sockets::SetNonBlocking(int sockfd) const { 156 return HANDLE_EINTR( 157 fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK)); 158 } 159 160 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 165 int Sockets::ShutDown(int sockfd, int how) const { 166 return HANDLE_EINTR(shutdown(sockfd, how)); 167 } 168 169 int Sockets::Socket(int domain, int type, int protocol) const { 170 return socket(domain, type, protocol); 171 } 172 173 ScopedSocketCloser::ScopedSocketCloser(Sockets* sockets, int fd) 174 : sockets_(sockets), 175 fd_(fd) {} 176 177 ScopedSocketCloser::~ScopedSocketCloser() { 178 sockets_->Close(fd_); 179 fd_ = Sockets::kInvalidFileDescriptor; 180 } 181 182 int ScopedSocketCloser::Release() { 183 int fd = fd_; 184 fd_ = Sockets::kInvalidFileDescriptor; 185 return fd; 186 } 187 188 } // namespace shill 189