Nifty!
I played around with this a little, trying to get it to decode packets that I saved using tcpdump's "-w" option. I used the following two functions to read the pcap file. This is throwing away some information that is present in the pcap framing, such as frame number, arrival time, delta since previous packet etc. It also seems to throw away the Ethernet type: reading
http://www.hw-server.com/ethernet#link_layer
I discovered that there are two Ethernet formats, the old "Ethernet II" format and the IEEE 802.3 format. They aren't quite equivalent, so for Ethernet II packets GRAB-ETHERNET-HEADER is reading what it thinks is the protocol but is in fact LLC data.
(defun pcap-file-frames (pathname) (let ((frames (list))) (block reading (with-open-file (raw pathname :direction :input :element-type 'octet) ;; skip over the pcap per-file header (dotimes (i 24) (read-byte raw)) (loop ;; skip over the per-frame header (dotimes (i 12) (unless (read-byte raw nil nil) (return-from reading))) ;; read the frame length (let* ((frame-length (read-uint32 raw)) (frame (make-array frame-length :element-type 'octet))) (read-sequence frame raw) (push frame frames))))) (reverse frames)))
(defun decode-pcap-file (pathname) (loop :for frame :in (pcap-file-frames pathname) :collect (decode (coerce frame 'buffer))))
STRUCTURE-SYMBOL-NAMES should be written as follows to avoid problems with *PRINT-CASE*:
(defun structure-symbol-names (name) "Return all the interesting symbols generated by DEFSTRUCT for NAME. Assumes a FOO type name, MAKE-FOO constructor, and FOO-P predicate to avoid excessively low-level introspection." (list* name (find-symbol (concatenate 'string (symbol-name name) "-P")) (find-symbol (concatenate 'string "MAKE-" (symbol-name name))) (structure-accessors name)))
Furthermore as I mentioned to Luke on IRC, I think this would benefit from splitting out into multiple files: a README, a package file, a test file, a system-definition file etc.
small-cl-src-discuss@common-lisp.net