syscalls: Add 'network-interface-flags'.
* guix/build/syscalls.scm (SIOCGIFFLAGS, IFF_UP, IFF_BROADCAST, IFF_LOOPBACK, IF_NAMESIZE): New variables. (network-interface-flags, loopback-network-interface?): New procedures. * tests/syscalls.scm ("network-interface-flags", "loopback-network-interface?"): New tests.
This commit is contained in:
parent
7585016f53
commit
973eea3478
|
@ -31,7 +31,13 @@
|
||||||
mount
|
mount
|
||||||
umount
|
umount
|
||||||
processes
|
processes
|
||||||
network-interfaces))
|
|
||||||
|
IFF_UP
|
||||||
|
IFF_BROADCAST
|
||||||
|
IFF_LOOPBACK
|
||||||
|
network-interfaces
|
||||||
|
network-interface-flags
|
||||||
|
loopback-network-interface?))
|
||||||
|
|
||||||
;;; Commentary:
|
;;; Commentary:
|
||||||
;;;
|
;;;
|
||||||
|
@ -190,6 +196,18 @@ user-land process."
|
||||||
(if (string-contains %host-type "linux")
|
(if (string-contains %host-type "linux")
|
||||||
#x8912 ;GNU/Linux
|
#x8912 ;GNU/Linux
|
||||||
#xf00801a4)) ;GNU/Hurd
|
#xf00801a4)) ;GNU/Hurd
|
||||||
|
(define SIOCGIFFLAGS
|
||||||
|
(if (string-contains %host-type "linux")
|
||||||
|
#x8913 ;GNU/Linux
|
||||||
|
#xc4804191)) ;GNU/Hurd
|
||||||
|
|
||||||
|
;; Flags and constants from <net/if.h>.
|
||||||
|
|
||||||
|
(define IFF_UP #x1) ;Interface is up
|
||||||
|
(define IFF_BROADCAST #x2) ;Broadcast address valid.
|
||||||
|
(define IFF_LOOPBACK #x8) ;Is a loopback net.
|
||||||
|
|
||||||
|
(define IF_NAMESIZE 16) ;maximum interface name size
|
||||||
|
|
||||||
(define ifconf-struct
|
(define ifconf-struct
|
||||||
;; 'struct ifconf', from <net/if.h>.
|
;; 'struct ifconf', from <net/if.h>.
|
||||||
|
@ -197,8 +215,9 @@ user-land process."
|
||||||
'*)) ;struct ifreq *ifc_ifcu
|
'*)) ;struct ifreq *ifc_ifcu
|
||||||
|
|
||||||
(define ifreq-struct-size
|
(define ifreq-struct-size
|
||||||
;; 'struct ifreq' begins with a char array containing the interface name,
|
;; 'struct ifreq' begins with an array of IF_NAMESIZE bytes containing the
|
||||||
;; followed by a bunch of stuff. This is its size in bytes.
|
;; interface name (nul-terminated), followed by a bunch of stuff. This is
|
||||||
|
;; its size in bytes.
|
||||||
(if (= 8 (sizeof '*))
|
(if (= 8 (sizeof '*))
|
||||||
40
|
40
|
||||||
32))
|
32))
|
||||||
|
@ -245,4 +264,32 @@ most LEN bytes from BV."
|
||||||
(list (strerror err))
|
(list (strerror err))
|
||||||
(list err)))))
|
(list err)))))
|
||||||
|
|
||||||
|
(define (network-interface-flags socket name)
|
||||||
|
"Return a number that is the bit-wise or of 'IFF*' flags for network
|
||||||
|
interface NAME."
|
||||||
|
(let ((req (make-bytevector ifreq-struct-size)))
|
||||||
|
(bytevector-copy! (string->utf8 name) 0 req 0
|
||||||
|
(min (string-length name) (- IF_NAMESIZE 1)))
|
||||||
|
(let* ((ret (%ioctl (fileno socket) SIOCGIFFLAGS
|
||||||
|
(bytevector->pointer req)))
|
||||||
|
(err (errno)))
|
||||||
|
(if (zero? ret)
|
||||||
|
|
||||||
|
;; The 'ifr_flags' field is IF_NAMESIZE bytes after the beginning of
|
||||||
|
;; 'struct ifreq', and it's a short int.
|
||||||
|
(bytevector-sint-ref req IF_NAMESIZE (native-endianness)
|
||||||
|
(sizeof short))
|
||||||
|
|
||||||
|
(throw 'system-error "network-interface-flags"
|
||||||
|
"network-interface-flags on ~A: ~A"
|
||||||
|
(list name (strerror err))
|
||||||
|
(list err))))))
|
||||||
|
|
||||||
|
(define (loopback-network-interface? name)
|
||||||
|
"Return true if NAME designates a loopback network interface."
|
||||||
|
(let* ((sock (socket SOCK_STREAM AF_INET 0))
|
||||||
|
(flags (network-interface-flags sock name)))
|
||||||
|
(close-port sock)
|
||||||
|
(not (zero? (logand flags IFF_LOOPBACK)))))
|
||||||
|
|
||||||
;;; syscalls.scm ends here
|
;;; syscalls.scm ends here
|
||||||
|
|
|
@ -48,6 +48,23 @@
|
||||||
(((? string? names) ..1)
|
(((? string? names) ..1)
|
||||||
(member "lo" names))))
|
(member "lo" names))))
|
||||||
|
|
||||||
|
(test-assert "network-interface-flags"
|
||||||
|
(let* ((sock (socket SOCK_STREAM AF_INET 0))
|
||||||
|
(flags (network-interface-flags sock "lo")))
|
||||||
|
(close-port sock)
|
||||||
|
(and (not (zero? (logand flags IFF_LOOPBACK)))
|
||||||
|
(not (zero? (logand flags IFF_UP))))))
|
||||||
|
|
||||||
|
(test-equal "loopback-network-interface?"
|
||||||
|
ENODEV
|
||||||
|
(and (loopback-network-interface? "lo")
|
||||||
|
(catch 'system-error
|
||||||
|
(lambda ()
|
||||||
|
(loopback-network-interface? "nonexistent")
|
||||||
|
#f)
|
||||||
|
(lambda args
|
||||||
|
(system-error-errno args)))))
|
||||||
|
|
||||||
(test-end)
|
(test-end)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue