<?xml version="1.0"?>
<paste-with-annotations>
  <paste>
    <number>
      <integer>51474</integer>
    </number>
    <user>
      <string>xristos</string>
    </user>
    <title>
      <string>libpcap</string>
    </title>
    <contents>
      <string>(defclass pcap ()
  ((pcap_t
    :initform nil
    :documentation &quot;Foreign pointer to pcap structure.&quot;)
   (callback
    :initform nil
    :documentation &quot;Foreign callback for packet handler.&quot;)
   (interface
    :initarg :interface
    :reader pcap-interface
    :initform nil
    :documentation &quot;Interface to capture packets from.&quot;)
   (snaplen
    :initarg :snaplen
    :reader pcap-snaplen
    :initform 1600 ; Same as tcpdump, 68 enough for headers
    :documentation &quot;How many bytes to capture per packet received.&quot;)
   (promisc
    :initarg :promisc
    :reader pcap-promisc
    :initform nil
    :documentation &quot;True if capturing in promiscuous mode.&quot;)
   (timeout
    :initarg :timeout
    :reader pcap-timeout
    :initform 1
    :documentation &quot;Read timeout in milliseconds. 0 will wait forever.&quot;)
   (datalink
    :reader pcap-datalink
    :initform nil
    :documentation &quot;Datalink protocol for this device.&quot;)
   (buffer
    :reader pcap-buffer
    :initform nil
    :documentation &quot;Packet buffer to hold captured packets.&quot;)
   (handler
    :initform nil
    :documentation &quot;Lisp packet handler for capture. Called by callback.&quot;)
   (live
    :reader pcap-live
    :initform nil
    :documentation &quot;Packet capture object is live.&quot;)))


(defmethod initialize-instance :after ((cap pcap) &amp;key)
  (with-slots (pcap_t callback interface snaplen promisc timeout datalink
                      buffer handler live)
      cap
    (with-error-buffer (eb)
      ;; No interface given, call lookupdev to get one
      (when (null interface)
        (let ((res (%pcap-lookupdev eb)))
          (when (null res)
            (error 'network-interface-error :text
                   (error-buffer-to-lisp eb)))
          (setf interface res)))
      (clear-error-buffer eb)
      ;; Open interface for capture
      (let* ((res (%pcap-open-live interface snaplen promisc timeout eb))
             (ebtext (error-buffer-to-lisp eb)))
        (when (null-pointer-p res)
          (error 'network-interface-error :text ebtext))
        (setf pcap_t res)
        ;; Supported datalink test
        (let ((dlink (rassoc (%pcap-datalink pcap_t) *supported-datalinks*)))
          (if (not dlink)
              (progn
                (%pcap-close pcap_t)
                (error 'network-interface-error :text
                       &quot;Unsupported datalink protocol&quot;))
              (setf datalink (car dlink))))
        (when (not (= 0 (length ebtext)))
          (warn ebtext))
        (setf buffer (make-array snaplen :element-type
                                        '(unsigned-byte 8)))
        (setf callback 
                        (defcallback pcap-handler :void
                            ((user :pointer) (pkthdr :pointer)
                             (bytes :pointer))
                          (with-foreign-slots ((caplen len) pkthdr pcap_pkthdr)
                            ;; Copy packet data from C to lisp
                            #+:sbcl
                            (let ((dst (sb-sys:vector-sap buffer)))
                              (%memcpy dst bytes caplen))
                            #-:sbcl
                            (loop for i from 0 to (- caplen 1) do
                                 (setf (aref buffer i)
                                       (mem-aref bytes :uint8 i)))
                            ;; Call lisp packet handler
                            (funcall handler caplen len))))
        (setf live t)))))</string>
    </contents>
    <universal-time>
      <integer>3405181903</integer>
    </universal-time>
    <channel>
      <string>#lispcafe</string>
    </channel>
    <colorization-mode>
      <string></string>
    </colorization-mode>
    <maybe-spam>
      <null/>
    </maybe-spam>
    <is-unicode>
      <null/>
    </is-unicode>
  </paste>
</paste-with-annotations>