Home | History | Annotate | Download | only in net
      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