Random cleanup.
[small-scheme-stack.git] / icmp.scm
blobcb68dd972a8a782226b37bee758c8b2b6e7df3f2
1 ;;;; Lysiane Bouchard - Vincent St-Amour
2 ;;;; icmp.scm
4 ;; ICMP constants
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)
25                                                     ip-header-length
26                                                     icmp-header-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
38 ;; IP datagram)
39 (define (compute-icmp-checksum)
40   (pkt-checksum icmp-header
41                 (+ ip-header (pkt-ref-2 ip-length))
42                 0))
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)
67                     icmp-checksum
68                     compute-icmp-checksum
69                     (+ ip-header-length data-amount icmp-header-length)))