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 all-network-interface-names
network-interface-names network-interface-names
network-interface-flags network-interface-flags
network-interface-netmask
loopback-network-interface? loopback-network-interface?
network-interface-address network-interface-address
set-network-interface-flags set-network-interface-flags
set-network-interface-address set-network-interface-address
set-network-interface-netmask
set-network-interface-up set-network-interface-up
configure-network-interface configure-network-interface
@ -764,6 +766,14 @@ exception if it's already taken."
(if (string-contains %host-type "linux") (if (string-contains %host-type "linux")
#x8916 ;GNU/Linux #x8916 ;GNU/Linux
-1)) ;FIXME: GNU/Hurd? -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>. ;; Flags and constants from <net/if.h>.
@ -970,6 +980,22 @@ interface NAME."
(list name (strerror err)) (list name (strerror err))
(list 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) (define (network-interface-address socket name)
"Return the address of network interface NAME. The result is an object of "Return the address of network interface NAME. The result is an object of
the same type as that returned by 'make-socket-address'." 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 name (strerror err))
(list 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) (define (configure-network-interface name sockaddr flags)
"Configure network interface NAME to use SOCKADDR, an address as returned by "Configure network interface NAME to use SOCKADDR, an address as returned by
'make-socket-address', and FLAGS, a bitwise-or of IFF_* constants." '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. ;; We get EPERM with Linux 3.18ish and EACCES with 2.6.32.
(memv (system-error-errno args) (list EPERM EACCES)))))) (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" (test-equal "network-interfaces returns one or more interfaces"
'(#t #t #t) '(#t #t #t)
(match (network-interfaces) (match (network-interfaces)