Update of /project/snmp1/cvsroot/snmp1 In directory clnet:/tmp/cvs-serv11926
Modified Files: ber.lisp snmp.lisp Log Message: Documentations strings for all functions
--- /project/snmp1/cvsroot/snmp1/ber.lisp 2007/01/20 15:55:08 1.2 +++ /project/snmp1/cvsroot/snmp1/ber.lisp 2007/01/21 02:25:02 1.3 @@ -53,22 +53,31 @@ (loop for (id value) in tag-list do (setf (gethash id tag->octet) value) (setf (gethash value octet->tag) id)) - (defun encode-tag (tag) (gethash tag tag->octet)) - (defun decode-tag (octet) (gethash octet octet->tag)) + (defun encode-tag (tag) + "Convert a symbolic tag value to an octet" + (gethash tag tag->octet)) + (defun decode-tag (octet) + "Convert a tag octest to its symbolic value" + (gethash octet octet->tag)) ) (defun container-type-p (tag) + "Returns true if the tag is one of the container tags" (member tag (list :sequence :get :getnext :response :set :trap)))
(defun integer-type-p (tag) + "Returns true if the tag is one of the ineger type tags" (member tag (list :integer :counter :gauge :timeticks)))
(defun octet-string-type-p (tag) + "Returns true if tag is one of the tags that encode octet strings" (member tag (list :octet-string :opaque :ipaddress)))
(defun object-identifier-type-p (tag) + "Return true if the tag is :object-identitier" (member tag (list :object-identifier)))
(defun null-type-p (tag) + "Returns true if the tag is :null" (member tag (list :null)))
(defun decode-length (from-array pos) @@ -163,7 +172,10 @@
(defun ber-decode-object-identifier-value (buffer start end) - ;; return array of subidentifiers + "Decodes part of the octet string array and returns an array of subidentifiers +Each subidentifier can be one or more octets. Each octet that has its seventh +bit set, continues to the next octet. The first octet is special, as it +ecodes the two first subidentifiers." (let ((result (make-array 20 :adjustable t :fill-pointer 0))) ;; first and second oid are special
@@ -191,7 +203,10 @@ result))
(defun ber-encode-integer-value (value to-array) - "Push value as integer" + "Push value as integer to the tail oof the array. Every bit of +each octet is used, but we must make sure that the first octet +is less than 128 for positive numbers, as the 7.th bit in the +first octet signals a negative number" (let ((numbytes (ceiling (1+ (integer-length value)) 8))) (loop for pos from (1- numbytes) downto 0 do (vector-push-extend (ldb (byte 8 (* pos 8)) value) to-array)) @@ -199,13 +214,18 @@
(defun ber-encode-octet-string-value (value to-array) - "Push value as octet-string" + "Push value as octet-string. If the value is a string, +the result mitht be longer, depending on the current external +format" (when (typep value 'string) (setf value (string-to-octets value))) (loop for octet across value do (vector-push-extend octet to-array)) to-array)
(defun ber-encode-object-identifier-value (in-value to-array) - "Push value as octet-string Return to-array" + "Push value as octet-string Return to-array. The first two +subidentifers go into one octet. Most other subidentifiers go into +one octet each. If a subidentifier is greater than 127, several +octets are usec" (let ((value (if (stringp in-value) (oid-string-to-oid in-value) in-value))) ;; first and second subidentifier compressed into one octet (vector-push-extend (+ (* 40 (aref value 0)) (aref value 1)) to-array) @@ -223,14 +243,17 @@
(defun ber-encode (what &optional buffer) - ;; always one tag, but may be a container + "Encode a single tag and value, or recursively encode a sequence. +Example of input is '(:sequence (:object-identifier #(1 3 4 5 6)) (:integer 42)) +Normally, this function is called on the complete snmp message, which is such +sequence" (unless buffer (setf buffer (make-array 50 :element-type '(unsigned-byte 8) :fill-pointer 0))) (let ((tag (first what)) (encoded-tag (encode-tag (first what))) (start-pos (fill-pointer buffer))) (vector-push-extend encoded-tag buffer) ;; unfortunately we don't know length of length at this time. - ;; Guess length of length is 1, set length to 0 for now + ;; Guess length of length is 1, reserve an octet by pushing a zero to the buffer. (vector-push-extend 0 buffer) (cond ((container-type-p tag) @@ -243,9 +266,9 @@ ;; if length is 127 or less, we can place it directly in the reserved octet (if (< length-of-value 128) (setf (aref buffer (+ start-pos 1)) length-of-value) + ;; our guess was wrong, now we have to move the value some places to the right (let ((length-of-length (ceiling (1+ (integer-length length-of-value)) 8))) (setf (aref buffer (+ start-pos 1)) (logior #b10000000 (ldb (byte 8 0) length-of-length ))) - ;; now we have to move the value some places to the right (adjust-array buffer #1=(+ length-of-length (fill-pointer buffer)) :fill-pointer #1#) (loop for to-pos from (1- (fill-pointer buffer)) downto (+ start-pos length-of-length 2) @@ -260,8 +283,10 @@ buffer)
(defun ber-decode (buffer &optional (input-start 0) input-end (level 0)) - ;; the buffer is a single tag, possibly a sequence containing one or more tags - ;; resurn the buffer in list form and length of buffer that is used as second value + "the buffer is an octet string vector received from the net. It normally start with +a sequence containing the rest of the message. When a sequence tag is found, the +function calls itself recursively to decode the contents. +Resurn the buffer in list form and length of buffer that is used as second value" (when (null buffer) (return-from ber-decode)) (unless input-end (setf input-end (length buffer))) (let* ((start input-start) --- /project/snmp1/cvsroot/snmp1/snmp.lisp 2007/01/20 15:55:08 1.2 +++ /project/snmp1/cvsroot/snmp1/snmp.lisp 2007/01/21 02:25:03 1.3 @@ -18,19 +18,35 @@ |# (in-package "SNMP1")
-(defparameter *community* "public") -(defparameter *agent-ip* #(127 0 0 1)) -(defparameter *agent-port* 161) -(defparameter *wait* 1) -(defparameter *retries* 3) +(defparameter *community* "public" + "The default community string used. Assign your own value to this dynamic +variable before you call any snmp functions") +(defparameter *agent-ip* #(127 0 0 1) + "The default ip address of the snmp agent you want to communicate with. +Assign your own value to this before you call any of the snmp functions. +The ip-address can be in any form; dotted quad, integer array or a single +number") +(defparameter *agent-port* 161 + "The default udp port where the agent listens for incoming calls. Change this +if the snmp-agent you try to communicate with listens on another port. Normally +the agent listens on the default port") +(defparameter *wait* 1 + "This is the number of seconds we wait for an snmp agent to answer before +we try again or give up. The time can also be specified with a float.") +(defparameter *retries* 3 + "The maximum number of times we retry a communication with the agent")
(defun ip-string-to-ip-octets (dotted-quad) + "Conversion of ip, example 127.0.0.1 as string to #(127 0 0 1). There +is also a from any form to ip octets conversion function" (let ((list (split-sequence:split-sequence #. dotted-quad)) (vector (make-array 4))) (loop for n from 0 for component in list do (setf (aref vector n) (parse-integer component))) vector))
(defun ip-string-to-numeric (dotted-quad) + "Convert for example 80.68.86.115 as string to a single integer 1346655859. Did +you know that you can paste this integer directly into a web browser?" (let ((octets (ip-string-to-ip-octets dotted-quad)) (ip-numeric 0)) (loop for octet across octets do @@ -38,26 +54,32 @@ ip-numeric))
(defun ip-numeric-to-ip-octets (ip-numeric) + "Convert an ip address expressed as a single intger, to its +octet array form" (apply #'vector (reverse (loop for x from 1 to 4 collect (ldb (byte 8 0) ip-numeric) do (setf ip-numeric (truncate ip-numeric 256))))))
(defun ip-octets-to-ip-string (ip-octets) + "Convert an ip adress, example #(127 0 0 1) to its strign form 127.0.0.1" (format nil "~{~d.~d.~d.~d~}" (loop for o across ip-octets collect o)))
(defun ip-numeric (ip-some-form) + "Convert an ip adress in any of the three forms to a single integer" (typecase ip-some-form (simple-vector (ip-string-to-numeric (ip-octets-to-ip-string ip-some-form))) (string (ip-string-to-numeric ip-some-form)) (otherwise ip-some-form)))
(defun ip-octets (ip-some-form) + "Convert an ip adress in any of the three forms to an array of four integers" (typecase ip-some-form (integer (ip-numeric-to-ip-octets ip-some-form)) (string (ip-string-to-ip-octets ip-some-form)) (otherwise ip-some-form)))
(defun ip-string (ip-some-form) + "Convert an ip adress in any of the three forms to the dotted quad string form" (typecase ip-some-form (simple-vector (ip-octets-to-ip-string ip-some-form)) (integer (ip-octets-to-ip-string (ip-numeric-to-ip-octets ip-some-form))) @@ -75,12 +97,17 @@
(defun pdu-from-message (decoded-message) + "Extract the Protocol Data Unit from a decoded message" (fourth decoded-message))
(defun value-from-encoding (encoding) + "Extract the value from a single encoding, example (:integer 5) produces 5" (second encoding))
(defun request-id (decoded-message) + "Extract the request identifier from a message. We can validate the integrity +of a response by checking that the recieved request-id is the same we used +in he corresponding get/set" (value-from-encoding (second (pdu-from-message decoded-message))))
;; (defun nreplace-request-id (new-value decoded-message) @@ -91,9 +118,12 @@ ;; )
(defun varbind-list% (decoded-pdu) + "Return the sequence containing all the variable bindings. Note that the input +here is the pdu part of the message, not the whole message" (fifth decoded-pdu))
(defun varbind-list (message) + "Return the sequence containing all the variable bindings from a message" (varbind-list% (pdu-from-message message)))
;; (defun oid-and-value (varbind) @@ -108,12 +138,14 @@ (push :sequence vars)))
(defun varbind-to-triple (varbind) + "Reduce a varbind sequence to a list of oid, type and value" (let ((requested-oid (second (second varbind))) (tag (first (third varbind))) (value (second (third varbind)))) (list requested-oid tag value)))
(defun triples-from-decoded-message (decoded-message) + "Return the varbinds in a message as a list of oid, type and value triples" (let ((varbind-list (varbind-list decoded-message))) (loop for pair in (cdr varbind-list) collect (varbind-to-triple pair))))
@@ -124,7 +156,8 @@ ;; ))
(defun udp-send-and-receive (host port timeout repetitions message) - "send one pqcket and receive one packet" + "send one pqcket and receive one packet. Do timeouts and retries. +This function is specific to sbcl" (let ((socket (make-instance 'sb-bsd-sockets:inet-socket :protocol :udp :type :datagram)) result (recvbuf (make-array 2000 :element-type '(unsigned-byte 8)))) @@ -203,6 +236,8 @@ (t oid)))
(defun snmp-get- (oid) + "Request a single value from the agent, but do not transform the +result. Resultt is a triple of object identifier, type and value" (let ((triple-list (snmp-get-many- (list (oid-basic-form oid))))) (first triple-list)))
@@ -281,6 +316,9 @@
(defun translate-triple (triple) + "Translate object identifiers in the triple to its symbolic form, +translacte octet strings to strings, and enumerator integers to +symbolic form" (let ((translated-oid (symbolic-oid-from-oid (first triple))) (tag (second triple)) (value (third triple))) @@ -306,10 +344,18 @@
(defun snmp-get-many (oid-list) + "Request one or more values from the agent, parmater is a list of object +identifiers" (let ((triple-list (snmp-get-many- (mapcar #'oid-basic-form oid-list)))) (loop for triple in triple-list collect (translate-triple triple))))
(defun snmp-get-many-safe- (oid-list identifying-oid in-identifier) + "This version of snmp-get takes a list of oid's as ususal, but prepends +the list with the oid in the identifying-oid parameter, and thecks the +returned value with in-identifier parameter. The identifying oid can be +the serial number of the agent device. If the serial number is not as +expected, nil is returned. This version of the function does not translate +the result" (let ((result+identifier (snmp-get-many- (mapcar #'oid-basic-form (cons identifying-oid oid-list))))) (let* ((read-identifier-triple (translate-triple (first result+identifier))) (result (rest result+identifier))) @@ -317,6 +363,11 @@ result))))
(defun snmp-get-many-safe (oid-list identifying-oid in-identifier) + "This version of snmp-get takes a list of oid's as ususal, but prepends +the list with the oid in the identifying-oid parameter, and thecks the +returned value with in-identifier parameter. The identifying oid can be +the serial number of the agent device. If the serial number is not as +expected, nil is returned" (let ((result+identifier (snmp-get-many- (mapcar #'oid-basic-form (cons identifying-oid oid-list))))) (let ((read-identifier-triple (translate-triple (first result+identifier))) (result (rest result+identifier)))