From bded1e349662eeb634383ad46ec3e1605b317ec7 Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Thu, 10 Jan 2019 23:12:06 +0100 Subject: Emit low-level sendmsg/recvmsg debugging When running in transparent proxy mode, log syscall parameters to aid troubleshooting --- pysnmp/carrier/asyncore/dgram/base.py | 7 +++++++ pysnmp/carrier/sockmsg.py | 21 +++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/pysnmp/carrier/asyncore/dgram/base.py b/pysnmp/carrier/asyncore/dgram/base.py index 274b1eba..4edae19b 100644 --- a/pysnmp/carrier/asyncore/dgram/base.py +++ b/pysnmp/carrier/asyncore/dgram/base.py @@ -75,8 +75,10 @@ class DgramSocketTransport(AbstractSocketTransport): try: if self.socket.family in (socket.AF_INET, socket.AF_INET6): self.socket.setsockopt(socket.SOL_IP, socket.IP_PKTINFO, flag) + if self.socket.family == socket.AF_INET6: self.socket.setsockopt(socket.SOL_IPV6, socket.IPV6_RECVPKTINFO, flag) + except socket.error: raise error.CarrierError('setsockopt() for %s failed: %s' % (self.socket.family == socket.AF_INET6 and "IPV6_RECVPKTINFO" or "IP_PKTINFO", sys.exc_info()[1])) @@ -96,8 +98,10 @@ class DgramSocketTransport(AbstractSocketTransport): self.socket.setsockopt( socket.SOL_IPV6, socket.IP_TRANSPARENT, flag ) + except socket.error: raise error.CarrierError('setsockopt() for IP_TRANSPARENT failed: %s' % sys.exc_info()[1]) + except OSError: raise error.CarrierError('IP_TRANSPARENT socket option requires superusre previleges') @@ -113,14 +117,17 @@ class DgramSocketTransport(AbstractSocketTransport): def normalizeAddress(self, transportAddress): if not isinstance(transportAddress, self.addressType): transportAddress = self.addressType(transportAddress) + if not transportAddress.getLocalAddress(): transportAddress.setLocalAddress(self.getLocalAddress()) + return transportAddress def getLocalAddress(self): # one evil OS does not seem to support getsockname() for DGRAM sockets try: return self.socket.getsockname() + except Exception: return '0.0.0.0', 0 diff --git a/pysnmp/carrier/sockmsg.py b/pysnmp/carrier/sockmsg.py index 0d79b2c7..0b21233b 100644 --- a/pysnmp/carrier/sockmsg.py +++ b/pysnmp/carrier/sockmsg.py @@ -17,6 +17,8 @@ # import sys +from pysnmp import debug + if sys.version_info[:2] < (3, 3): # noinspection PyUnusedLocal def getRecvFrom(addressType): @@ -69,38 +71,57 @@ else: def getRecvFrom(addressType): + def recvfrom(s, sz): _to = None + data, ancdata, msg_flags, _from = s.recvmsg(sz, socket.CMSG_LEN(sz)) + for anc in ancdata: if anc[0] == socket.SOL_IP and anc[1] == socket.IP_PKTINFO: addr = in_pktinfo.from_buffer_copy(anc[2]) addr = ipaddress.IPv4Address(memoryview(addr.ipi_addr).tobytes()) _to = (str(addr), s.getsockname()[1]) + break + elif anc[0] == socket.SOL_IPV6 and anc[1] == socket.IPV6_PKTINFO: addr = in6_pktinfo.from_buffer_copy(anc[2]) addr = ipaddress.ip_address(memoryview(addr.ipi6_addr).tobytes()) _to = (str(addr), s.getsockname()[1]) + break + + debug.logger & debug.flagIO and debug.logger( + 'recvfrom: received %d octets from %s to %s; ' + 'iov blob %r' % (len(data), _from, _to, ancdata)) + return data, addressType(_from).setLocalAddress(_to) return recvfrom def getSendTo(addressType): + def sendto(s, _data, _to): ancdata = [] if type(_to) == addressType: addr = ipaddress.ip_address(_to.getLocalAddress()[0]) + else: addr = ipaddress.ip_address(s.getsockname()[0]) + if type(addr) == ipaddress.IPv4Address: _f = in_pktinfo() _f.ipi_spec_dst = in_addr.from_buffer_copy(addr.packed) ancdata = [(socket.SOL_IP, socket.IP_PKTINFO, memoryview(_f).tobytes())] + elif s.family == socket.AF_INET6 and type(addr) == ipaddress.IPv6Address: _f = in6_pktinfo() _f.ipi6_addr = in6_addr.from_buffer_copy(addr.packed) ancdata = [(socket.SOL_IPV6, socket.IPV6_PKTINFO, memoryview(_f).tobytes())] + + debug.logger & debug.flagIO and debug.logger( + 'sendto: sending %d octets to %s; iov blob %r' % (len(data), _to, ancdata)) + return s.sendmsg([_data], ancdata, 0, _to) return sendto -- cgit v1.2.1