### Configure IPv6 Stack with Mirage TCP/IP Source: https://context7.com/mirage/mirage-tcpip/llms.txt This example demonstrates the configuration of an IPv6 stack using Mirage TCP/IP. It enables support for the Neighbor Discovery Protocol (NDP) and Router Advertisements, and allows for stateless address autoconfiguration. ```ocaml (* IPv6 stack configuration *) open Lwt.Infix module Ipv6Stack = Ipv6.Make(Netif)(Ethernet) let create_ipv6_stack netif ethernet = let cidr = Some (Ipaddr.V6.Prefix.of_string_exn "2001:db8::1/64") in let gateway = Some (Ipaddr.V6.of_string_exn "2001:db8::ffff") in Ipv6Stack.connect ~handle_ra:true (* Process Router Advertisements *) ?cidr ?gateway netif ethernet >>= fun ipv6 -> Logs.info (fun m -> m "IPv6 stack initialized"); Lwt.return ipv6 ``` -------------------------------- ### OCaml TCP Server and Client Operations with Mirage TCPIP Source: https://context7.com/mirage/mirage-tcpip/llms.txt Demonstrates TCP server (echo) and client (connection establishment) functionalities using Mirage TCPIP. It requires a MirageOS TCP/IP stack implementation (Tcpip.Stack.V4V6) and handles connection management, data reading/writing, and keep-alive probes. ```ocaml (* TCP flow operations and connection management *) open Lwt.Infix module Main (S: Tcpip.Stack.V4V6) = struct (* Echo server: reads data and echoes it back *) let rec echo flow = S.TCP.read flow >>= function | Error e -> Logs.warn (fun m -> m "Read error: %a" S.TCP.pp_error e); S.TCP.close flow | Ok `Eof -> Logs.info (fun m -> m "Connection closed by peer"); S.TCP.close flow | Ok (`Data buf) -> S.TCP.write flow buf >>= function | Ok () -> echo flow | Error e -> Logs.warn (fun m -> m "Write error: %a" S.TCP.pp_write_error e); S.TCP.close flow (* TCP client: creates outbound connection *) let connect_to_server tcp dst_ip dst_port = let keepalive = Tcpip.Tcp.Keepalive.{ after = Duration.of_sec 60; (* Start probes after 60s idle *) interval = Duration.of_sec 10; (* Probe every 10 seconds *) probes = 5; (* Close after 5 failed probes *) } in S.TCP.create_connection ~keepalive tcp (dst_ip, dst_port) >>= function | Error `Timeout -> Logs.err (fun m -> m "Connection timeout"); Lwt.return_unit | Error `Refused -> Logs.err (fun m -> m "Connection refused"); Lwt.return_unit | Ok flow -> let dst_ip, dst_port = S.TCP.dst flow in let src_ip, src_port = S.TCP.src flow in Logs.info (fun m -> m "Connected %a:%d -> %a:%d" Ipaddr.pp src_ip src_port Ipaddr.pp dst_ip dst_port); (* Send data without buffering *) let data = Cstruct.of_string "Hello, server!\n" in S.TCP.write_nodelay flow data >>= function | Ok () -> S.TCP.close flow | Error _ -> S.TCP.close flow (* Start TCP server listening on port 8080 *) let start s = S.TCP.listen (S.tcp s) ~port:8080 echo; S.listen s end ``` -------------------------------- ### Configure Static IPv4 Stack with Mirage TCP/IP Source: https://context7.com/mirage/mirage-tcpip/llms.txt This code snippet shows how to initialize a static IPv4 stack using Mirage TCP/IP. It configures a static IP address, subnet mask, and default gateway, and sets up a fragment cache for handling IP packet fragmentation and reassembly. ```ocaml (* Static IPv4 stack configuration *) open Lwt.Infix (* Functor application for direct stack *) module Ipv4 = Static_ipv4.Make(Ethernet)(Arp) let create_ipv4_stack ethernet arp = let cidr = Ipaddr.V4.Prefix.of_string_exn "192.168.1.100/24" in let gateway = Some (Ipaddr.V4.of_string_exn "192.168.1.1") in Ipv4.connect ~cidr ~gateway ~fragment_cache_size:(256 * 1024) (* 256KB fragment cache *) ethernet arp >>= fun ipv4 -> Logs.info (fun m -> m "IPv4 stack initialized"); Lwt.return ipv4 ``` -------------------------------- ### Create and Connect Socket-Based TCP/IP Stack (OCaml) Source: https://context7.com/mirage/mirage-tcpip/llms.txt Provides a networking stack interface identical to the direct stack but utilizes Unix system sockets. This is primarily for testing MirageOS applications on Unix before deployment. It involves creating TCP and UDP socket layers and then assembling the complete stack. ```ocaml (* Socket-based stack for Unix testing *) open Lwt.Infix let create_socket_stack () = let ipv4_prefix = Ipaddr.V4.Prefix.of_string_exn "0.0.0.0/0" in let ipv6_prefix = Some (Ipaddr.V6.Prefix.of_string_exn "::/0") in (* Create TCP and UDP socket layers *) Tcpv4v6_socket.connect ~ipv4_only:false ~ipv6_only:false ipv4_prefix ipv6_prefix >>= fun tcp -> Udpv4v6_socket.connect ~ipv4_only:false ~ipv6_only:false ipv4_prefix ipv6_prefix >>= fun udp -> (* Assemble socket stack *) Tcpip_stack_socket.V4V6.connect udp tcp >>= fun stack -> Logs.info (fun m -> m "Socket stack ready"); Lwt.return stack ``` -------------------------------- ### Assemble and Use Direct TCP/IP Stack (OCaml) Source: https://context7.com/mirage/mirage-tcpip/llms.txt Assembles a complete networking stack for unikernel deployments by combining various protocol layers including Ethernet, ARP, IPv4/IPv6, ICMP, UDP, and TCP. It facilitates packet demultiplexing and routing, and allows setting up listeners for TCP and UDP services. ```ocaml (* Complete direct stack assembly *) open Lwt.Infix (* Functor instantiation for direct stack *) module Ipv4v6 = Tcpip_stack_direct.IPV4V6(Static_ipv4)(Ipv6) module Stack = Tcpip_stack_direct.MakeV4V6(Netif)(Ethernet)(Arp)(Ipv4v6)(Icmpv4)(Udp)(Tcp) let create_direct_stack netif ethernet arp ipv4 ipv6 icmp udp tcp = (* Combine IPv4 and IPv6 *) Ipv4v6.connect ~ipv4_only:false ~ipv6_only:false ipv4 ipv6 >>= fun ip -> (* Assemble complete stack *) Stack.connect netif ethernet arp ip icmp udp tcp >>= fun stack -> Logs.info (fun m -> m "Direct stack connected"); Lwt.return stack (* Using the stack *) module App (S: Tcpip.Stack.V4V6) = struct let start s = (* Access protocol layers *) let tcp = S.tcp s in let udp = S.udp s in let ip = S.ip s in (* Set up listeners *) S.TCP.listen tcp ~port:80 (fun flow -> Logs.info (fun m -> m "HTTP connection"); S.TCP.close flow ); S.UDP.listen udp ~port:53 (fun ~src ~dst ~src_port buf -> Logs.info (fun m -> m "DNS query from %a" Ipaddr.pp src); Lwt.return_unit ); (* Start listening for packets *) S.listen s end ``` -------------------------------- ### Implement Echo and Discard TCP Services in MirageOS Unikernel (OCaml) Source: https://context7.com/mirage/mirage-tcpip/llms.txt This snippet shows the implementation of an Echo (RFC 862) and a Discard (RFC 863) TCP service within a MirageOS unikernel. It utilizes the Mirage TCP/IP stack interface for listening on ports, reading data, and writing data back or discarding it. The implementation assumes the TCP/IP stack is already configured and provided. ```ocaml (* services.ml - Unikernel implementation *) open Lwt.Infix module Main (S: Tcpip.Stack.V4V6) = struct let start s = (* RFC 862 Echo service *) S.TCP.listen (S.tcp s) ~port:7 (fun flow -> let rec echo () = S.TCP.read flow >>= function | Ok (`Data buf) -> S.TCP.write flow buf >>= fun _ -> echo () | _ -> S.TCP.close flow in echo () ); (* RFC 863 Discard service *) S.TCP.listen (S.tcp s) ~port:9 (fun flow -> let rec discard () = S.TCP.read flow >>= function | Ok (`Data _) -> discard () | _ -> S.TCP.close flow in discard () ); S.listen s end ``` -------------------------------- ### Send Raw IP Packet with Mirage TCP/IP Source: https://context7.com/mirage/mirage-tcpip/llms.txt Demonstrates how to send a raw IP packet using the Mirage TCP/IP stack's IP module. This function allows for manual construction of IP packets, including header fields and payload, and handles potential errors like no available routes or fragmentation issues. ```ocaml (* IP layer operations *) open Lwt.Infix module IpExample (IP: Tcpip.Ip.S with type ipaddr = Ipaddr.t) = struct (* Write raw IP packet *) let send_raw_packet ip dst_ip = let proto = `UDP in let payload = [Cstruct.of_string "raw payload"] in IP.write ip ~fragment:true (* Allow fragmentation if needed *) ~ttl:64 (* Time-to-live *) dst_ip proto ~size:8 (* Header size to allocate *) (fun buf -> (* Write UDP header into buf, return bytes written *) Cstruct.set_uint8 buf 0 0x00; (* src_port high *) 8) payload >>= function | Ok () -> Logs.info (fun m -> m "Packet sent"); Lwt.return_unit | Error `No_route msg -> Logs.err (fun m -> m "No route: %s" msg); Lwt.return_unit | Error `Would_fragment -> Logs.err (fun m -> m "Would fragment but DF set"); Lwt.return_unit (* Get IP configuration *) let show_config ip = let prefixes = IP.configured_ips ip in List.iter (fun prefix -> Logs.info (fun m -> m "Configured: %a" IP.pp_prefix prefix) ) prefixes; let src = IP.src ip ~dst:(Ipaddr.of_string_exn "8.8.8.8") in Logs.info (fun m -> m "Source for 8.8.8.8: %a" IP.pp_ipaddr src); let mtu = IP.mtu ip ~dst:(Ipaddr.of_string_exn "8.8.8.8") in Logs.info (fun m -> m "MTU: %d bytes" mtu) (* IP input demultiplexing *) let handle_input ip buf = let tcp_handler ~src ~dst payload = Logs.info (fun m -> m "TCP from %a to %a" IP.pp_ipaddr src IP.pp_ipaddr dst); Lwt.return_unit in let udp_handler ~src ~dst payload = Logs.info (fun m -> m "UDP from %a to %a" IP.pp_ipaddr src IP.pp_ipaddr dst); Lwt.return_unit in let default_handler ~proto ~src ~dst payload = Logs.info (fun m -> m "Protocol %d from %a" proto IP.pp_ipaddr src); Lwt.return_unit in IP.input ip ~tcp:tcp_handler ~udp:udp_handler ~default:default_handler buf end ``` -------------------------------- ### Calculate Checksums (OCaml) Source: https://context7.com/mirage/mirage-tcpip/llms.txt Provides RFC1071 one's complement checksum calculations for TCP, UDP, and ICMP. Supports calculating checksums for single buffers and multiple buffers (scatter-gather I/O). ```ocaml (* Checksum calculations *) let calculate_checksums () = let data = Cstruct.of_string "test data for checksum" in (* Single buffer checksum *) let checksum = Tcpip_checksum.ones_complement data in Logs.info (fun m -> m "Checksum: 0x%04x" checksum); (* Multi-buffer checksum (for scatter-gather I/O) *) let buffers = [ Cstruct.of_string "header"; Cstruct.of_string "payload"; ] in let checksum_list = Tcpip_checksum.ones_complement_list buffers in Logs.info (fun m -> m "Combined checksum: 0x%04x" checksum_list) ``` -------------------------------- ### OCaml UDP Datagram Sending and Receiving with Mirage TCPIP Source: https://context7.com/mirage/mirage-tcpip/llms.txt Illustrates UDP datagram operations including sending and receiving using Mirage TCPIP. It requires a MirageOS TCP/IP stack (Tcpip.Stack.V4V6) and defines a callback for incoming UDP packets, with options for specifying source port and TTL during transmission. ```ocaml (* UDP datagram sending and receiving *) open Lwt.Infix module UdpExample (S: Tcpip.Stack.V4V6) = struct (* UDP echo server callback *) let udp_callback ~src ~dst ~src_port buf = Logs.info (fun m -> m "Received %d bytes from %a:%d to %a" (Cstruct.length buf) Ipaddr.pp src src_port Ipaddr.pp dst); Lwt.return_unit (* Send UDP datagram *) let send_udp udp dst_ip dst_port data = S.UDP.write ~src_port:12345 (* Optional: specify source port *) ~ttl:64 (* Optional: set time-to-live *) ~dst:dst_ip ~dst_port udp (Cstruct.of_string data) >>= function | Ok () -> Logs.info (fun m -> m "UDP packet sent"); Lwt.return_unit | Error e -> Logs.err (fun m -> m "UDP error: %a" S.UDP.pp_error e); Lwt.return_unit let start s = (* Listen for UDP on port 53 *) S.UDP.listen (S.udp s) ~port:53 udp_callback; (* Stop listening *) S.UDP.unlisten (S.udp s) ~port:53; S.listen s end ``` -------------------------------- ### Configure MirageOS Unikernel with TCP/IP Stack (OCaml) Source: https://context7.com/mirage/mirage-tcpip/llms.txt This snippet demonstrates how to configure a MirageOS unikernel to use the TCP/IP stack (IPv4/IPv6). It specifies necessary packages and registers the unikernel with the Mirage build system. Dependencies include the 'ipaddr' package. ```ocaml (* config.ml - MirageOS unikernel configuration *) open Mirage let main = let packages = [package ~min:"2.9.0" "ipaddr"] in main ~packages "Services.Main" (stackv4v6 @-> job) let stack = generic_stackv4v6 default_network let () = register "my_unikernel" [main $ stack] ``` -------------------------------- ### Parse and Create UDP Packets (OCaml) Source: https://context7.com/mirage/mirage-tcpip/llms.txt Provides functions for parsing and creating UDP datagrams with proper checksum handling. Supports parsing a buffer into header and payload, and creating a UDP packet with specified ports, pseudoheader, and payload. ```ocaml (* UDP packet parsing and creation *) let parse_udp_packet buf = match Udp_packet.Unmarshal.of_cstruct buf with | Error msg -> Logs.err (fun m -> m "UDP parse error: %s" msg); None | Ok (header, payload) -> Logs.info (fun m -> m "UDP: %d -> %d, %d bytes payload" header.Udp_packet.src_port header.Udp_packet.dst_port (Cstruct.length payload)); Some (header, payload) let create_udp_packet ~src_port ~dst_port ~pseudoheader ~payload = let header = Udp_packet.{ src_port; dst_port } in let udp_header = Udp_packet.Marshal.make_cstruct ~pseudoheader ~payload header in Cstruct.concat [udp_header; payload] ``` -------------------------------- ### Parse and Create IPv4 Packets (OCaml) Source: https://context7.com/mirage/mirage-tcpip/llms.txt Offers low-level functionality for marshalling and unmarshalling IPv4 headers. It includes parsing functions that log source, destination, protocol, and TTL, and functions to create IPv4 headers, including generating pseudoheaders for transport layer checksums. ```ocaml (* IPv4 packet parsing and generation *) let parse_ipv4_packet buf = match Ipv4_packet.Unmarshal.of_cstruct buf with | Error msg -> Logs.err (fun m -> m "IPv4 parse error: %s" msg); None | Ok (header, payload) -> Logs.info (fun m -> m "IPv4: %a -> %a, proto=%d, ttl=%d" Ipaddr.V4.pp header.Ipv4_packet.src Ipaddr.V4.pp header.Ipv4_packet.dst header.Ipv4_packet.proto header.Ipv4_packet.ttl); Some (header, payload) let create_ipv4_header ~src ~dst ~proto ~id = let header = Ipv4_packet.{ src; dst; id; off = 0; (* No fragmentation *) ttl = 64; proto = (Ipv4_packet.Marshal.protocol_to_int proto); options = Cstruct.empty; } in let payload_len = 100 in Ipv4_packet.Marshal.make_cstruct ~payload_len header (* Generate pseudoheader for TCP/UDP checksum *) let make_pseudoheader ~src ~dst ~proto payload_len = Ipv4_packet.Marshal.pseudoheader ~src ~dst ~proto payload_len ``` -------------------------------- ### Parse and Create TCP Packets (OCaml) Source: https://context7.com/mirage/mirage-tcpip/llms.txt Handles TCP header marshalling and unmarshalling, including checksum calculation. Supports parsing a buffer into header and payload, and creating a TCP SYN packet with specified ports, sequence number, and pseudoheader. ```ocaml (* TCP packet parsing and creation *) let parse_tcp_packet buf = match Tcp_packet.Unmarshal.of_cstruct buf with | Error msg -> Logs.err (fun m -> m "TCP parse error: %s" msg); None | Ok (header, payload) -> Logs.info (fun m -> m "TCP: %d -> %d, seq=%a, ack=%a, flags=[%s%s%s%s%s%s]" header.Tcp_packet.src_port header.Tcp_packet.dst_port Sequence.pp header.Tcp_packet.sequence Sequence.pp header.Tcp_packet.ack_number (if header.Tcp_packet.syn then "SYN " else "") (if header.Tcp_packet.ack then "ACK " else "") (if header.Tcp_packet.fin then "FIN " else "") (if header.Tcp_packet.rst then "RST " else "") (if header.Tcp_packet.psh then "PSH " else "") (if header.Tcp_packet.urg then "URG " else "")); Some (header, payload) let create_tcp_syn_packet ~src_port ~dst_port ~seq ~pseudoheader = let header = Tcp_packet.{ src_port; dst_port; sequence = Sequence.of_int32 seq; ack_number = Sequence.zero; window = 65535; urg = false; ack = false; psh = false; rst = false; syn = true; fin = false; options = []; } in let payload = Cstruct.empty in Tcp_packet.Marshal.make_cstruct ~pseudoheader ~payload header ``` -------------------------------- ### IPv4 Fragments Cache Size Configuration (OCaml) Source: https://github.com/mirage/mirage-tcpip/blob/main/CHANGES.md Introduced an optional `fragment_cache_size` parameter to `Static_ipv4.connect`. This allows users to specify the byte size of the IPv4 fragment cache, enabling control over memory consumption and performance for fragmented IPv4 packets. Implemented in OCaml. ```ocaml (* Example usage with fragment cache size *) module Static_ipv4 = struct val connect : cidr:Ipaddr.V4.Prefix.t -> ?gateway:Ipaddr.V4.t -> ?fragment_cache_size:int -> E.t -> A.t -> t Lwt.t end let configure_ipv4 stack = Static_ipv4.connect ~cidr:("192.168.1.0/24", "192.168.1.1") ~fragment_cache_size:1024 stack ``` -------------------------------- ### Static_ipv4.connect API Change (OCaml) Source: https://github.com/mirage/mirage-tcpip/blob/main/CHANGES.md The `Static_ipv4.connect` function signature was updated to accept a `cidr:Ipaddr.V4.Prefix.t` instead of separate `ip:Ipaddr.V4.t` and `network:Ipaddr.V4.Prefix.t` arguments. This change aims for greater type safety and clarity in network configuration. Implemented in OCaml. ```ocaml (* Old signature (pre v5.0.0) *) (* val connect : ?ip:Ipaddr.V4.t -> ?network:Ipaddr.V4.Prefix.t -> ... -> t Lwt.t *) (* New signature (v5.0.0 and later) *) val connect : cidr:Ipaddr.V4.Prefix.t -> ?gateway:Ipaddr.V4.t -> ?fragment_cache_size:int -> E.t -> A.t -> t Lwt.t ``` -------------------------------- ### Implement ICMP Ping and Reply Handling (OCaml) Source: https://context7.com/mirage/mirage-tcpip/llms.txt Handles ICMP operations such as sending echo requests (ping) and processing echo replies. It utilizes `Icmpv4_socket` for Unix-based systems and `Cstruct` for packet manipulation. Errors during socket operations or packet parsing are logged. ```ocaml (* ICMP operations - ping implementation *) open Lwt.Infix (* Using socket-based ICMP for Unix *) let ping dst_ip = let dst = Ipaddr.V4.of_string_exn dst_ip in Icmpv4_socket.connect () >>= fun icmp -> (* Build ICMP echo request *) let payload = Cstruct.of_string "ping payload data" in let req = Icmpv4_packet.{ code = 0x00; ty = Icmpv4_wire.Echo_request; subheader = Id_and_seq (0x1234, 1); (* id=0x1234, seq=1 *) } in let header = Icmpv4_packet.Marshal.make_cstruct req ~payload in let echo_request = Cstruct.concat [header; payload] in (* Send ICMP packet *) Icmpv4_socket.write icmp ~dst ~ttl:64 echo_request >>= function | Ok () -> Logs.info (fun m -> m "ICMP echo request sent to %a" Ipaddr.V4.pp dst); Lwt.return_unit | Error e -> Logs.err (fun m -> m "ICMP error: %a" Icmpv4_socket.pp_error e); Lwt.return_unit (* ICMP input handler *) let handle_icmp_reply buf = match Icmpv4_packet.Unmarshal.of_cstruct buf with | Error msg -> Logs.err (fun m -> m "Parse error: %s" msg) | Ok (reply, payload) -> match reply.Icmpv4_packet.subheader with | Icmpv4_packet.Id_and_seq (id, seq) -> Logs.info (fun m -> m "Echo reply id=%d seq=%d" id seq) | _ -> Logs.info (fun m -> m "Other ICMP message") ``` -------------------------------- ### TCP/IP Stack: Ensure Listen Binds Socket (OCaml) Source: https://github.com/mirage/mirage-tcpip/blob/main/CHANGES.md Ensures that the `listen` operation on `tcpip.stack-socket` correctly binds the given socket before proceeding to create a task. This prevents race conditions and ensures the socket is properly configured before network activity begins. Implemented in OCaml. ```ocaml (* Conceptual flow for listen operation *) module Stack_socket = struct type socket val bind : socket -> int -> unit Lwt.t val listen : socket -> int -> unit Lwt.t let safe_listen sock port = bind sock port >>= fun () -> listen sock port end ``` -------------------------------- ### IPv4 Fragment Reassembly (OCaml) Source: https://context7.com/mirage/mirage-tcpip/llms.txt Implements IPv4 packet fragmentation and reassembly using an LRU cache. Handles out-of-order fragments and protects against overlapping fragment attacks. Supports creating a cache, processing incoming fragments, and fragmenting outgoing packets. ```ocaml (* IPv4 fragmentation and reassembly *) let reassemble_fragments () = (* Create fragment cache (256KB max) *) let cache = Fragments.Cache.empty (256 * 1024) in (* Process incoming fragment *) let process_fragment cache timestamp ipv4_header payload = let cache', result = Fragments.process cache timestamp ipv4_header payload in match result with | None -> Logs.debug (fun m -> m "Fragment cached, waiting for more"); cache' | Some (reassembled_header, reassembled_payload) -> Logs.info (fun m -> m "Reassembled %d bytes from %a" (Cstruct.length reassembled_payload) Ipaddr.V4.pp reassembled_header.Ipv4_packet.src); cache' in (* Fragment outgoing packet if needed *) let fragment_packet ~mtu ipv4_header payload = Fragments.fragment ~mtu ipv4_header payload |> List.iter (fun frag -> Logs.debug (fun m -> m "Fragment: %d bytes" (Cstruct.length frag))) in cache ``` -------------------------------- ### TCP Sequence Number Arithmetic (OCaml) Source: https://context7.com/mirage/mirage-tcpip/llms.txt Provides 32-bit sequence number arithmetic with proper wraparound handling for TCP's sequence space. Supports comparison, addition, and checking if a sequence number is within a given window. ```ocaml (* TCP sequence number operations *) let sequence_operations () = let seq1 = Sequence.of_int32 0xFFFFFFFEl in (* Near wraparound *) let seq2 = Sequence.of_int32 0x00000005l in (* After wraparound *) (* Comparison handles wraparound correctly *) assert (Sequence.lt seq1 seq2); (* true: seq1 < seq2 *) assert (Sequence.gt seq2 seq1); (* true: seq2 > seq1 *) (* Arithmetic *) let seq3 = Sequence.add seq1 (Sequence.of_int 10) in Logs.info (fun m -> m "Seq: %a + 10 = %a" Sequence.pp seq1 Sequence.pp seq3); (* Check if sequence is in window *) let in_window = Sequence.between seq2 seq1 seq3 in Logs.info (fun m -> m "In window: %b" in_window) ``` -------------------------------- ### IPv6 Improvements: Packet Handling and DAD Protocol (OCaml) Source: https://github.com/mirage/mirage-tcpip/blob/main/CHANGES.md This update includes several IPv6 improvements, such as correctly setting the length in outgoing packets, preserving context in Ndv6.handle, fixing ICMP checksum computation, and enhancing the Duplicate Address Detection (DAD) protocol implementation. It also adds tests for DAD and ensures bounds checking for IPv6 packet access. Implemented in OCaml. ```ocaml (* Conceptual representation of IPv6 packet handling improvements *) module Ipv6 = struct type packet val set_length : packet -> int -> unit val handle_nd_message : Ndv6.context -> Ndv6.message -> Ndv6.context val compute_icmp_checksum : packet -> int val dad_protocol_step : unit -> unit end ``` -------------------------------- ### IPv4 Fragments: Use Lru.M.t instead of Lru.F.t (OCaml) Source: https://github.com/mirage/mirage-tcpip/blob/main/CHANGES.md The IPv4 fragmentation module now uses `Lru.M.t` (a mutable LRU cache) instead of `Lru.F.t` (a functional LRU cache). This change was made to address excessive memory consumption issues associated with `Lru.M.t` allocating a `Hashtbl.t` of a fixed size, which could lead to ~2MB memory usage per fragment cache. Implemented in OCaml. ```ocaml (* Conceptual change in cache implementation *) module Fragments = struct (* Before: uses Lru.F.t *) (* type t = ... Lru.F.t ... *) (* After: uses Lru.M.t *) type t = ... Lru.M.t ... end ``` -------------------------------- ### Dual Socket Stack: Listen on Same Port as UDP Send (OCaml) Source: https://github.com/mirage/mirage-tcpip/blob/main/CHANGES.md Allows listening on the same port as sending via UDP in a dual socket stack. This feature prevents file descriptor leaks within the socket stack by ensuring proper management of opened file descriptors during disconnect operations. It is implemented in OCaml. ```ocaml (* Example demonstrating dual socket stack functionality - actual implementation details omitted for brevity *) module Socket_stack = struct type t val listen : t -> int -> unit Lwt.t val send_udp : t -> Ipaddr.t -> int -> Cstruct.t -> unit Lwt.t val disconnect : t -> unit -> unit end ``` -------------------------------- ### Socket Stack: Convert Incoming Dual Socket Packet to IPv4 (OCaml) Source: https://github.com/mirage/mirage-tcpip/blob/main/CHANGES.md This functionality ensures that an incoming packet on a dual socket stack is correctly converted to an IPv4 source IP if it was received via IPv4. This is crucial for maintaining consistent IP addressing within the stack. Implemented in OCaml. ```ocaml (* Conceptual representation of packet conversion in a dual socket stack *) module Packet_handler = struct type dual_socket type ip_packet val process_incoming : dual_socket -> ip_packet -> ip_packet (* If packet is from IPv4, ensure source IP is treated as IPv4 *) end ``` -------------------------------- ### Fragments.fragment for Write Side (OCaml) Source: https://github.com/mirage/mirage-tcpip/blob/main/CHANGES.md Introduces the `Fragments.fragment` function, which provides fragmentation capabilities for the write side of packet transmission. This function is utilized within `Static_ipv4` to handle the fragmentation of outgoing IPv4 packets when necessary. Implemented in OCaml. ```ocaml (* Conceptual usage of Fragments.fragment *) module Static_ipv4 = struct val connect : ... -> t Lwt.t end module Fragments = struct val fragment : Cstruct.t -> Cstruct.t list end let send_packet stack packet = let fragments = Fragments.fragment packet in (* Send each fragment *) Lwt_list.iter_s (fun frag -> Stack.write stack frag) fragments ``` -------------------------------- ### TCP Compatibility with Lwt >= 5.0.0 (OCaml) Source: https://github.com/mirage/mirage-tcpip/blob/main/CHANGES.md The TCP module has been updated to be compatible with Lwt version 5.0.0 and later. Specifically, it now correctly handles the change where `Lwt.async` requires a function of type `(unit -> unit Lwt.t)`. This ensures seamless integration with newer Lwt versions. Implemented in OCaml. ```ocaml (* Example of using Lwt.async with the updated TCP module *) module Tcp = struct val process_data : unit -> unit Lwt.t end let start_tcp_processing () (* In Lwt < 5.0.0, Lwt.async (Tcp.process_data) might have worked directly *) = Lwt.async (fun () -> Tcp.process_data ()) ``` -------------------------------- ### TCP/IP Stack: Cancellation on tcpip.stack-socket (OCaml) Source: https://github.com/mirage/mirage-tcpip/blob/main/CHANGES.md Adds cancellation capabilities to the `tcpip.stack-socket` operations. This allows for more robust handling of long-running network tasks by enabling them to be interrupted or cancelled when necessary. Implemented in OCaml. ```ocaml (* Example of using cancellation with Lwt promises *) module Tcpip_stack = struct val connect : unit -> ('a, 'b) result Lwt.t val disconnect : 'a -> unit Lwt.t end let connect_with_cancel stack = Lwt.pick [ (Tcpip_stack.connect stack); (Lwt_unix.sleep 5.0 >|= fun () -> Error `Timeout) ] ``` -------------------------------- ### Checksum Stubs: Name Changes (OCaml) Source: https://github.com/mirage/mirage-tcpip/blob/main/CHANGES.md In version 6.1.0, checksum stubs had their names updated by removing the `caml_` prefix. This change aligns with broader naming conventions and simplifies the interface. The implementation is in OCaml. ```ocaml (* Before v6.1.0: *) external caml_tcpip_checksum : Cstruct.t -> int = "caml_tcpip_checksum" (* After v6.1.0: *) external tcpip_checksum : Cstruct.t -> int = "tcpip_checksum" ``` -------------------------------- ### UDP and ICMP Write: Add TTL Parameter (OCaml) Source: https://github.com/mirage/mirage-tcpip/blob/main/CHANGES.md Adds an optional `?ttl:int` parameter to the `Udp.write` and `Icmp.write` functions. This allows users to specify the Time-To-Live (TTL) value for outgoing UDP and ICMP packets, providing more control over network routing. Implemented in OCaml. ```ocaml (* Example of writing UDP packet with TTL *) module Udp = struct val write : src:Ipaddr.t -> dst:Ipaddr.t -> src_port:int -> dst_port:int -> ?ttl:int -> Cstruct.t -> unit Lwt.t end let send_udp_packet stack = Udp.write ~src:src_ip ~dst:dst_ip ~src_port:1234 ~dst_port:5678 ~ttl:64 payload ``` -------------------------------- ### Unix Sockets: Use SOCK_RAW for ICMP (OCaml) Source: https://github.com/mirage/mirage-tcpip/blob/main/CHANGES.md The Unix sockets API now uses `SOCK_RAW` for ICMP sockets instead of `SOCK_DGRAM`. This change is necessary because `SOCK_DGRAM` does not correctly handle ICMP messages, ensuring proper ICMP communication. Implemented in OCaml. ```ocaml (* Conceptual socket creation for ICMP *) module Unix_sockets = struct val create_icmp_socket : unit -> Unix.file_descr let create_icmp_socket () (* In older versions, this might have used Unix.socket Unix.PF_INET Unix.SOCK_DGRAM ... *) = Unix.socket Unix.PF_INET Unix.SOCK_RAW (Unix.protocol_of_name "icmp") end ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.