@@ -27,6 +27,12 @@ impl Ipv4Addr {
27
27
}
28
28
}
29
29
30
+ impl From < libc:: in_addr > for Ipv4Addr {
31
+ fn from ( value : libc:: in_addr ) -> Self {
32
+ Self ( value. s_addr . to_be_bytes ( ) )
33
+ }
34
+ }
35
+
30
36
impl Display for Ipv4Addr {
31
37
fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
32
38
f. write_str ( & format ! (
@@ -368,47 +374,94 @@ fn get_macaddress<'a>() -> &'a [u8; 6] {
368
374
. try_call_once ( || unsafe {
369
375
let fd = cvt ( libc:: socket ( libc:: AF_INET , libc:: SOCK_DGRAM , 0 ) ) ?;
370
376
371
- let mut buffer = [ 0u8 ; 6 ] ;
372
- cvt ( libc:: ioctl ( fd, libc:: SIOCGIFHWADDR , buffer . as_mut_ptr ( ) ) ) ?;
377
+ let macaddr = IfReq :: new ( DEFAULT_NIC ) ;
378
+ cvt ( libc:: ioctl ( fd, libc:: SIOCGIFHWADDR , & macaddr ) ) ?;
373
379
374
- Ok :: < [ u8 ; 6 ] , io:: Error > ( buffer )
380
+ Ok :: < [ u8 ; 6 ] , io:: Error > ( macaddr . macaddr ( ) )
375
381
} )
376
382
// FIXME: Should we panic here?
377
383
. expect ( "[ DHCPD ] (EE) failed to retrieve the mac address" )
378
384
}
379
385
380
- fn configure ( interface : & str , ip : Ipv4Addr ) -> io:: Result < ( ) > {
381
- let fd = cvt ( unsafe { libc:: socket ( libc:: AF_INET , libc:: SOCK_DGRAM , 0 ) } ) ?;
382
- let socket = libc:: sockaddr_in {
383
- sin_family : libc:: AF_INET as _ ,
384
- sin_addr : libc:: in_addr {
385
- s_addr : ip. as_u32 ( ) ,
386
- } ,
386
+ struct SockAddrIn ( libc:: sockaddr_in ) ;
387
387
388
- sin_port : 0 ,
389
- sin_zero : [ 0 ; 8 ] ,
390
- } ;
388
+ impl SockAddrIn {
389
+ pub fn new ( addr : Ipv4Addr ) -> Self {
390
+ let sin_addr = libc:: in_addr {
391
+ s_addr : addr. as_u32 ( ) ,
392
+ } ;
391
393
392
- let mut ifr: libc:: ifreq = unsafe { core:: mem:: zeroed ( ) } ;
393
- assert ! ( interface. len( ) <= libc:: IFNAMSIZ ) ;
394
+ Self ( libc:: sockaddr_in {
395
+ sin_family : libc:: AF_INET as _ ,
396
+ sin_addr,
394
397
395
- // SAFETY: We have verified above that the name will fit
396
- // in the buffer.
397
- unsafe {
398
- core:: ptr:: copy_nonoverlapping (
399
- interface. as_ptr ( ) ,
400
- ifr. ifr_name . as_mut_ptr ( ) as * mut u8 ,
401
- interface. len ( ) ,
402
- ) ;
398
+ ..unsafe { core:: mem:: zeroed ( ) }
399
+ } )
403
400
}
401
+ }
404
402
405
- ifr. ifr_ifru . ifru_addr = unsafe { * ( & socket as * const _ as * const libc:: sockaddr ) } ;
403
+ impl Into < libc:: sockaddr > for SockAddrIn {
404
+ fn into ( self ) -> libc:: sockaddr {
405
+ unsafe { core:: mem:: transmute_copy ( & self . 0 ) }
406
+ }
407
+ }
408
+
409
+ struct IfReq ( libc:: ifreq ) ;
410
+
411
+ impl IfReq {
412
+ pub fn new ( interface : & str ) -> Self {
413
+ let mut ifr: libc:: ifreq = unsafe { core:: mem:: zeroed ( ) } ;
414
+ assert ! ( interface. len( ) <= libc:: IFNAMSIZ ) ;
415
+
416
+ // SAFETY: We have verified above that the name will fit
417
+ // in the buffer.
418
+ unsafe {
419
+ core:: ptr:: copy_nonoverlapping (
420
+ interface. as_ptr ( ) ,
421
+ ifr. ifr_name . as_mut_ptr ( ) as * mut u8 ,
422
+ interface. len ( ) ,
423
+ ) ;
424
+ }
425
+
426
+ Self ( ifr)
427
+ }
428
+
429
+ fn set_addr ( mut self , ip : Ipv4Addr ) -> libc:: ifreq {
430
+ self . 0 . ifr_ifru . ifru_addr = SockAddrIn :: new ( ip) . into ( ) ;
431
+ self . 0
432
+ }
433
+
434
+ unsafe fn macaddr ( & self ) -> [ u8 ; 6 ] {
435
+ let data: & [ i8 ; 6 ] = & self . 0 . ifr_ifru . ifru_hwaddr . sa_data [ ..6 ]
436
+ . try_into ( )
437
+ . expect ( "macaddr: address validation failed" ) ;
438
+
439
+ let data: [ i8 ; 6 ] = data. clone ( ) ;
440
+
441
+ // SAFETY: The caller guarantees that union field we are accessing
442
+ // has been initialized with a mac address. With all of that,
443
+ // transmuting the data array into [u8; 6] is safe.
444
+ core:: mem:: transmute ( data)
445
+ }
446
+ }
447
+
448
+ fn configure ( interface : & str , ip : Ipv4Addr , subnet_mask : Ipv4Addr ) -> io:: Result < ( ) > {
449
+ let fd = cvt ( unsafe { libc:: socket ( libc:: AF_INET , libc:: SOCK_DGRAM , 0 ) } ) ?;
450
+
451
+ let interface_addr = IfReq :: new ( interface) . set_addr ( ip) ;
406
452
407
453
// Set the interface address.
408
454
unsafe {
409
- cvt ( libc:: ioctl ( fd, libc:: SIOCSIFADDR , & ifr ) ) ?;
455
+ cvt ( libc:: ioctl ( fd, libc:: SIOCSIFADDR , & interface_addr ) ) ?;
410
456
}
411
457
458
+ let subnet_mask = IfReq :: new ( interface) . set_addr ( subnet_mask) ;
459
+
460
+ // Set the subnet mask.
461
+ // unsafe {
462
+ // cvt(libc::ioctl(fd, libc::SIOCSIFNETMASK, &subnet_mask))?;
463
+ // }
464
+
412
465
Ok ( ( ) )
413
466
}
414
467
@@ -466,7 +519,7 @@ pub fn main() -> Result<(), Box<dyn Error>> {
466
519
let subnet_mask = subnet_mask. unwrap ( ) ;
467
520
let dns = dns. unwrap ( ) ;
468
521
469
- configure ( DEFAULT_NIC , ack. your_ip ) ?;
522
+ configure ( DEFAULT_NIC , ack. your_ip , subnet_mask ) ?;
470
523
471
524
println ! ( "[ DHCPD ] (!!) Configured:" ) ;
472
525
println ! ( "[ DHCPD ] (!!) IP: {}" , ack. your_ip) ;
0 commit comments