1 ;;;; Lysiane Bouchard - Vincent St-Amour
5 (define icmp-ip-header-bad '#u8(12 0))
6 (define icmp-port-unreachable '#u8(3 3))
7 (define icmp-protocol-unreachable '#u8(3 2))
8 (define icmp-time-exceeded '#u8(11 0))
9 (define icmp-parameter-problem '#u8(12 0))
10 (define icmp-echo-request '#u8(8 0))
11 (define icmp-echo-reply '#u8(0 0))
12 (define icmp-address-mask-request '#u8(17 0))
13 (define icmp-address-mask-reply '#u8(18 0))
14 (define icmp-host-precedence-violation '#u8(3 14))
17 ;; called when an icmp datagram is received
18 (define (icmp-pkt-in) ;; TODO we do have a pattern for protocols, do some checks, then dispatch to an upper level function. the generic reception functions were a pita, maybe try a macro ?
19 ;; TODO maybe make sure it's for one of our addresses ?
20 (if (= 65535 (compute-icmp-checksum)) ; checksum ok
21 ;; dispatch. see eth.scm for justification of the repetition
22 (cond ((u8vector-equal-field? pkt icmp-type
23 icmp-echo-request 0 2)
24 (icmp-encapsulation icmp-echo-reply (- (pkt-ref-2 ip-length)
27 ;; TODO if we have a pkt-len var, we wouldn't have to calculate the length like this, it would simply remain unchanged
28 ((u8vector-equal-field? pkt icmp-type
29 icmp-address-mask-request 0 2)
30 (u8vector-copy! my-address-mask 0 pkt icmp-data 4)
31 (icmp-encapsulation icmp-address-mask-reply 4))
32 (else #f)))) ;; TODO remove ?
33 ;; TODO maybe have some better error handling
34 ;; TODO do we accept any other requests ?
35 ;; TODO send error cases to applications, as special tokens when they do the next operation
37 ;; this checksum covers the whole icmp datagram (which ends at the end of the
39 (define (compute-icmp-checksum)
40 (pkt-checksum icmp-header
41 (+ ip-header (pkt-ref-2 ip-length))
45 (define (icmp-send-ip-header-bad-error) ; TODO wasn't checked, and I can't see it in the rfc
46 (u8vector-copy! pkt ip-header pkt icmp-data 20) ; copy IP header
47 (icmp-encapsulation icmp-ip-header-bad 20)) ;; TODO used only once, inline ?
49 ;; sets up the packet in case of "unreachable" error, or for a time-exceeded,
50 ;; since it has the same structure
51 (define (icmp-unreachable type)
52 ;; copy IP headers first 20 bytes, and first 8 bytes of data
53 (u8vector-copy! pkt udp-header pkt (+ icmp-data 20) 8)
54 (u8vector-copy! pkt ip-header pkt icmp-data 20) ; copy IP header
55 (integer->pkt 0 icmp-options 4) ; set the 4 optional bytes to 0
56 (icmp-encapsulation type (+ 20 8)))
59 ;; data-amount is excluding icmp header
60 (define (icmp-encapsulation key data-amount)
61 (u8vector-copy! key 0 pkt icmp-type 2)
62 (integer->pkt 0 icmp-checksum 2)
63 ;; unlike other protocols, this change is necessary, since ICMP packets can
64 ;; be sent in response to other protocols
65 (u8vector-set! pkt ip-protocol ip-protocol-icmp)
66 (ip-encapsulation (u8vector-ref-field pkt ip-source-ip 4)
69 (+ ip-header-length data-amount icmp-header-length)))