def __init__(self, my_sa=0xF9, interface='can0'): self.my_sa = my_sa self.interface = interface self.can_socket = socket.socket(socket.PF_CAN, socket.SOCK_DGRAM, socket.CAN_J1939) addr_set = False while self.my_sa < 256 and not addr_set: try: self.can_socket.bind((self.interface, socket.J1939_NO_NAME, socket.J1939_NO_PGN, self.my_sa)) except OSError: print("Failed to bind %s with id %d" % (self.interface, self.my_sa)) self.my_sa += 1 except Exception as e: raise e else: addr_set = True if not addr_set: try: self.can_socket.bind((self.interface, socket.J1939_NO_NAME, socket.J1939_NO_PGN, 0xff)) self.my_sa = 0xff except Exception as e: print("last-try binding failed: %s" % (repr(e))) self.can_socket.settimeout(5) socket.CMSG_SPACE(1) + socket.CMSG_SPACE(8) #what does this do?
def recv(self): while not self.terminated: try: fds = array.array('i') header, ancdata = xrecvmsg( self.sock, 8, socket.CMSG_SPACE(MAXFDS * fds.itemsize) + socket.CMSG_SPACE(CMSGCRED_SIZE)) if header == b'' or len(header) != 8: break magic, length = struct.unpack('II', header) if magic != 0xdeadbeef: debug_log('Message with wrong magic dropped (magic {0:x})'. format(magic)) continue message, _, = xrecvmsg(self.sock, length) if message == b'' or len(message) != length: break debug_log("Received data: {0}", message) for cmsg_level, cmsg_type, cmsg_data in ancdata: if cmsg_level == socket.SOL_SOCKET and cmsg_type == socket.SCM_CREDS: pid, uid, euid, gid = struct.unpack( 'iiii', cmsg_data[:struct.calcsize('iiii')]) self.parent.credentials = { 'pid': pid, 'uid': uid, 'euid': euid, 'gid': gid } if cmsg_level == socket.SOL_SOCKET and cmsg_type == socket.SCM_RIGHTS: fds.fromstring( cmsg_data[:len(cmsg_data) - (len(cmsg_data) % fds.itemsize)]) self.parent.on_message(message, fds=fds) except OSError: break with contextlib.suppress(OSError): self.sock.close() if not self.terminated: self.closed()
def recv_udp(listener, bufsize): debug3('Accept UDP using socket_ext recvmsg.\n') srcip, data, adata, flags = listener.recvmsg((bufsize, ), socket.CMSG_SPACE(24)) dstip = None family = None for a in adata: if a.cmsg_level == socket.SOL_IP and a.cmsg_type == IP_ORIGDSTADDR: family, port = struct.unpack('=HH', a.cmsg_data[0:4]) port = socket.htons(port) if family == socket.AF_INET: start = 4 length = 4 else: raise Fatal("Unsupported socket type '%s'" % family) ip = socket.inet_ntop(family, a.cmsg_data[start:start + length]) dstip = (ip, port) break elif a.cmsg_level == SOL_IPV6 and a.cmsg_type == IPV6_ORIGDSTADDR: family, port = struct.unpack('=HH', a.cmsg_data[0:4]) port = socket.htons(port) if family == socket.AF_INET6: start = 8 length = 16 else: raise Fatal("Unsupported socket type '%s'" % family) ip = socket.inet_ntop(family, a.cmsg_data[start:start + length]) dstip = (ip, port) break return (srcip, dstip, data[0])
def udp_server(src_ip, greeting, port): payload = bytes(greeting + '\n', 'utf-8') s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.setsockopt(socket.SOL_IP, socket.IP_TRANSPARENT, 1) s.setsockopt(socket.SOL_IP, IP_RECVORIGDSTADDR, 1) s.bind(('127.0.0.1', port)) print(f"[+] Bound to udp://127.0.0.1:{port}") while True: ancdata = s.recvmsg(0, socket.CMSG_SPACE(24)) r_ip, r_port = ancdata[3] l_ip = s.getsockname()[0] l_port = get_src_port(ancdata[1]) print( f"[ ]Connection from udp://{r_ip}:{r_port} to udp://{l_ip}:{l_port}" ) s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s2.setsockopt(socket.IPPROTO_IP, socket.IP_TRANSPARENT, 1) s2.bind((src_ip, l_port)) try: s2.sendto(payload, (r_ip, r_port)) except socket.error: pass finally: s2.close() s.close()
def recvfds(sock, size): '''Receive an array of fds over an AF_UNIX socket.''' a = array.array('i') bytes_size = a.itemsize * size msg, ancdata, flags, addr = sock.recvmsg(1, socket.CMSG_SPACE(bytes_size)) if not msg and not ancdata: raise EOFError try: if ACKNOWLEDGE: sock.send(b'A') if len(ancdata) != 1: raise RuntimeError('received %d items of ancdata' % len(ancdata)) cmsg_level, cmsg_type, cmsg_data = ancdata[0] if (cmsg_level == socket.SOL_SOCKET and cmsg_type == socket.SCM_RIGHTS): if len(cmsg_data) % a.itemsize != 0: raise ValueError a.frombytes(cmsg_data) if len(a) % 256 != msg[0]: raise AssertionError( "Len is {0:n} but msg[0] is {1!r}".format( len(a), msg[0])) return list(a) except (ValueError, IndexError): pass raise RuntimeError('Invalid data received')
def recv_udp(listener, bufsize): debug3('Accept UDP python using recvmsg.') data, ancdata, _, srcip = listener.recvmsg(4096, socket.CMSG_SPACE(24)) dstip = None family = None for cmsg_level, cmsg_type, cmsg_data in ancdata: if cmsg_level == socket.SOL_IP and cmsg_type == IP_ORIGDSTADDR: family, port = struct.unpack('=HH', cmsg_data[0:4]) port = socket.htons(port) if family == socket.AF_INET: start = 4 length = 4 else: raise Fatal("Unsupported socket type '%s'" % family) ip = socket.inet_ntop(family, cmsg_data[start:start + length]) dstip = (ip, port) break elif cmsg_level == SOL_IPV6 and cmsg_type == IPV6_ORIGDSTADDR: family, port = struct.unpack('=HH', cmsg_data[0:4]) port = socket.htons(port) if family == socket.AF_INET6: start = 8 length = 16 else: raise Fatal("Unsupported socket type '%s'" % family) ip = socket.inet_ntop(family, cmsg_data[start:start + length]) dstip = (ip, port) break return (srcip, dstip, data)
def read(self): buf, ancdata, _, addr = self._sock.recvmsg(512, socket.CMSG_SPACE(100)) respond = self._get_cmsg_to(ancdata).encode('utf8') thread = threading.Thread(group=None, target=self.process, args=(buf, addr, respond)) thread.start()
def get_request(self): iface_index = None data, ancdata, flags, client_addr = self.socket.recvmsg( self.max_packet_size, socket.CMSG_SPACE(ctypes.sizeof(ctypes.in6_pktinfo))) for anc in ancdata: if anc[0] == socket.IPPROTO_IPV6 and anc[1] == socket.IPV6_PKTINFO: _in6_pktinfo = ctypes.in6_pktinfo.from_buffer_copy(anc[2]) iface_index = _in6_pktinfo.ipi6_ifindex return (data, self.socket, iface_index), client_addr
def fds_buf_size(): # If there may be file descriptors, we try to read 1 message at a time. # The reference implementation of D-Bus defaults to allowing 16 FDs per # message, and the Linux kernel currently allows 253 FDs per sendmsg() # call. So hopefully allowing 256 FDs per recvmsg() will always suffice. global _fds_buf_size_cache if _fds_buf_size_cache is None: maxfds = 256 fd_size = array.array('i').itemsize _fds_buf_size_cache = socket.CMSG_SPACE(maxfds * fd_size) return _fds_buf_size_cache
def recv_udp(listener, bufsize): debug3('Accept UDP python using recvmsg.') data, ancdata, _, srcip = listener.recvmsg(4096, socket.CMSG_SPACE(4)) dstip = None for cmsg_level, cmsg_type, cmsg_data in ancdata: if cmsg_level == socket.SOL_IP and cmsg_type == IP_RECVDSTADDR: port = 53 ip = socket.inet_ntop(socket.AF_INET, cmsg_data[0:4]) dstip = (ip, port) break return (srcip, dstip, data)
def recv_udp(listener, bufsize): debug3('Accept UDP using socket_ext recvmsg.') srcip, data, adata, _ = listener.recvmsg((bufsize, ), socket.CMSG_SPACE(4)) dstip = None for a in adata: if a.cmsg_level == socket.SOL_IP and a.cmsg_type == IP_RECVDSTADDR: port = 53 ip = socket.inet_ntop(socket.AF_INET, a.cmsg_data[0:4]) dstip = (ip, port) break return (srcip, dstip, data[0])
def listen(sock): message, ancillary_data, _, (address, _) = sock.recvmsg(4096, socket.CMSG_SPACE(24)) port = None for cmsg_level, cmsg_type, cmsg_data in ancillary_data: if cmsg_level == socket.SOL_IP and cmsg_type == IP_ORIGDSTADDR: _, port = struct.unpack('=HH', cmsg_data[0:4]) port = socket.htons(port) break return message, address, port
def get_request(self): data, anc_data, _, client_addr = self.socket.recvmsg( self.max_packet_size, socket.CMSG_SPACE(65535)) ifindex = None for anc_record in anc_data: (anc_level, anc_type, anc_datum) = anc_record # Check for IPV6_PKTINFO ancilliary data if anc_level == socket.IPPROTO_IPV6 and anc_type == socket.IPV6_PKTINFO: # Parse binary ancilliary data pktinfo = in6_pktinfo.from_buffer_copy(anc_datum) ifindex = pktinfo.ipi6_ifindex return (data, self.socket, ifindex), client_addr
def retrieve_console_fd(sock): fds = array.array('i') conn, _ = sock.accept() sock.close() msg, ancdata, msg_flags, _addr = conn.recvmsg( 16, socket.CMSG_SPACE(fds.itemsize), socket.MSG_CMSG_CLOEXEC, ) cmsg_level, cmsg_type, cmsg_data = ancdata[0] assert cmsg_level == socket.SOL_SOCKET, cmsg_level assert cmsg_type == socket.SCM_RIGHTS, cmsg_type fds.frombytes(cmsg_data) return list(fds)[0]
def recv(self): try: fds = array.array("i") data, ancdata, msg_flags, address = self.connection.recvmsg( 1024, socket.CMSG_SPACE(16 * fds.itemsize)) for cmsg_level, cmsg_type, cmsg_data in ancdata: if cmsg_level == socket.SOL_SOCKET and cmsg_type == socket.SCM_RIGHTS: fds.fromstring(cmsg_data[:len(cmsg_data) - len(cmsg_data) % fds.itemsize()]) self.incoming_fds.extend(fds) if data: self.decode(data) except socket.error as e: if e.errno == 11: return raise
def __init__( self, iface_name: str, mtu: int, loop: typing.Optional[asyncio.AbstractEventLoop] = None) -> None: """ CAN Classic/FD is selected automatically based on the MTU. It is not possible to use CAN FD with MTU of 8 bytes. :param iface_name: E.g., ``can0``. :param mtu: The maximum data field size in bytes. CAN FD is used if this value > 8, Classic CAN otherwise. This value must belong to Media.VALID_MTU_SET. :param loop: Deprecated. """ self._mtu = int(mtu) if self._mtu not in self.VALID_MTU_SET: raise ValueError( f"Invalid MTU: {self._mtu} not in {self.VALID_MTU_SET}") if loop: warnings.warn("The loop argument is deprecated", DeprecationWarning) self._iface_name = str(iface_name) self._is_fd = self._mtu > _NativeFrameDataCapacity.CAN_CLASSIC self._native_frame_data_capacity = int({ False: _NativeFrameDataCapacity.CAN_CLASSIC, True: _NativeFrameDataCapacity.CAN_FD, }[self._is_fd]) self._native_frame_size = _FRAME_HEADER_STRUCT.size + self._native_frame_data_capacity self._sock = _make_socket(iface_name, can_fd=self._is_fd) self._ctl_main, self._ctl_worker = socket.socketpair( ) # This is used for controlling the worker thread. self._closed = False self._maybe_thread: typing.Optional[threading.Thread] = None self._loopback_enabled = False self._ancillary_data_buffer_size = socket.CMSG_SPACE( _TIMEVAL_STRUCT.size) # Used for recvmsg() super().__init__()
def recv_fds(sock, msglen, maxfds, inheritable=False): ''' Receives via a Unix domain socket a message of at most `msglen` bytes, with at most `maxfds` file descriptors in the ancillary data. The file descriptors will be marked O_CLOEXEC unless inheritable is set to False. ''' fds = array.array('i') msg, ancdata, msg_flags, _addr = sock.recvmsg( msglen, maxfds * socket.CMSG_SPACE(fds.itemsize), 0 if inheritable else socket.MSG_CMSG_CLOEXEC, ) assert not (msg_flags & socket.MSG_TRUNC), msg_flags assert not (msg_flags & socket.MSG_CTRUNC), msg_flags assert not (msg_flags & socket.MSG_ERRQUEUE), msg_flags for cmsg_level, cmsg_type, cmsg_data in ancdata: assert cmsg_level == socket.SOL_SOCKET, cmsg_level assert cmsg_type == socket.SCM_RIGHTS, cmsg_type assert len(cmsg_data) % fds.itemsize == 0, cmsg_data fds.frombytes(cmsg_data) return msg, list(fds)
def __init__( self, iface_name: str, mtu: int, loop: typing.Optional[asyncio.AbstractEventLoop] = None) -> None: """ CAN Classic/FD is selected automatically based on the MTU. It is not possible to use CAN FD with MTU of 8 bytes. :param iface_name: E.g., ``can0``. :param mtu: The maximum data field size in bytes. CAN FD is used if this value > 8, Classic CAN otherwise. This value must belong to Media.VALID_MTU_SET. :param loop: The event loop to use. Defaults to :func:`asyncio.get_event_loop`. """ self._mtu = int(mtu) if self._mtu not in self.VALID_MTU_SET: raise ValueError( f'Invalid MTU: {self._mtu} not in {self.VALID_MTU_SET}') self._iface_name = str(iface_name) self._loop = loop if loop is not None else asyncio.get_event_loop() self._is_fd = self._mtu > _NativeFrameDataCapacity.CAN_CLASSIC self._native_frame_data_capacity = int({ False: _NativeFrameDataCapacity.CAN_CLASSIC, True: _NativeFrameDataCapacity.CAN_FD, }[self._is_fd]) self._native_frame_size = _FRAME_HEADER_STRUCT.size + self._native_frame_data_capacity self._sock = _make_socket(iface_name, can_fd=self._is_fd) self._closed = False self._maybe_thread: typing.Optional[threading.Thread] = None self._loopback_enabled = False self._ancillary_data_buffer_size = socket.CMSG_SPACE( _TIMEVAL_STRUCT.size) # Used for recvmsg() super(SocketCANMedia, self).__init__()
def _recv_loop(self): try: while self.connected: b = self._sock.recv(MIN_HEADER_SIZE, socket.MSG_PEEK) if not b: raise TransportError() total_size, fields_size = get_sizes(RawData(b)) if total_size > MAX_MESSAGE_LEN: raise TooLongError('message too long: %d bytes' % total_size) raw = RawData(bytearray(total_size)) view = raw.getbuffer() if self.unix_fds_enabled: b = self._sock.recv(MIN_HEADER_SIZE + fields_size, socket.MSG_PEEK) unix_fds_cnt = get_unix_fds_cnt(RawData(b)) else: unix_fds_cnt = 0 if unix_fds_cnt: fds = array.array('i') cnt, anc, _, _ = self._sock.recvmsg_into( [view], socket.CMSG_SPACE(unix_fds_cnt * fds.itemsize)) for cmsg_level, cmsg_type, cmsg_data in anc: if (cmsg_level == socket.SOL_SOCKET and cmsg_type == socket.SCM_RIGHTS): fds.frombytes( cmsg_data[:len(cmsg_data) - (len(cmsg_data) % fds.itemsize)]) raw.unix_fds = fds.tolist() else: cnt = self._sock.recv_into(view) view.release() if not cnt: raise TransportError() self._router.incoming(Message.from_bytes(raw)) except Exception as ex: if self.connected: _logger.debug('recv loop', exc_info=True) self._set_error(ex) self.disconnect() _logger.debug('EXIT recv loop')
def receive(self, timeout=None): self._check_write_feedback() timeout = -1 if timeout is None else (timeout * 1000) if self._poll_rx.poll(timeout): ts_real = None ts_mono = None if NATIVE_SOCKETCAN: # Reading the frame together with timestamps in the ancillary data structures ancillary_len = 64 # Arbitrary value, must be large enough to accommodate all ancillary data packet_raw, ancdata, _flags, _addr = self.socket.recvmsg( self.FRAME_SIZE, socket.CMSG_SPACE(ancillary_len)) # Parsing the timestamps for cmsg_level, cmsg_type, cmsg_data in ancdata: if cmsg_level == socket.SOL_SOCKET and cmsg_type == SO_TIMESTAMP: sec, usec = struct.unpack(self.TIMEVAL_FORMAT, cmsg_data) ts_real = sec + usec * 1e-6 else: packet_raw = self.socket.recv(self.FRAME_SIZE) # Parsing the frame can_id, can_dlc, can_data = struct.unpack(self.FRAME_FORMAT, packet_raw) # TODO: receive timestamps directly from hardware # TODO: ...or at least obtain timestamps from the socket layer in local monotonic domain if ts_real and not ts_mono: ts_mono = self._convert_real_to_monotonic(ts_real) frame = CANFrame(can_id & CAN_EFF_MASK, can_data[0:can_dlc], bool(can_id & CAN_EFF_FLAG), ts_monotonic=ts_mono, ts_real=ts_real) self._rx_hook(frame) return frame
def __init__(self, group: str, port: int, hop_limit: int, max_buffer: int = 4096) -> None: self.group = group self.port = port self.hop_limit = hop_limit self.max_buffer = max_buffer # Look up multicast group address in name server and find out IP version of the first suitable target # and then get the address family of it (socket.AF_INET or socket.AF_INET6) connection_candidates = socket.getaddrinfo( # type: ignore group, self.port, type=socket.SOCK_DGRAM) sock = None for connection_candidate in connection_candidates: address_family: socket.AddressFamily = connection_candidate[0] self.ip_version = 4 if address_family == socket.AF_INET else 6 try: sock = self._create_socket(address_family) except OSError as error: log.info( f"could not connect to the multicast IP network of candidate %s; reason: {error}", connection_candidates, ) if sock is not None: self._socket = sock else: raise RuntimeError("could not connect to a multicast IP network") # used in recv() self.received_timestamp_struct = "@ll" ancillary_data_size = struct.calcsize(self.received_timestamp_struct) self.received_ancillary_buffer_size = socket.CMSG_SPACE( ancillary_data_size) # used by send() self._send_destination = (self.group, self.port) self._last_send_timeout: Optional[float] = None
def read(self): buf, ancdata, _, addr = self._sock.recvmsg(512, socket.CMSG_SPACE(100)) interface = self._get_cmsg_to(ancdata) try: query = Packet.parse(buf) answer, pool = self._handler.handle(interface, query) if not pool: return if answer.is_broadcast(): logging.info('dhcp: got net broadcast on %s', interface) self.broadcast(answer, interface, addr[1]) elif addr[0] == '0.0.0.0': logging.info('dhcp: got adr broadcast on %s', interface) addr = (socket.inet_ntoa(pool.broadcast), addr[1]) self._queue.append((addr, answer)) else: logging.info('dhcp: got unicast from %s', addr[0]) self._queue.append((addr, answer)) except Exception as e: traceback.print_exc()
s.inet_ntoa(packed_ip) # Преобразует 32-разрядный упакованный формат в строку IР-адреса # (только для адресов IPv4) s.inet_pton(address_family, ip_string) # Преобразует строку IР-адреса в упакованный двоичный формат, # (и для адресов IPv4, и для адресов IPvб) s.inet_ntop(address_family, packed_ip) # Преобразует упакованный двоичный формат в строку IР-адреса, # (и для адресов IPv4, и для адресов IPvб) s.CMSG_LEN(length) # s.CMSG_SPACE(length) # s.getdefaulttimeout() # Возвращает значение по умолчанию тайм-аута сокета в секундах # (число с плавающей точкой) s.setdefaulttimeout(timeout) # задает значение по умолчанию тайм-аута сокета в секундах # (число с плавающей точкой) s.sethostname(name) # Задайте имя хоста машины. Это приведет к вызову OSError, если у # вас недостаточно прав. s.if_nameindex()
def main(argv=None): parser = argparse.ArgumentParser(description="Simple multihomed UDP server") parser.add_argument('-p', '--port', type=int, default=4242, help="UDP port to be used (default: 4242)") parser.add_argument('-w', '--wait', action='store_true', help="wait for connections instead of creating one") group = parser.add_mutually_exclusive_group() group.add_argument('-4', '--ipv4', action='store_true', help="create an IPv4-only socket") group.add_argument('-6', '--ipv6', action='store_true', help="create an IPv6-only socket") args = parser.parse_args(argv) # Compute local variables af = socket.AF_INET if args.ipv4 else socket.AF_INET6 localaddr = '127.0.0.1' if args.ipv4 else '::1' anyaddr = '0.0.0.0' if args.ipv4 else '::' port = args.port if args.port > 0 else 4242 # Create and configure socket for multihoming skserver = socket.socket(af, socket.SOCK_DGRAM, socket.IPPROTO_UDP) if not args.ipv6: if hasattr(socket, 'IP_PKTINFO'): skserver.setsockopt(socket.SOL_IP, socket.IP_PKTINFO, 1) elif hasattr(socket, 'IP_RECVDSTADDR'): skserver.setsockopt(socket.IPPROTO_IP, socket.IP_RECVDSTADDR, 1) if not args.ipv4: if hasattr(socket, 'IPV6_RECVPKTINFO'): skserver.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_RECVPKTINFO, 1) elif hasattr(socket, 'IPV6_RECVDSTADDR'): skserver.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_RECVDSTADDR, 1) if not args.ipv4: skserver.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, args.ipv6) # Listen if args.wait: listenaddr = anyaddr elif args.ipv6 or args.ipv4: listenaddr = localaddr else: # To protect dual-stack listen, bind the socket to the loopback interface listenaddr = anyaddr try: skserver.setsockopt(socket.SOL_SOCKET, socket.SO_BINDTODEVICE, b'lo\0') except PermissionError as exc: logger.warning("Unable to bind to loopback interface: %s", exc) ainfos = socket.getaddrinfo(listenaddr, port, af, socket.SOCK_DGRAM, socket.IPPROTO_UDP) skserver.bind(ainfos[0][4]) if args.wait: logger.info("Waiting for a connection on UDP port %d.", port) else: # Create a client socket, which uses IPv4-in-IPv6 if enabled clientaf = socket.AF_INET if not args.ipv6 else socket.AF_INET6 clientdstaddr = '127.0.0.1' if not args.ipv6 else '::1' skclient = socket.socket(clientaf, socket.SOCK_DGRAM, socket.IPPROTO_UDP) skclient.sendto(b'Hello, world!', (clientdstaddr, port)) # Receive an incoming packet (msg, ancdata, _, clientaddrport) = skserver.recvmsg(1024, socket.CMSG_SPACE(100)) assert args.wait or msg == b'Hello, world!' # Check the socket channel dst_addr = None ifindex = None for cmsg_level, cmsg_type, cmsg_data in ancdata: if cmsg_level == socket.SOL_IP and hasattr(socket, 'IP_PKTINFO') and cmsg_type == socket.IP_PKTINFO: # struct in_pktinfo { int ipi_ifindex; struct in_addr ipi_spec_dst, ipi_addr; }; assert len(cmsg_data) == 12 dst_addr = socket.inet_ntop(socket.AF_INET, cmsg_data[4:8]) ifindex = struct.unpack('I', cmsg_data[:4])[0] elif cmsg_level == socket.IPPROTO_IPV6 and hasattr(socket, 'IPV6_PKTINFO') and cmsg_type == socket.IPV6_PKTINFO: # struct in6_pktinfo { struct in6_addr ipi6_addr; int ipi_ifindex; }; assert len(cmsg_data) == 20 dst_addr = socket.inet_ntop(socket.AF_INET6, cmsg_data[:16]) ifindex = struct.unpack('I', cmsg_data[16:20])[0] else: logger.warning("Unknown anciliary data: %s, %s, %r", cmsg_level, cmsg_type, cmsg_data) # TODO: decode IP_RECVDSTADDR/IPV6_RECVDSTADDR text = "Received UDP packet from {0[0]} port {0[1]}".format(clientaddrport) if dst_addr is not None: text += " to {} port {} interface {}".format(dst_addr, port, ifindex) logger.info(text) # Send back a reply with the same ancillary data skserver.sendmsg([b'Bye!\n'], ancdata, 0, clientaddrport) skserver.close() if not args.wait: skclient.close() return 0
def space(self): return socket.CMSG_SPACE(self._data_len)
def handle_connection(self): self.conn.on_open() while True: try: fds = array.array('i') header, ancdata = xrecvmsg( self.connfd, 8, socket.CMSG_SPACE(MAXFDS * fds.itemsize) + socket.CMSG_SPACE(CMSGCRED_SIZE)) if header == b'' or len(header) != 8: if len(header) > 0: self.server.logger.info( 'Short read (len {0})'.format(len(header))) break magic, length = struct.unpack('II', header) if magic != 0xdeadbeef: self.server.logger.info( 'Message with wrong magic dropped (magic {0:x})'. format(magic)) break msg, _ = xrecvmsg(self.connfd, length) if msg == b'' or len(msg) != length: self.server.logger.info( 'Message with wrong length dropped; closing connection' ) break for cmsg_level, cmsg_type, cmsg_data in ancdata: if cmsg_level == socket.SOL_SOCKET and cmsg_type == socket.SCM_CREDS: pid, uid, euid, gid = struct.unpack( 'iiii', cmsg_data[:struct.calcsize('iiii')]) self.client_address = ('unix', pid) self.conn.credentials = { 'pid': pid, 'uid': uid, 'euid': euid, 'gid': gid } if cmsg_level == socket.SOL_SOCKET and cmsg_type == socket.SCM_RIGHTS: fds.fromstring( cmsg_data[:len(cmsg_data) - (len(cmsg_data) % fds.itemsize)]) except (OSError, ValueError) as err: if getattr(err, 'errno', None) == errno.EBADF: # in gevent, shutdown() on a socket from other greenlets results in recv*() returning # with EBADF. break self.server.logger.info( 'Receive failed: {0}; closing connection'.format( str(err)), exc_info=True) break self.conn.on_message(msg, fds=fds) self.close()
import errno # EBADF import logging # getLogger import os # close, write import socket # CMSG_SPACE, SOL_SOCKET, SCM_RIGHTS, socketpair import socketserver # StreamRequestHandler import struct # calcsize, pack, unpack import threading # Thread from pathlib import Path import apkfoundry.container # Container _LOGGER = logging.getLogger(__name__) NUM_FDS = 3 PASSFD_FMT = NUM_FDS * "i" PASSFD_SIZE = socket.CMSG_SPACE(struct.calcsize(PASSFD_FMT)) RC_FMT = "i" BUF_SIZE = 4096 def abuild_fetch(argv): expected_argv = ( "-d", "/af/distfiles", ..., ) if len(argv) != len(expected_argv): raise ValueError("apkfoundry: abuild-fetch: invalid usage") for arg, expected in zip(argv, expected_argv):