1*2f2c4c7aSAndroid Build Coastguard Worker# Copyright 2014 The Android Open Source Project 2*2f2c4c7aSAndroid Build Coastguard Worker# 3*2f2c4c7aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 4*2f2c4c7aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 5*2f2c4c7aSAndroid Build Coastguard Worker# You may obtain a copy of the License at 6*2f2c4c7aSAndroid Build Coastguard Worker# 7*2f2c4c7aSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 8*2f2c4c7aSAndroid Build Coastguard Worker# 9*2f2c4c7aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 10*2f2c4c7aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 11*2f2c4c7aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*2f2c4c7aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 13*2f2c4c7aSAndroid Build Coastguard Worker# limitations under the License. 14*2f2c4c7aSAndroid Build Coastguard Worker 15*2f2c4c7aSAndroid Build Coastguard Worker"""Python wrapper for C socket calls and data structures.""" 16*2f2c4c7aSAndroid Build Coastguard Worker 17*2f2c4c7aSAndroid Build Coastguard Workerimport ctypes 18*2f2c4c7aSAndroid Build Coastguard Workerimport ctypes.util 19*2f2c4c7aSAndroid Build Coastguard Workerimport os 20*2f2c4c7aSAndroid Build Coastguard Workerimport re 21*2f2c4c7aSAndroid Build Coastguard Workerimport socket 22*2f2c4c7aSAndroid Build Coastguard Workerimport struct 23*2f2c4c7aSAndroid Build Coastguard Worker 24*2f2c4c7aSAndroid Build Coastguard Workerimport cstruct 25*2f2c4c7aSAndroid Build Coastguard Workerimport util 26*2f2c4c7aSAndroid Build Coastguard Worker 27*2f2c4c7aSAndroid Build Coastguard Worker 28*2f2c4c7aSAndroid Build Coastguard Worker# Data structures. 29*2f2c4c7aSAndroid Build Coastguard Worker# These aren't constants, they're classes. So, pylint: disable=invalid-name 30*2f2c4c7aSAndroid Build Coastguard WorkerCMsgHdr = cstruct.Struct("cmsghdr", "@Lii", "len level type") 31*2f2c4c7aSAndroid Build Coastguard WorkerIovec = cstruct.Struct("iovec", "@PL", "base len") 32*2f2c4c7aSAndroid Build Coastguard WorkerMsgHdr = cstruct.Struct("msghdr", "@LLPLPLi", 33*2f2c4c7aSAndroid Build Coastguard Worker "name namelen iov iovlen control msg_controllen flags") 34*2f2c4c7aSAndroid Build Coastguard WorkerSockaddrIn = cstruct.Struct("sockaddr_in", "=HH4sxxxxxxxx", "family port addr") 35*2f2c4c7aSAndroid Build Coastguard WorkerSockaddrIn6 = cstruct.Struct("sockaddr_in6", "=HHI16sI", 36*2f2c4c7aSAndroid Build Coastguard Worker "family port flowinfo addr scope_id") 37*2f2c4c7aSAndroid Build Coastguard WorkerSockaddrStorage = cstruct.Struct("sockaddr_storage", "=H126s", "family data") 38*2f2c4c7aSAndroid Build Coastguard WorkerSockExtendedErr = cstruct.Struct("sock_extended_err", "@IBBBxII", 39*2f2c4c7aSAndroid Build Coastguard Worker "errno origin type code info data") 40*2f2c4c7aSAndroid Build Coastguard WorkerInPktinfo = cstruct.Struct("in_pktinfo", "@i4s4s", "ifindex spec_dst addr") 41*2f2c4c7aSAndroid Build Coastguard WorkerIn6Pktinfo = cstruct.Struct("in6_pktinfo", "@16si", "addr ifindex") 42*2f2c4c7aSAndroid Build Coastguard Worker 43*2f2c4c7aSAndroid Build Coastguard Worker# Constants. 44*2f2c4c7aSAndroid Build Coastguard Worker# IPv4 socket options and cmsg types. 45*2f2c4c7aSAndroid Build Coastguard WorkerIP_TTL = 2 46*2f2c4c7aSAndroid Build Coastguard WorkerIP_MTU_DISCOVER = 10 47*2f2c4c7aSAndroid Build Coastguard WorkerIP_PKTINFO = 8 48*2f2c4c7aSAndroid Build Coastguard WorkerIP_RECVERR = 11 49*2f2c4c7aSAndroid Build Coastguard WorkerIP_RECVTTL = 12 50*2f2c4c7aSAndroid Build Coastguard WorkerIP_MTU = 14 51*2f2c4c7aSAndroid Build Coastguard Worker 52*2f2c4c7aSAndroid Build Coastguard Worker# IPv6 socket options and cmsg types. 53*2f2c4c7aSAndroid Build Coastguard WorkerIPV6_MTU_DISCOVER = 23 54*2f2c4c7aSAndroid Build Coastguard WorkerIPV6_RECVERR = 25 55*2f2c4c7aSAndroid Build Coastguard WorkerIPV6_RECVPKTINFO = 49 56*2f2c4c7aSAndroid Build Coastguard WorkerIPV6_PKTINFO = 50 57*2f2c4c7aSAndroid Build Coastguard WorkerIPV6_RECVHOPLIMIT = 51 58*2f2c4c7aSAndroid Build Coastguard WorkerIPV6_HOPLIMIT = 52 59*2f2c4c7aSAndroid Build Coastguard WorkerIPV6_PATHMTU = 61 60*2f2c4c7aSAndroid Build Coastguard WorkerIPV6_DONTFRAG = 62 61*2f2c4c7aSAndroid Build Coastguard Worker 62*2f2c4c7aSAndroid Build Coastguard Worker# PMTUD values. 63*2f2c4c7aSAndroid Build Coastguard WorkerIP_PMTUDISC_DO = 1 64*2f2c4c7aSAndroid Build Coastguard Worker 65*2f2c4c7aSAndroid Build Coastguard WorkerCMSG_ALIGNTO = struct.calcsize("@L") # The kernel defines this as sizeof(long). 66*2f2c4c7aSAndroid Build Coastguard Worker 67*2f2c4c7aSAndroid Build Coastguard Worker# Sendmsg flags 68*2f2c4c7aSAndroid Build Coastguard WorkerMSG_CONFIRM = 0X800 69*2f2c4c7aSAndroid Build Coastguard WorkerMSG_ERRQUEUE = 0x2000 70*2f2c4c7aSAndroid Build Coastguard Worker 71*2f2c4c7aSAndroid Build Coastguard Worker# Linux errqueue API. 72*2f2c4c7aSAndroid Build Coastguard WorkerSO_ORIGIN_ICMP = 2 73*2f2c4c7aSAndroid Build Coastguard WorkerSO_ORIGIN_ICMP6 = 3 74*2f2c4c7aSAndroid Build Coastguard Worker 75*2f2c4c7aSAndroid Build Coastguard Worker# Find the C library. 76*2f2c4c7aSAndroid Build Coastguard Workerlibc = ctypes.CDLL(ctypes.util.find_library("c"), use_errno=True) 77*2f2c4c7aSAndroid Build Coastguard Worker 78*2f2c4c7aSAndroid Build Coastguard Worker 79*2f2c4c7aSAndroid Build Coastguard Worker# TODO: Unlike most of this file, these functions aren't specific to wrapping C 80*2f2c4c7aSAndroid Build Coastguard Worker# library calls. Move them to a utils.py or constants.py file, once we have one. 81*2f2c4c7aSAndroid Build Coastguard Workerdef LinuxVersion(): 82*2f2c4c7aSAndroid Build Coastguard Worker # Example: "3.4.67-00753-gb7a556f", "4.4.135+". 83*2f2c4c7aSAndroid Build Coastguard Worker # Get the prefix consisting of digits and dots. 84*2f2c4c7aSAndroid Build Coastguard Worker version = re.search("^[0-9.]*", os.uname()[2]).group() 85*2f2c4c7aSAndroid Build Coastguard Worker # Convert it into a tuple such as (3, 4, 67). That allows comparing versions 86*2f2c4c7aSAndroid Build Coastguard Worker # using < and >, since tuples are compared lexicographically. 87*2f2c4c7aSAndroid Build Coastguard Worker version = tuple(int(i) for i in version.split(".")) 88*2f2c4c7aSAndroid Build Coastguard Worker return version 89*2f2c4c7aSAndroid Build Coastguard Worker 90*2f2c4c7aSAndroid Build Coastguard Worker 91*2f2c4c7aSAndroid Build Coastguard Workerdef AddressVersion(addr): 92*2f2c4c7aSAndroid Build Coastguard Worker return 6 if ":" in addr else 4 93*2f2c4c7aSAndroid Build Coastguard Worker 94*2f2c4c7aSAndroid Build Coastguard Worker 95*2f2c4c7aSAndroid Build Coastguard Workerdef SetSocketTimeout(sock, ms): 96*2f2c4c7aSAndroid Build Coastguard Worker s = ms // 1000 97*2f2c4c7aSAndroid Build Coastguard Worker us = (ms % 1000) * 1000 98*2f2c4c7aSAndroid Build Coastguard Worker sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, 99*2f2c4c7aSAndroid Build Coastguard Worker struct.pack("LL", s, us)) 100*2f2c4c7aSAndroid Build Coastguard Worker 101*2f2c4c7aSAndroid Build Coastguard Worker 102*2f2c4c7aSAndroid Build Coastguard Workerdef VoidPointer(s): 103*2f2c4c7aSAndroid Build Coastguard Worker return ctypes.cast(s.CPointer(), ctypes.c_void_p) 104*2f2c4c7aSAndroid Build Coastguard Worker 105*2f2c4c7aSAndroid Build Coastguard Worker 106*2f2c4c7aSAndroid Build Coastguard Workerdef MaybeRaiseSocketError(ret): 107*2f2c4c7aSAndroid Build Coastguard Worker if ret < 0: 108*2f2c4c7aSAndroid Build Coastguard Worker errno = ctypes.get_errno() 109*2f2c4c7aSAndroid Build Coastguard Worker raise socket.error(errno, os.strerror(errno)) 110*2f2c4c7aSAndroid Build Coastguard Worker 111*2f2c4c7aSAndroid Build Coastguard Worker 112*2f2c4c7aSAndroid Build Coastguard Workerdef Sockaddr(addr): 113*2f2c4c7aSAndroid Build Coastguard Worker if ":" in addr[0]: 114*2f2c4c7aSAndroid Build Coastguard Worker family = socket.AF_INET6 115*2f2c4c7aSAndroid Build Coastguard Worker if len(addr) == 4: 116*2f2c4c7aSAndroid Build Coastguard Worker addr, port, flowinfo, scope_id = addr 117*2f2c4c7aSAndroid Build Coastguard Worker else: 118*2f2c4c7aSAndroid Build Coastguard Worker (addr, port), flowinfo, scope_id = addr, 0, 0 119*2f2c4c7aSAndroid Build Coastguard Worker addr = socket.inet_pton(family, addr) 120*2f2c4c7aSAndroid Build Coastguard Worker return SockaddrIn6((family, socket.ntohs(port), socket.ntohl(flowinfo), 121*2f2c4c7aSAndroid Build Coastguard Worker addr, scope_id)) 122*2f2c4c7aSAndroid Build Coastguard Worker else: 123*2f2c4c7aSAndroid Build Coastguard Worker family = socket.AF_INET 124*2f2c4c7aSAndroid Build Coastguard Worker addr, port = addr 125*2f2c4c7aSAndroid Build Coastguard Worker addr = socket.inet_pton(family, addr) 126*2f2c4c7aSAndroid Build Coastguard Worker return SockaddrIn((family, socket.ntohs(port), addr)) 127*2f2c4c7aSAndroid Build Coastguard Worker 128*2f2c4c7aSAndroid Build Coastguard Worker 129*2f2c4c7aSAndroid Build Coastguard Workerdef _MakeMsgControl(optlist): 130*2f2c4c7aSAndroid Build Coastguard Worker """Creates a msg_control blob from a list of cmsg attributes. 131*2f2c4c7aSAndroid Build Coastguard Worker 132*2f2c4c7aSAndroid Build Coastguard Worker Takes a list of cmsg attributes. Each attribute is a tuple of: 133*2f2c4c7aSAndroid Build Coastguard Worker - level: An integer, e.g., SOL_IPV6. 134*2f2c4c7aSAndroid Build Coastguard Worker - type: An integer, the option identifier, e.g., IPV6_HOPLIMIT. 135*2f2c4c7aSAndroid Build Coastguard Worker - data: The option data. This is either a string or an integer. If it's an 136*2f2c4c7aSAndroid Build Coastguard Worker integer it will be written as an unsigned integer in host byte order. If 137*2f2c4c7aSAndroid Build Coastguard Worker it's a string, it's used as is. 138*2f2c4c7aSAndroid Build Coastguard Worker 139*2f2c4c7aSAndroid Build Coastguard Worker Data is padded to an integer multiple of CMSG_ALIGNTO. 140*2f2c4c7aSAndroid Build Coastguard Worker 141*2f2c4c7aSAndroid Build Coastguard Worker Args: 142*2f2c4c7aSAndroid Build Coastguard Worker optlist: A list of tuples describing cmsg options. 143*2f2c4c7aSAndroid Build Coastguard Worker 144*2f2c4c7aSAndroid Build Coastguard Worker Returns: 145*2f2c4c7aSAndroid Build Coastguard Worker A string, a binary blob usable as the control data for a sendmsg call. 146*2f2c4c7aSAndroid Build Coastguard Worker 147*2f2c4c7aSAndroid Build Coastguard Worker Raises: 148*2f2c4c7aSAndroid Build Coastguard Worker TypeError: Option data is neither an integer nor a string. 149*2f2c4c7aSAndroid Build Coastguard Worker """ 150*2f2c4c7aSAndroid Build Coastguard Worker msg_control = b"" 151*2f2c4c7aSAndroid Build Coastguard Worker 152*2f2c4c7aSAndroid Build Coastguard Worker for i, opt in enumerate(optlist): 153*2f2c4c7aSAndroid Build Coastguard Worker msg_level, msg_type, data = opt 154*2f2c4c7aSAndroid Build Coastguard Worker if isinstance(data, int): 155*2f2c4c7aSAndroid Build Coastguard Worker data = struct.pack("=I", data) 156*2f2c4c7aSAndroid Build Coastguard Worker elif isinstance(data, ctypes.c_uint32): 157*2f2c4c7aSAndroid Build Coastguard Worker data = struct.pack("=I", data.value) 158*2f2c4c7aSAndroid Build Coastguard Worker elif not isinstance(data, bytes): 159*2f2c4c7aSAndroid Build Coastguard Worker raise TypeError("unknown data type for opt (%d, %d): %s" % ( 160*2f2c4c7aSAndroid Build Coastguard Worker msg_level, msg_type, type(data))) 161*2f2c4c7aSAndroid Build Coastguard Worker 162*2f2c4c7aSAndroid Build Coastguard Worker datalen = len(data) 163*2f2c4c7aSAndroid Build Coastguard Worker msg_len = len(CMsgHdr) + datalen 164*2f2c4c7aSAndroid Build Coastguard Worker padding = b"\x00" * util.GetPadLength(CMSG_ALIGNTO, datalen) 165*2f2c4c7aSAndroid Build Coastguard Worker msg_control += CMsgHdr((msg_len, msg_level, msg_type)).Pack() 166*2f2c4c7aSAndroid Build Coastguard Worker msg_control += data + padding 167*2f2c4c7aSAndroid Build Coastguard Worker 168*2f2c4c7aSAndroid Build Coastguard Worker return msg_control 169*2f2c4c7aSAndroid Build Coastguard Worker 170*2f2c4c7aSAndroid Build Coastguard Worker 171*2f2c4c7aSAndroid Build Coastguard Workerdef _ParseMsgControl(buf): 172*2f2c4c7aSAndroid Build Coastguard Worker """Parse a raw control buffer into a list of tuples.""" 173*2f2c4c7aSAndroid Build Coastguard Worker msglist = [] 174*2f2c4c7aSAndroid Build Coastguard Worker while len(buf) > 0: 175*2f2c4c7aSAndroid Build Coastguard Worker cmsghdr, buf = cstruct.Read(buf, CMsgHdr) 176*2f2c4c7aSAndroid Build Coastguard Worker datalen = cmsghdr.len - len(CMsgHdr) 177*2f2c4c7aSAndroid Build Coastguard Worker padlen = util.GetPadLength(CMSG_ALIGNTO, datalen) 178*2f2c4c7aSAndroid Build Coastguard Worker data, buf = buf[:datalen], buf[padlen + datalen:] 179*2f2c4c7aSAndroid Build Coastguard Worker 180*2f2c4c7aSAndroid Build Coastguard Worker if cmsghdr.level == socket.IPPROTO_IP: 181*2f2c4c7aSAndroid Build Coastguard Worker if cmsghdr.type == IP_PKTINFO: 182*2f2c4c7aSAndroid Build Coastguard Worker data = InPktinfo(data) 183*2f2c4c7aSAndroid Build Coastguard Worker elif cmsghdr.type == IP_TTL: 184*2f2c4c7aSAndroid Build Coastguard Worker data = struct.unpack("@I", data)[0] 185*2f2c4c7aSAndroid Build Coastguard Worker 186*2f2c4c7aSAndroid Build Coastguard Worker if cmsghdr.level == socket.IPPROTO_IPV6: 187*2f2c4c7aSAndroid Build Coastguard Worker if cmsghdr.type == IPV6_PKTINFO: 188*2f2c4c7aSAndroid Build Coastguard Worker data = In6Pktinfo(data) 189*2f2c4c7aSAndroid Build Coastguard Worker elif cmsghdr.type == IPV6_RECVERR: 190*2f2c4c7aSAndroid Build Coastguard Worker err, source = cstruct.Read(data, SockExtendedErr) 191*2f2c4c7aSAndroid Build Coastguard Worker if err.origin == SO_ORIGIN_ICMP6: 192*2f2c4c7aSAndroid Build Coastguard Worker source, pad = cstruct.Read(source, SockaddrIn6) 193*2f2c4c7aSAndroid Build Coastguard Worker data = (err, source) 194*2f2c4c7aSAndroid Build Coastguard Worker elif cmsghdr.type == IPV6_HOPLIMIT: 195*2f2c4c7aSAndroid Build Coastguard Worker data = struct.unpack("@I", data)[0] 196*2f2c4c7aSAndroid Build Coastguard Worker 197*2f2c4c7aSAndroid Build Coastguard Worker # If not, leave data as just the raw bytes. 198*2f2c4c7aSAndroid Build Coastguard Worker 199*2f2c4c7aSAndroid Build Coastguard Worker msglist.append((cmsghdr.level, cmsghdr.type, data)) 200*2f2c4c7aSAndroid Build Coastguard Worker 201*2f2c4c7aSAndroid Build Coastguard Worker return msglist 202*2f2c4c7aSAndroid Build Coastguard Worker 203*2f2c4c7aSAndroid Build Coastguard Worker 204*2f2c4c7aSAndroid Build Coastguard Workerdef Bind(s, to): 205*2f2c4c7aSAndroid Build Coastguard Worker """Python wrapper for bind.""" 206*2f2c4c7aSAndroid Build Coastguard Worker ret = libc.bind(s.fileno(), VoidPointer(to), len(to)) 207*2f2c4c7aSAndroid Build Coastguard Worker MaybeRaiseSocketError(ret) 208*2f2c4c7aSAndroid Build Coastguard Worker return ret 209*2f2c4c7aSAndroid Build Coastguard Worker 210*2f2c4c7aSAndroid Build Coastguard Worker 211*2f2c4c7aSAndroid Build Coastguard Workerdef Connect(s, to): 212*2f2c4c7aSAndroid Build Coastguard Worker """Python wrapper for connect.""" 213*2f2c4c7aSAndroid Build Coastguard Worker ret = libc.connect(s.fileno(), VoidPointer(to), len(to)) 214*2f2c4c7aSAndroid Build Coastguard Worker MaybeRaiseSocketError(ret) 215*2f2c4c7aSAndroid Build Coastguard Worker return ret 216*2f2c4c7aSAndroid Build Coastguard Worker 217*2f2c4c7aSAndroid Build Coastguard Worker 218*2f2c4c7aSAndroid Build Coastguard Workerdef Sendmsg(s, to, data, control, flags): 219*2f2c4c7aSAndroid Build Coastguard Worker """Python wrapper for sendmsg. 220*2f2c4c7aSAndroid Build Coastguard Worker 221*2f2c4c7aSAndroid Build Coastguard Worker Args: 222*2f2c4c7aSAndroid Build Coastguard Worker s: A Python socket object. Becomes sockfd. 223*2f2c4c7aSAndroid Build Coastguard Worker to: An address tuple, or a SockaddrIn[6] struct. Becomes msg->msg_name. 224*2f2c4c7aSAndroid Build Coastguard Worker data: A string, the data to write. Goes into msg->msg_iov. 225*2f2c4c7aSAndroid Build Coastguard Worker control: A list of cmsg options. Becomes msg->msg_control. 226*2f2c4c7aSAndroid Build Coastguard Worker flags: An integer. Becomes msg->msg_flags. 227*2f2c4c7aSAndroid Build Coastguard Worker 228*2f2c4c7aSAndroid Build Coastguard Worker Returns: 229*2f2c4c7aSAndroid Build Coastguard Worker If sendmsg succeeds, returns the number of bytes written as an integer. 230*2f2c4c7aSAndroid Build Coastguard Worker 231*2f2c4c7aSAndroid Build Coastguard Worker Raises: 232*2f2c4c7aSAndroid Build Coastguard Worker socket.error: If sendmsg fails. 233*2f2c4c7aSAndroid Build Coastguard Worker """ 234*2f2c4c7aSAndroid Build Coastguard Worker # Create ctypes buffers and pointers from our structures. We need to hang on 235*2f2c4c7aSAndroid Build Coastguard Worker # to the underlying Python objects, because we don't want them to be garbage 236*2f2c4c7aSAndroid Build Coastguard Worker # collected and freed while we have C pointers to them. 237*2f2c4c7aSAndroid Build Coastguard Worker 238*2f2c4c7aSAndroid Build Coastguard Worker # Convert the destination address into a struct sockaddr. 239*2f2c4c7aSAndroid Build Coastguard Worker if to: 240*2f2c4c7aSAndroid Build Coastguard Worker if isinstance(to, tuple): 241*2f2c4c7aSAndroid Build Coastguard Worker to = Sockaddr(to) 242*2f2c4c7aSAndroid Build Coastguard Worker msg_name = to.CPointer() 243*2f2c4c7aSAndroid Build Coastguard Worker msg_namelen = len(to) 244*2f2c4c7aSAndroid Build Coastguard Worker else: 245*2f2c4c7aSAndroid Build Coastguard Worker msg_name = 0 246*2f2c4c7aSAndroid Build Coastguard Worker msg_namelen = 0 247*2f2c4c7aSAndroid Build Coastguard Worker 248*2f2c4c7aSAndroid Build Coastguard Worker # Convert the data to a data buffer and a struct iovec pointing at it. 249*2f2c4c7aSAndroid Build Coastguard Worker if data: 250*2f2c4c7aSAndroid Build Coastguard Worker databuf = ctypes.create_string_buffer(data) 251*2f2c4c7aSAndroid Build Coastguard Worker iov = Iovec((ctypes.addressof(databuf), len(data))) 252*2f2c4c7aSAndroid Build Coastguard Worker msg_iov = iov.CPointer() 253*2f2c4c7aSAndroid Build Coastguard Worker msg_iovlen = 1 254*2f2c4c7aSAndroid Build Coastguard Worker else: 255*2f2c4c7aSAndroid Build Coastguard Worker msg_iov = 0 256*2f2c4c7aSAndroid Build Coastguard Worker msg_iovlen = 0 257*2f2c4c7aSAndroid Build Coastguard Worker 258*2f2c4c7aSAndroid Build Coastguard Worker # Marshal the cmsg options. 259*2f2c4c7aSAndroid Build Coastguard Worker if control: 260*2f2c4c7aSAndroid Build Coastguard Worker control = _MakeMsgControl(control) 261*2f2c4c7aSAndroid Build Coastguard Worker controlbuf = ctypes.create_string_buffer(control) 262*2f2c4c7aSAndroid Build Coastguard Worker msg_control = ctypes.addressof(controlbuf) 263*2f2c4c7aSAndroid Build Coastguard Worker msg_controllen = len(control) 264*2f2c4c7aSAndroid Build Coastguard Worker else: 265*2f2c4c7aSAndroid Build Coastguard Worker msg_control = 0 266*2f2c4c7aSAndroid Build Coastguard Worker msg_controllen = 0 267*2f2c4c7aSAndroid Build Coastguard Worker 268*2f2c4c7aSAndroid Build Coastguard Worker # Assemble the struct msghdr. 269*2f2c4c7aSAndroid Build Coastguard Worker msghdr = MsgHdr((msg_name, msg_namelen, msg_iov, msg_iovlen, 270*2f2c4c7aSAndroid Build Coastguard Worker msg_control, msg_controllen, flags)).Pack() 271*2f2c4c7aSAndroid Build Coastguard Worker 272*2f2c4c7aSAndroid Build Coastguard Worker # Call sendmsg. 273*2f2c4c7aSAndroid Build Coastguard Worker ret = libc.sendmsg(s.fileno(), msghdr, 0) 274*2f2c4c7aSAndroid Build Coastguard Worker MaybeRaiseSocketError(ret) 275*2f2c4c7aSAndroid Build Coastguard Worker 276*2f2c4c7aSAndroid Build Coastguard Worker return ret 277*2f2c4c7aSAndroid Build Coastguard Worker 278*2f2c4c7aSAndroid Build Coastguard Worker 279*2f2c4c7aSAndroid Build Coastguard Workerdef _ToSocketAddress(addr, alen): 280*2f2c4c7aSAndroid Build Coastguard Worker addr = addr[:alen] 281*2f2c4c7aSAndroid Build Coastguard Worker 282*2f2c4c7aSAndroid Build Coastguard Worker # Attempt to convert the address to something we understand. 283*2f2c4c7aSAndroid Build Coastguard Worker if alen == 0: 284*2f2c4c7aSAndroid Build Coastguard Worker return None 285*2f2c4c7aSAndroid Build Coastguard Worker elif alen == len(SockaddrIn) and SockaddrIn(addr).family == socket.AF_INET: 286*2f2c4c7aSAndroid Build Coastguard Worker return SockaddrIn(addr) 287*2f2c4c7aSAndroid Build Coastguard Worker elif alen == len(SockaddrIn6) and SockaddrIn6(addr).family == socket.AF_INET6: 288*2f2c4c7aSAndroid Build Coastguard Worker return SockaddrIn6(addr) 289*2f2c4c7aSAndroid Build Coastguard Worker elif alen == len(SockaddrStorage): # Can this ever happen? 290*2f2c4c7aSAndroid Build Coastguard Worker return SockaddrStorage(addr) 291*2f2c4c7aSAndroid Build Coastguard Worker else: 292*2f2c4c7aSAndroid Build Coastguard Worker return addr # Unknown or malformed. Return the raw bytes. 293*2f2c4c7aSAndroid Build Coastguard Worker 294*2f2c4c7aSAndroid Build Coastguard Worker 295*2f2c4c7aSAndroid Build Coastguard Workerdef Recvmsg(s, buflen, controllen, flags, addrlen=len(SockaddrStorage)): 296*2f2c4c7aSAndroid Build Coastguard Worker """Python wrapper for recvmsg. 297*2f2c4c7aSAndroid Build Coastguard Worker 298*2f2c4c7aSAndroid Build Coastguard Worker Args: 299*2f2c4c7aSAndroid Build Coastguard Worker s: A Python socket object. Becomes sockfd. 300*2f2c4c7aSAndroid Build Coastguard Worker buflen: An integer, the maximum number of bytes to read. 301*2f2c4c7aSAndroid Build Coastguard Worker addrlen: An integer, the maximum size of the source address. 302*2f2c4c7aSAndroid Build Coastguard Worker controllen: An integer, the maximum size of the cmsg buffer. 303*2f2c4c7aSAndroid Build Coastguard Worker 304*2f2c4c7aSAndroid Build Coastguard Worker Returns: 305*2f2c4c7aSAndroid Build Coastguard Worker A tuple of received bytes, socket address tuple, and cmg list. 306*2f2c4c7aSAndroid Build Coastguard Worker 307*2f2c4c7aSAndroid Build Coastguard Worker Raises: 308*2f2c4c7aSAndroid Build Coastguard Worker socket.error: If recvmsg fails. 309*2f2c4c7aSAndroid Build Coastguard Worker """ 310*2f2c4c7aSAndroid Build Coastguard Worker addr = ctypes.create_string_buffer(addrlen) 311*2f2c4c7aSAndroid Build Coastguard Worker msg_name = ctypes.addressof(addr) 312*2f2c4c7aSAndroid Build Coastguard Worker msg_namelen = addrlen 313*2f2c4c7aSAndroid Build Coastguard Worker 314*2f2c4c7aSAndroid Build Coastguard Worker buf = ctypes.create_string_buffer(buflen) 315*2f2c4c7aSAndroid Build Coastguard Worker iov = Iovec((ctypes.addressof(buf), buflen)) 316*2f2c4c7aSAndroid Build Coastguard Worker msg_iov = iov.CPointer() 317*2f2c4c7aSAndroid Build Coastguard Worker msg_iovlen = 1 318*2f2c4c7aSAndroid Build Coastguard Worker 319*2f2c4c7aSAndroid Build Coastguard Worker control = ctypes.create_string_buffer(controllen) 320*2f2c4c7aSAndroid Build Coastguard Worker msg_control = ctypes.addressof(control) 321*2f2c4c7aSAndroid Build Coastguard Worker msg_controllen = controllen 322*2f2c4c7aSAndroid Build Coastguard Worker 323*2f2c4c7aSAndroid Build Coastguard Worker msghdr = MsgHdr((msg_name, msg_namelen, msg_iov, msg_iovlen, 324*2f2c4c7aSAndroid Build Coastguard Worker msg_control, msg_controllen, flags)) 325*2f2c4c7aSAndroid Build Coastguard Worker ret = libc.recvmsg(s.fileno(), VoidPointer(msghdr), flags) 326*2f2c4c7aSAndroid Build Coastguard Worker MaybeRaiseSocketError(ret) 327*2f2c4c7aSAndroid Build Coastguard Worker 328*2f2c4c7aSAndroid Build Coastguard Worker data = buf.raw[:ret] 329*2f2c4c7aSAndroid Build Coastguard Worker msghdr = MsgHdr(msghdr._buffer.raw) 330*2f2c4c7aSAndroid Build Coastguard Worker addr = _ToSocketAddress(addr, msghdr.namelen) 331*2f2c4c7aSAndroid Build Coastguard Worker control = control.raw[:msghdr.msg_controllen] 332*2f2c4c7aSAndroid Build Coastguard Worker msglist = _ParseMsgControl(control) 333*2f2c4c7aSAndroid Build Coastguard Worker 334*2f2c4c7aSAndroid Build Coastguard Worker return data, addr, msglist 335*2f2c4c7aSAndroid Build Coastguard Worker 336*2f2c4c7aSAndroid Build Coastguard Worker 337*2f2c4c7aSAndroid Build Coastguard Workerdef Recvfrom(s, size, flags=0): 338*2f2c4c7aSAndroid Build Coastguard Worker """Python wrapper for recvfrom.""" 339*2f2c4c7aSAndroid Build Coastguard Worker buf = ctypes.create_string_buffer(size) 340*2f2c4c7aSAndroid Build Coastguard Worker addr = ctypes.create_string_buffer(len(SockaddrStorage)) 341*2f2c4c7aSAndroid Build Coastguard Worker alen = ctypes.c_int(len(addr)) 342*2f2c4c7aSAndroid Build Coastguard Worker 343*2f2c4c7aSAndroid Build Coastguard Worker ret = libc.recvfrom(s.fileno(), buf, len(buf), flags, 344*2f2c4c7aSAndroid Build Coastguard Worker addr, ctypes.byref(alen)) 345*2f2c4c7aSAndroid Build Coastguard Worker MaybeRaiseSocketError(ret) 346*2f2c4c7aSAndroid Build Coastguard Worker 347*2f2c4c7aSAndroid Build Coastguard Worker data = buf[:ret] 348*2f2c4c7aSAndroid Build Coastguard Worker alen = alen.value 349*2f2c4c7aSAndroid Build Coastguard Worker 350*2f2c4c7aSAndroid Build Coastguard Worker addr = _ToSocketAddress(addr.raw, alen) 351*2f2c4c7aSAndroid Build Coastguard Worker 352*2f2c4c7aSAndroid Build Coastguard Worker return data, addr 353*2f2c4c7aSAndroid Build Coastguard Worker 354*2f2c4c7aSAndroid Build Coastguard Worker 355*2f2c4c7aSAndroid Build Coastguard Workerdef Setsockopt(s, level, optname, optval, optlen): 356*2f2c4c7aSAndroid Build Coastguard Worker """Python wrapper for setsockopt. 357*2f2c4c7aSAndroid Build Coastguard Worker 358*2f2c4c7aSAndroid Build Coastguard Worker Mostly identical to the built-in setsockopt, but allows passing in arbitrary 359*2f2c4c7aSAndroid Build Coastguard Worker binary blobs, including NULL options, which the built-in python setsockopt does 360*2f2c4c7aSAndroid Build Coastguard Worker not allow. 361*2f2c4c7aSAndroid Build Coastguard Worker 362*2f2c4c7aSAndroid Build Coastguard Worker Args: 363*2f2c4c7aSAndroid Build Coastguard Worker s: The socket object on which to set the option. 364*2f2c4c7aSAndroid Build Coastguard Worker level: The level parameter. 365*2f2c4c7aSAndroid Build Coastguard Worker optname: The option to set. 366*2f2c4c7aSAndroid Build Coastguard Worker optval: A raw byte string, the value to set the option to (None for NULL). 367*2f2c4c7aSAndroid Build Coastguard Worker optlen: An integer, the length of the option. 368*2f2c4c7aSAndroid Build Coastguard Worker 369*2f2c4c7aSAndroid Build Coastguard Worker Raises: 370*2f2c4c7aSAndroid Build Coastguard Worker socket.error: if setsockopt fails. 371*2f2c4c7aSAndroid Build Coastguard Worker """ 372*2f2c4c7aSAndroid Build Coastguard Worker ret = libc.setsockopt(s.fileno(), level, optname, optval, optlen) 373*2f2c4c7aSAndroid Build Coastguard Worker MaybeRaiseSocketError(ret) 374