xref: /aosp_15_r20/kernel/tests/net/test/csocket.py (revision 2f2c4c7ab4226c71756b9c31670392fdd6887c4f)
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