From 3fed7633ee4556907408c55ae29c12641ad6d80c Mon Sep 17 00:00:00 2001 From: David Thompson Date: Sun, 3 May 2015 09:35:49 -0400 Subject: [PATCH] socket: Add AF_NETLINK support. * libguile/socket.c (scm_fill_sockaddr, _scm_from_sockaddr, scm_to_sockaddr): Add AF_NETLINK cases. (AF_NETLINK, PF_NETLINK, NETLINK_ROUTE, NETLINK_USERSOCK, NETLINK_FIREWALL, NETLINK_SOCK_DIAG, NETLINK_NFLOG, NETLINK_XFRM, NETLINK_SELINUX, NETLINK_ISCSI, NETLINK_AUDIT, NETLINK_FIB_LOOKUP, NETLINK_CONNECTOR, NETLINK_NETFILTER, NETLINK_IP6_FW, NETLINK_DNRTMSG, NETLINK_UEVENT, NETLINK_GENERIC, NETLINK_SCSITRANSPORT, NETLINK_ECRYPTFS, NETLINK_RDMA, NETLINK_CRYPTO, RTNLGRP_NONE, RTNGRP_LINK, RTNGRP_NOTIFY, RTNGRP_NEIGH, RTNGRP_TC, RTNGRP_IPV4_IFADDR, RTNGRP_IPV4_MROUTE, RTNGRP_IPV4_ROUTE, RTNGRP_IPV4_RULE, RTNGRP_IPV6_IFADDR, RTNGRP_IPV6_MROUTE, RTNGRP_IPV6_ROUTE, RTNGRP_IPV6_IFINFO, RTNGRP_DECnet_IFADDR, RTNGRP_DECnet_ROUTE, RTNGRP_DECnet_RULE, RTNGRP_IPV6_PREFIX, RTNGRP_IPV6_RULE, RTNGRP_ND_USEROPT, RTNGRP_PHONET_IFADDR, RTNGRP_PHONET_ROUTE, RTNGRP_DCB, RTNGRP_IPV4_NETCONF, RTNGRP_IPV6_NETCONF, RTNGRP_MDB): New Scheme variables. * module/ice-9/networking.scm (sockaddr:pid, sockaddr:groups): New procedures. * doc/ref/posix.texi (make-socket-address, connect, bind): Document AF_NETLINK usage. (sockaddr:pid, sockaddr:groups): Document new procedures. (socket): Document PF_NETLINK family constant. --- doc/ref/posix.texi | 17 ++++ libguile/socket.c | 203 ++++++++++++++++++++++++++++++++++++++++++++ module/ice-9/networking.scm | 2 + 3 files changed, 222 insertions(+) diff --git a/doc/ref/posix.texi b/doc/ref/posix.texi index ad5460c..33fe185 100644 --- a/doc/ref/posix.texi +++ b/doc/ref/posix.texi @@ -2950,6 +2950,7 @@ created with, @deffn {Scheme Procedure} make-socket-address AF_INET ipv4addr port @deffnx {Scheme Procedure} make-socket-address AF_INET6 ipv6addr port [flowinfo [scopeid]] @deffnx {Scheme Procedure} make-socket-address AF_UNIX path +@deffnx {Scheme Procedure} make-socket-address AF_NETLINK pid groups @deffnx {C Function} scm_make_socket_address (family, address, arglist) Return a new socket address object. The first argument is the address family, one of the @code{AF} constants, then the arguments vary @@ -2964,6 +2965,9 @@ arguments may be given (both integers, default 0). For @code{AF_UNIX} the argument is a filename (a string). +For @code{AF_NETLINK}, the arguments are a process ID and a multicast +groups bitmask. This socket type is only available on Linux. + The C function @code{scm_make_socket_address} takes the @var{family} and @var{address} arguments directly, then @var{arglist} is a list of further arguments, being the port for IPv4, port and optional flowinfo @@ -3004,6 +3008,16 @@ For an @code{AF_INET6} socket address object @var{sa}, return the scope ID value. @end deffn +@deffn {Scheme Procedure} sockaddr:pid sa +For an @code{AF_NETLINK} socket address object @var{sa}, return the +process ID number. +@end deffn + +@deffn {Scheme Procedure} sockaddr:groups sa +For an @code{AF_NETLINK} socket address object @var{sa}, return the +multicast groups bitmask. +@end deffn + @tpindex @code{struct sockaddr} @tpindex @code{sockaddr} The functions below convert to and from the C @code{struct sockaddr} @@ -3075,6 +3089,7 @@ the system, @defvar PF_UNIX @defvarx PF_INET @defvarx PF_INET6 +@defvarx PF_NETLINK @end defvar The possible values for @var{style} are as follows, again where @@ -3213,6 +3228,7 @@ The return value is unspecified. @deffnx {Scheme Procedure} connect sock AF_INET ipv4addr port @deffnx {Scheme Procedure} connect sock AF_INET6 ipv6addr port [flowinfo [scopeid]] @deffnx {Scheme Procedure} connect sock AF_UNIX path +@deffnx {Scheme Procedure} connect sock AF_NETLINK pid groups @deffnx {C Function} scm_connect (sock, fam, address, args) Initiate a connection on socket port @var{sock} to a given address. The destination is either a socket address object, or arguments the @@ -3229,6 +3245,7 @@ same as @code{make-socket-address} would take to make such an object @deffnx {Scheme Procedure} bind sock AF_INET ipv4addr port @deffnx {Scheme Procedure} bind sock AF_INET6 ipv6addr port [flowinfo [scopeid]] @deffnx {Scheme Procedure} bind sock AF_UNIX path +@deffnx {Scheme Procedure} bind sock AF_NETLINK pid groups @deffnx {C Function} scm_bind (sock, fam, address, args) Bind socket port @var{sock} to the given address. The address is either a socket address object, or arguments the same as diff --git a/libguile/socket.c b/libguile/socket.c index 5b17a74..3501646 100644 --- a/libguile/socket.c +++ b/libguile/socket.c @@ -43,6 +43,11 @@ #include #include +#ifdef __linux__ +#include +#include +#endif + #include #include "libguile/_scm.h" @@ -802,6 +807,22 @@ scm_fill_sockaddr (int fam, SCM address, SCM *args, int which_arg, return (struct sockaddr *) soka; } #endif +#ifdef __linux__ + case AF_NETLINK: + { + struct sockaddr_nl *soka; + + soka = (struct sockaddr_nl *) scm_malloc (sizeof (struct sockaddr_nl)); + + soka->nl_family = AF_NETLINK; + soka->nl_pad = 0; + soka->nl_pid = 0; + soka->nl_groups = 0; + + *size = sizeof (struct sockaddr_nl); + return (struct sockaddr *) soka; + } +#endif #ifdef HAVE_UNIX_DOMAIN_SOCKETS case AF_UNIX: { @@ -1024,6 +1045,19 @@ _scm_from_sockaddr (const scm_t_max_sockaddr *address, unsigned addr_size, } break; #endif +#ifdef AF_NETLINK + case AF_NETLINK: + { + const struct sockaddr_nl *nad = (struct sockaddr_nl *) address; + + result = scm_c_make_vector (3, SCM_UNSPECIFIED); + SCM_SIMPLE_VECTOR_SET(result, 0, scm_from_short (fam)); + SCM_SIMPLE_VECTOR_SET(result, 1, scm_from_uint32 (nad->nl_pid)); + SCM_SIMPLE_VECTOR_SET(result, 2, scm_from_uint32 (nad->nl_groups)); + + break; + } +#endif #ifdef HAVE_UNIX_DOMAIN_SOCKETS case AF_UNIX: { @@ -1140,6 +1174,30 @@ scm_to_sockaddr (SCM address, size_t *address_size) } #endif +#ifdef __linux__ + case AF_NETLINK: + { + if (SCM_SIMPLE_VECTOR_LENGTH (address) != 3) + scm_misc_error (FUNC_NAME, "invalid netlink address representation: ~A", + scm_list_1 (address)); + else + { + struct sockaddr_nl c_nl; + + c_nl.nl_family = AF_NETLINK; + c_nl.nl_pad = 0; + c_nl.nl_pid = scm_to_uint32 (SCM_SIMPLE_VECTOR_REF (address, 1)); + c_nl.nl_groups = scm_to_uint32 (SCM_SIMPLE_VECTOR_REF (address, 2)); + + *address_size = sizeof (c_nl); + c_address = scm_malloc (sizeof (c_nl)); + memcpy (c_address, &c_nl, sizeof (c_nl)); + } + + break; + } +#endif + #ifdef HAVE_UNIX_DOMAIN_SOCKETS case AF_UNIX: { @@ -1699,6 +1757,9 @@ scm_init_socket () #ifdef AF_INET6 scm_c_define ("AF_INET6", scm_from_int (AF_INET6)); #endif +#ifdef AF_NETLINK + scm_c_define ("AF_NETLINK", scm_from_int (AF_NETLINK)); +#endif #ifdef PF_UNSPEC scm_c_define ("PF_UNSPEC", scm_from_int (PF_UNSPEC)); @@ -1712,6 +1773,71 @@ scm_init_socket () #ifdef PF_INET6 scm_c_define ("PF_INET6", scm_from_int (PF_INET6)); #endif +#ifdef PF_NETLINK + scm_c_define ("PF_NETLINK", scm_from_int (PF_NETLINK)); +#endif + + /* netlink families. */ +#ifdef NETLINK_ROUTE + scm_c_define ("NETLINK_ROUTE", scm_from_int (NETLINK_ROUTE)); +#endif +#ifdef NETLINK_USERSOCK + scm_c_define ("NETLINK_USERSOCK", scm_from_int (NETLINK_USERSOCK)); +#endif +#ifdef NETLINK_FIREWALL + scm_c_define ("NETLINK_FIREWALL", scm_from_int (NETLINK_FIREWALL)); +#endif +#ifdef NETLINK_SOCK_DIAG + scm_c_define ("NETLINK_SOCK_DIAG", scm_from_int (NETLINK_SOCK_DIAG)); +#endif +#ifdef NETLINK_NFLOG + scm_c_define ("NETLINK_NFLOG", scm_from_int (NETLINK_NFLOG)); +#endif +#ifdef NETLINK_XFRM + scm_c_define ("NETLINK_XFRM", scm_from_int (NETLINK_XFRM)); +#endif +#ifdef NETLINK_SELINUX + scm_c_define ("NETLINK_SELINUX", scm_from_int (NETLINK_SELINUX)); +#endif +#ifdef NETLINK_ISCSI + scm_c_define ("NETLINK_ISCSI", scm_from_int (NETLINK_ISCSI)); +#endif +#ifdef NETLINK_AUDIT + scm_c_define ("NETLINK_AUDIT", scm_from_int (NETLINK_AUDIT)); +#endif +#ifdef NETLINK_FIB_LOOKUP + scm_c_define ("NETLINK_FIB_LOOKUP", scm_from_int (NETLINK_FIB_LOOKUP)); +#endif +#ifdef NETLINK_CONNECTOR + scm_c_define ("NETLINK_CONNECTOR", scm_from_int (NETLINK_CONNECTOR)); +#endif +#ifdef NETLINK_NETFILTER + scm_c_define ("NETLINK_NETFILTER", scm_from_int (NETLINK_NETFILTER)); +#endif +#ifdef NETLINK_IP6_FW + scm_c_define ("NETLINK_IP6_FW", scm_from_int (NETLINK_IP6_FW)); +#endif +#ifdef NETLINK_DNRTMSG + scm_c_define ("NETLINK_DNRTMSG", scm_from_int (NETLINK_DNRTMSG)); +#endif +#ifdef NETLINK_KOBJECT_UEVENT + scm_c_define ("NETLINK_KOBJECT_UEVENT", scm_from_int (NETLINK_KOBJECT_UEVENT)); +#endif +#ifdef NETLINK_GENERIC + scm_c_define ("NETLINK_GENERIC", scm_from_int (NETLINK_GENERIC)); +#endif +#ifdef NETLINK_SCSITRANSPORT + scm_c_define ("NETLINK_SCSITRANSPORT", scm_from_int (NETLINK_SCSITRANSPORT)); +#endif +#ifdef NETLINK_ECRYPTFS + scm_c_define ("NETLINK_ECRYPTFS", scm_from_int (NETLINK_ECRYPTFS)); +#endif +#ifdef NETLINK_RDMA + scm_c_define ("NETLINK_RDMA", scm_from_int (NETLINK_RDMA)); +#endif +#ifdef NETLINK_CRYPTO + scm_c_define ("NETLINK_CRYPTO", scm_from_int (NETLINK_CRYPTO)); +#endif /* standard addresses. */ #ifdef INADDR_ANY @@ -1843,6 +1969,83 @@ scm_init_socket () scm_c_define ("IP_MULTICAST_IF", scm_from_int ( IP_MULTICAST_IF)); #endif + /* netlink multicast groups */ +#ifdef RTNLGRP_NONE + scm_c_define ("RTNLGRP_NONE", scm_from_int (RTNLGRP_NONE)); +#endif +#ifdef RTNLGRP_LINK + scm_c_define ("RTNLGRP_LINK", scm_from_int (RTNLGRP_LINK)); +#endif +#ifdef RTNLGRP_NOTIFY + scm_c_define ("RTNLGRP_NOTIFY", scm_from_int (RTNLGRP_NOTIFY)); +#endif +#ifdef RTNLGRP_NEIGH + scm_c_define ("RTNLGRP_NEIGH", scm_from_int (RTNLGRP_NEIGH)); +#endif +#ifdef RTNLGRP_TC + scm_c_define ("RTNLGRP_TC", scm_from_int (RTNLGRP_TC)); +#endif +#ifdef RTNLGRP_IPV4_IFADDR + scm_c_define ("RTNLGRP_IPV4_IFADDR", scm_from_int (RTNLGRP_IPV4_IFADDR)); +#endif +#ifdef RTNLGRP_IPV4_MROUTE + scm_c_define ("RTNLGRP_IPV4_MROUTE", scm_from_int (RTNLGRP_IPV4_MROUTE)); +#endif +#ifdef RTNLGRP_IPV4_ROUTE + scm_c_define ("RTNLGRP_IPV4_ROUTE", scm_from_int (RTNLGRP_IPV4_ROUTE)); +#endif +#ifdef RTNLGRP_IPV4_RULE + scm_c_define ("RTNLGRP_IPV4_RULE", scm_from_int (RTNLGRP_IPV4_RULE)); +#endif +#ifdef RTNLGRP_IPV6_IFADDR + scm_c_define ("RTNLGRP_IPV6_IFADDR", scm_from_int (RTNLGRP_IPV6_IFADDR)); +#endif +#ifdef RTNLGRP_IPV6_MROUTE + scm_c_define ("RTNLGRP_IPV6_MROUTE", scm_from_int (RTNLGRP_IPV6_MROUTE)); +#endif +#ifdef RTNLGRP_IPV6_ROUTE + scm_c_define ("RTNLGRP_IPV6_ROUTE", scm_from_int (RTNLGRP_IPV6_ROUTE)); +#endif +#ifdef RTNLGRP_IPV6_IFINFO + scm_c_define ("RTNLGRP_IPV6_IFINFO", scm_from_int (RTNLGRP_IPV6_IFINFO)); +#endif +#ifdef RTNLGRP_DECnet_IFADDR + scm_c_define ("RTNLGRP_DECnet_IFADDR", scm_from_int (RTNLGRP_DECnet_IFADDR)); +#endif +#ifdef RTNLGRP_DECnet_ROUTE + scm_c_define ("RTNLGRP_DECnet_ROUTE", scm_from_int (RTNLGRP_DECnet_ROUTE)); +#endif +#ifdef RTNLGRP_DECnet_RULE + scm_c_define ("RTNLGRP_DECnet_RULE", scm_from_int (RTNLGRP_DECnet_RULE)); +#endif +#ifdef RTNLGRP_IPV6_PREFIX + scm_c_define ("RTNLGRP_IPV6_PREFIX", scm_from_int (RTNLGRP_IPV6_PREFIX)); +#endif +#ifdef RTNLGRP_IPV6_RULE + scm_c_define ("RTNLGRP_IPV6_RULE", scm_from_int (RTNLGRP_IPV6_RULE)); +#endif +#ifdef RTNLGRP_ND_USEROPT + scm_c_define ("RTNLGRP_ND_USEROPT", scm_from_int (RTNLGRP_ND_USEROPT)); +#endif +#ifdef RTNLGRP_PHONET_IFADDR + scm_c_define ("RTNLGRP_PHONET_IFADDR", scm_from_int (RTNLGRP_PHONET_IFADDR)); +#endif +#ifdef RTNLGRP_PHONET_ROUTE + scm_c_define ("RTNLGRP_PHONET_ROUTE", scm_from_int (RTNLGRP_PHONET_ROUTE)); +#endif +#ifdef RTNLGRP_DCB + scm_c_define ("RTNLGRP_DCB", scm_from_int (RTNLGRP_DCB)); +#endif +#ifdef RTNLGRP_IPV4_NETCONF + scm_c_define ("RTNLGRP_IPV4_NETCONF", scm_from_int (RTNLGRP_IPV4_NETCONF)); +#endif +#ifdef RTNLGRP_IPV6_NETCONF + scm_c_define ("RTNLGRP_IPV6_NETCONF", scm_from_int (RTNLGRP_IPV6_NETCONF)); +#endif +#ifdef RTNLGRP_MDB + scm_c_define ("RTNLGRP_MDB", scm_from_int (RTNLGRP_MDB)); +#endif + scm_add_feature ("socket"); #include "libguile/socket.x" diff --git a/module/ice-9/networking.scm b/module/ice-9/networking.scm index f9ff394..1146d80 100644 --- a/module/ice-9/networking.scm +++ b/module/ice-9/networking.scm @@ -85,6 +85,8 @@ (define (sockaddr:port obj) (vector-ref obj 2)) (define (sockaddr:flowinfo obj) (vector-ref obj 3)) (define (sockaddr:scopeid obj) (vector-ref obj 4)) +(define (sockaddr:pid obj) (vector-ref obj 1)) +(define (sockaddr:groups obj) (vector-ref obj 2)) (define (addrinfo:flags obj) (vector-ref obj 0)) (define (addrinfo:fam obj) (vector-ref obj 1)) -- 2.1.4