3
3
use futures:: stream:: StreamExt ;
4
4
use std:: {
5
5
marker:: PhantomData ,
6
- net:: { Ipv4Addr , Ipv6Addr } ,
6
+ net:: { IpAddr , Ipv4Addr , Ipv6Addr } ,
7
7
} ;
8
8
9
9
use netlink_packet_core:: {
@@ -22,7 +22,7 @@ use crate::{try_nl, Error, Handle};
22
22
23
23
/// A request to create a new route. This is equivalent to the `ip route add`
24
24
/// commands.
25
- pub struct RouteAddRequest < T = ( ) > {
25
+ pub struct RouteAddRequest < T = IpAddr > {
26
26
handle : Handle ,
27
27
message : RouteMessage ,
28
28
replace : bool ,
@@ -246,3 +246,153 @@ impl RouteAddRequest<Ipv6Addr> {
246
246
self
247
247
}
248
248
}
249
+
250
+ #[ derive( Debug , thiserror:: Error ) ]
251
+ pub enum InvalidRequest {
252
+ #[ error( "invalid address family {:?}" , _0) ]
253
+ AddressFamily ( AddressFamily ) ,
254
+
255
+ #[ error( "invalid gateway {}" , _0) ]
256
+ Gateway ( IpAddr ) ,
257
+
258
+ #[ error( "invalid preferred source {}" , _0) ]
259
+ PrefSource ( IpAddr ) ,
260
+
261
+ #[ error( "invalid source prefix {}/{}" , _0, _1) ]
262
+ SourcePrefix ( IpAddr , u8 ) ,
263
+
264
+ #[ error( "invalid destination prefix {}/{}" , _0, _1) ]
265
+ DestinationPrefix ( IpAddr , u8 ) ,
266
+ }
267
+
268
+ impl RouteAddRequest < IpAddr > {
269
+ /// Sets the source address prefix.
270
+ pub fn source_prefix (
271
+ mut self ,
272
+ addr : IpAddr ,
273
+ prefix_length : u8 ,
274
+ ) -> Result < Self , InvalidRequest > {
275
+ self . set_address_family_from_ip_addr ( addr) ;
276
+ match self . message . header . address_family {
277
+ AddressFamily :: Inet => {
278
+ if addr. is_ipv6 ( ) || prefix_length > 32 {
279
+ return Err ( InvalidRequest :: SourcePrefix (
280
+ addr,
281
+ prefix_length,
282
+ ) ) ;
283
+ }
284
+ }
285
+ AddressFamily :: Inet6 => {
286
+ if addr. is_ipv4 ( ) || prefix_length > 128 {
287
+ return Err ( InvalidRequest :: SourcePrefix (
288
+ addr,
289
+ prefix_length,
290
+ ) ) ;
291
+ }
292
+ }
293
+ af => return Err ( InvalidRequest :: AddressFamily ( af) ) ,
294
+ } ;
295
+ self . message
296
+ . attributes
297
+ . push ( RouteAttribute :: Source ( addr. into ( ) ) ) ;
298
+ self . message . header . source_prefix_length = prefix_length;
299
+ Ok ( self )
300
+ }
301
+
302
+ /// Sets the preferred source address.
303
+ pub fn pref_source ( mut self , addr : IpAddr ) -> Result < Self , InvalidRequest > {
304
+ self . set_address_family_from_ip_addr ( addr) ;
305
+ match self . message . header . address_family {
306
+ AddressFamily :: Inet => {
307
+ if addr. is_ipv6 ( ) {
308
+ return Err ( InvalidRequest :: PrefSource ( addr) ) ;
309
+ } ;
310
+ }
311
+ AddressFamily :: Inet6 => {
312
+ if addr. is_ipv4 ( ) {
313
+ return Err ( InvalidRequest :: PrefSource ( addr) ) ;
314
+ } ;
315
+ }
316
+ af => {
317
+ return Err ( InvalidRequest :: AddressFamily ( af) ) ;
318
+ }
319
+ }
320
+ self . message
321
+ . attributes
322
+ . push ( RouteAttribute :: PrefSource ( addr. into ( ) ) ) ;
323
+ Ok ( self )
324
+ }
325
+
326
+ /// Sets the destination address prefix.
327
+ pub fn destination_prefix (
328
+ mut self ,
329
+ addr : IpAddr ,
330
+ prefix_length : u8 ,
331
+ ) -> Result < Self , InvalidRequest > {
332
+ self . set_address_family_from_ip_addr ( addr) ;
333
+ match self . message . header . address_family {
334
+ AddressFamily :: Inet => {
335
+ if addr. is_ipv6 ( ) || prefix_length > 32 {
336
+ return Err ( InvalidRequest :: DestinationPrefix (
337
+ addr,
338
+ prefix_length,
339
+ ) ) ;
340
+ }
341
+ }
342
+ AddressFamily :: Inet6 => {
343
+ if addr. is_ipv4 ( ) || prefix_length > 128 {
344
+ return Err ( InvalidRequest :: DestinationPrefix (
345
+ addr,
346
+ prefix_length,
347
+ ) ) ;
348
+ }
349
+ }
350
+ af => {
351
+ return Err ( InvalidRequest :: AddressFamily ( af) ) ;
352
+ }
353
+ } ;
354
+ self . message . header . destination_prefix_length = prefix_length;
355
+ self . message
356
+ . attributes
357
+ . push ( RouteAttribute :: Destination ( addr. into ( ) ) ) ;
358
+ Ok ( self )
359
+ }
360
+
361
+ /// Sets the gateway (via) address.
362
+ pub fn gateway ( mut self , addr : IpAddr ) -> Result < Self , InvalidRequest > {
363
+ self . set_address_family_from_ip_addr ( addr) ;
364
+ match self . message . header . address_family {
365
+ AddressFamily :: Inet => {
366
+ if addr. is_ipv6 ( ) {
367
+ return Err ( InvalidRequest :: Gateway ( addr) ) ;
368
+ } ;
369
+ }
370
+ AddressFamily :: Inet6 => {
371
+ if addr. is_ipv4 ( ) {
372
+ return Err ( InvalidRequest :: Gateway ( addr) ) ;
373
+ } ;
374
+ }
375
+ af => {
376
+ return Err ( InvalidRequest :: AddressFamily ( af) ) ;
377
+ }
378
+ }
379
+ self . message
380
+ . attributes
381
+ . push ( RouteAttribute :: Gateway ( addr. into ( ) ) ) ;
382
+ Ok ( self )
383
+ }
384
+
385
+ /// If it is not set already, set the address family based on the
386
+ /// given IP address. This is a noop is the address family is
387
+ /// already set.
388
+ fn set_address_family_from_ip_addr ( & mut self , addr : IpAddr ) {
389
+ if self . message . header . address_family != AddressFamily :: Unspec {
390
+ return ;
391
+ }
392
+ if addr. is_ipv4 ( ) {
393
+ self . message . header . address_family = AddressFamily :: Inet ;
394
+ } else {
395
+ self . message . header . address_family = AddressFamily :: Inet6 ;
396
+ }
397
+ }
398
+ }
0 commit comments