connection: Add 'add-socket-membership'.

Ludovic Court??sTue May 23 20:45:20+0200 2023

d6aa16d

connection: Add 'add-socket-membership'. * netlink/connection.scm (socklen_t, ffi-setsockopt, SOL_NETLINK) * netlink/connection.scm (NETLINK_ADD_MEMBERSHIP) (NETLINK_DROP_MEMBERSHIP, NETLINK_PKTINFO) (NETLINK_BROADCAST_ERROR, NETLINK_NO_ENOBUFS) (NETLINK_LISTEN_ALL_NSID, NETLINK_LIST_MEMBERSHIPS) (NETLINK_CAP_ACK, NETLINK_EXT_ACK, NETLINK_GET_STRICT_CHK): New variables. (add-socket-membership): New procedure. * netlink/constant.scm (int->rtnetlink-group): New enum. * doc/guile-netlink.texi (Netlink Connections): Document it. Signed-off-by: Julien Lepiller <julien@lepiller.eu>

doc/guile-netlink.texi

263263
to the @code{socket} system call---e.g., @code{SOCK_NONBLOCK}.
264264
@end deffn
265265
266+
@cindex subscribing, to an rtnetlink group
267+
@deffn {Scheme Procedure} add-socket-membership @var{sock} @var{group}
268+
Make @var{sock} a member of @var{group}, an @code{RTNLGRP_} constant,
269+
meaning that it will be subscribed to events of that group.
270+
271+
For example, here is how you could create a netlink socket and subscribe
272+
it to the ``link'' group so that it receives notifications for new and
273+
removed links:
274+
275+
@lisp
276+
(let ((sock (connect-route)))
277+
  (add-socket-membership sock RTNLGRP_LINK)
278+
  @dots{})
279+
@end lisp
280+
281+
This procedure is implemented as a @code{setsockopt} call.
282+
@end deffn
283+
266284
@deffn {Scheme Procedure} send-msg @var{msg} @var{sock} [#:@var{addr}]
267285
Send @var{msg} (it must be of type message, @xref{Netlink Headers}) to
268286
@var{addr} using @var{sock}.  If not passed, @var{addr} is the address of

netlink/connection.scm

3030
                                          current-write-waiter)
3131
  #:export (connect
3232
            connect-route
33+
            add-socket-membership
3334
            close-socket
3435
            send-msg
3536
            receive-msg

7374
  (syscall->procedure int "bind" (list int '* int)
7475
                      #:waiter (lambda () (current-read-waiter))))
7576
77+
(define socklen_t uint32)                         ;per <posix/bits/types.h>
78+
(define ffi-setsockopt
79+
  (syscall->procedure int "setsockopt" (list int int int '* socklen_t)))
80+
81+
(define SOL_NETLINK 270)
82+
83+
(define NETLINK_ADD_MEMBERSHIP 1)
84+
(define NETLINK_DROP_MEMBERSHIP 2)
85+
(define NETLINK_PKTINFO 3)
86+
(define NETLINK_BROADCAST_ERROR 4)
87+
(define NETLINK_NO_ENOBUFS 5)
88+
(define NETLINK_LISTEN_ALL_NSID 8)
89+
(define NETLINK_LIST_MEMBERSHIPS 9)
90+
(define NETLINK_CAP_ACK 10)
91+
(define NETLINK_EXT_ACK 11)
92+
(define NETLINK_GET_STRICT_CHK 12)
93+
7694
;; define simple functions to open/close sockets
7795
(define (open-socket proto flags)
7896
  (socket AF_NETLINK (logior SOCK_RAW SOCK_CLOEXEC flags) proto))
7997
98+
(define (add-socket-membership sock group)
99+
  "Make @var{sock} a member of @var{group}, an @code{RTNLGRP_} constant,
100+
meaning that it will be subscribed to events of that group."
101+
  (let ((bv (make-bytevector (sizeof int))))
102+
    (bytevector-uint-set! bv 0 group (native-endianness) (sizeof int))
103+
    (ffi-setsockopt sock SOL_NETLINK NETLINK_ADD_MEMBERSHIP
104+
                    (bytevector->pointer bv) (bytevector-length bv))))
105+
80106
(define (close-socket sock)
81107
  (issue-deprecation-warning
82108
   "'close-socket' is deprecated; use 'close-port' instead.")

netlink/constant.scm

345345
(define-enum int->link-type
346346
  (ARPHRD_ETHER 1)
347347
  (ARPHRD_LOOPBACK 772))
348+
349+
;; enum rtnetlink_groups
350+
(define-enum int->rtnetlink-group
351+
  (RTNLGRP_NONE 0)
352+
  RTNLGRP_LINK
353+
  RTNLGRP_NOTIFY
354+
  RTNLGRP_NEIGH
355+
  RTNLGRP_TC
356+
  RTNLGRP_IPV4_IFADDR
357+
  RTNLGRP_IPV4_MROUTE
358+
  RTNLGRP_IPV4_ROUTE
359+
  RTNLGRP_IPV4_RULE
360+
  RTNLGRP_IPV6_IFADDR
361+
  RTNLGRP_IPV6_MROUTE
362+
  RTNLGRP_IPV6_ROUTE
363+
  RTNLGRP_IPV6_IFINFO
364+
  RTNLGRP_DECnet_IFADDR
365+
  RTNLGRP_NOP2
366+
  RTNLGRP_DECnet_ROUTE
367+
  RTNLGRP_DECnet_RULE
368+
  RTNLGRP_NOP4
369+
  RTNLGRP_IPV6_PREFIX
370+
  RTNLGRP_IPV6_RULE
371+
  RTNLGRP_ND_USEROPT
372+
  RTNLGRP_PHONET_IFADDR
373+
  RTNLGRP_PHONET_ROUTE
374+
  RTNLGRP_DCB
375+
  RTNLGRP_IPV4_NETCONF
376+
  RTNLGRP_IPV6_NETCONF
377+
  RTNLGRP_MDB
378+
  RTNLGRP_MPLS_ROUTE
379+
  RTNLGRP_NSID
380+
  RTNLGRP_MPLS_NETCONF
381+
  RTNLGRP_IPV4_MROUTE_R
382+
  RTNLGRP_IPV6_MROUTE_R
383+
  RTNLGRP_NEXTHOP
384+
  RTNLGRP_BRVLAN
385+
  RTNLGRP_MCTP_IFADDR
386+
  RTNLGRP_TUNNEL
387+
  RTNLGRP_STATS)