2020-01-31 00:45:14 +00:00
|
|
|
#lang racket
|
|
|
|
(provide (all-defined-out))
|
|
|
|
|
|
|
|
(require json
|
|
|
|
"iputil.rkt")
|
|
|
|
|
2020-01-31 00:47:32 +00:00
|
|
|
(module+ test
|
|
|
|
(require rackunit))
|
|
|
|
|
2020-01-31 00:45:14 +00:00
|
|
|
;; src, dst : IP
|
|
|
|
;; data : Any
|
|
|
|
(struct msg [src dst]
|
|
|
|
#:transparent)
|
|
|
|
|
2020-02-01 04:13:49 +00:00
|
|
|
(struct route [nexthop subnet pref self-origin? as-path origin]
|
|
|
|
;; nexthop : IP
|
2020-01-31 00:45:14 +00:00
|
|
|
;; subnet : Subnet
|
|
|
|
;; pref : Int
|
|
|
|
;; self-origin? : Boolean
|
|
|
|
;; as-path : [Listof Int]
|
|
|
|
;; origin : (U 'IGP 'EGP 'UNK)
|
|
|
|
#:transparent)
|
|
|
|
|
2020-02-01 02:31:03 +00:00
|
|
|
(struct msg:update msg [route]
|
|
|
|
;; route : Route
|
|
|
|
#:transparent)
|
|
|
|
|
2020-01-31 00:45:14 +00:00
|
|
|
(struct msg:revoke msg [networks]
|
|
|
|
;; networks : [Listof Subnet]
|
|
|
|
#:transparent)
|
|
|
|
|
|
|
|
(struct msg:data msg [stuff]
|
|
|
|
;; stuff : Any
|
|
|
|
#:transparent)
|
|
|
|
|
|
|
|
(struct msg:no-route msg []
|
|
|
|
#:transparent)
|
|
|
|
|
|
|
|
(struct msg:dump msg []
|
|
|
|
#:transparent)
|
|
|
|
|
|
|
|
(struct msg:table msg [networks]
|
|
|
|
;; networks : [Listof [List Subnet IP]]
|
|
|
|
#:transparent)
|
|
|
|
|
|
|
|
;; Any -> Msg
|
|
|
|
(define (jsexpr->msg j)
|
|
|
|
(define src (string->ip (hash-ref j 'src)))
|
|
|
|
(define dst (string->ip (hash-ref j 'dst)))
|
|
|
|
(define type (hash-ref j 'type))
|
|
|
|
(define data (hash-ref j 'msg))
|
|
|
|
|
|
|
|
(define (hash->subnet h)
|
|
|
|
(subnet (string->ip (hash-ref h 'network))
|
|
|
|
(ip-netmask (string->ip (hash-ref h 'netmask)))))
|
|
|
|
|
|
|
|
(match type
|
|
|
|
["update"
|
|
|
|
(msg:update src dst
|
2020-02-01 04:13:49 +00:00
|
|
|
(route src
|
|
|
|
(hash->subnet data)
|
2020-02-01 02:31:03 +00:00
|
|
|
(hash-ref data 'localpref)
|
|
|
|
(hash-ref data 'selfOrigin)
|
|
|
|
(hash-ref data 'ASPath)
|
|
|
|
(string->symbol (hash-ref data 'origin))))]
|
2020-01-31 00:45:14 +00:00
|
|
|
["revoke"
|
|
|
|
(msg:revoke src dst
|
|
|
|
(map hash->subnet data))]
|
|
|
|
["data"
|
|
|
|
(msg:data src dst
|
|
|
|
data)]
|
|
|
|
["no route"
|
|
|
|
(msg:no-route src dst)]
|
|
|
|
["dump"
|
|
|
|
(msg:dump src dst)]
|
|
|
|
["table"
|
|
|
|
(msg:table src dst
|
|
|
|
(map (λ (h) (list (hash->subnet h)
|
|
|
|
(string->ip (hash-ref h 'peer))))
|
|
|
|
data))]))
|
|
|
|
|
|
|
|
;; Bytes -> Msg
|
|
|
|
(define (bytes->msg bs)
|
2020-01-31 00:49:18 +00:00
|
|
|
(jsexpr->msg (bytes->jsexpr bs)))
|
2020-01-31 00:45:14 +00:00
|
|
|
|
2020-02-01 04:30:38 +00:00
|
|
|
;; Msg -> String
|
|
|
|
(define (msg-type m)
|
|
|
|
(cond
|
|
|
|
[(msg:update? m) "update"]
|
|
|
|
[(msg:revoke? m) "revoke"]
|
|
|
|
[(msg:data? m) "data"]
|
|
|
|
[(msg:no-route? m) "no route"]
|
|
|
|
[(msg:dump? m) "dump"]
|
|
|
|
[(msg:table? m) "table"]))
|
|
|
|
|
|
|
|
;; Msg -> Any
|
|
|
|
(define (msg->jsexpr msg)
|
|
|
|
(hash 'src (ip->string (msg-src msg))
|
|
|
|
'dst (ip->string (msg-dst msg))
|
|
|
|
'type (msg-type msg)
|
|
|
|
'msg (match msg
|
|
|
|
[(msg:data _ _ data) data]
|
|
|
|
[(msg:no-route _ _) (hash)]
|
2020-02-01 04:41:10 +00:00
|
|
|
|
|
|
|
[(msg:update _ _
|
|
|
|
(route _
|
|
|
|
net
|
|
|
|
pref
|
|
|
|
self-orig?
|
|
|
|
as
|
|
|
|
org))
|
|
|
|
(hash 'network (ip->string (subnet-ip net))
|
|
|
|
'netmask (ip->string (netmask-ip (subnet-mask net)))
|
|
|
|
'localpref pref
|
|
|
|
'selfOrigin self-orig?
|
|
|
|
'ASPath as
|
|
|
|
'origin (symbol->string org))]
|
|
|
|
|
2020-02-02 03:21:25 +00:00
|
|
|
[(msg:table _ _ networks)
|
|
|
|
(for/list ([entry (in-list networks)])
|
|
|
|
(hash 'network (ip->string (subnet-ip (first entry)))
|
|
|
|
'netmask (ip->string (netmask-ip (subnet-mask (first entry))))
|
|
|
|
'peer (ip->string (second entry))))]
|
|
|
|
|
2020-02-01 04:30:38 +00:00
|
|
|
[_ (error 'msg->jsexpr
|
|
|
|
(format "unimplemented ~a" (msg-type msg)))])))
|
|
|
|
|
|
|
|
;; Msg -> Bytes
|
|
|
|
(define (msg->bytes msg)
|
|
|
|
(jsexpr->bytes (msg->jsexpr msg)))
|
|
|
|
|
2020-01-31 00:45:14 +00:00
|
|
|
(module+ test
|
2020-02-01 04:30:38 +00:00
|
|
|
(check-equal? (msg->jsexpr
|
|
|
|
(msg:update
|
|
|
|
(string->ip "1.2.3.4")
|
|
|
|
(string->ip "1.2.3.7")
|
2020-02-01 04:41:10 +00:00
|
|
|
(route (string->ip "1.2.3.4")
|
|
|
|
(subnet (string->ip "1.2.3.5") 25)
|
2020-02-01 04:30:38 +00:00
|
|
|
100
|
|
|
|
#t
|
|
|
|
'(1 2)
|
|
|
|
'UNK)))
|
|
|
|
(hash 'src "1.2.3.4"
|
|
|
|
'dst "1.2.3.7"
|
|
|
|
'type "update"
|
|
|
|
'msg (hash 'network "1.2.3.5"
|
|
|
|
'netmask "255.255.255.128"
|
|
|
|
'localpref 100
|
|
|
|
'selfOrigin #t
|
|
|
|
'ASPath '(1 2)
|
|
|
|
'origin "UNK")))
|
|
|
|
|
2020-01-31 00:47:32 +00:00
|
|
|
(check-equal? (jsexpr->msg
|
|
|
|
(hash 'src "1.2.3.4"
|
|
|
|
'dst "1.2.3.7"
|
|
|
|
'type "update"
|
|
|
|
'msg (hash 'network "1.2.3.5"
|
|
|
|
'netmask "255.255.255.128"
|
|
|
|
'localpref 100
|
|
|
|
'selfOrigin #t
|
|
|
|
'ASPath '(1 2)
|
|
|
|
'origin "UNK")))
|
|
|
|
(msg:update
|
|
|
|
(string->ip "1.2.3.4")
|
|
|
|
(string->ip "1.2.3.7")
|
2020-02-01 04:13:49 +00:00
|
|
|
(route (string->ip "1.2.3.4")
|
2020-02-01 04:41:10 +00:00
|
|
|
(subnet (string->ip "1.2.3.5") 25)
|
2020-02-01 02:31:03 +00:00
|
|
|
100
|
|
|
|
#t
|
|
|
|
'(1 2)
|
|
|
|
'UNK))))
|