1
1
use { TxPacket , WriteOut , ip_checksum} ;
2
2
use udp:: UdpPacket ;
3
+ use tcp:: TcpPacket ;
3
4
use icmp:: IcmpPacket ;
4
5
use core:: convert:: TryInto ;
5
6
use core:: fmt;
@@ -87,6 +88,19 @@ impl<T> Ipv4Packet<UdpPacket<T>> {
87
88
}
88
89
}
89
90
91
+ impl < ' a , T > Ipv4Packet < & ' a TcpPacket < T > > {
92
+ pub fn new_tcp ( src_addr : Ipv4Address , dst_addr : Ipv4Address , tcp : & ' a TcpPacket < T > ) -> Self {
93
+ Ipv4Packet {
94
+ header : Ipv4Header {
95
+ src_addr : src_addr,
96
+ dst_addr : dst_addr,
97
+ protocol : IpProtocol :: Tcp ,
98
+ } ,
99
+ payload : tcp,
100
+ }
101
+ }
102
+ }
103
+
90
104
impl < T > Ipv4Packet < IcmpPacket < T > > {
91
105
pub fn new_icmp ( src_addr : Ipv4Address , dst_addr : Ipv4Address , icmp : IcmpPacket < T > ) -> Self {
92
106
Ipv4Packet {
@@ -169,8 +183,32 @@ impl<T: WriteOut> WriteOut for Ipv4Packet<UdpPacket<T>> {
169
183
}
170
184
}
171
185
186
+ impl < ' a , T : WriteOut > WriteOut for Ipv4Packet < & ' a TcpPacket < T > > {
187
+ fn write_out < P : TxPacket > ( & self , packet : & mut P ) -> Result < ( ) , ( ) > {
188
+ self . write_out_impl ( packet) ?;
189
+
190
+ let tcp_start_index = packet. len ( ) ;
191
+ self . payload . write_out ( packet) ?;
192
+
193
+ // calculate tcp checksum
194
+ let pseudo_header_checksum = !ip_checksum:: pseudo_header ( & self . header . src_addr ,
195
+ & self . header . dst_addr ,
196
+ self . header . protocol ,
197
+ self . payload . len ( ) ) ;
198
+
199
+ let tcp_checksum_idx = tcp_start_index + 16 ;
200
+ packet. update_u16 ( tcp_checksum_idx, |checksum| {
201
+ let checksums = [ checksum, pseudo_header_checksum] ;
202
+ ip_checksum:: combine ( & checksums)
203
+ } ) ;
204
+
205
+ Ok ( ( ) )
206
+ }
207
+ }
208
+
172
209
use parse:: { Parse , ParseError } ;
173
210
use udp:: UdpKind ;
211
+ use tcp:: TcpKind ;
174
212
175
213
impl < ' a > Parse < ' a > for Ipv4Packet < & ' a [ u8 ] > {
176
214
fn parse ( data : & ' a [ u8 ] ) -> Result < Self , ParseError > {
@@ -191,6 +229,7 @@ impl<'a> Parse<'a> for Ipv4Packet<&'a [u8]> {
191
229
#[ derive( Debug ) ]
192
230
pub enum Ipv4Kind < ' a > {
193
231
Udp ( UdpPacket < UdpKind < ' a > > ) ,
232
+ Tcp ( TcpPacket < TcpKind < ' a > > ) ,
194
233
Icmp ( IcmpPacket < & ' a [ u8 ] > ) ,
195
234
Unknown ( u8 , & ' a [ u8 ] ) ,
196
235
}
@@ -206,6 +245,13 @@ impl<'a> Parse<'a> for Ipv4Packet<Ipv4Kind<'a>> {
206
245
payload : Ipv4Kind :: Udp ( udp) ,
207
246
} )
208
247
}
248
+ IpProtocol :: Tcp => {
249
+ let tcp = TcpPacket :: parse ( ip. payload ) ?;
250
+ Ok ( Ipv4Packet {
251
+ header : ip. header ,
252
+ payload : Ipv4Kind :: Tcp ( tcp) ,
253
+ } )
254
+ }
209
255
IpProtocol :: Icmp => {
210
256
let icmp = IcmpPacket :: parse ( ip. payload ) ?;
211
257
Ok ( Ipv4Packet {
@@ -219,7 +265,6 @@ impl<'a> Parse<'a> for Ipv4Packet<Ipv4Kind<'a>> {
219
265
payload : Ipv4Kind :: Unknown ( number, ip. payload ) ,
220
266
} )
221
267
}
222
- _ => return Err ( ParseError :: Unimplemented ( "unimplemented ip protocol" ) ) ,
223
268
}
224
269
}
225
270
}
0 commit comments