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