Skip to content

Commit 0b8d3ce

Browse files
committed
Merge pull request #33 from fugitifduck/master
Add IPv6 support
2 parents d358f4e + 943dbdd commit 0b8d3ce

File tree

5 files changed

+76
-2
lines changed

5 files changed

+76
-2
lines changed

lib/Packet.ml

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ let get_byte32 (n : Int32.t) (i : int) : int =
3030
to_int (logand 0xFFl (shift_right_logical n (8 * i)))
3131

3232
let get_byte (n:int64) (i:int) : int =
33-
if i < 0 || i > 5 then
33+
if i < 0 || i > 7 then
3434
raise (Invalid_argument "Int64.get_byte index out of range");
3535
Int64.to_int (Int64.logand 0xFFL (Int64.shift_right_logical n (8 * i)))
3636

@@ -58,6 +58,13 @@ let string_of_ip (ip : Int32.t) : string =
5858
Format.sprintf "%d.%d.%d.%d" (get_byte32 ip 3) (get_byte32 ip 2)
5959
(get_byte32 ip 1) (get_byte32 ip 0)
6060

61+
let string_of_ipv6 ((ip1,ip2) : int64*int64) : string =
62+
Format.sprintf "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x"
63+
(get_byte ip1 7) (get_byte ip1 6) (get_byte ip1 5) (get_byte ip1 4)
64+
(get_byte ip1 3) (get_byte ip1 2) (get_byte ip1 1) (get_byte ip1 0)
65+
(get_byte ip2 7) (get_byte ip2 6) (get_byte ip2 5) (get_byte ip2 4)
66+
(get_byte ip2 3) (get_byte ip2 2) (get_byte ip2 1) (get_byte ip2 0)
67+
6168
let string_of_mac (x:int64) : string =
6269
Format.sprintf "%02x:%02x:%02x:%02x:%02x:%02x"
6370
(get_byte x 5) (get_byte x 4) (get_byte x 3)
@@ -109,6 +116,8 @@ type nwProto = int8 with sexp
109116

110117
type nwTos = int8 with sexp
111118

119+
type ipv6Addr = int64*int64 with sexp
120+
112121
type tpPort = int16 with sexp
113122

114123
let mk_pseudo_header (src : nwAddr) (dst : nwAddr) (proto : int) (len : int) =
@@ -1376,3 +1385,27 @@ let mac_of_string (s : string) : dlAddr =
13761385
(logor (shift_left (parse_byte (List.nth bytes 3)) 16)
13771386
(logor (shift_left (parse_byte (List.nth bytes 4)) 8)
13781387
(parse_byte (List.nth bytes 5)))))))
1388+
1389+
let ipv6_of_string (s : string) : ipv6Addr =
1390+
let bytes = Str.split (Str.regexp ":") s in
1391+
let bytes_len = List.length bytes in
1392+
let rec fill_with_0 n =
1393+
if n = 0 then ["0"]
1394+
else "0"::(fill_with_0 (n-1)) in
1395+
let rec fill_bytes bytes =
1396+
match bytes with
1397+
| [] -> []
1398+
| ""::q -> List.append (fill_with_0 (8-bytes_len)) q
1399+
| t::q -> t::(fill_bytes q) in
1400+
let bytes = fill_bytes bytes in
1401+
let parse_byte str = Int64.of_string ("0x" ^ str) in
1402+
let open Int64 in
1403+
(logor (shift_left (parse_byte (List.nth bytes 0)) 48)
1404+
(logor (shift_left (parse_byte (List.nth bytes 1)) 32)
1405+
(logor (shift_left (parse_byte (List.nth bytes 2)) 16)
1406+
(parse_byte (List.nth bytes 3))))),
1407+
(logor (shift_left (parse_byte (List.nth bytes 4)) 48)
1408+
(logor (shift_left (parse_byte (List.nth bytes 5)) 32)
1409+
(logor (shift_left (parse_byte (List.nth bytes 6)) 16)
1410+
(parse_byte (List.nth bytes 7)))))
1411+

lib/Packet.mli

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ type nwProto = int8 with sexp
5151
(** [nwTos] is the type of IPv4 types of service. *)
5252
type nwTos = int8 with sexp
5353

54+
(** [ipv6Addr] is the type of IPv6 addresses. *)
55+
type ipv6Addr = int64*int64 with sexp
56+
5457
(** [tpPort] is the type of transport protocol ports. *)
5558
type tpPort = int16 with sexp
5659

@@ -376,6 +379,12 @@ val string_of_nwProto : nwProto -> string
376379
(** [string_of_nwTos t] pretty-prints an IPv4 type of service. *)
377380
val string_of_nwTos : nwTos -> string
378381

382+
(** [string_of_ipv6 t] pretty-prints an IPv6 address. **)
383+
val string_of_ipv6 : ipv6Addr -> string
384+
385+
(** [string_of_ipv6 t] Converts a colon-separated IPv6 address to ipv6Addr. **)
386+
val ipv6_of_string : string -> ipv6Addr
387+
379388
(** [string_of_tpPort p] pretty-prints a transport protocol port number. *)
380389
val string_of_tpPort : tpPort -> string
381390

quickcheck/Arbitrary_Base.ml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
open QuickCheck
22
module Gen = QuickCheck_gen
33

4+
type int128 = int64 * int64
5+
46
(* arbitrary instance for usigned integers, using `int` type. *)
57
let arbitrary_uint = Gen.sized (fun n -> Gen.choose_int (0, n))
68

@@ -42,7 +44,7 @@ let arbitrary_uint48 =
4244
let lo = of_int c in
4345
ret_gen Int64.(logor (logor hi mid) lo)
4446

45-
(* arbitrary instance for unsigned int48, using the `int64` type. *)
47+
(* arbitrary instance for unsigned int68, using the `int64` type. *)
4648
let arbitrary_uint64 =
4749
let open Gen in
4850
arbitrary_uint16 >>= fun a ->
@@ -56,6 +58,13 @@ let arbitrary_uint64 =
5658
let lo = of_int d in
5759
ret_gen Int64.(logor (logor hi (logor mid1 mid2)) lo)
5860

61+
(* arbitrary instance for unsigned int128, using the `int64` type. *)
62+
let arbitrary_uint128 =
63+
let open Gen in
64+
arbitrary_uint64 >>= fun a ->
65+
arbitrary_uint64 >>= fun b ->
66+
ret_gen (a,b)
67+
5968

6069
(* arbitrary instance for option type, favoring `Some` rather than `None` *)
6170
let arbitrary_option arb =

quickcheck/Arbitrary_Base.mli

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
open QuickCheck
22

3+
type int128 = int64 * int64
4+
35
(* arbitrary instance for usigned integers. Still uses the `int` type. *)
46
val arbitrary_uint : int arbitrary
57

@@ -27,5 +29,8 @@ val arbitrary_uint48 : int64 arbitrary
2729
(* arbitrary instance for unsigned int64, using the `int64` type. *)
2830
val arbitrary_uint64 : int64 arbitrary
2931

32+
(* arbitrary instance for unsigned int64, using the `int64` type. *)
33+
val arbitrary_uint128 : int128 arbitrary
34+
3035
(* arbitrary instance for option type, favoring `Some` rather than `None` *)
3136
val arbitrary_option : 'a arbitrary -> 'a option arbitrary

test/Test.ml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
open Packet
22
open QuickCheck
3+
open Arbitrary_Base
34

45
module Gen = QuickCheck_gen
56

@@ -104,6 +105,23 @@ module RoundTrip = struct
104105
(packet_quickCheck (mk_ip tcp)
105106
(prop_roundtrip2 parse marshal))
106107

108+
let addr_roundtrip parse marshal e =
109+
(parse (marshal e)) = e
110+
111+
let addr_quickcheck arbitrary parse marshal =
112+
let show (p1,p2) =
113+
Format.sprintf "%Lu %Lu" p1 p2 in
114+
let test = testable_fun arbitrary show testable_bool in
115+
match quickCheck test (addr_roundtrip parse marshal) with
116+
| Success -> true
117+
| Failure _ -> failwith "No failure expected"
118+
| Exhausted _ -> failwith "No exhaustion expected"
119+
120+
TEST "Roundtrip property for IPv6 Address" =
121+
(addr_quickcheck arbitrary_uint128
122+
ipv6_of_string string_of_ipv6)
123+
124+
107125
end
108126

109127
Pa_ounit_lib.Runtime.summarize ()

0 commit comments

Comments
 (0)