def address_family(self): """ The packet address family: - socket.AF_INET, if IPv4 - socket.AF_INET6, if IPv6 - None, otherwise. """ if len(self.raw) >= 20: v = i(self.raw[0]) >> 4 if v == 4: return socket.AF_INET if v == 6: return socket.AF_INET6
def protocol(self): """ - | A (ipproto, proto_start) tuple. | ``ipproto`` is the IP protocol in use, e.g. Protocol.TCP or Protocol.UDP. | ``proto_start`` denotes the beginning of the protocol data. | If the packet does not match our expectations, both ipproto and proto_start are None. """ if self.address_family == socket.AF_INET: proto = i(self.raw[9]) start = (i(self.raw[0]) & 0b1111) * 4 elif self.address_family == socket.AF_INET6: proto = i(self.raw[6]) # skip over well-known ipv6 headers start = 40 while proto in IPV6_EXT_HEADERS: if start >= len(self.raw): # less than two bytes left start = None proto = None break if proto == Protocol.FRAGMENT: hdrlen = 8 elif proto == Protocol.AH: hdrlen = (i(self.raw[start + 1]) + 2) * 4 else: # Protocol.HOPOPT, Protocol.DSTOPTS, Protocol.ROUTING hdrlen = (i(self.raw[start + 1]) + 1) * 8 proto = i(self.raw[start]) start += hdrlen else: start = None proto = None out_of_bounds = ((proto == Protocol.TCP and start + 20 > len(self.raw)) or (proto == Protocol.UDP and start + 8 > len(self.raw)) or (proto in {Protocol.ICMP, Protocol.ICMPV6} and start + 4 > len(self.raw))) if out_of_bounds: # special-case tcp/udp so that we can rely on .protocol for the port properties. start = None proto = None return proto, start
def protocol(self): """ - | A (ipproto, proto_start) tuple. | ``ipproto`` is the IP protocol in use, e.g. Protocol.TCP or Protocol.UDP. | ``proto_start`` denotes the beginning of the protocol data. | If the packet does not match our expectations, both ipproto and proto_start are None. """ if self.address_family == socket.AF_INET: proto = i(self.raw[9]) start = (i(self.raw[0]) & 0b1111) * 4 elif self.address_family == socket.AF_INET6: proto = i(self.raw[6]) # skip over well-known ipv6 headers start = 40 while proto in IPV6_EXT_HEADERS: if start >= len(self.raw): # less than two bytes left start = None proto = None break if proto == Protocol.FRAGMENT: hdrlen = 8 elif proto == Protocol.AH: hdrlen = (i(self.raw[start + 1]) + 2) * 4 else: # Protocol.HOPOPT, Protocol.DSTOPTS, Protocol.ROUTING hdrlen = (i(self.raw[start + 1]) + 1) * 8 proto = i(self.raw[start]) start += hdrlen else: start = None proto = None out_of_bounds = ( (proto == Protocol.TCP and start + 20 > len(self.raw)) or (proto == Protocol.UDP and start + 8 > len(self.raw)) or (proto in {Protocol.ICMP, Protocol.ICMPV6} and start + 4 > len(self.raw)) ) if out_of_bounds: # special-case tcp/udp so that we can rely on .protocol for the port properties. start = None proto = None return proto, start
def reserved(self): """ The reserved field. """ return (i(self.raw[12]) >> 1) & 0x07
def ecn(self): """ The Explicit Congestion Notification field. """ return i(self.raw[1]) & 0x03
def hdr_len(self): """ The header length in words of 32bit. """ return i(self.raw[0]) & 0x0F
def type(self, val): self.raw[0] = i(val)
def dscp(self): """ The Differentiated Services Code Point field (originally defined as Type of Service) also known as DiffServ. """ return (i(self.raw[1]) >> 2) & 0x3F
def code(self): """ The ICMP message code. """ return i(self.raw[1])
def data_offset(self): """ The size of TCP header in 32bit words. """ return i(self.raw[12]) >> 4
def flags(self): """ The flags field: RESERVED (the evil bit), DF (don't fragment), MF (more fragments). """ return i(self.raw[6]) >> 5
def code(self, val): self.raw[1] = i(val)
def type(self): """ The ICMP message type. """ return i(self.raw[0])