resynth/stdlib/ipv4/
mod.rs1use std::net::Ipv4Addr;
2
3use pkt::Packet;
4use pkt::eth::{eth_hdr, ethertype};
5use pkt::ipv4::{ip_hdr, proto};
6
7use ezpkt::IpFrag;
8
9use crate::libapi::{Class, ClassDef, FuncDef, Module};
10use crate::str::Buf;
11use crate::sym::Symbol;
12use crate::val::{Val, ValDef};
13
14mod icmp;
15mod tcp;
16mod udp;
17
18use icmp::ICMP4;
19use tcp::TCP4;
20use udp::UDP4;
21
22const PROTO: Module = module! {
23 resynth mod proto {
25 ICMP => Symbol::u8(proto::ICMP),
26 TCP => Symbol::u8(proto::TCP),
27 UDP => Symbol::u8(proto::UDP),
28 GRE => Symbol::u8(proto::GRE),
29 }
30};
31
32const IPV4_DGRAM_OVERHEAD: usize = std::mem::size_of::<eth_hdr>() + std::mem::size_of::<ip_hdr>();
33
34const DGRAM: FuncDef = func!(
35 resynth fn datagram(
37 src: Ip4,
38 dst: Ip4,
39 =>
40 id: U16 = 0,
41 evil: Bool = false,
42 df: Bool = false,
43 mf: Bool = false,
44 ttl: U8 = 64,
45 frag_off: U16 = 0,
46 proto: U8 = proto::UDP,
47 =>
48 Str
49 ) -> Pkt
50 |mut args| {
51 let src: Ipv4Addr = args.next().into();
52 let dst: Ipv4Addr = args.next().into();
53
54 let id: u16 = args.next().into();
55 let evil: bool = args.next().into();
56 let df: bool = args.next().into();
57 let mf: bool = args.next().into();
58 let ttl: u8 = args.next().into();
59 let frag_off: u16 = args.next().into();
60 let proto: u8 = args.next().into();
61
62 let data: Buf = args.join_extra(b"").into();
63
64 let payload_size: u16 = data.len() as u16;
65 let tot_len: u16 = std::mem::size_of::<ip_hdr>() as u16 + payload_size;
66
67 let eth = eth_hdr::new(
68 src.into(),
69 dst.into(),
70 ethertype::IPV4,
71 );
72
73 let mut iph = ip_hdr::default();
74 iph.set_tot_len(tot_len)
75 .set_id(id)
76 .set_evil(evil)
77 .set_df(df)
78 .set_mf(mf)
79 .set_frag_off(frag_off)
80 .set_ttl(ttl)
81 .set_protocol(proto)
82 .set_saddr(src)
83 .set_daddr(dst)
84 .calc_csum();
85
86 let pkt = Packet::with_capacity(IPV4_DGRAM_OVERHEAD + payload_size as usize);
87 pkt.push(eth);
88 pkt.push(iph);
89 pkt.push_bytes(data);
90
91 Ok(Val::from(pkt))
92 }
93);
94
95const FRAG_FRAGMENT: FuncDef = func!(
96 resynth fn fragment(
103 frag_off: U16,
104 len: U16,
105 =>
106 raw: Bool = false,
107 =>
108 Str
109 ) -> Pkt
110 |mut args| {
111 let obj = args.take_this();
112 let mut r = obj.borrow_mut();
113 let this: &mut IpFrag = r.as_mut_any().downcast_mut().unwrap();
114
115 let frag_off: u16 = args.next().into();
116 let len: u16 = args.next().into();
117 let raw: bool = args.next().into();
118
119 Ok(this.fragment(frag_off, len, raw).into())
120 }
121);
122
123const FRAG_TAIL: FuncDef = func!(
124 resynth fn tail(
131 frag_off: U16,
132 =>
133 raw: Bool = false,
134 =>
135 Str
136 ) -> Pkt
137 |mut args| {
138 let obj = args.take_this();
139 let mut r = obj.borrow_mut();
140 let this: &mut IpFrag = r.as_mut_any().downcast_mut().unwrap();
141
142 let frag_off: u16 = args.next().into();
143 let raw: bool = args.next().into();
144
145 Ok(this.tail(frag_off, raw).into())
146 }
147);
148
149const FRAG_DATAGRAM: FuncDef = func!(
150 resynth fn datagram(
155 =>
156 raw: Bool = false,
157 =>
158 Str
159 ) -> Pkt
160 |mut args| {
161 let obj = args.take_this();
162 let mut r = obj.borrow_mut();
163 let this: &mut IpFrag = r.as_mut_any().downcast_mut().unwrap();
164 let raw: bool = args.next().into();
165
166 Ok(this.datagram(raw).into())
167 }
168);
169
170const IPFRAG: ClassDef = class!(
171 resynth class IpFrag {
173 fragment => Symbol::Func(&FRAG_FRAGMENT),
174 tail => Symbol::Func(&FRAG_TAIL),
175 datagram => Symbol::Func(&FRAG_DATAGRAM),
176 }
177);
178
179impl Class for IpFrag {
180 fn def(&self) -> &'static ClassDef {
181 &IPFRAG
182 }
183}
184
185const FRAG: FuncDef = func!(
186 resynth fn frag(
188 src: Ip4,
189 dst: Ip4,
190 =>
191 id: U16 = 0,
192 evil: Bool = false,
193 df: Bool = false,
194 ttl: U8 = 64,
195 proto: U8 = proto::UDP,
196 =>
197 Str
198 ) -> Obj
199 |mut args| {
200 let src: Ipv4Addr = args.next().into();
201 let dst: Ipv4Addr = args.next().into();
202
203 let id: u16 = args.next().into();
204 let evil: bool = args.next().into();
205 let df: bool = args.next().into();
206 let ttl: u8 = args.next().into();
207 let proto: u8 = args.next().into();
208
209 let payload: Buf = args.join_extra(b"").into();
210
211 let mut iph: ip_hdr = Default::default();
212 iph
213 .set_id(id)
214 .set_evil(evil)
215 .set_df(df)
216 .set_ttl(ttl)
217 .set_protocol(proto)
218 .set_saddr(src)
219 .set_daddr(dst);
220
221 Ok(Val::from(IpFrag::new(iph, payload.cow_buffer().into())))
222 }
223);
224
225pub const IPV4: Module = module! {
226 resynth mod ipv4 {
228 IpFrag => Symbol::Class(&IPFRAG),
229 tcp => Symbol::Module(&TCP4),
230 udp => Symbol::Module(&UDP4),
231 icmp => Symbol::Module(&ICMP4),
232 datagram => Symbol::Func(&DGRAM),
233 frag => Symbol::Func(&FRAG),
234 proto => Symbol::Module(&PROTO),
235 }
236};