83 lines
3.0 KiB
Nim
83 lines
3.0 KiB
Nim
|
from nativesockets import Port, ntohs, ntohl
|
||
|
from posix import InAddr, inet_ntoa
|
||
|
|
||
|
type
|
||
|
Ether_header {.importc: "struct ether_header", pure, final,
|
||
|
header: "<netinet/if_ether.h>".} = object
|
||
|
ether_dhost: array[6, cuchar]
|
||
|
ether_shost: array[6, cuchar]
|
||
|
ether_type: cushort
|
||
|
|
||
|
Ip {.importc: "struct ip", pure, final,
|
||
|
header: "<netinet/ip.h>".} = 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: "<netinet/tcp.h>".} = 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: "<netinet/if_ether.h>".}: cushort
|
||
|
IPPROTO_TCP {.importc: "IPPROTO_TCP", header: "<netinet/in.h>".}: 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)
|