Skip to content

Commit bb07b44

Browse files
committed
more Linux specific options, skipping multicast ones
1 parent 46a80e5 commit bb07b44

File tree

3 files changed

+98
-0
lines changed

3 files changed

+98
-0
lines changed

lib_eio_linux/low_level.ml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,14 @@ module Sockopt = struct
647647
let ip_freebind = 15 (* IP_FREEBIND *)
648648
let ip_bind_address_no_port = 24 (* IP_BIND_ADDRESS_NO_PORT *)
649649
let ip_local_port_range = 51 (* IP_LOCAL_PORT_RANGE *)
650+
let ip_ttl = 2 (* IP_TTL *)
651+
let ip_mtu = 14 (* IP_MTU *)
652+
let ip_mtu_discover = 10 (* IP_MTU_DISCOVER *)
653+
(* IP_MTU_DISCOVER values *)
654+
let ip_pmtudisc_want = 1 (* IP_PMTUDISC_WANT *)
655+
let ip_pmtudisc_dont = 0 (* IP_PMTUDISC_DONT *)
656+
let ip_pmtudisc_do = 2 (* IP_PMTUDISC_DO *)
657+
let ip_pmtudisc_probe = 3 (* IP_PMTUDISC_PROBE *)
650658

651659
external setsockopt_int : Unix.file_descr -> int -> int -> int -> unit = "caml_eio_sockopt_int_set"
652660
external getsockopt_int : Unix.file_descr -> int -> int -> int = "caml_eio_sockopt_int_get"
@@ -671,6 +679,9 @@ module Sockopt = struct
671679
| IP_FREEBIND : bool Eio.Net.Sockopt.t
672680
| IP_BIND_ADDRESS_NO_PORT : bool Eio.Net.Sockopt.t
673681
| IP_LOCAL_PORT_RANGE : (int * int) Eio.Net.Sockopt.t
682+
| IP_TTL : int Eio.Net.Sockopt.t
683+
| IP_MTU : int Eio.Net.Sockopt.t
684+
| IP_MTU_DISCOVER : [`Want | `Dont | `Do | `Probe] Eio.Net.Sockopt.t
674685

675686
let set : type a. Fd.t -> a Eio.Net.Sockopt.t -> a -> unit = fun fd opt v ->
676687
match opt with
@@ -754,6 +765,22 @@ module Sockopt = struct
754765
let combined = (upper lsl 16) lor lower in
755766
Fd.use_exn "setsockopt" fd (fun fd ->
756767
setsockopt_int fd ipproto_ip ip_local_port_range combined)
768+
| IP_TTL ->
769+
if v < 1 || v > 255 then
770+
invalid_arg (Printf.sprintf "IP_TTL must be between 1 and 255, got %d" v);
771+
Fd.use_exn "setsockopt" fd (fun fd ->
772+
setsockopt_int fd ipproto_ip ip_ttl v)
773+
| IP_MTU ->
774+
invalid_arg "IP_MTU is a read-only socket option"
775+
| IP_MTU_DISCOVER ->
776+
let intval = match v with
777+
| `Want -> ip_pmtudisc_want
778+
| `Dont -> ip_pmtudisc_dont
779+
| `Do -> ip_pmtudisc_do
780+
| `Probe -> ip_pmtudisc_probe
781+
in
782+
Fd.use_exn "setsockopt" fd (fun fd ->
783+
setsockopt_int fd ipproto_ip ip_mtu_discover intval)
757784
| _ -> Eio_unix.Net.Sockopt.set fd opt v
758785

759786
let get : type a. Fd.t -> a Eio.Net.Sockopt.t -> a = fun fd opt ->
@@ -811,5 +838,20 @@ module Sockopt = struct
811838
let lower = combined land 0xFFFF in
812839
let upper = (combined lsr 16) land 0xFFFF in
813840
(lower, upper))
841+
| IP_TTL ->
842+
Fd.use_exn "getsockopt" fd (fun fd ->
843+
getsockopt_int fd ipproto_ip ip_ttl)
844+
| IP_MTU ->
845+
Fd.use_exn "getsockopt" fd (fun fd ->
846+
getsockopt_int fd ipproto_ip ip_mtu)
847+
| IP_MTU_DISCOVER ->
848+
let intval = Fd.use_exn "getsockopt" fd (fun fd ->
849+
getsockopt_int fd ipproto_ip ip_mtu_discover)
850+
in
851+
if intval = ip_pmtudisc_want then `Want
852+
else if intval = ip_pmtudisc_dont then `Dont
853+
else if intval = ip_pmtudisc_do then `Do
854+
else if intval = ip_pmtudisc_probe then `Probe
855+
else failwith (Printf.sprintf "Unknown IP_MTU_DISCOVER value: %d" intval)
814856
| _ -> Eio_unix.Net.Sockopt.get fd opt
815857
end

lib_eio_linux/low_level.mli

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,18 @@ module Sockopt : sig
253253
(** Set the per-socket local port range as (lower_bound, upper_bound).
254254
Both bounds are inclusive and must be in range 0-65535.
255255
Use (0, 0) to reset to system defaults. *)
256+
| IP_TTL : int Eio.Net.Sockopt.t
257+
(** Set or retrieve the time-to-live field used in every packet sent from this socket.
258+
Valid range is 1-255. *)
259+
| IP_MTU : int Eio.Net.Sockopt.t
260+
(** Retrieve the current known path MTU of the current socket.
261+
Only valid for connected sockets. This is a read-only option. *)
262+
| IP_MTU_DISCOVER : [`Want | `Dont | `Do | `Probe] Eio.Net.Sockopt.t
263+
(** Set or receive the Path MTU Discovery setting for a socket.
264+
- [`Want]: Use per-route settings (fragment if needed)
265+
- [`Dont]: Never do Path MTU Discovery
266+
- [`Do]: Always do Path MTU Discovery (reject large datagrams with EMSGSIZE)
267+
- [`Probe]: Set DF but ignore Path MTU (for diagnostic tools) *)
256268

257269
val set : fd -> 'a Eio.Net.Sockopt.t -> 'a -> unit
258270
(** [set fd opt v] sets socket option [opt] to value [v] on file descriptor [fd]. *)

lib_eio_linux/tests/network.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,44 @@ Test that invalid values are rejected properly:
209209
ELS.set fd ELS.TCP_LINGER2 None;
210210
traceln "TCP_LINGER2 accepts None for system default";
211211
212+
(* Test IP_TTL *)
213+
ELS.set fd ELS.IP_TTL 64;
214+
let ttl = ELS.get fd ELS.IP_TTL in
215+
traceln "IP_TTL: %d" ttl;
216+
217+
(* Test IP_TTL validation *)
218+
(try
219+
ELS.set fd ELS.IP_TTL 0;
220+
traceln "ERROR: IP_TTL accepted value 0"
221+
with Invalid_argument msg ->
222+
traceln "IP_TTL zero check: %s" msg);
223+
224+
(try
225+
ELS.set fd ELS.IP_TTL 256;
226+
traceln "ERROR: IP_TTL accepted value 256"
227+
with Invalid_argument msg ->
228+
traceln "IP_TTL overflow check: %s" msg);
229+
230+
(* Test IP_MTU_DISCOVER *)
231+
ELS.set fd ELS.IP_MTU_DISCOVER `Dont;
232+
let mtu_disc = ELS.get fd ELS.IP_MTU_DISCOVER in
233+
traceln "IP_MTU_DISCOVER: %s" (match mtu_disc with
234+
| `Want -> "Want"
235+
| `Dont -> "Dont"
236+
| `Do -> "Do"
237+
| `Probe -> "Probe");
238+
239+
(* Test IP_MTU (read-only, should work on connected socket) *)
240+
let mtu = ELS.get fd ELS.IP_MTU in
241+
traceln "IP_MTU: %d bytes" mtu;
242+
243+
(* Test that IP_MTU cannot be set *)
244+
(try
245+
ELS.set fd ELS.IP_MTU 1500;
246+
traceln "ERROR: IP_MTU allowed setting (should be read-only)"
247+
with Invalid_argument msg ->
248+
traceln "IP_MTU set validation: %s" msg);
249+
212250
(* Test IP_LOCAL_PORT_RANGE validation *)
213251
(try
214252
(* Lower bound > upper bound *)
@@ -245,6 +283,12 @@ Test that invalid values are rejected properly:
245283
+TCP_WINDOW_CLAMP validation: TCP_WINDOW_CLAMP must be non-negative, got -100
246284
+TCP_LINGER2 validation: TCP_LINGER2 must be non-negative, got -2
247285
+TCP_LINGER2 accepts None for system default
286+
+IP_TTL: 64
287+
+IP_TTL zero check: IP_TTL must be between 1 and 255, got 0
288+
+IP_TTL overflow check: IP_TTL must be between 1 and 255, got 256
289+
+IP_MTU_DISCOVER: Dont
290+
+IP_MTU: 65535 bytes
291+
+IP_MTU set validation: IP_MTU is a read-only socket option
248292
+IP_LOCAL_PORT_RANGE validation: IP_LOCAL_PORT_RANGE lower bound (2000) must be <= upper bound (1000)
249293
+IP_LOCAL_PORT_RANGE upper bound check: IP_LOCAL_PORT_RANGE upper bound must be 0-65535, got 70000
250294
+IP_LOCAL_PORT_RANGE accepts valid range 40000-50000

0 commit comments

Comments
 (0)