summaryrefslogtreecommitdiff
path: root/src/bgpstore/bgpstore.lisp
blob: eb4fc2a9d114657d05a13f45be78f3c18d91aed2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*-

(in-package :bgp-logger)

(defun xml-top-elem-from-octets (xml-octets)
  (dom:document-element
   (cxml:parse xml-octets (cxml-dom:make-dom-builder))))

(defun new-entries (top-elem)
  "Return BGP-MESSAGE's, one per prefix mentioned in TOP-ELEM.
TOP-ELEM is an XML document element."
  ;; We assume that top-elem is "BGP_MESSAGE".
  ;(print (describe top-elem))
  (let ((updates (dom:get-elements-by-tag-name top-elem "UPDATE"))
	(new-elements nil))
    (when (> (length updates) 0)
      (let ((update (aref updates 0)))
	(when (string= (dom:tag-name (dom:parent-node update)) "ASCII_MSG")
	  (let ((templ (make-instance 'bgp-message))
		(new-prefs nil)
		(octet-msgs (dom:get-elements-by-tag-name top-elem "OCTET_MSG"))
		(prefixes (dom:get-elements-by-tag-name top-elem "PREFIX"))
		(time (aref (dom:get-elements-by-tag-name top-elem "TIME") 0)))

	    ;; Populate new-prefs.
	    (when (> (length prefixes) 0)
	      (setf new-prefs
		    (concatenate
		     'list
		     new-elements
		     (map 'list
			  (lambda (p)
			    (list (dom:data (aref (dom:child-nodes p) 0))
				  (dom:get-attribute p "label")))
			  prefixes))))

	    ;; TIMESTAMP and PRECISION_TIME --> template.
	    (let ((ts (aref (dom:get-elements-by-tag-name time "TIMESTAMP") 0))
		  (pt (aref (dom:get-elements-by-tag-name time "PRECISION_TIME") 0)))
	      (setf (timestamp templ)
		    (dom:data (aref (dom:child-nodes ts) 0)))
	      (setf (precision-time templ)
		    (dom:data (aref (dom:child-nodes pt) 0))))

	    ;; AS-PATH --> template.  Note that we want AS_PATH->AS
	    ;; only, to avoid getting COMMUNITY->AS.
	    (setf (path templ)
		  (let ((as-paths (dom:get-elements-by-tag-name update
								"AS_PATH")))
		    (if (= 0 (length as-paths))
			"{}"
			(let ((str "{"))
			  (map nil (lambda (node)
				     (let ((as (dom:data (aref (dom:child-nodes node) 0))))
				       (setf str (concatenate 'string
							      str
							      (format nil "~A," as)))))
			       (dom:child-nodes (aref as-paths 0)))
			  (concatenate 'string
				       (subseq str 0 (- (length str) 1))
				       "}")))))

	    ;; NEXT_HOP --> template.
	    (setf (nexthop templ)
		  (let ((nexthops (dom:get-elements-by-tag-name
				   update "NEXT_HOP")))
		    (if (= 0 (length nexthops))
			"0.0.0.0"
			(dom:data (aref (dom:child-nodes (aref nexthops 0)) 0)))))

	    ;; OCTETS --> template.
	    (when (> (length octet-msgs) 0)
	      (let* ((oct (aref (dom:get-elements-by-tag-name
				 (aref octet-msgs 0) "OCTETS") 0))
		     (txt (aref (dom:child-nodes oct) 0)))
		(setf (bgp-octets templ) (dom:data txt))))

	    ;; Create new elements from new-prefs and the template.
	    ;(format t "templ: ~A~%" (describe templ))
	    ;(format t "new-prefs: ~A~%" new-prefs)
	    (dolist (p new-prefs)
	      (push (new-bgp-message templ p) new-elements))))))
    new-elements))

(defun new-entry-klacks (xml-doc)
  "Return a fresh BGP-MESSAGE built from XML-DOC (array of unsigned bytes)."
  (let ((s (cxml:make-source xml-doc))
	(e (make-instance 'bgp-message))
	(cur-name nil))
    (do ((key (klacks:peek s) (klacks:peek s)))
	((null key) e)
      (case key
	(:start-element (setf cur-name (klacks:current-qname s)))
	(:end-element (setf cur-name nil))
	(:characters (let ((txt (klacks:current-characters s)))
		       (unless (or (string= cur-name "OCTET_MSG"))
			 (setf (slot-value e (intern cur-name)) txt)))))
      (klacks:consume s))))

(defun marker (mark)
  (format t mark)
  (force-output))

(defun start-bgpstore (host port)
  (with-connection *db-spec* 
    (let ((reader (new-reader host port))
	  (count 0))
      (marker (format nil "~A: bgpstore started "
		      (iso-date (get-universal-time) t)))
      (do ((e (next-xml-blurb reader "BGP_MESSAGE")
	      (next-xml-blurb reader "BGP_MESSAGE")))
	  ((null e))
	(dolist (obj (new-entries (xml-top-elem-from-octets e)))
	  (insert-dao obj)
	  (incf count)
	  (if (= 0 (mod count 10000))
	      (marker (format nil "~%~A: ~A "
			      (iso-date (get-universal-time) t)
			      count))
	      (if (= 0 (mod count 1000))
		  (marker "*")
		  (if (= 0 (mod count 100))
		      (marker "."))))))
      (close-reader))))

(defun stop-bgpstore ())

;;;;