from nativesockets import Port, ntohs, ntohl from posix import InAddr, inet_ntoa type Ether_header {.importc: "struct ether_header", pure, final, header: "".} = object ether_dhost: array[6, cuchar] ether_shost: array[6, cuchar] ether_type: cushort Ip {.importc: "struct ip", pure, final, header: "".} = object when cpuEndian == littleEndian: ip_hl {.bitsize:4.}: cuchar # header length ip_v {.bitsize:4.}: cuchar # version else: ip_v {.bitsize:4.}: cuchar # version ip_hl {.bitsize:4.}: cuchar # header length ip_tos: cuchar # type of service ip_len: cshort # total length ip_id: cushort # identification ip_off: cshort # fragment offset field ip_ttl: cuchar # time to live ip_p: cuchar # protocol ip_sum: cushort # checksum ip_src: InAddr # source address ip_dst: InAddr # destination address Tcphdr {.importc: "struct tcphdr", pure, final, header: "".} = object th_sport: cushort # source port th_dport: cushort # destination port th_seq: uint32 # sequence number th_ack: uint32 # ackkowledgment number when cpuEndian == littleEndian: th_x2 {.bitsize:4.}: cuchar # (unused) th_off {.bitsize:4.}: cuchar # data offset else: th_off {.bitsize:4.}: cuchar # (unused) th_x2 {.bitsize:4.}: cuchar # data offset th_flags: cuchar # flags th_win: cushort # window th_sum: cushort # checksum th_urp: cushort # urgent pointer Protocol* = enum tcp other PacketInfo* = object case protocol*: Protocol of tcp: tcpIpSrc*: string tcpIpDst*: string tcpPortSrc*: Port tcpPortDst*: Port tcpSeqNumber*: uint32 else: discard var ETHERTYPE_IP {.importc: "ETHERTYPE_IP", header: "".}: cushort IPPROTO_TCP {.importc: "IPPROTO_TCP", header: "".}: cint proc fromString*(packet: string): PacketInfo = let etherHeader = cast[ptr Ether_header](packet.cstring) if ntohs(etherHeader.ether_type) == ETHERTYPE_IP: let ipHeader = cast[ptr Ip](cast[int](packet.cstring) + sizeof(Ether_header)) let ipSrc = $inet_ntoa(ipHeader.ip_src) let ipDst = $inet_ntoa(ipHeader.ip_dst) if ipHeader.ip_p.int == IPPROTO_TCP: let tcpHeader = cast[ptr Tcphdr](cast[int](ipHeader) + ipHeader.ip_hl.int * 4) result = PacketInfo(protocol: tcp, tcpIpSrc: ipSrc, tcpIpDst: ipDst, tcpPortSrc: Port(ntohs(tcpHeader.th_sport)), tcpPortDst: Port(ntohs(tcpHeader.th_dport)), tcpSeqNumber: ntohl(tcpHeader.th_seq)) else: result = PacketInfo(protocol: other) else: result = PacketInfo(protocol: other)