Skip to content

Commit 1b2b5f6

Browse files
author
Luigi Rizzo
committedDec 22, 2014
add initial version
0 parents  commit 1b2b5f6

13 files changed

+2834
-0
lines changed
 

‎BSDmakefile

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# to be put in sys/modules/netlink/Makefile
2+
#
3+
# gcc honors -Wmissing-include-dirs
4+
.if ${.CURDIR:H:T} == modules
5+
_MYPATH=${.CURDIR}/../../netlink
6+
.else
7+
_MYPATH=${.CURDIR}
8+
.endif
9+
10+
.PATH: ${_MYPATH}
11+
12+
KMOD = netlink
13+
14+
SRCS = bsd_nlsock.c \
15+
genetlink.c \
16+
netlink.c
17+
18+
CFLAGS += -I${_MYPATH}
19+
20+
.include <bsd.kmod.mk>

‎README

+155
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
Sources for building netlink sockets on FreeBSD,
2+
derived from routing sockets in FreeBSD and modified by
3+
Daniele Di Proietto and Luigi Rizzo, Universita` di Pisa - 2014
4+
5+
This project implements netlink and generic netlink sockets,
6+
enough to build the in-kernel openvswitch datapath.
7+
8+
Documentation on netlink sockets is at
9+
10+
http://1984.lsi.us.es/~pablo/docs/spae.pdf
11+
http://tools.ietf.org/html/rfc3549
12+
13+
Code is organised as follows:
14+
- main source files in sys/netlink/
15+
- the BSDmakefile to be copied to sys/modules/netlink/Makefile
16+
- headers part of the API in sys/netlink/net and sys/netlink/linux
17+
to be copied into /usr/include/net and /usr/include/linux
18+
(or /usr/include/netlink/net and /usr/include/netlink/linux/ )
19+
20+
--- NETLINK sockets and functions ---
21+
22+
netlink sockets natively operate on mbufs in FreeBSD,
23+
on sk_buff on linux. To build the native linux code in FreeBSD, use
24+
#define __COMPAT_MBUF_TYPE sk_buff
25+
in the forced include so the netlink prototypes use the correct type.
26+
27+
netlink build routines expect a linear buffer, which is not what
28+
mbufs provide. To help that, we may allocate a linear buffer during
29+
the construction, which is then freed at the end before sending
30+
the mbuf to the kernel clients.
31+
32+
------
33+
34+
NOTE ON THE HEADERS
35+
In the new-world linux kernel:
36+
37+
According to linux convention sources:
38+
include/uapi/linux/netlink.h
39+
API shared by user and kernel, guarded by _UAPI__LINUX_NETLINK_H
40+
and then installed to userspace as
41+
include/linux/*netlink.h guarded by __LINUX_NETLINK_H
42+
43+
include/linux/netlink.h
44+
main kernel API, starts with #include <uapi/linux/netlink.h>
45+
not used by userspace
46+
47+
include/net/netlink.h
48+
extended kernel API, starts with #include <linux/netlink.h>
49+
(i.e. knows everything)
50+
51+
(same goes for genetlink.h nfnetlink.h and other subfamilies).
52+
In FreeBSD we rename uapi/linux/netlink.h to linux/uapi_netlink.h
53+
so we do not need to modify it when installing.
54+
55+
For installation of the header we need to change
56+
etc/mtree/BSD.include.dist
57+
58+
Case 1: files in /usr/include/linux and /usr/include/net
59+
60+
Index: /home/luigi/FreeBSD/head/etc/mtree/BSD.include.dist
61+
===================================================================
62+
--- /home/luigi/FreeBSD/head/etc/mtree/BSD.include.dist (revision 273452)
63+
+++ /home/luigi/FreeBSD/head/etc/mtree/BSD.include.dist (working copy)
64+
@@ -249,6 +249,8 @@
65+
..
66+
libmilter
67+
..
68+
+ linux
69+
+ ..
70+
lzma
71+
..
72+
machine
73+
Index: /home/luigi/FreeBSD/head/share/mk/src.opts.mk
74+
===================================================================
75+
--- /home/luigi/FreeBSD/head/share/mk/src.opts.mk (revision 273452)
76+
+++ /home/luigi/FreeBSD/head/share/mk/src.opts.mk (working copy)
77+
@@ -116,6 +116,7 @@
78+
NDIS \
79+
NETCAT \
80+
NETGRAPH \
81+
+ NETLINK \
82+
NLS_CATALOGS \
83+
NS_CACHING \
84+
NTP \
85+
Index: /home/luigi/FreeBSD/head/include/Makefile
86+
===================================================================
87+
--- /home/luigi/FreeBSD/head/include/Makefile (revision 273452)
88+
+++ /home/luigi/FreeBSD/head/include/Makefile (working copy)
89+
@@ -186,6 +186,14 @@
90+
${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 *.h \
91+
${DESTDIR}${INCLUDEDIR}/netinet
92+
.endif
93+
+.if ${MK_NETLINK} != "no"
94+
+ cd ${.CURDIR}/../sys/netlink/linux; \
95+
+ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 *.h \
96+
+ ${DESTDIR}${INCLUDEDIR}/linux
97+
+ cd ${.CURDIR}/../sys/netlink/net; \
98+
+ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 *.h \
99+
+ ${DESTDIR}${INCLUDEDIR}/net
100+
+.endif
101+
.if ${MK_PF} != "no"
102+
cd ${.CURDIR}/../sys/netpfil/pf; \
103+
${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 *.h \
104+
@@ -287,6 +295,18 @@
105+
${DESTDIR}${INCLUDEDIR}/netinet; \
106+
done
107+
.endif
108+
+.if ${MK_NETLINK} != "no"
109+
+ cd ${.CURDIR}/../sys/netlink/linux; \
110+
+ for h in *.h; do \
111+
+ ln -fs ../../../sys/netlink/linux/$$h \
112+
+ ${DESTDIR}${INCLUDEDIR}/linux; \
113+
+ done
114+
+ cd ${.CURDIR}/../sys/netlink/net; \
115+
+ for h in *.h; do \
116+
+ ln -fs ../../../sys/netlink/net/$$h \
117+
+ ${DESTDIR}${INCLUDEDIR}/net; \
118+
+ done
119+
+.endif
120+
.if ${MK_PF} != "no"
121+
cd ${.CURDIR}/../sys/netpfil/pf; \
122+
for h in *.h; do \
123+
124+
--- case 2: files in /usr/include/netlink/{net|linux}
125+
126+
127+
Index: /home/luigi/FreeBSD/head/etc/mtree/BSD.include.dist
128+
===================================================================
129+
--- /home/luigi/FreeBSD/head/etc/mtree/BSD.include.dist (revision 273452)
130+
+++ /home/luigi/FreeBSD/head/etc/mtree/BSD.include.dist (working copy)
131+
@@ -275,6 +275,12 @@
132+
..
133+
netipsec
134+
..
135+
+ netlink
136+
+ linux
137+
+ ..
138+
+ net
139+
+ ..
140+
+ ..
141+
netnatm
142+
api
143+
..
144+
Index: /home/luigi/FreeBSD/head/include/Makefile
145+
===================================================================
146+
--- /home/luigi/FreeBSD/head/include/Makefile (revision 273452)
147+
+++ /home/luigi/FreeBSD/head/include/Makefile (working copy)
148+
@@ -52,6 +52,7 @@
149+
geom/mirror geom/mountver geom/multipath geom/nop \
150+
geom/raid geom/raid3 geom/shsec geom/stripe geom/virstor \
151+
netgraph/atm netgraph/netflow \
152+
+ netlink/linux netlink/net \
153+
security/audit \
154+
security/mac_biba security/mac_bsdextended security/mac_lomac \
155+
security/mac_mls security/mac_partition \

‎bsd_nlsock.c

+482
Large diffs are not rendered by default.

‎genetlink.c

+465
Large diffs are not rendered by default.

‎linux/genetlink.h

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright (C) 2014 Daniele Di Proietto, Luigi Rizzo,
3+
* Universita` di Pisa. All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions
7+
* are met:
8+
*
9+
* 1. Redistributions of source code must retain the above copyright
10+
* notice, this list of conditions and the following disclaimer.
11+
* 2. Redistributions in binary form must reproduce the above copyright
12+
* notice, this list of conditions and the following disclaimer in the
13+
* documentation and/or other materials provided with the distribution.
14+
*
15+
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18+
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21+
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24+
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25+
* SUCH DAMAGE.
26+
*/
27+
28+
/*
29+
* $FreeBSD$
30+
*
31+
* The genetlink API (both userspace and kernel).
32+
* For compatibility with linux, the user API part is in a separate file.
33+
* Both need to be installed in the headers for building user apps.
34+
*/
35+
36+
#ifndef _LINUX_GENETLINK_H
37+
#define _LINUX_GENETLINK_H
38+
39+
#include <linux/uapi_genetlink.h>
40+
41+
#ifdef _KERNEL
42+
/*
43+
* Kernel-specific genetlink API
44+
*/
45+
#endif /* _KERNEL */
46+
47+
#endif /* _LINUX_GENETLINK_H */

‎linux/netlink.h

+175
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
/*
2+
* Copyright (C) 2014 Daniele Di Proietto, Luigi Rizzo,
3+
* Universita` di Pisa. All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions
7+
* are met:
8+
*
9+
* 1. Redistributions of source code must retain the above copyright
10+
* notice, this list of conditions and the following disclaimer.
11+
* 2. Redistributions in binary form must reproduce the above copyright
12+
* notice, this list of conditions and the following disclaimer in the
13+
* documentation and/or other materials provided with the distribution.
14+
*
15+
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18+
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21+
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24+
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25+
* SUCH DAMAGE.
26+
*/
27+
28+
/*
29+
* $FreeBSD$
30+
*
31+
* The netlink API (both userspace and kernel).
32+
* For compatibility with linux, the user API part is in a separate file.
33+
* Both need to be installed in the headers for building user apps.
34+
*/
35+
36+
#ifndef _LINUX_NETLINK_H
37+
#define _LINUX_NETLINK_H
38+
39+
#include <linux/uapi_netlink.h>
40+
41+
#ifdef _KERNEL
42+
/*
43+
* Kernel-specific netlink api
44+
*/
45+
46+
/*---- start debugging macros --- luigi */
47+
#define ND(format, ...)
48+
#define D(format, ...) \
49+
do { \
50+
struct timeval __xxts; \
51+
microtime(&__xxts); \
52+
printf("%03d.%06d [%4d] %-25s " format "\n", \
53+
(int)__xxts.tv_sec % 1000, (int)__xxts.tv_usec, \
54+
__LINE__, __FUNCTION__, ##__VA_ARGS__); \
55+
} while (0)
56+
57+
/* rate limited, lps indicates how many per second */
58+
#define RD(lps, format, ...) \
59+
do { \
60+
static int t0, __cnt; \
61+
if (t0 != time_second) { \
62+
t0 = time_second; \
63+
__cnt = 0; \
64+
} \
65+
if (__cnt++ < lps) \
66+
D(format, ##__VA_ARGS__); \
67+
} while (0)
68+
/* XXX 32-bit pointers */
69+
#define _P32(x) ((void *)( \
70+
((uintptr_t)x & 0x8fffffff) | (((uintptr_t)x >> 32) & 0x80000000) ) )
71+
72+
73+
/*---- end debugging macros --- luigi */
74+
75+
#ifdef __COMPAT_MBUF_TYPE
76+
/*
77+
* native linux kernel code has sk_buff * as first argument to netlink calls.
78+
* Our code handles both mbufs and skbufs, but we want to avoid errors
79+
* on the prototype, so linux-derived code can #define __COMPAT_MBUF_TYPE
80+
* to sk_buff so the compiler gets the correct prototypes.
81+
* The definition is only used within the headers.
82+
*/
83+
#define mbuf __COMPAT_MBUF_TYPE
84+
#endif /* __COMPAT_MBUF_TYPE */
85+
86+
struct socket;
87+
struct mbuf; /* we must be compilable with an opaque type */
88+
89+
/*
90+
* Some mbuf pkthdr fields have special meaning when used with netlink:
91+
*
92+
* FIELD MACRO DESCRIPTION
93+
*
94+
* rcvif _MA() linear buffer, possibly external
95+
* fibnum _ML() linear buffer length
96+
* len -- current write offset
97+
* flowid NETLINK_CB() src_portid, 32 bit
98+
* rsstype _MP() protocol (NETLINK_GENERIC etc.)
99+
*
100+
* In more detail:
101+
*
102+
* 1. netlink messages are built incrementally in a linear buffer of
103+
* predefined size. This is a poor match with mbuf chains,
104+
* which may be split and have no predefined size.
105+
* Hence we use two mbuf fields (see above, _MA() and _ML() )
106+
* for the linear buffer pointer and max len,
107+
* and use m_pkthdr.len to record the space used so far
108+
* (remember of course to copy back and fix things before sending).
109+
* These are abstracted by the three macros _MA)(), _ML() and _MC()
110+
* _MA() and _ML() are cleared when passing the buffer back to the kernel
111+
*
112+
* 2. The protocol is mapped through _MP(m) into rsstype, and is used
113+
* in netlink_input()
114+
*
115+
* 3. sk_buff have a 48-byte "control buffer" (cb) to carry aux info.
116+
* In netlink this is wrapped by NETLINK_CB() into a pointer to a
117+
* struct netlink_skb_parms.
118+
* We need at least the portid, the source port for
119+
* messages coming from userspace, which in turn is used to locate the
120+
* destination socket when building a reply.
121+
* Netlink messages do not need flowid, so we store the portid there.
122+
*
123+
*/
124+
125+
#ifndef __COMPAT_MBUF_TYPE /* mappings only work in native systems */
126+
127+
#define _MA(m) (m)->m_pkthdr.rcvif /* linear buffer pointer */
128+
#define _ML(m) ((m)->m_pkthdr.fibnum) /* max length, 16 bit */
129+
#define _MC(m) ((char *)_MA(m) + (m)->m_pkthdr.len) /* cur data ptr */
130+
131+
#define _MP(m) ((m)->m_pkthdr.rsstype) /* netlink proto, 8 bit */
132+
133+
#define NETLINK_CB(_m) (*(struct netlink_skb_parms*)&((_m)->m_pkthdr.flowid))
134+
135+
#else /* __COMPAT_MBUF_TYPE */ /* mbufs are remapped XXX */
136+
/* returns a readonly object */
137+
struct netlink_skb_parms NETLINK_CB(struct mbuf *);
138+
#endif /* !__COMPAT_MBUF_TYPE */
139+
140+
struct netlink_skb_parms { /* XXX needs work */
141+
#if 0
142+
struct scm_creds creds; /* skb credentials */
143+
#endif
144+
uint32_t portid;
145+
#if 0
146+
uint32_t dst_group;
147+
uint32_t flags;
148+
struct sock *ssk;
149+
#endif
150+
};
151+
152+
CTASSERT(sizeof(struct netlink_skb_parms) <= sizeof(uint32_t));
153+
154+
155+
/* TODO: this function is not really remapped.
156+
* It is just a stub that logs the error
157+
*/
158+
#include <sys/syslog.h> /* LOG_INFO */
159+
static inline void
160+
netlink_set_err(void *sock, uint32_t pid, uint32_t group, int err)
161+
{
162+
log(LOG_INFO, "Netlink set err, func:%s\n", __func__);
163+
}
164+
165+
/*
166+
* Linux uses 8192 as a limit, but probably we can go down to 4k
167+
*/
168+
// #define NLMSG_DEFAULT_SIZE (8192 - NLMSG_HDRLEN)
169+
#define NLMSG_DEFAULT_SIZE (4096 - NLMSG_HDRLEN)
170+
171+
#undef mbuf /* XXX see __COMPAT_MBUF_TYPE */
172+
173+
#endif /* _KERNEL */
174+
175+
#endif /* _LINUX_NETLINK_H */

‎linux/uapi_genetlink.h

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* Copyright (C) 2014 Daniele Di Proietto, Luigi Rizzo,
3+
* Universita` di Pisa. All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions
7+
* are met:
8+
*
9+
* 1. Redistributions of source code must retain the above copyright
10+
* notice, this list of conditions and the following disclaimer.
11+
* 2. Redistributions in binary form must reproduce the above copyright
12+
* notice, this list of conditions and the following disclaimer in the
13+
* documentation and/or other materials provided with the distribution.
14+
*
15+
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18+
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21+
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24+
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25+
* SUCH DAMAGE.
26+
*/
27+
28+
/*
29+
* $FreeBSD$
30+
*
31+
* The user-visible API for genetlink sockets.
32+
* These definitions are visible to userspace and kernel.
33+
* In linux similar content is in uapi/linux/genetlink.h,
34+
* copied to /usr/include/linux/genetlink.h with guard changed.
35+
* For simplicity, in FreeBSD we install both uapi_genetlink.h and genetlink.h
36+
* and kernel and userspace both include the latter.
37+
*/
38+
39+
#ifndef _UAPI_LINUX_GENETLINK_H
40+
#define _UAPI_LINUX_GENETLINK_H
41+
42+
#include <linux/netlink.h> /* nested include as in linux */
43+
44+
#define GENL_ID_CTRL 0x10
45+
46+
#define GENL_NAMSIZ 16 /* length of family name */
47+
48+
#define GENL_ID_GENERATE 0
49+
50+
struct genlmsghdr {
51+
uint8_t cmd;
52+
uint8_t version;
53+
uint16_t reserved;
54+
};
55+
56+
#define GENL_HDRLEN NLMSG_ALIGN(sizeof(struct genlmsghdr))
57+
58+
/**************************************************************************
59+
* Controller
60+
**************************************************************************/
61+
62+
enum {
63+
CTRL_CMD_UNSPEC,
64+
CTRL_CMD_NEWFAMILY,
65+
CTRL_CMD_DELFAMILY,
66+
CTRL_CMD_GETFAMILY,
67+
CTRL_CMD_NEWOPS,
68+
CTRL_CMD_DELOPS,
69+
CTRL_CMD_GETOPS,
70+
CTRL_CMD_NEWMCAST_GRP,
71+
CTRL_CMD_DELMCAST_GRP,
72+
CTRL_CMD_GETMCAST_GRP, /* unused */
73+
__CTRL_CMD_MAX,
74+
};
75+
76+
#define CTRL_CMD_MAX (__CTRL_CMD_MAX - 1)
77+
78+
enum {
79+
CTRL_ATTR_UNSPEC,
80+
CTRL_ATTR_FAMILY_ID,
81+
CTRL_ATTR_FAMILY_NAME,
82+
CTRL_ATTR_VERSION,
83+
CTRL_ATTR_HDRSIZE,
84+
CTRL_ATTR_MAXATTR,
85+
CTRL_ATTR_OPS,
86+
CTRL_ATTR_MCAST_GROUPS,
87+
__CTRL_ATTR_MAX,
88+
};
89+
90+
#define CTRL_ATTR_MAX (__CTRL_ATTR_MAX - 1)
91+
92+
enum {
93+
CTRL_ATTR_OP_UNSPEC,
94+
CTRL_ATTR_OP_ID,
95+
CTRL_ATTR_OP_FLAGS,
96+
__CTRL_ATTR_OP_MAX,
97+
};
98+
99+
#define CTRL_ATTR_OP_MAX (__CTRL_ATTR_OP_MAX - 1)
100+
101+
enum {
102+
CTRL_ATTR_MCAST_GRP_UNSPEC,
103+
CTRL_ATTR_MCAST_GRP_NAME,
104+
CTRL_ATTR_MCAST_GRP_ID,
105+
__CTRL_ATTR_MCAST_GRP_MAX,
106+
};
107+
108+
#define CTRL_ATTR_MCAST_GRP_MAX (__CTRL_ATTR_MCAST_GRP_MAX - 1)
109+
110+
111+
#endif /* _UAPI_LINUX_GENETLINK_H */

‎linux/uapi_netlink.h

+207
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
/*
2+
* Copyright (C) 2014 Daniele Di Proietto, Luigi Rizzo,
3+
* Universita` di Pisa. All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions
7+
* are met:
8+
*
9+
* 1. Redistributions of source code must retain the above copyright
10+
* notice, this list of conditions and the following disclaimer.
11+
* 2. Redistributions in binary form must reproduce the above copyright
12+
* notice, this list of conditions and the following disclaimer in the
13+
* documentation and/or other materials provided with the distribution.
14+
*
15+
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18+
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21+
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24+
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25+
* SUCH DAMAGE.
26+
*/
27+
28+
#ifndef _UAPI_LINUX_NETLINK_H
29+
#define _UAPI_LINUX_NETLINK_H
30+
31+
/*
32+
* $FreeBSD$
33+
*
34+
* The user-visible API for netlink sockets.
35+
* These definitions are visible to userspace and kernel.
36+
* In linux similar content is in uapi/linux/netlink.h,
37+
* copied to /usr/include/linux/netlink.h with guard changed.
38+
* For simplicity, in FreeBSD we install both uapi_netlink.h and netlink.h
39+
* and kernel and userspace both include the latter.
40+
*/
41+
42+
#include <sys/types.h>
43+
#include <sys/socket.h>
44+
45+
/*
46+
* AF_NETLINK and PF_NETLINK should go in sys/sys/socket.h.
47+
* We replicate them here for convenience, but eventually should go away.
48+
*/
49+
#ifndef AF_NETLINK
50+
#define AF_NETLINK 38
51+
#define PF_NETLINK 38
52+
#endif /* !AF_NETLINK */
53+
54+
/* XXX Make sure that SOL_NETLINK != SOL_SOCKET */
55+
#define SOL_NETLINK 270 /* in linux it is in linux/socket.h */
56+
57+
/*
58+
* NETLINK_ROUTE is not implemented now.
59+
*/
60+
#define NETLINK_ROUTE 0 /* not implemented */
61+
#define NETLINK_GENERIC 16
62+
#define MAX_LINKS 32 /* how many netlink protocols ? */
63+
64+
/*
65+
* On FreeBSD, sa_family_t is 8 bit, on linux it is 16.
66+
* All sockets on FreeBSD start with an 8-bit len field which we add for
67+
* compatibility here (but probably should not check because linux sw
68+
* will not set it).
69+
* There is no good way to make the two formats binary compatible given
70+
* the endianness.
71+
*/
72+
struct sockaddr_nl {
73+
uint8_t nl_len; /* FreeBSD SPECIFIC */
74+
sa_family_t nl_family; /* AF_NETLINK */
75+
uint16_t nl_pad; /* keep it zero */
76+
uint32_t nl_pid; /* port ID. */
77+
uint32_t nl_groups; /* multicast groups mask */
78+
};
79+
80+
/*
81+
* Messages have this 16-byte header, in host order.
82+
*/
83+
struct nlmsghdr {
84+
uint32_t nlmsg_len; /* total length including header */
85+
uint16_t nlmsg_type; /* type of content */
86+
uint16_t nlmsg_flags; /* additional flags */
87+
uint32_t nlmsg_seq; /* sequence number */
88+
uint32_t nlmsg_pid; /* sender port ID */
89+
};
90+
91+
92+
/* Flags for nlmsg_flags */
93+
94+
#define NLM_F_REQUEST 0x1 /* request message */
95+
#define NLM_F_MULTI 0x2 /* multipart message, ends with NLMSG_DONE */
96+
#define NLM_F_ACK 0x4 /* reply with ack, with zero or error code */
97+
#define NLM_F_ECHO 0x8 /* echo this request */
98+
#define NLM_F_DUMP_INTR 0x10 /* dump inconsistent due to sequence change */
99+
100+
/* Modifiers to GET request */
101+
#define NLM_F_ROOT 0x100 /* specify tree root */
102+
#define NLM_F_MATCH 0x200 /* return all matching */
103+
#define NLM_F_ATOMIC 0x400 /* atomic GET */
104+
#define NLM_F_DUMP (NLM_F_ROOT|NLM_F_MATCH)
105+
106+
/* Modifiers to NEW request */
107+
#define NLM_F_REPLACE 0x100 /* override existing */
108+
#define NLM_F_EXCL 0x200 /* do not touch, if it exists */
109+
#define NLM_F_CREATE 0x400 /* create, if it does not exist */
110+
#define NLM_F_APPEND 0x800 /* add to end of list */
111+
112+
/*
113+
* Both header and body are padded to the next 4 byte boundary.
114+
* (the header is already 16 so there is no real header padding).
115+
*
116+
* When reading the message, we only fetch the useful payload
117+
* (i.e. sizeof(struct nlmsghdr) and NLMSG_LENGTH().
118+
* The padding is accessed/skipped only if there is a following block.
119+
*/
120+
#define NLMSG_ALIGNTO 4U
121+
#define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) )
122+
123+
/*
124+
* Use a compile time assert to check that we do not need header padding,
125+
* and do not bother with complications in the code.
126+
*/
127+
#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
128+
129+
#ifdef CTASSERT
130+
CTASSERT(NLMSG_HDRLEN == sizeof(struct nlmsghdr));
131+
#endif
132+
133+
/*
134+
* NLMSG_LENGTH() is what we need to read, NLMSG_SPACE() is the
135+
* space taken if we have a subsequent part.
136+
* Note that NLMSG_ALIGN(NLMSG_HDRLEN) is pointless as the argument
137+
* is already aligned.
138+
*/
139+
#define NLMSG_LENGTH(len) ((len) + NLMSG_HDRLEN)
140+
#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len))
141+
142+
#if 0 /* unused macros */
143+
/* returns a pointer to the payload of the message */
144+
#define NLMSG_DATA(nlh) ( (void *)((char *)(nlh) + NLMSG_HDRLEN) )
145+
146+
/*
147+
* helper macro, apparently unused.
148+
*/
149+
#define NLMSG_NEXT(nlh, len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \
150+
(struct nlmsghdr*)(((char *)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))
151+
152+
/*
153+
* Returns true if len is >= the message size. Can be used to validate
154+
* the messages.
155+
*/
156+
#define NLMSG_OK(nlh, len) ((len) >= (int)sizeof(struct nlmsghdr) && \
157+
(nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \
158+
(nlh)->nlmsg_len <= (len))
159+
160+
/*
161+
* How much space is left after a header of length 'len'
162+
*/
163+
#define NLMSG_PAYLOAD(nlh, len) ((nlh)->nlmsg_len - NLMSG_SPACE((len)))
164+
165+
#endif /* unused macros */
166+
167+
#define NLMSG_NOOP 0x1 /* Nothing. */
168+
#define NLMSG_ERROR 0x2 /* Error */
169+
#define NLMSG_DONE 0x3 /* End of a dump */
170+
#define NLMSG_OVERRUN 0x4 /* Data lost */
171+
172+
#define NLMSG_MIN_TYPE 0x10
173+
174+
struct nlmsgerr {
175+
int error;
176+
struct nlmsghdr msg;
177+
};
178+
179+
#define NETLINK_ADD_MEMBERSHIP 1
180+
#define NETLINK_DROP_MEMBERSHIP 2
181+
/* there are others which we do not support */
182+
183+
/*
184+
* nlattr is TLV encoded message
185+
* The two high bits of the type encode info.
186+
* The NESTED and BYTEORDER bits are mutually exclusive.
187+
*/
188+
struct nlattr {
189+
uint16_t nla_len;
190+
uint16_t nla_type;
191+
};
192+
193+
/* attributes use the high 2 bits of nla_type for nested and byteorder */
194+
#define NLA_F_NESTED (1 << 15) /* nested attributes */
195+
#define NLA_F_NET_BYTEORDER (1 << 14) /* set if data in net order */
196+
#define NLA_TYPE_MASK ~(NLA_F_NESTED | NLA_F_NET_BYTEORDER)
197+
198+
#define NLA_ALIGNTO 4U
199+
#define NLA_ALIGN(len) (((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1))
200+
#define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr)))
201+
202+
#define MAX_LINKS 32
203+
204+
#define _SC_UIO_MAXIOV _SC_IOV_MAX
205+
#define SO_RCVBUFFORCE SO_RCVBUF
206+
207+
#endif /* _UAPI_LINUX_NETLINK_H */

‎net/genetlink.h

+233
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
/*
2+
* Copyright (C) 2014 Daniele Di Proietto, Luigi Rizzo,
3+
* Universita` di Pisa. All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions
7+
* are met:
8+
*
9+
* 1. Redistributions of source code must retain the above copyright
10+
* notice, this list of conditions and the following disclaimer.
11+
* 2. Redistributions in binary form must reproduce the above copyright
12+
* notice, this list of conditions and the following disclaimer in the
13+
* documentation and/or other materials provided with the distribution.
14+
*
15+
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18+
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21+
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24+
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25+
* SUCH DAMAGE.
26+
*/
27+
28+
/*
29+
* $FreeBSD$
30+
*
31+
* Kernel-private header for genetlink.
32+
* Has nested includes for the whole netlink kernel API
33+
*/
34+
35+
#ifndef _NET_GENETLINK_H
36+
#define _NET_GENETLINK_H
37+
38+
#include <linux/genetlink.h>
39+
#include <net/netlink.h>
40+
41+
#ifdef __COMPAT_MBUF_TYPE
42+
#define mbuf __COMPAT_MBUF_TYPE
43+
#endif /* __COMPAT_MBUF_TYPE */
44+
45+
#define GENL_HDRLEN NLMSG_ALIGN(sizeof(struct genlmsghdr))
46+
47+
#define GENL_ADMIN_PERM 0x01
48+
#define GENL_CMD_CAP_DO 0x02
49+
#define GENL_CMD_CAP_DUMP 0x04
50+
#define GENL_CMD_CAP_HASPOL 0x08
51+
52+
struct genl_info;
53+
struct mbuf; /* we must be compilable with an opaque type */
54+
struct netlink_callback;
55+
struct net;
56+
57+
struct genl_multicast_group;
58+
59+
struct genl_family {
60+
unsigned int id;
61+
unsigned int hdrsize;
62+
char name[GENL_NAMSIZ];
63+
unsigned int version;
64+
unsigned int maxattr;
65+
bool netnsok;
66+
bool parallel_ops;
67+
#if 0 /* XXX TODO:restore it */
68+
int (*pre_doit)(struct genl_ops *ops,
69+
struct mbuf *m,
70+
struct genl_info *info);
71+
void (*post_doit)(struct genl_ops *ops,
72+
struct mbuf *m,
73+
struct genl_info *info);
74+
struct nlattr ** attrbuf; /* private */
75+
76+
77+
struct list_head ops_list; /* private */
78+
struct list_head family_list; /* private */
79+
struct list_head mcast_groups; /* private */
80+
#endif
81+
LIST_ENTRY(genl_family) family_list;
82+
const struct genl_ops *ops; // XXX was ops_list;
83+
/* TODO: only one possible group per family */
84+
const struct genl_multicast_group *mcgrps; // XXX was mcast_group;
85+
unsigned int n_ops; // XXX was size_t ops_num;
86+
unsigned int n_mcgrps;
87+
unsigned int mcgrp_offset; // from 3.13
88+
};
89+
90+
struct genl_multicast_group {
91+
struct genl_family * family; /* private */
92+
char name[GENL_NAMSIZ];
93+
uint32_t id;
94+
};
95+
96+
struct genl_ops {
97+
uint8_t cmd;
98+
uint8_t internal_flags;
99+
unsigned int flags;
100+
const struct nla_policy *policy;
101+
int (*doit)(struct mbuf *m,
102+
struct genl_info *info);
103+
int (*dumpit)(struct mbuf *m,
104+
struct netlink_callback *cb);
105+
#if 0
106+
/* TODO: fields not used by openvswitch */
107+
int (*done)(struct netlink_callback *cb);
108+
struct list_head ops_list;
109+
#endif
110+
};
111+
112+
struct genl_info {
113+
uint32_t snd_seq;
114+
uint32_t snd_portid;
115+
struct nlmsghdr * nlhdr;
116+
struct genlmsghdr * genlhdr;
117+
void * userhdr;
118+
struct nlattr ** attrs;
119+
#if 0 // XXX check
120+
#ifdef CONFIG_NET_NS
121+
struct net * _net;
122+
#endif
123+
void * user_ptr[2];
124+
#endif
125+
};
126+
127+
struct netlink_callback {
128+
struct mbuf *skb; /* linux calls this this way */
129+
const struct nlmsghdr *nlh;
130+
#if 0
131+
int (*dump)(struct mbuf * m,
132+
struct netlink_callback *cb);
133+
int (*done)(struct netlink_callback *cb);
134+
void *data;
135+
/* the module that dump function belong to */
136+
struct module *module;
137+
u16 family;
138+
u16 min_dump_alloc;
139+
unsigned int prev_seq, seq;
140+
#endif
141+
long args[6];
142+
};
143+
144+
145+
146+
int genl_register_family_with_ops(struct genl_family *family,
147+
struct genl_ops *ops, size_t n_ops);
148+
static inline int
149+
genl_register_family(struct genl_family *family)
150+
{
151+
return genl_register_family_with_ops(family, NULL, 0);
152+
}
153+
154+
int genl_unregister_family(struct genl_family *family);
155+
156+
/*
157+
* XXX incomplete
158+
*/
159+
static inline int
160+
genl_set_err(struct genl_family *fam, struct net *net,
161+
uint32_t portid, uint32_t group, uint32_t code)
162+
{
163+
if (group >= fam->mcgrp_offset)
164+
return -EINVAL;
165+
group += fam->mcgrp_offset;
166+
/* we do not support namespaces yet */
167+
netlink_set_err(NULL /* net->genl_sock */, portid, group, code);
168+
return 0;
169+
}
170+
171+
/**
172+
* genlmsg_msg_size - length of genetlink message not including padding
173+
* @payload: length of message payload
174+
*/
175+
static inline int
176+
genlmsg_msg_size(int payload)
177+
{
178+
return GENL_HDRLEN + payload;
179+
}
180+
181+
/**
182+
* genlmsg_total_size - length of genetlink message including padding
183+
* @payload: length of message payload
184+
*/
185+
static inline int
186+
genlmsg_total_size(int payload)
187+
{
188+
return NLMSG_ALIGN(genlmsg_msg_size(payload));
189+
}
190+
191+
static inline void *
192+
genlmsg_data(const struct genlmsghdr *gnlh)
193+
{
194+
return ((unsigned char *) (uintptr_t)gnlh + GENL_HDRLEN);
195+
}
196+
197+
/**
198+
* genlmsg_new - Allocate a new generic netlink message
199+
* @payload: size of the message payload
200+
* @flags: the type of memory to allocate.
201+
*/
202+
static inline struct mbuf *
203+
genlmsg_new(size_t payload, int flags)
204+
{
205+
return nlmsg_new(genlmsg_total_size(payload), flags);
206+
}
207+
208+
static inline void
209+
genlmsg_cancel(struct mbuf *m, void *hdr)
210+
{
211+
}
212+
213+
void *genlmsg_put(struct mbuf *m, uint32_t portid, uint32_t seq,
214+
struct genl_family *family, int flags, uint8_t cmd);
215+
int genlmsg_end(struct mbuf *m, void *hdr);
216+
int genlmsg_reply(struct mbuf *m, struct genl_info *info);
217+
void genl_notify(struct genl_family *f,
218+
struct mbuf *m, struct net *net, uint32_t portid, uint32_t group,
219+
struct nlmsghdr *nlh, int flags);
220+
int genlmsg_multicast(struct genl_family *family,
221+
struct mbuf *m, uint32_t portid, unsigned int group, int flags);
222+
/* TODO: net namespace not implemented */
223+
#define genlmsg_multicast_netns(f, net,a,b,c,d) genlmsg_multicast(f, a,b,c,d)
224+
int genl_register_mc_group(struct genl_family *family,
225+
struct genl_multicast_group *grp);
226+
int genlmsg_unicast(struct net *net, struct mbuf *m, uint32_t portid);
227+
228+
/* TODO: net namespace not implemented */
229+
#define genl_info_net(info) NULL
230+
231+
#undef mbuf // just in case, see __COMPAT_MBUF_TYPE
232+
233+
#endif /* _NET_GENETLINK_H */

‎net/netlink.h

+301
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,301 @@
1+
/*
2+
* Copyright (C) 2014 Daniele Di Proietto, Luigi Rizzo,
3+
* Universita` di Pisa. All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions
7+
* are met:
8+
*
9+
* 1. Redistributions of source code must retain the above copyright
10+
* notice, this list of conditions and the following disclaimer.
11+
* 2. Redistributions in binary form must reproduce the above copyright
12+
* notice, this list of conditions and the following disclaimer in the
13+
* documentation and/or other materials provided with the distribution.
14+
*
15+
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18+
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21+
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24+
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25+
* SUCH DAMAGE.
26+
*/
27+
28+
/*
29+
* $FreeBSD$
30+
*
31+
* Extended kernel netlink APIs
32+
* Has nested include for linux/netlink.h
33+
*/
34+
35+
#ifndef _NET_NETLINK_H
36+
#define _NET_NETLINK_H
37+
38+
#ifndef _KERNEL
39+
#error this is a kernel-only file
40+
#endif
41+
42+
#include <sys/param.h>
43+
#include <sys/types.h>
44+
#include <sys/systm.h>
45+
#include <sys/syslog.h>
46+
47+
#include <linux/netlink.h>
48+
49+
#ifdef __COMPAT_MBUF_TYPE
50+
#define mbuf __COMPAT_MBUF_TYPE
51+
#endif /* __COMPAT_MBUF_TYPE */
52+
53+
/*
54+
* support for registering NETLINK protocols.
55+
* bsd_nl_fn is the protocol descriptor, bsd_nl_proto_reg() registers it.
56+
* We do not support unloading.
57+
*/
58+
struct bsd_nl_fn { /* protocol descriptors */
59+
uint32_t id; /* protocol id */
60+
int (*rx)(char *data);
61+
};
62+
63+
/* register a protocol */
64+
int bsd_nl_proto_reg(struct bsd_nl_fn *);
65+
/* EINVAL for bad proto numbers, EAFNOSUPPORT if not set, 0 if ok */
66+
int bsd_nl_proto_check(int proto);
67+
68+
/* these are FreeBSD internal APIs */
69+
int bsd_netlink_send_msg(struct socket *so, struct mbuf *m);
70+
int netlink_receive_packet(struct mbuf *, struct socket *, int);
71+
72+
#define M_NETLINK_MULTICAST M_PROTO1
73+
74+
#define nl_src_portid so_fibnum
75+
#define nl_dst_portid so_user_cookie
76+
77+
78+
/*
79+
* netlink attribute types.
80+
*/
81+
enum {
82+
NLA_UNSPEC,
83+
NLA_U8,
84+
NLA_U16,
85+
NLA_U32,
86+
NLA_U64,
87+
NLA_STRING,
88+
NLA_FLAG,
89+
NLA_MSECS,
90+
NLA_NESTED,
91+
NLA_NESTED_COMPAT,
92+
NLA_NUL_STRING,
93+
NLA_BINARY,
94+
NLA_S8,
95+
NLA_S16,
96+
NLA_S32,
97+
NLA_S64,
98+
__NLA_TYPE_MAX,
99+
};
100+
101+
#define NLA_TYPE_MAX (__NLA_TYPE_MAX - 1)
102+
103+
struct nla_policy {
104+
uint16_t type;
105+
uint16_t len;
106+
};
107+
108+
struct mbuf *nlmsg_new(size_t payload, int flags);
109+
110+
/*
111+
* nla_put() and __nla_put() append data to a nlmsg.
112+
* __nla_put() does not check for space.
113+
* Return 0 if ok, EMSGSIZE on error
114+
*/
115+
int nla_put(struct mbuf *m, int attrtype, int attrlen, const void *data);
116+
#define __nla_put nla_put
117+
118+
static inline int
119+
nla_put_u8(struct mbuf *m, int attrtype, uint8_t value)
120+
{
121+
return nla_put(m, attrtype, sizeof(uint8_t), &value);
122+
}
123+
124+
static inline int
125+
nla_put_u16(struct mbuf *m, int attrtype, uint16_t value)
126+
{
127+
return nla_put(m, attrtype, sizeof(uint16_t), &value);
128+
}
129+
130+
static inline int
131+
nla_put_u32(struct mbuf *m, int attrtype, uint32_t value)
132+
{
133+
return nla_put(m, attrtype, sizeof(uint32_t), &value);
134+
}
135+
136+
static inline int
137+
nla_put_u64(struct mbuf *m, int attrtype, uint64_t value)
138+
{
139+
return nla_put(m, attrtype, sizeof(uint64_t), &value);
140+
}
141+
142+
static inline int
143+
nla_put_flag(struct mbuf *m, int attrtype)
144+
{
145+
return nla_put(m, attrtype, 0, NULL);
146+
}
147+
148+
static inline int
149+
nla_put_string(struct mbuf *m, int attrtype,
150+
const char *str)
151+
{
152+
return nla_put(m, attrtype, strlen(str) + 1, str);
153+
}
154+
155+
/* note we de-const the argument */
156+
static inline void *
157+
nla_data(const struct nlattr *nla)
158+
{
159+
return (char *)(uintptr_t) nla + NLA_HDRLEN;
160+
}
161+
162+
static inline uint8_t
163+
nla_get_u8(const struct nlattr *nla)
164+
{
165+
return *(const uint8_t *) nla_data(nla);
166+
}
167+
168+
static inline uint16_t
169+
nla_get_u16(const struct nlattr *nla)
170+
{
171+
return *(const uint16_t *) nla_data(nla);
172+
}
173+
174+
static inline uint32_t
175+
nla_get_u32(const struct nlattr *nla)
176+
{
177+
return *(const uint32_t *) nla_data(nla);
178+
}
179+
180+
static inline uint64_t nla_get_u64(const struct nlattr *nla)
181+
{
182+
/* TODO: in linux this is done differently. why? */
183+
return *(const uint64_t *) nla_data(nla);
184+
}
185+
186+
struct nlattr *nla_nest_start(struct mbuf *m, int attrtype);
187+
int nla_nest_end(struct mbuf *m, struct nlattr *start);
188+
void nla_nest_cancel(struct mbuf *m, struct nlattr* start);
189+
struct nlattr * nla_reserve(struct mbuf *m, int attrtype, int attrlen);
190+
#define __nla_reserve nla_reserve
191+
192+
/**
193+
* nla_attr_size - length of attribute not including padding
194+
* @payload: length of payload
195+
*/
196+
static inline int
197+
nla_attr_size(int payload)
198+
{
199+
return NLA_HDRLEN + payload;
200+
}
201+
202+
/**
203+
* nla_total_size - total length of attribute including padding
204+
* @payload: length of payload
205+
*/
206+
static inline int
207+
nla_total_size(int payload)
208+
{
209+
return NLA_ALIGN(nla_attr_size(payload));
210+
}
211+
212+
static inline void *
213+
nlmsg_data(const struct nlmsghdr *nlh)
214+
{
215+
return (unsigned char *)(uintptr_t) nlh + NLMSG_HDRLEN;
216+
}
217+
218+
219+
220+
static inline int
221+
nla_ok(const struct nlattr *nla, int remaining)
222+
{
223+
return remaining >= (int) sizeof(*nla) &&
224+
nla->nla_len >= sizeof(*nla) &&
225+
nla->nla_len <= remaining;
226+
}
227+
228+
static inline struct nlattr *
229+
nla_next(const struct nlattr *nla, int *remaining)
230+
{
231+
int totlen = NLA_ALIGN(nla->nla_len);
232+
233+
*remaining -= totlen;
234+
return (struct nlattr *) ((char *) (uintptr_t)nla + totlen);
235+
}
236+
237+
static inline int
238+
nla_is_last(const struct nlattr *nla, int rem)
239+
{
240+
return nla->nla_len == rem;
241+
}
242+
243+
/*
244+
* NOTE: this should return unsigned, not signed, because the underlying
245+
* nla->nla_type is unsigned. Unfortunately also on linux the function
246+
* returns a signed value.
247+
*/
248+
static inline int
249+
nla_type(const struct nlattr *nla)
250+
{
251+
return nla->nla_type & NLA_TYPE_MASK;
252+
}
253+
254+
static inline int
255+
nla_len(const struct nlattr *nla)
256+
{
257+
return nla->nla_len - NLA_HDRLEN;
258+
}
259+
260+
static inline int
261+
nla_padlen(int payload)
262+
{
263+
return nla_total_size(payload) - nla_attr_size(payload);
264+
}
265+
266+
267+
#define nla_for_each_attr(pos, head, len, rem) \
268+
for (pos = head, rem = len; \
269+
nla_ok(pos, rem); \
270+
pos = nla_next(pos, &(rem)))
271+
272+
#define nla_for_each_nested(pos, nla, rem) \
273+
nla_for_each_attr(pos, nla_data(nla), nla_len(nla), rem)
274+
275+
#define nla_put_be64 nla_put_u64
276+
#define nla_put_be32 nla_put_u32
277+
#define nla_put_be16 nla_put_u16
278+
#define nla_get_be16 nla_get_u16
279+
#define nla_get_be32 nla_get_u32
280+
#define nla_get_be64 nla_get_u64
281+
282+
int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head,
283+
int len, const struct nla_policy *policy);
284+
285+
static inline int
286+
nla_parse_nested(struct nlattr *tb[], int maxtype,
287+
const struct nlattr *nla, const struct nla_policy *policy)
288+
{
289+
return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy);
290+
}
291+
292+
int nlmsg_end(struct mbuf *m, struct nlmsghdr *nlh);
293+
struct genl_info; // XXX
294+
int nlmsg_reply(struct mbuf *m, struct genl_info *info);
295+
296+
#define nla_memcpy(dest, src, len) \
297+
memcpy(dest, nla_data(src), min(len,nla_len(src)))
298+
299+
#undef mbuf /* XXX see __COMPAT_MBUF_TYPE */
300+
301+
#endif /* _NET_NETLINK_H */

‎netlink.c

+512
Large diffs are not rendered by default.

‎test/Makefile

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
CFLAGS += -I.. -Wall -Werror -O2
2+
3+
all: nltest
4+
5+
clean:
6+
-rm *.o nltest

‎test/nltest.c

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/*
2+
* netlink test program
3+
* Simple commands (command line arguments)
4+
* o N open netlink protocol n
5+
* r N read N bytes
6+
* w N write N bytes
7+
* c close
8+
* Starts with a GENETLINK socket open
9+
*/
10+
11+
#include <stdio.h>
12+
#include <stdlib.h>
13+
#include <strings.h> /* bzero */
14+
#include <unistd.h>
15+
#include <errno.h>
16+
#include <sys/time.h>
17+
#include <linux/netlink.h>
18+
19+
/*---- start debugging macros --- luigi */
20+
#define ND(format, ...)
21+
#define D(format, ...) \
22+
do { \
23+
struct timeval __xxts; \
24+
gettimeofday(&__xxts, NULL); \
25+
printf("%03d.%06d [%4d] %-25s " format "\n", \
26+
(int)__xxts.tv_sec % 1000, (int)__xxts.tv_usec, \
27+
__LINE__, __FUNCTION__, ##__VA_ARGS__); \
28+
} while (0)
29+
30+
/*
31+
* open the netlink socket
32+
*/
33+
static int
34+
do_open(int proto)
35+
{
36+
struct sockaddr_nl a = { AF_NETLINK, 0 };
37+
int i, s = socket(AF_NETLINK, SOCK_RAW, proto);
38+
if (s < 0) {
39+
D("open %d fails with error %d", proto, errno);
40+
return s;
41+
}
42+
i = connect(s, (struct sockaddr *)&a, sizeof(a));
43+
D("connect returns %d pid %d", i, a.nl_pid);
44+
return s;
45+
}
46+
47+
char buf[65536];
48+
49+
static int
50+
do_read(int s, int l)
51+
{
52+
int ret;
53+
socklen_t srclen;
54+
struct sockaddr_nl src;
55+
if (s < 0 || l < 1 || l > sizeof(buf)) {
56+
D("wrong arguments s %d len %d", s, l);
57+
return -1;
58+
}
59+
srclen = sizeof(src);
60+
bzero(&src, sizeof(src));
61+
ret = recvfrom(s, buf, l, 0, (struct sockaddr *)&src, &srclen);
62+
D("recvfrom %d returns %d from sa_len %d family %d pid %d",
63+
l, ret, srclen, src.nl_len, src.nl_pid);
64+
return ret;
65+
}
66+
67+
static int
68+
do_write(int s, int l)
69+
{
70+
struct nlmsghdr *n;
71+
72+
int ret;
73+
if (s < 0 || l < 1 || l > sizeof(buf)) {
74+
D("wrong arguments s %d len %d", s, l);
75+
return -1;
76+
}
77+
78+
n = (struct nlmsghdr *)buf;
79+
n->nlmsg_len = l;
80+
n->nlmsg_flags |= NLM_F_REQUEST | NLM_F_ACK;
81+
n->nlmsg_type = NLMSG_MIN_TYPE; // force callback
82+
ret = send(s, buf, l, 0);
83+
D("send returns %d", ret);
84+
return ret;
85+
}
86+
87+
int
88+
main(int argc, char *argv[])
89+
{
90+
int s;
91+
int x = NETLINK_GENERIC;
92+
int i = 1; /* argument pointer */
93+
94+
if (0 && argc > 1) {
95+
x = atoi(argv[1]);
96+
i++;
97+
}
98+
s = do_open(x);
99+
D("socket returns %d", s);
100+
101+
for (; i < argc; i++) {
102+
switch (*argv[i]) {
103+
case 'r': /* read */
104+
do_read(s, atoi(argv[++i]));
105+
break;
106+
case 'w': /* write */
107+
do_write(s, atoi(argv[++i]));
108+
break;
109+
case 'c': /* close */
110+
close(s);
111+
s = -1;
112+
break;
113+
case 'o': /* open */
114+
s = do_open(atoi(argv[++i]));
115+
break;
116+
}
117+
}
118+
119+
return 0;
120+
}

0 commit comments

Comments
 (0)
Please sign in to comment.