syscalls: Add bindings for SIOCGIFNETMASK and SIOCSIFNETMASK.

* guix/build/syscalls.scm (SIOCGIFNETMASK, SIOCSIFNETMASK): New
variables.
(set-network-interface-netmask, network-interface-netmask): New
procedures.
* tests/syscalls.scm ("network-interface-netmask lo")
("set-network-interface-netmask"): New tests.
This commit is contained in:
Ludovic Courtès 2016-11-16 23:36:29 +01:00
parent 9d9d0c9c98
commit 67e5f3b71d
No known key found for this signature in database
GPG Key ID: 090B11993D9AEBB5
2 changed files with 63 additions and 0 deletions

View File

@ -87,10 +87,12 @@
all-network-interface-names
network-interface-names
network-interface-flags
network-interface-netmask
loopback-network-interface?
network-interface-address
set-network-interface-flags
set-network-interface-address
set-network-interface-netmask
set-network-interface-up
configure-network-interface
@ -764,6 +766,14 @@ exception if it's already taken."
(if (string-contains %host-type "linux")
#x8916 ;GNU/Linux
-1)) ;FIXME: GNU/Hurd?
(define SIOCGIFNETMASK
(if (string-contains %host-type "linux")
#x891b ;GNU/Linux
-1)) ;FIXME: GNU/Hurd?
(define SIOCSIFNETMASK
(if (string-contains %host-type "linux")
#x891c ;GNU/Linux
-1)) ;FIXME: GNU/Hurd?
;; Flags and constants from <net/if.h>.
@ -970,6 +980,22 @@ interface NAME."
(list name (strerror err))
(list err))))))
(define (set-network-interface-netmask socket name sockaddr)
"Set the network mask of interface NAME to SOCKADDR."
(let ((req (make-bytevector ifreq-struct-size)))
(bytevector-copy! (string->utf8 name) 0 req 0
(min (string-length name) (- IF_NAMESIZE 1)))
;; Set the 'ifr_addr' field.
(write-socket-address! sockaddr req IF_NAMESIZE)
(let-values (((ret err)
(%ioctl (fileno socket) SIOCSIFNETMASK
(bytevector->pointer req))))
(unless (zero? ret)
(throw 'system-error "set-network-interface-netmask"
"set-network-interface-netmask on ~A: ~A"
(list name (strerror err))
(list err))))))
(define (network-interface-address socket name)
"Return the address of network interface NAME. The result is an object of
the same type as that returned by 'make-socket-address'."
@ -986,6 +1012,22 @@ the same type as that returned by 'make-socket-address'."
(list name (strerror err))
(list err))))))
(define (network-interface-netmask socket name)
"Return the netmask of network interface NAME. The result is an object of
the same type as that returned by 'make-socket-address'."
(let ((req (make-bytevector ifreq-struct-size)))
(bytevector-copy! (string->utf8 name) 0 req 0
(min (string-length name) (- IF_NAMESIZE 1)))
(let-values (((ret err)
(%ioctl (fileno socket) SIOCGIFNETMASK
(bytevector->pointer req))))
(if (zero? ret)
(read-socket-address req IF_NAMESIZE)
(throw 'system-error "network-interface-netmask"
"network-interface-netmask on ~A: ~A"
(list name (strerror err))
(list err))))))
(define (configure-network-interface name sockaddr flags)
"Configure network interface NAME to use SOCKADDR, an address as returned by
'make-socket-address', and FLAGS, a bitwise-or of IFF_* constants."

View File

@ -326,6 +326,27 @@
;; We get EPERM with Linux 3.18ish and EACCES with 2.6.32.
(memv (system-error-errno args) (list EPERM EACCES))))))
(test-equal "network-interface-netmask lo"
(make-socket-address AF_INET (inet-pton AF_INET "255.0.0.0") 0)
(let* ((sock (socket AF_INET SOCK_STREAM 0))
(addr (network-interface-netmask sock "lo")))
(close-port sock)
addr))
(test-skip (if (zero? (getuid)) 1 0))
(test-assert "set-network-interface-netmask"
(let ((sock (socket AF_INET SOCK_STREAM 0)))
(catch 'system-error
(lambda ()
(set-network-interface-netmask sock "nonexistent"
(make-socket-address
AF_INET
(inet-pton AF_INET "255.0.0.0")
0)))
(lambda args
(close-port sock)
(memv (system-error-errno args) (list EPERM EACCES))))))
(test-equal "network-interfaces returns one or more interfaces"
'(#t #t #t)
(match (network-interfaces)