network_simulator/
glue.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT license.
3
4//======================================================================================================================
5// Imports
6//======================================================================================================================
7
8use ::std::{
9    fmt::Debug,
10    net::SocketAddr,
11    time::Duration,
12};
13
14//======================================================================================================================
15
16#[derive(Clone, Debug)]
17pub struct Event {
18    pub time: Duration,
19    pub action: Action,
20}
21
22#[derive(Clone, Debug)]
23pub enum Action {
24    SyscallEvent(SyscallEvent),
25    PacketEvent(PacketEvent),
26}
27
28#[derive(Clone, Debug)]
29pub struct SyscallEvent {
30    pub end_time: Option<Duration>,
31    pub syscall: DemikernelSyscall,
32}
33
34#[derive(Clone)]
35#[allow(dead_code)]
36pub enum DemikernelSyscall {
37    Socket(SocketArgs, i32),
38    Bind(BindArgs, i32),
39    Listen(ListenArgs, i32),
40    Accept(AcceptArgs, i32),
41    Connect(ConnectArgs, i32),
42    Push(PushArgs, i32),
43    PushTo(PushToArgs, i32),
44    Pop(PopArgs, i32),
45    Close(CloseArgs, i32),
46    Wait(WaitArgs, i32),
47    Unsupported,
48}
49
50impl Debug for DemikernelSyscall {
51    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52        match self {
53            DemikernelSyscall::Socket(args, _qd) => write!(f, "demi_socket({:?})", args),
54            DemikernelSyscall::Bind(args, _ok) => write!(f, "demi_bind({:?})", args),
55            DemikernelSyscall::Listen(args, _ok) => write!(f, "demi_listen({:?})", args),
56            DemikernelSyscall::Accept(args, _qd) => write!(f, "demi_accept({:?})", args),
57            DemikernelSyscall::Connect(args, _ok) => write!(f, "demi_connect({:?})", args),
58            DemikernelSyscall::Push(args, _ret) => write!(f, "demi_push({:?})", args),
59            DemikernelSyscall::PushTo(args, _ret) => write!(f, "demi_pushto({:?})", args),
60            DemikernelSyscall::Pop(args, _ret) => write!(f, "demi_pop({:?})", args),
61            DemikernelSyscall::Close(args, _ret) => write!(f, "demi_close({:?})", args),
62            DemikernelSyscall::Wait(args, _ret) => write!(f, "demi_wait({:?})", args),
63            DemikernelSyscall::Unsupported => write!(f, "Unsupported"),
64        }
65    }
66}
67
68#[derive(Clone, Debug, PartialEq)]
69#[allow(non_camel_case_types)]
70pub enum SocketDomain {
71    AF_INET,
72}
73
74#[derive(Clone, Debug, PartialEq)]
75#[allow(non_camel_case_types)]
76pub enum SocketType {
77    SOCK_STREAM,
78    SOCK_DGRAM,
79}
80
81#[derive(Clone, Debug, PartialEq)]
82#[allow(non_camel_case_types)]
83pub enum SocketProtocol {
84    IPPROTO_TCP,
85    IPPROTO_UDP,
86}
87
88#[derive(Clone, Debug)]
89pub struct SocketArgs {
90    pub domain: SocketDomain,
91    pub typ: SocketType,
92    pub protocol: SocketProtocol,
93}
94
95#[derive(Clone, Debug)]
96pub struct BindArgs {
97    pub qd: Option<u32>,
98    pub addr: Option<SocketAddr>,
99}
100
101#[derive(Clone, Debug)]
102pub struct ListenArgs {
103    pub qd: Option<u32>,
104    pub backlog: Option<usize>,
105}
106
107#[derive(Clone, Debug)]
108pub struct AcceptArgs {
109    pub qd: Option<u32>,
110}
111
112#[derive(Clone, Debug)]
113pub struct ConnectArgs {
114    pub qd: Option<u32>,
115    pub addr: Option<SocketAddr>,
116}
117
118#[derive(Clone, Debug)]
119pub struct PushArgs {
120    pub qd: Option<u32>,
121    pub buf: Option<Vec<u8>>,
122    pub len: Option<u32>,
123}
124
125#[derive(Clone, Debug)]
126pub struct PushToArgs {
127    pub qd: Option<u32>,
128    pub buf: Option<Vec<u8>>,
129    pub len: Option<u32>,
130    pub addr: Option<SocketAddr>,
131}
132
133#[derive(Clone, Debug)]
134pub struct PopArgs {
135    pub qd: u32,
136    pub len: Option<u32>,
137}
138
139#[derive(Clone, Debug)]
140pub struct WaitArgs {
141    pub qd: Option<u32>,
142    pub timeout: Option<Duration>,
143}
144
145#[derive(Clone, Debug)]
146pub struct CloseArgs {
147    pub qd: u32,
148}
149
150#[derive(Clone, Debug)]
151pub enum PacketEvent {
152    Tcp(PacketDirection, TcpPacket),
153    Udp(PacketDirection, UdpPacket),
154}
155
156#[derive(Clone, Debug, PartialEq)]
157pub enum PacketDirection {
158    Incoming,
159    Outgoing,
160}
161
162#[derive(Clone, Debug)]
163pub struct TcpPacket {
164    pub flags: TcpFlags,
165    pub seqnum: TcpSequenceNumber,
166    pub ack: Option<u32>,
167    pub win: Option<u32>,
168    pub options: Vec<TcpOption>,
169}
170
171#[derive(Clone, Debug)]
172pub struct UdpPacket {
173    pub len: u32,
174}
175
176#[derive(Clone)]
177pub struct TcpFlags {
178    pub syn: bool,
179    pub ack: bool,
180    pub fin: bool,
181    pub rst: bool,
182    pub psh: bool,
183    pub urg: bool,
184    pub ece: bool,
185    pub cwr: bool,
186}
187
188#[derive(Clone, Debug)]
189pub struct TcpSequenceNumber {
190    pub seq: u32,
191    pub win: u32,
192}
193
194#[derive(Clone, Debug)]
195pub enum TcpOption {
196    Noop,
197    Mss(u16),
198    WindowScale(u8),
199    SackOk,
200    Timestamp(u32, u32),
201    EndOfOptions,
202}
203
204impl Debug for TcpFlags {
205    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
206        let mut flags = String::new();
207        if self.syn {
208            flags.push_str("SYN ");
209        }
210        if self.ack {
211            flags.push_str("ACK ");
212        }
213        if self.fin {
214            flags.push_str("FIN ");
215        }
216        if self.rst {
217            flags.push_str("RST ");
218        }
219        if self.psh {
220            flags.push_str("PSH ");
221        }
222        if self.urg {
223            flags.push_str("URG ");
224        }
225        if self.ece {
226            flags.push_str("ECE ");
227        }
228        if self.cwr {
229            flags.push_str("CWR ");
230        }
231        write!(f, "{}", flags)
232    }
233}
234
235pub fn parse_int(s: &str) -> Result<u32, ()> {
236    match s.parse::<u32>() {
237        Ok(val) => Ok(val),
238        Err(_) => {
239            eprintln!("{} cannot be represented as a u32", s);
240            Err(())
241        },
242    }
243}
244
245pub fn parse_ret_code(s: &str) -> Result<i32, ()> {
246    if let Ok(val) = s.parse::<i32>() {
247        Ok(val)
248    } else {
249        // Try to convert to an errno value.
250        match s {
251            "EPERM" => Ok(libc::EPERM),
252            "ENOENT" => Ok(libc::ENOENT),
253            "ESRCH" => Ok(libc::ESRCH),
254            "EINTR" => Ok(libc::EINTR),
255            "EIO" => Ok(libc::EIO),
256            "ENXIO" => Ok(libc::ENXIO),
257            "E2BIG" => Ok(libc::E2BIG),
258            "ENOEXEC" => Ok(libc::ENOEXEC),
259            "EBADF" => Ok(libc::EBADF),
260            "ECHILD" => Ok(libc::ECHILD),
261            "EAGAIN" => Ok(libc::EAGAIN),
262            "ENOMEM" => Ok(libc::ENOMEM),
263            "EACCES" => Ok(libc::EACCES),
264            "EFAULT" => Ok(libc::EFAULT),
265            "EBUSY" => Ok(libc::EBUSY),
266            "EEXIST" => Ok(libc::EEXIST),
267            "EXDEV" => Ok(libc::EXDEV),
268            "ENODEV" => Ok(libc::ENODEV),
269            "ENOTDIR" => Ok(libc::ENOTDIR),
270            "EISDIR" => Ok(libc::EISDIR),
271            "EINVAL" => Ok(libc::EINVAL),
272            "ENFILE" => Ok(libc::ENFILE),
273            "EMFILE" => Ok(libc::EMFILE),
274            "ENOTTY" => Ok(libc::ENOTTY),
275            "EFBIG" => Ok(libc::EFBIG),
276            "ENOSPC" => Ok(libc::ENOSPC),
277            "ESPIPE" => Ok(libc::ESPIPE),
278            "EROFS" => Ok(libc::EROFS),
279            "EMLINK" => Ok(libc::EMLINK),
280            "EPIPE" => Ok(libc::EPIPE),
281            "EDOM" => Ok(libc::EDOM),
282            "ERANGE" => Ok(libc::ERANGE),
283            "EDEADLK" => Ok(libc::EDEADLK),
284            "EDEADLOCK" => Ok(libc::EDEADLOCK),
285            "ENAMETOOLONG" => Ok(libc::ENAMETOOLONG),
286            "ENOLCK" => Ok(libc::ENOLCK),
287            "ENOSYS" => Ok(libc::ENOSYS),
288            "ENOTEMPTY" => Ok(libc::ENOTEMPTY),
289            "EILSEQ" => Ok(libc::EILSEQ),
290            "EADDRINUSE" => Ok(libc::EADDRINUSE),
291            "EADDRNOTAVAIL" => Ok(libc::EADDRNOTAVAIL),
292            "EAFNOSUPPORT" => Ok(libc::EAFNOSUPPORT),
293            "EALREADY" => Ok(libc::EALREADY),
294            "EBADMSG" => Ok(libc::EBADMSG),
295            "ECANCELED" => Ok(libc::ECANCELED),
296            "ECONNABORTED" => Ok(libc::ECONNABORTED),
297            "ECONNREFUSED" => Ok(libc::ECONNREFUSED),
298            "ECONNRESET" => Ok(libc::ECONNRESET),
299            "EDESTADDRREQ" => Ok(libc::EDESTADDRREQ),
300            "EHOSTUNREACH" => Ok(libc::EHOSTUNREACH),
301            "EIDRM" => Ok(libc::EIDRM),
302            "EINPROGRESS" => Ok(libc::EINPROGRESS),
303            "EISCONN" => Ok(libc::EISCONN),
304            "ELOOP" => Ok(libc::ELOOP),
305            "EMSGSIZE" => Ok(libc::EMSGSIZE),
306            "ENETDOWN" => Ok(libc::ENETDOWN),
307            "ENETRESET" => Ok(libc::ENETRESET),
308            "ENETUNREACH" => Ok(libc::ENETUNREACH),
309            "ENOBUFS" => Ok(libc::ENOBUFS),
310            "ENODATA" => Ok(libc::ENODATA),
311            "ENOLINK" => Ok(libc::ENOLINK),
312            "ENOMSG" => Ok(libc::ENOMSG),
313            "ENOPROTOOPT" => Ok(libc::ENOPROTOOPT),
314            "ENOSR" => Ok(libc::ENOSR),
315            "ENOSTR" => Ok(libc::ENOSTR),
316            "ENOTCONN" => Ok(libc::ENOTCONN),
317            "ENOTRECOVERABLE" => Ok(libc::ENOTRECOVERABLE),
318            "ENOTSOCK" => Ok(libc::ENOTSOCK),
319            "ENOTSUP" => Ok(libc::ENOTSUP),
320            "EOPNOTSUPP" => Ok(libc::EOPNOTSUPP),
321            "EOVERFLOW" => Ok(libc::EOVERFLOW),
322            "EOWNERDEAD" => Ok(libc::EOWNERDEAD),
323            "EPROTO" => Ok(libc::EPROTO),
324            "EPROTONOSUPPORT" => Ok(libc::EPROTONOSUPPORT),
325            "EPROTOTYPE" => Ok(libc::EPROTOTYPE),
326            "ETIME" => Ok(libc::ETIME),
327            "ETIMEDOUT" => Ok(libc::ETIMEDOUT),
328            "ETXTBSY" => Ok(libc::ETXTBSY),
329            "EWOULDBLOCK" => Ok(libc::EWOULDBLOCK),
330            _ => panic!("Unknown error code"),
331        }
332    }
333}