Various newlisp scripts.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

147 lines
4.3 KiB

#!/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)