From: Ralph Ronnquist Date: Sat, 19 Feb 2022 08:28:52 +0000 (+1100) Subject: initial X-Git-Url: https://git.rrq.au/?a=commitdiff_plain;h=70e7563e0394234575ac497d66deffb104690dff;p=rrq%2Fnewlisp-ftw.git initial --- diff --git a/rwhod-sniffer.lsp b/rwhod-sniffer.lsp new file mode 100755 index 0000000..f39e841 --- /dev/null +++ b/rwhod-sniffer.lsp @@ -0,0 +1,147 @@ +#!/usr/bin/newlisp +# +# Use pcap to sniff out rwhod broadcasts on an interface, and +# store select ones at /var/spool/rwho/rwho.$HOST + +(define (die) + (write-line 2 (join (map string (args)) " ")) + (exit 1)) + +;(signal 2 'die) ;; THIS DOESN'T WORK?? + +(constant + 'IFACE "hemmanet" + 'HOSTS '( "mini" "borta" ) + ) + +(setf ERRBUF (dup "\0" 356)) + +(constant + 'PCAPLIB "/usr/lib/x86_64-linux-gnu/libpcap.so" + 'PCAP_CHAR_ENC_LOCAL 0 + 'PCAP_CHAR_ENC_UTF_8 1 + ) +(import PCAPLIB "pcap_init" "int" "int" "char*") +(import PCAPLIB "pcap_open_live" "void*" "char*" "int" "int" "int" "char*") +(import PCAPLIB "pcap_loop" "int" "void*" "int" "void*" "void*") + +;; syntax helper +(define (estruct NAME) + (apply struct (cons NAME (map string (flat (args)))))) + +;; /usr/include/linux/time.h +(struct 'timeval + "long" ;; seconds + "long" ;; microseconds */ + ) +(struct 'bpf_u_int32 "unsigned int") + +;; /usr/include/pcap/pcap.h +(struct 'pcap_pkthdr + "timeval" ;; time stamp + "bpf_u_int32" ;; length of portion present + "bpf_u_int32" ;; length of this packet + ) + +(define (pcap_handling RECEIVER (LIMIT 10) (SNAP 500)) + (letn ((RECEIVER_FN RECEIVER) + (CALLBACK (callback RECEIVER_FN + "void" ;; no return value + "void*" ;; userdata + "void*" ;; struct pcap_pkthdr* + "void*" ;; unsigned char* + ))) + + (when (!= (setf RET (pcap_init PCAP_CHAR_ENC_LOCAL ERRBUF))) + (die "pcap_init" RET ERRBUF)) + + (when (= (setf HANDLE (pcap_open_live IFACE SNAP 0 0 ERRBUF))) + (die "pcap_open_live" ERRBUF)) + + (when (!= (setf RET (pcap_loop HANDLE LIMIT CALLBACK 0))) + (die "pcap_loop" RET)) + )) + +(estruct 'macaddr (dup 'byte 6)) +(estruct 'ethertype (dup 'byte 2)) +(struct 'ether_head + "macaddr" ;; destination mac + "macaddr" ;; source mac + "ethertype" ;; ether type + ) + +(estruct 'ipv4addr (dup 'byte 4)) +(struct 'byte2 "byte" "byte") +(struct 'uint16 "unsigned short int") ; +(define (ntohs S) (unpack ">u" (address S))) +(struct 'ipv4_head + "byte2" ;; Version[4] IHL[4] DSCP[6] ECV[2] + "uint16" ;; Length[16] (in network byte order!) + "uint16" ;; Identification + "uint16" ;; Flags[3] Fragment-offset[13] + "byte" ;; TTL + "byte" ;; protocol + "uint16" ;; header-checksum + "ipv4addr" ;; source IP + "ipv4addr" ;; destinetion IP + ) + +(struct 'udp_head_real + "uint16" ;; source port (network order) + "uint16" ;; destination port (network order) + "uint16" ;; payload length (network order) + "uint16" ;; checksum (network order) + ) +(constant 'udp_head ">uuuu"); loading data into host order + +(estruct 'wd_hostname (dup 'char 32)) +(struct 'wd_loadav "int" "int" "int") +(struct 'rwhod + "char" ;; wd_vers; + "char" ;; wd_type; + "char" "char" ;; wd_fill[2]; + "int" ;; wd_sendtime; + "int" ;; wd_recvtime; + "wd_hostname" ;; char[32]; + "wd_loadav" ;; "int" "int" "int" [3]; + "int" ;; wd_boottime; + ;; struct whoent { + ;; struct outmp we_utmp; + ;; int we_idle; + ;; } wd_we[1024 / sizeof (struct whoent)]; + ) + +(unless (directory? "/var/spool/rwho") + (make-dir "/var/spool/rwho")) + +;; Save rwhod report +(define (receive_rwhod BYTES LEN) + (let ((HOST ((unpack "s32" (+ BYTES 12)) 0)) + (DATA (get-string BYTES LEN))) + (when (member HOST HOSTS) + (write-file (format "/var/spool/rwho/whod.%s" HOST) DATA)))) + +(define (receive_udp BYTES LEN) + (let ((HDR (unpack udp_head BYTES))) + (when (= '(513 513) (0 2 HDR)) + (receive_rwhod (+ BYTES 8) (- LEN 8))) + )) + +(define (receive_ipv4 BYTES LEN REAL) + (letn ((HDR (unpack ipv4_head BYTES)) + (SZ (* 4 (& (HDR 0 0) 0xf)))) + (when (and (= LEN REAL) (= (HDR 5) 17)) + (receive_udp (+ BYTES SZ) (- LEN SZ)) + ))) + +(define (receive_packet USERDATA PKTHDR BYTES) + (let ((HDR (unpack pcap_pkthdr PKTHDR)) + (MAC (unpack ether_head BYTES))) + (when (and (> (HDR 1 0) 34) (= (dup 255 6) (MAC 0)) (= '(8 0) (MAC 2))) + (receive_ipv4 (+ BYTES 14) (- (HDR 1 0) 14) (- (HDR 2 0) 14))) + )) + +;;; Main program +(pcap_handling 'receive_packet) + +(exit 0)