]>
Commit | Line | Data |
---|---|---|
0302c83d MT |
1 | 718183 - Provide native systemd unit file |
2 | ||
3 | Gathered from following upstream git commits and backported to 5.7. | |
4 | ||
5 | commit 19499c3c90bf9d7b2b9e5d08baa26cc6bba28a11 | |
6 | Author: Jan Safranek <jsafranek@users.sourceforge.net> | |
7 | Date: Mon Aug 8 15:48:54 2011 +0200 | |
8 | ||
9 | CHANGES: snmpd: integrated with systemd, see README.systemd for details. | |
10 | ||
11 | It brings sd-daemon.c and .h directly downloaded from systemd. I've made very | |
12 | few changes to it to match our NETSNMP_NO_SYSTEMD and include paths. | |
13 | ||
14 | commit fef6cddfdb94da1a6b1fb768af62918b80f11fd3 | |
15 | Author: Jan Safranek <jsafranek@users.sourceforge.net> | |
16 | Date: Mon Aug 8 15:48:54 2011 +0200 | |
17 | ||
18 | CHANGES: snmptrapd: integrate systemd notification support. | |
19 | ||
20 | commit 0641e43c694c485cbbffef0556efc4641bd3ff50 | |
21 | Author: Jan Safranek <jsafranek@users.sourceforge.net> | |
22 | Date: Mon Aug 8 15:48:54 2011 +0200 | |
23 | ||
24 | Add sd_find_inet_socket() and sd_find_inet_unisx() helpers into | |
25 | system-specific code. This will help us to find various sockets | |
26 | created by systemd much easier. | |
27 | ||
28 | commit 76530a89f1c8bbd0b63acce63e10d5d4812a1a16 | |
29 | Author: Jan Safranek <jsafranek@users.sourceforge.net> | |
30 | Date: Mon Aug 8 15:48:54 2011 +0200 | |
31 | ||
32 | Check sockets created by systemd when opening new server sockets. | |
33 | ||
34 | systemd can pass sockets to our daemons during startup using LISTEN_FDS | |
35 | environment variable. So check this variable when opening new listening | |
36 | socket - maybe system has already opened the socket for us. | |
37 | ||
38 | commit bf108d7f1354f6276fc43c129963f2c49b9fc242 | |
39 | Author: Jan Safranek <jsafranek@users.sourceforge.net> | |
40 | Date: Mon Aug 8 15:48:54 2011 +0200 | |
41 | ||
42 | Added sample systemd service files. | |
43 | ||
44 | commit 884ec488a6596380ba283d707827dd926a52e0b2 | |
45 | Author: Jan Safranek <jsafranek@users.sourceforge.net> | |
46 | Date: Mon Aug 8 15:48:55 2011 +0200 | |
47 | ||
48 | Run autoheader+autoconf. | |
49 | ||
50 | commit 86132e3f1e6ef7b4e0b96d8fa24e37c81b71b0e0 | |
51 | Author: Jan Safranek <jsafranek@users.sourceforge.net> | |
52 | Date: Tue Aug 9 10:53:43 2011 +0200 | |
53 | ||
54 | Update systemd documentation and samples. | |
55 | ||
56 | - add socket unit for snmpd to paralelize boot | |
57 | - update WantedBy in socket units as recommended by http://0pointer.de/blog/projects/socket-activation.html | |
58 | - rephrase README.systemd | |
59 | ||
60 | ||
61 | diff -up net-snmp-5.7.2/agent/snmpd.c.systemd net-snmp-5.7.2/agent/snmpd.c | |
62 | --- net-snmp-5.7.2/agent/snmpd.c.systemd 2012-10-10 00:28:58.000000000 +0200 | |
63 | +++ net-snmp-5.7.2/agent/snmpd.c 2012-11-12 10:18:46.084369548 +0100 | |
64 | @@ -164,6 +164,10 @@ typedef long fd_mask; | |
65 | ||
66 | #endif | |
67 | ||
68 | +#ifndef NETSNMP_NO_SYSTEMD | |
69 | +#include <net-snmp/library/sd-daemon.h> | |
70 | +#endif | |
71 | + | |
72 | netsnmp_feature_want(logging_file) | |
73 | netsnmp_feature_want(logging_stdio) | |
74 | netsnmp_feature_want(logging_syslog) | |
75 | @@ -441,18 +445,26 @@ main(int argc, char *argv[]) | |
76 | int agent_mode = -1; | |
77 | char *pid_file = NULL; | |
78 | char option_compatability[] = "-Le"; | |
79 | + int prepared_sockets = 0; | |
80 | #if HAVE_GETPID | |
81 | int fd; | |
82 | FILE *PID; | |
83 | #endif | |
84 | ||
85 | #ifndef WIN32 | |
86 | +#ifndef NETSNMP_NO_SYSYSTEMD | |
87 | + /* check if systemd has sockets for us and don't close them */ | |
88 | + prepared_sockets = netsnmp_sd_listen_fds(0); | |
89 | +#endif /* NETSNMP_NO_SYSYSTEMD */ | |
90 | + | |
91 | /* | |
92 | * close all non-standard file descriptors we may have | |
93 | * inherited from the shell. | |
94 | */ | |
95 | - for (i = getdtablesize() - 1; i > 2; --i) { | |
96 | - (void) close(i); | |
97 | + if (!prepared_sockets) { | |
98 | + for (i = getdtablesize() - 1; i > 2; --i) { | |
99 | + (void) close(i); | |
100 | + } | |
101 | } | |
102 | #endif /* #WIN32 */ | |
103 | ||
104 | @@ -1100,6 +1112,19 @@ main(int argc, char *argv[]) | |
105 | netsnmp_addrcache_initialise(); | |
106 | ||
107 | /* | |
108 | + * Let systemd know we're up. | |
109 | + */ | |
110 | +#ifndef NETSNMP_NO_SYSTEMD | |
111 | + netsnmp_sd_notify(1, "READY=1\n"); | |
112 | + if (prepared_sockets) | |
113 | + /* | |
114 | + * Clear the environment variable, we already processed all the sockets | |
115 | + * by now. | |
116 | + */ | |
117 | + netsnmp_sd_listen_fds(1); | |
118 | +#endif | |
119 | + | |
120 | + /* | |
121 | * Forever monitor the dest_port for incoming PDUs. | |
122 | */ | |
123 | DEBUGMSGTL(("snmpd/main", "We're up. Starting to process data.\n")); | |
124 | diff -up net-snmp-5.7.2/apps/snmptrapd.c.systemd net-snmp-5.7.2/apps/snmptrapd.c | |
125 | --- net-snmp-5.7.2/apps/snmptrapd.c.systemd 2012-10-10 00:28:58.000000000 +0200 | |
126 | +++ net-snmp-5.7.2/apps/snmptrapd.c 2012-11-12 10:18:46.084369548 +0100 | |
127 | @@ -125,6 +125,10 @@ SOFTWARE. | |
128 | ||
129 | #include <net-snmp/net-snmp-features.h> | |
130 | ||
131 | +#ifndef NETSNMP_NO_SYSTEMD | |
132 | +#include <net-snmp/library/sd-daemon.h> | |
133 | +#endif | |
134 | + | |
135 | #ifndef BSD4_3 | |
136 | #define BSD4_2 | |
137 | #endif | |
138 | @@ -655,15 +659,22 @@ main(int argc, char *argv[]) | |
139 | int agentx_subagent = 1; | |
140 | #endif | |
141 | netsnmp_trapd_handler *traph; | |
142 | + int prepared_sockets = 0; | |
143 | ||
144 | ||
145 | #ifndef WIN32 | |
146 | +#ifndef NETSNMP_NO_SYSTEMD | |
147 | + /* check if systemd has sockets for us and don't close them */ | |
148 | + prepared_sockets = netsnmp_sd_listen_fds(0); | |
149 | +#endif | |
150 | /* | |
151 | * close all non-standard file descriptors we may have | |
152 | * inherited from the shell. | |
153 | */ | |
154 | - for (i = getdtablesize() - 1; i > 2; --i) { | |
155 | - (void) close(i); | |
156 | + if (!prepared_sockets) { | |
157 | + for (i = getdtablesize() - 1; i > 2; --i) { | |
158 | + (void) close(i); | |
159 | + } | |
160 | } | |
161 | #endif /* #WIN32 */ | |
162 | ||
163 | @@ -1311,6 +1322,19 @@ main(int argc, char *argv[]) | |
164 | #endif | |
165 | #endif | |
166 | ||
167 | + /* | |
168 | + * Let systemd know we're up. | |
169 | + */ | |
170 | +#ifndef NETSNMP_NO_SYSTEMD | |
171 | + netsnmp_sd_notify(1, "READY=1\n"); | |
172 | + if (prepared_sockets) | |
173 | + /* | |
174 | + * Clear the environment variable, we already processed all the sockets | |
175 | + * by now. | |
176 | + */ | |
177 | + netsnmp_sd_listen_fds(1); | |
178 | +#endif | |
179 | + | |
180 | #ifdef WIN32SERVICE | |
181 | trapd_status = SNMPTRAPD_RUNNING; | |
182 | #endif | |
183 | diff -up net-snmp-5.7.2/configure.d/config_modules_lib.systemd net-snmp-5.7.2/configure.d/config_modules_lib | |
184 | --- net-snmp-5.7.2/configure.d/config_modules_lib.systemd 2012-10-10 00:28:58.000000000 +0200 | |
185 | +++ net-snmp-5.7.2/configure.d/config_modules_lib 2012-11-12 10:18:46.085369546 +0100 | |
186 | @@ -53,6 +53,14 @@ if test "x$PARTIALTARGETOS" = "xmingw32" | |
187 | other_ftobjs_list="$other_ftobjs_list winpipe.ft" | |
188 | fi | |
189 | ||
190 | +# Linux systemd | |
191 | +if test "x$with_systemd" == "xyes"; then | |
192 | + other_src_list="$other_src_list sd-daemon.c" | |
193 | + other_objs_list="$other_objs_list sd-daemon.o" | |
194 | + other_lobjs_list="$other_lobjs_list sd-daemon.lo" | |
195 | + other_ftobjs_list="$other_ftobjs_list sd-daemon.ft" | |
196 | +fi | |
197 | + | |
198 | AC_SUBST(other_src_list) | |
199 | AC_SUBST(other_objs_list) | |
200 | AC_SUBST(other_lobjs_list) | |
201 | diff -up net-snmp-5.7.2/configure.d/config_project_with_enable.systemd net-snmp-5.7.2/configure.d/config_project_with_enable | |
202 | --- net-snmp-5.7.2/configure.d/config_project_with_enable.systemd 2012-10-10 00:28:58.000000000 +0200 | |
203 | +++ net-snmp-5.7.2/configure.d/config_project_with_enable 2012-11-12 10:18:46.086369544 +0100 | |
204 | @@ -690,6 +690,15 @@ if test "x$with_dummy_values" != "xyes"; | |
205 | data for]) | |
206 | fi | |
207 | ||
208 | +NETSNMP_ARG_WITH(systemd, | |
209 | +[ --with-systemd Provide systemd support. See README.systemd | |
210 | + for details.]) | |
211 | +# Define unless specifically suppressed (i.e., option defaults to false). | |
212 | +if test "x$with_systemd" != "xyes"; then | |
213 | + AC_DEFINE(NETSNMP_NO_SYSTEMD, 1, | |
214 | + [If you don't want to integrate with systemd.]) | |
215 | +fi | |
216 | + | |
217 | NETSNMP_ARG_ENABLE(set-support, | |
218 | [ --disable-set-support Do not allow SNMP set requests.]) | |
219 | if test "x$enable_set_support" = "xno"; then | |
220 | diff -up net-snmp-5.7.2/configure.systemd net-snmp-5.7.2/configure | |
221 | --- net-snmp-5.7.2/configure.systemd 2012-10-10 00:35:37.000000000 +0200 | |
222 | +++ net-snmp-5.7.2/configure 2012-11-12 10:18:46.099369517 +0100 | |
223 | @@ -950,6 +950,8 @@ with_kmem_usage | |
224 | enable_kmem_usage | |
225 | with_dummy_values | |
226 | enable_dummy_values | |
227 | +with_systemd | |
228 | +enable_systemd | |
229 | enable_set_support | |
230 | with_set_support | |
231 | with_sys_contact | |
232 | @@ -1866,6 +1868,8 @@ Configuring the agent: | |
233 | This is technically not compliant with the | |
234 | SNMP specifications, but was how the agent | |
235 | operated for versions < 4.0. | |
236 | + --with-systemd Provide systemd support. See README.systemd | |
237 | + for details. | |
238 | --with-sys-contact="who@where" Default system contact. | |
239 | (Default: LOGIN@DOMAINNAME) | |
240 | --with-sys-location="location" Default system location. | |
241 | @@ -4397,6 +4401,24 @@ $as_echo "#define NETSNMP_NO_DUMMY_VALUE | |
242 | ||
243 | fi | |
244 | ||
245 | + | |
246 | +# Check whether --with-systemd was given. | |
247 | +if test "${with_systemd+set}" = set; then : | |
248 | + withval=$with_systemd; | |
249 | +fi | |
250 | + | |
251 | + # Check whether --enable-systemd was given. | |
252 | +if test "${enable_systemd+set}" = set; then : | |
253 | + enableval=$enable_systemd; as_fn_error $? "Invalid option. Use --with-systemd/--without-systemd instead" "$LINENO" 5 | |
254 | +fi | |
255 | + | |
256 | +# Define unless specifically suppressed (i.e., option defaults to false). | |
257 | +if test "x$with_systemd" != "xyes"; then | |
258 | + | |
259 | +$as_echo "#define NETSNMP_NO_SYSTEMD 1" >>confdefs.h | |
260 | + | |
261 | +fi | |
262 | + | |
263 | # Check whether --enable-set-support was given. | |
264 | if test "${enable_set_support+set}" = set; then : | |
265 | enableval=$enable_set_support; | |
266 | @@ -18239,6 +18261,14 @@ if test "x$PARTIALTARGETOS" = "xmingw32" | |
267 | other_ftobjs_list="$other_ftobjs_list winpipe.ft" | |
268 | fi | |
269 | ||
270 | +# Linux systemd | |
271 | +if test "x$with_systemd" == "xyes"; then | |
272 | + other_src_list="$other_src_list sd-daemon.c" | |
273 | + other_objs_list="$other_objs_list sd-daemon.o" | |
274 | + other_lobjs_list="$other_lobjs_list sd-daemon.lo" | |
275 | + other_ftobjs_list="$other_ftobjs_list sd-daemon.ft" | |
276 | +fi | |
277 | + | |
278 | ||
279 | ||
280 | ||
281 | diff -up net-snmp-5.7.2/dist/snmpd.service.systemd net-snmp-5.7.2/dist/snmpd.service | |
282 | --- net-snmp-5.7.2/dist/snmpd.service.systemd 2012-11-12 10:18:46.104369507 +0100 | |
283 | +++ net-snmp-5.7.2/dist/snmpd.service 2012-11-12 10:18:46.104369507 +0100 | |
284 | @@ -0,0 +1,18 @@ | |
285 | +# | |
286 | +# SNMP agent service file for systemd | |
287 | +# | |
288 | +# | |
289 | +# The service should be enabled, i.e. snmpd should start during machine boot. | |
290 | +# Socket activation shall not be used. See README.systemd for details. | |
291 | + | |
292 | +[Unit] | |
293 | +Description=Simple Network Management Protocol (SNMP) daemon. | |
294 | +After=syslog.target network.target | |
295 | + | |
296 | +[Service] | |
297 | +# Type=notify is also supported. It should be set when snmpd.socket is not used. | |
298 | +Type=simple | |
299 | +ExecStart=/usr/sbin/snmpd -f | |
300 | + | |
301 | +[Install] | |
302 | +WantedBy=multi-user.target | |
303 | diff -up net-snmp-5.7.2/dist/snmpd.socket.systemd net-snmp-5.7.2/dist/snmpd.socket | |
304 | --- net-snmp-5.7.2/dist/snmpd.socket.systemd 2012-11-12 10:18:46.104369507 +0100 | |
305 | +++ net-snmp-5.7.2/dist/snmpd.socket 2012-11-12 10:18:46.104369507 +0100 | |
306 | @@ -0,0 +1,17 @@ | |
307 | +[Unit] | |
308 | +Description=Socket listening for SNMP and AgentX messages | |
309 | + | |
310 | +[Socket] | |
311 | +ListenDatagram=0.0.0.0:161 | |
312 | +# Uncomment other listening addresses as needed - TCP, UDP6, TCP6. | |
313 | +# It must match listening addresses/ports defined in snmpd.service | |
314 | +# or snmpd.conf. | |
315 | +# ListenStream=0.0.0.0:161 | |
316 | +# ListenDatagram=[::]:161 | |
317 | +# ListenStream=[::]:161 | |
318 | +# | |
319 | +# Uncomment AgentX socket if snmpd.conf enables AgentX protocol. | |
320 | +# ListenStream=/var/agentx/master | |
321 | + | |
322 | +[Install] | |
323 | +WantedBy=sockets.target | |
324 | diff -up net-snmp-5.7.2/dist/snmptrapd.service.systemd net-snmp-5.7.2/dist/snmptrapd.service | |
325 | --- net-snmp-5.7.2/dist/snmptrapd.service.systemd 2012-11-12 10:18:46.105369505 +0100 | |
326 | +++ net-snmp-5.7.2/dist/snmptrapd.service 2012-11-12 10:18:46.105369505 +0100 | |
327 | @@ -0,0 +1,16 @@ | |
328 | +# | |
329 | +# SNMP trap-processing service file for systemd | |
330 | +# | |
331 | + | |
332 | +[Unit] | |
333 | +Description=Simple Network Management Protocol (SNMP) Trap daemon. | |
334 | +After=syslog.target network.target | |
335 | + | |
336 | +[Service] | |
337 | +# Type=notify is also supported. It should be set when snmptrapd.socket is not | |
338 | +# used. | |
339 | +Type=simple | |
340 | +ExecStart=/usr/sbin/snmptrapd -f | |
341 | + | |
342 | +[Install] | |
343 | +WantedBy=multi-user.target | |
344 | diff -up net-snmp-5.7.2/dist/snmptrapd.socket.systemd net-snmp-5.7.2/dist/snmptrapd.socket | |
345 | --- net-snmp-5.7.2/dist/snmptrapd.socket.systemd 2012-11-12 10:18:46.105369505 +0100 | |
346 | +++ net-snmp-5.7.2/dist/snmptrapd.socket 2012-11-12 10:18:46.105369505 +0100 | |
347 | @@ -0,0 +1,14 @@ | |
348 | +[Unit] | |
349 | +Description=Socket listening for SNMP trap messages | |
350 | + | |
351 | +[Socket] | |
352 | +ListenDatagram=0.0.0.0:162 | |
353 | +# Uncomment other listening addresses as needed - TCP, UDP6, TCP6. | |
354 | +# It must match listening addresses/ports defined in snmptrapd.service | |
355 | +# or snmptrapd.conf. | |
356 | +# ListenStream=0.0.0.0:162 | |
357 | +# ListenDatagram=[::]:162 | |
358 | +# ListenStream=[::]:162 | |
359 | + | |
360 | +[Install] | |
361 | +WantedBy=sockets.target | |
362 | diff -up net-snmp-5.7.2/include/net-snmp/library/sd-daemon.h.systemd net-snmp-5.7.2/include/net-snmp/library/sd-daemon.h | |
363 | --- net-snmp-5.7.2/include/net-snmp/library/sd-daemon.h.systemd 2012-11-12 10:18:46.106369503 +0100 | |
364 | +++ net-snmp-5.7.2/include/net-snmp/library/sd-daemon.h 2012-11-12 10:18:46.106369503 +0100 | |
365 | @@ -0,0 +1,286 @@ | |
366 | +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ | |
367 | + | |
368 | +#ifndef SNMPD_SD_DAEMON_H | |
369 | +#define SNMPD_SD_DAEMON_H | |
370 | + | |
371 | +/*** | |
372 | + Copyright 2010 Lennart Poettering | |
373 | + | |
374 | + Permission is hereby granted, free of charge, to any person | |
375 | + obtaining a copy of this software and associated documentation files | |
376 | + (the "Software"), to deal in the Software without restriction, | |
377 | + including without limitation the rights to use, copy, modify, merge, | |
378 | + publish, distribute, sublicense, and/or sell copies of the Software, | |
379 | + and to permit persons to whom the Software is furnished to do so, | |
380 | + subject to the following conditions: | |
381 | + | |
382 | + The above copyright notice and this permission notice shall be | |
383 | + included in all copies or substantial portions of the Software. | |
384 | + | |
385 | + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
386 | + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
387 | + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
388 | + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |
389 | + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |
390 | + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
391 | + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
392 | + SOFTWARE. | |
393 | +***/ | |
394 | + | |
395 | +#include <sys/types.h> | |
396 | +#include <inttypes.h> | |
397 | + | |
398 | +#ifdef __cplusplus | |
399 | +extern "C" { | |
400 | +#endif | |
401 | + | |
402 | +/* | |
403 | + Reference implementation of a few systemd related interfaces for | |
404 | + writing daemons. These interfaces are trivial to implement. To | |
405 | + simplify porting we provide this reference implementation. | |
406 | + Applications are welcome to reimplement the algorithms described | |
407 | + here if they do not want to include these two source files. | |
408 | + | |
409 | + The following functionality is provided: | |
410 | + | |
411 | + - Support for logging with log levels on stderr | |
412 | + - File descriptor passing for socket-based activation | |
413 | + - Daemon startup and status notification | |
414 | + - Detection of systemd boots | |
415 | + | |
416 | + You may compile this with -DDISABLE_SYSTEMD to disable systemd | |
417 | + support. This makes all those calls NOPs that are directly related to | |
418 | + systemd (i.e. only sd_is_xxx() will stay useful). | |
419 | + | |
420 | + Since this is drop-in code we don't want any of our symbols to be | |
421 | + exported in any case. Hence we declare hidden visibility for all of | |
422 | + them. | |
423 | + | |
424 | + You may find an up-to-date version of these source files online: | |
425 | + | |
426 | + http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.h | |
427 | + http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.c | |
428 | + | |
429 | + This should compile on non-Linux systems, too, but with the | |
430 | + exception of the sd_is_xxx() calls all functions will become NOPs. | |
431 | + | |
432 | + See sd-daemon(7) for more information. | |
433 | +*/ | |
434 | + | |
435 | +#ifndef _sd_printf_attr_ | |
436 | +#if __GNUC__ >= 4 | |
437 | +#define _sd_printf_attr_(a,b) __attribute__ ((format (printf, a, b))) | |
438 | +#else | |
439 | +#define _sd_printf_attr_(a,b) | |
440 | +#endif | |
441 | +#endif | |
442 | + | |
443 | +/* | |
444 | + Log levels for usage on stderr: | |
445 | + | |
446 | + fprintf(stderr, SD_NOTICE "Hello World!\n"); | |
447 | + | |
448 | + This is similar to printk() usage in the kernel. | |
449 | +*/ | |
450 | +#define SD_EMERG "<0>" /* system is unusable */ | |
451 | +#define SD_ALERT "<1>" /* action must be taken immediately */ | |
452 | +#define SD_CRIT "<2>" /* critical conditions */ | |
453 | +#define SD_ERR "<3>" /* error conditions */ | |
454 | +#define SD_WARNING "<4>" /* warning conditions */ | |
455 | +#define SD_NOTICE "<5>" /* normal but significant condition */ | |
456 | +#define SD_INFO "<6>" /* informational */ | |
457 | +#define SD_DEBUG "<7>" /* debug-level messages */ | |
458 | + | |
459 | +/* The first passed file descriptor is fd 3 */ | |
460 | +#define SD_LISTEN_FDS_START 3 | |
461 | + | |
462 | +/* | |
463 | + Returns how many file descriptors have been passed, or a negative | |
464 | + errno code on failure. Optionally, removes the $LISTEN_FDS and | |
465 | + $LISTEN_PID file descriptors from the environment (recommended, but | |
466 | + problematic in threaded environments). If r is the return value of | |
467 | + this function you'll find the file descriptors passed as fds | |
468 | + SD_LISTEN_FDS_START to SD_LISTEN_FDS_START+r-1. Returns a negative | |
469 | + errno style error code on failure. This function call ensures that | |
470 | + the FD_CLOEXEC flag is set for the passed file descriptors, to make | |
471 | + sure they are not passed on to child processes. If FD_CLOEXEC shall | |
472 | + not be set, the caller needs to unset it after this call for all file | |
473 | + descriptors that are used. | |
474 | + | |
475 | + See sd_listen_fds(3) for more information. | |
476 | +*/ | |
477 | +int netsnmp_sd_listen_fds(int unset_environment); | |
478 | + | |
479 | +/* | |
480 | + Helper call for identifying a passed file descriptor. Returns 1 if | |
481 | + the file descriptor is a FIFO in the file system stored under the | |
482 | + specified path, 0 otherwise. If path is NULL a path name check will | |
483 | + not be done and the call only verifies if the file descriptor | |
484 | + refers to a FIFO. Returns a negative errno style error code on | |
485 | + failure. | |
486 | + | |
487 | + See sd_is_fifo(3) for more information. | |
488 | +*/ | |
489 | +int netsnmp_sd_is_fifo(int fd, const char *path); | |
490 | + | |
491 | +/* | |
492 | + Helper call for identifying a passed file descriptor. Returns 1 if | |
493 | + the file descriptor is a special character device on the file | |
494 | + system stored under the specified path, 0 otherwise. | |
495 | + If path is NULL a path name check will not be done and the call | |
496 | + only verifies if the file descriptor refers to a special character. | |
497 | + Returns a negative errno style error code on failure. | |
498 | + | |
499 | + See sd_is_special(3) for more information. | |
500 | +*/ | |
501 | +int netsnmp_sd_is_special(int fd, const char *path); | |
502 | + | |
503 | +/* | |
504 | + Helper call for identifying a passed file descriptor. Returns 1 if | |
505 | + the file descriptor is a socket of the specified family (AF_INET, | |
506 | + ...) and type (SOCK_DGRAM, SOCK_STREAM, ...), 0 otherwise. If | |
507 | + family is 0 a socket family check will not be done. If type is 0 a | |
508 | + socket type check will not be done and the call only verifies if | |
509 | + the file descriptor refers to a socket. If listening is > 0 it is | |
510 | + verified that the socket is in listening mode. (i.e. listen() has | |
511 | + been called) If listening is == 0 it is verified that the socket is | |
512 | + not in listening mode. If listening is < 0 no listening mode check | |
513 | + is done. Returns a negative errno style error code on failure. | |
514 | + | |
515 | + See sd_is_socket(3) for more information. | |
516 | +*/ | |
517 | +int netsnmp_sd_is_socket(int fd, int family, int type, int listening); | |
518 | + | |
519 | +/* | |
520 | + Helper call for identifying a passed file descriptor. Returns 1 if | |
521 | + the file descriptor is an Internet socket, of the specified family | |
522 | + (either AF_INET or AF_INET6) and the specified type (SOCK_DGRAM, | |
523 | + SOCK_STREAM, ...), 0 otherwise. If version is 0 a protocol version | |
524 | + check is not done. If type is 0 a socket type check will not be | |
525 | + done. If port is 0 a socket port check will not be done. The | |
526 | + listening flag is used the same way as in sd_is_socket(). Returns a | |
527 | + negative errno style error code on failure. | |
528 | + | |
529 | + See sd_is_socket_inet(3) for more information. | |
530 | +*/ | |
531 | +int netsnmp_sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port); | |
532 | + | |
533 | +/* | |
534 | + Helper call for identifying a passed file descriptor. Returns 1 if | |
535 | + the file descriptor is an AF_UNIX socket of the specified type | |
536 | + (SOCK_DGRAM, SOCK_STREAM, ...) and path, 0 otherwise. If type is 0 | |
537 | + a socket type check will not be done. If path is NULL a socket path | |
538 | + check will not be done. For normal AF_UNIX sockets set length to | |
539 | + 0. For abstract namespace sockets set length to the length of the | |
540 | + socket name (including the initial 0 byte), and pass the full | |
541 | + socket path in path (including the initial 0 byte). The listening | |
542 | + flag is used the same way as in sd_is_socket(). Returns a negative | |
543 | + errno style error code on failure. | |
544 | + | |
545 | + See sd_is_socket_unix(3) for more information. | |
546 | +*/ | |
547 | +int netsnmp_sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length); | |
548 | + | |
549 | +/* | |
550 | + Informs systemd about changed daemon state. This takes a number of | |
551 | + newline separated environment-style variable assignments in a | |
552 | + string. The following variables are known: | |
553 | + | |
554 | + READY=1 Tells systemd that daemon startup is finished (only | |
555 | + relevant for services of Type=notify). The passed | |
556 | + argument is a boolean "1" or "0". Since there is | |
557 | + little value in signaling non-readiness the only | |
558 | + value daemons should send is "READY=1". | |
559 | + | |
560 | + STATUS=... Passes a single-line status string back to systemd | |
561 | + that describes the daemon state. This is free-from | |
562 | + and can be used for various purposes: general state | |
563 | + feedback, fsck-like programs could pass completion | |
564 | + percentages and failing programs could pass a human | |
565 | + readable error message. Example: "STATUS=Completed | |
566 | + 66% of file system check..." | |
567 | + | |
568 | + ERRNO=... If a daemon fails, the errno-style error code, | |
569 | + formatted as string. Example: "ERRNO=2" for ENOENT. | |
570 | + | |
571 | + BUSERROR=... If a daemon fails, the D-Bus error-style error | |
572 | + code. Example: "BUSERROR=org.freedesktop.DBus.Error.TimedOut" | |
573 | + | |
574 | + MAINPID=... The main pid of a daemon, in case systemd did not | |
575 | + fork off the process itself. Example: "MAINPID=4711" | |
576 | + | |
577 | + Daemons can choose to send additional variables. However, it is | |
578 | + recommended to prefix variable names not listed above with X_. | |
579 | + | |
580 | + Returns a negative errno-style error code on failure. Returns > 0 | |
581 | + if systemd could be notified, 0 if it couldn't possibly because | |
582 | + systemd is not running. | |
583 | + | |
584 | + Example: When a daemon finished starting up, it could issue this | |
585 | + call to notify systemd about it: | |
586 | + | |
587 | + sd_notify(0, "READY=1"); | |
588 | + | |
589 | + See sd_notifyf() for more complete examples. | |
590 | + | |
591 | + See sd_notify(3) for more information. | |
592 | +*/ | |
593 | +int netsnmp_sd_notify(int unset_environment, const char *state); | |
594 | + | |
595 | +/* | |
596 | + Similar to sd_notify() but takes a format string. | |
597 | + | |
598 | + Example 1: A daemon could send the following after initialization: | |
599 | + | |
600 | + sd_notifyf(0, "READY=1\n" | |
601 | + "STATUS=Processing requests...\n" | |
602 | + "MAINPID=%lu", | |
603 | + (unsigned long) getpid()); | |
604 | + | |
605 | + Example 2: A daemon could send the following shortly before | |
606 | + exiting, on failure: | |
607 | + | |
608 | + sd_notifyf(0, "STATUS=Failed to start up: %s\n" | |
609 | + "ERRNO=%i", | |
610 | + strerror(errno), | |
611 | + errno); | |
612 | + | |
613 | + See sd_notifyf(3) for more information. | |
614 | +*/ | |
615 | +int netsnmp_sd_notifyf(int unset_environment, const char *format, ...) _sd_printf_attr_(2,3); | |
616 | + | |
617 | +/* | |
618 | + Returns > 0 if the system was booted with systemd. Returns < 0 on | |
619 | + error. Returns 0 if the system was not booted with systemd. Note | |
620 | + that all of the functions above handle non-systemd boots just | |
621 | + fine. You should NOT protect them with a call to this function. Also | |
622 | + note that this function checks whether the system, not the user | |
623 | + session is controlled by systemd. However the functions above work | |
624 | + for both user and system services. | |
625 | + | |
626 | + See sd_booted(3) for more information. | |
627 | +*/ | |
628 | +int netsnmp_sd_booted(void); | |
629 | + | |
630 | +/** | |
631 | + * Find an socket with given parameters. See man sd_is_socket_inet for | |
632 | + * description of the arguments. | |
633 | + * | |
634 | + * Returns the file descriptor if it is found, 0 otherwise. | |
635 | + */ | |
636 | +int netsnmp_sd_find_inet_socket(int family, int type, int listening, int port); | |
637 | + | |
638 | +/** | |
639 | + * Find an unix socket with given parameters. See man sd_is_socket_unix for | |
640 | + * description of the arguments. | |
641 | + * | |
642 | + * Returns the file descriptor if it is found, 0 otherwise. | |
643 | + */ | |
644 | +int | |
645 | +netsnmp_sd_find_unix_socket(int type, int listening, const char *path); | |
646 | + | |
647 | +#ifdef __cplusplus | |
648 | +} | |
649 | +#endif | |
650 | + | |
651 | +#endif /* SNMPD_SD_DAEMON_H */ | |
652 | diff -up net-snmp-5.7.2/include/net-snmp/net-snmp-config.h.in.systemd net-snmp-5.7.2/include/net-snmp/net-snmp-config.h.in | |
653 | --- net-snmp-5.7.2/include/net-snmp/net-snmp-config.h.in.systemd 2012-10-10 00:28:58.000000000 +0200 | |
654 | +++ net-snmp-5.7.2/include/net-snmp/net-snmp-config.h.in 2012-11-12 10:18:46.107369501 +0100 | |
655 | @@ -1389,6 +1389,9 @@ | |
656 | /* If you don't have root access don't exit upon kmem errors */ | |
657 | #undef NETSNMP_NO_ROOT_ACCESS | |
658 | ||
659 | +/* If you don't want to integrate with systemd. */ | |
660 | +#undef NETSNMP_NO_SYSTEMD | |
661 | + | |
662 | /* Define if you want to remove all SET/write access from the code */ | |
663 | #undef NETSNMP_NO_WRITE_SUPPORT | |
664 | ||
665 | diff -up net-snmp-5.7.2/README.systemd.systemd net-snmp-5.7.2/README.systemd | |
666 | --- net-snmp-5.7.2/README.systemd.systemd 2012-11-12 10:18:46.108369499 +0100 | |
667 | +++ net-snmp-5.7.2/README.systemd 2012-11-12 10:18:46.108369499 +0100 | |
668 | @@ -0,0 +1,41 @@ | |
669 | +README.systemd | |
670 | +-------------- | |
671 | +Net-SNMP provides two daemons, which support systemd system manager. | |
672 | +See http://www.freedesktop.org/wiki/Software/systemd to learn how | |
673 | +systemd works. Both socket activation and notification is supported by these | |
674 | +daemons. | |
675 | + | |
676 | +To enable systemd support, the sources must be compiled with | |
677 | +--with-systemd configure option. | |
678 | + | |
679 | +snmpd - The SNMP agent | |
680 | +---------------------- | |
681 | +Socket activation od snmpd daemon is implemented, but it's discouraged. | |
682 | +The reason is simple - snmpd not only listens and processes SNMP requests | |
683 | +from network, but also gathers system statistics counters, sends traps and | |
684 | +communicates with subagents. It even opens few netlink sockets. | |
685 | + | |
686 | +In other words, snmpd should run from system start to properly work. | |
687 | +This can be done in two ways: | |
688 | +1) either as snmpd service unit with 'Type=notification' and without a socket | |
689 | + unit | |
690 | +2) or as snmpd service unit with 'Type=simple', appropriate socket socket unit | |
691 | + and the snmpd service enabled. This way systemd creates the snmpd listening | |
692 | + socket early during boot and passes the sockets to snmpd slightly later | |
693 | + (but still during machine boot). This way systemd can paralelize start of | |
694 | + services, which depend on snmpd. Admins must adjust the socket file manually, | |
695 | + depending if the snmpd support AgentX, IPv6, SMUX etc. | |
696 | + | |
697 | +snmpd should be started with '-f' command line parameter to disable forking - | |
698 | +systemd does that for us automatically. | |
699 | + | |
700 | + | |
701 | +snmptrapd - The trap processing daemon | |
702 | +-------------------------------------- | |
703 | +snmptrapd supports full socket activation and also notification (if needed). | |
704 | +Both 'Type=simple' (with appropriate socket unit) and 'Type=notify' services | |
705 | +will work. Again, '-f' parameter should be provided on snmptrapd command line. | |
706 | + | |
707 | +If integration with SNMP agent using AgentX protocol is enabled, snmptrapd should | |
708 | +start during boot and not after first SNMP trap arrives. Same rules as for snmpd | |
709 | +applies then. | |
710 | \ No newline at end of file | |
711 | diff -up net-snmp-5.7.2/snmplib/sd-daemon.c.systemd net-snmp-5.7.2/snmplib/sd-daemon.c | |
712 | --- net-snmp-5.7.2/snmplib/sd-daemon.c.systemd 2012-11-12 10:18:46.109369497 +0100 | |
713 | +++ net-snmp-5.7.2/snmplib/sd-daemon.c 2012-11-12 10:18:46.109369497 +0100 | |
714 | @@ -0,0 +1,532 @@ | |
715 | +/* | |
716 | + * Systemd integration parts. | |
717 | + * | |
718 | + * Most of this file is directly copied from systemd sources. | |
719 | + * Changes: | |
720 | + * - all functions were renamed to have netsnmp_ prefix | |
721 | + * - includes were changed to match Net-SNMP style. | |
722 | + * - removed gcc export macros | |
723 | + * - removed POSIX message queues | |
724 | + */ | |
725 | + | |
726 | +#include <net-snmp/net-snmp-config.h> | |
727 | +#include <net-snmp/net-snmp-features.h> | |
728 | +#include <net-snmp/types.h> | |
729 | +#include <net-snmp/library/snmp_debug.h> | |
730 | + | |
731 | +#ifndef NETSNMP_NO_SYSTEMD | |
732 | + | |
733 | +/*** | |
734 | + Copyright 2010 Lennart Poettering | |
735 | + | |
736 | + Permission is hereby granted, free of charge, to any person | |
737 | + obtaining a copy of this software and associated documentation files | |
738 | + (the "Software"), to deal in the Software without restriction, | |
739 | + including without limitation the rights to use, copy, modify, merge, | |
740 | + publish, distribute, sublicense, and/or sell copies of the Software, | |
741 | + and to permit persons to whom the Software is furnished to do so, | |
742 | + subject to the following conditions: | |
743 | + | |
744 | + The above copyright notice and this permission notice shall be | |
745 | + included in all copies or substantial portions of the Software. | |
746 | + | |
747 | + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
748 | + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
749 | + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
750 | + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |
751 | + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |
752 | + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
753 | + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
754 | + SOFTWARE. | |
755 | +***/ | |
756 | + | |
757 | +#ifndef _GNU_SOURCE | |
758 | +#define _GNU_SOURCE | |
759 | +#endif | |
760 | + | |
761 | +#include <sys/types.h> | |
762 | +#include <sys/stat.h> | |
763 | +#include <sys/socket.h> | |
764 | +#include <sys/un.h> | |
765 | +#include <sys/fcntl.h> | |
766 | +#include <netinet/in.h> | |
767 | +#include <stdlib.h> | |
768 | +#include <errno.h> | |
769 | +#include <unistd.h> | |
770 | +#include <string.h> | |
771 | +#include <stdarg.h> | |
772 | +#include <stdio.h> | |
773 | +#include <stddef.h> | |
774 | +#include <limits.h> | |
775 | + | |
776 | +#include <net-snmp/library/sd-daemon.h> | |
777 | + | |
778 | +int netsnmp_sd_listen_fds(int unset_environment) { | |
779 | + | |
780 | + int r, fd; | |
781 | + const char *e; | |
782 | + char *p = NULL; | |
783 | + unsigned long l; | |
784 | + | |
785 | + if (!(e = getenv("LISTEN_PID"))) { | |
786 | + r = 0; | |
787 | + goto finish; | |
788 | + } | |
789 | + | |
790 | + errno = 0; | |
791 | + l = strtoul(e, &p, 10); | |
792 | + | |
793 | + if (errno != 0) { | |
794 | + r = -errno; | |
795 | + goto finish; | |
796 | + } | |
797 | + | |
798 | + if (!p || *p || l <= 0) { | |
799 | + r = -EINVAL; | |
800 | + goto finish; | |
801 | + } | |
802 | + | |
803 | + /* Is this for us? */ | |
804 | + if (getpid() != (pid_t) l) { | |
805 | + r = 0; | |
806 | + goto finish; | |
807 | + } | |
808 | + | |
809 | + if (!(e = getenv("LISTEN_FDS"))) { | |
810 | + r = 0; | |
811 | + goto finish; | |
812 | + } | |
813 | + | |
814 | + errno = 0; | |
815 | + l = strtoul(e, &p, 10); | |
816 | + | |
817 | + if (errno != 0) { | |
818 | + r = -errno; | |
819 | + goto finish; | |
820 | + } | |
821 | + | |
822 | + if (!p || *p) { | |
823 | + r = -EINVAL; | |
824 | + goto finish; | |
825 | + } | |
826 | + | |
827 | + for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + (int) l; fd ++) { | |
828 | + int flags; | |
829 | + | |
830 | + if ((flags = fcntl(fd, F_GETFD)) < 0) { | |
831 | + r = -errno; | |
832 | + goto finish; | |
833 | + } | |
834 | + | |
835 | + if (flags & FD_CLOEXEC) | |
836 | + continue; | |
837 | + | |
838 | + if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) { | |
839 | + r = -errno; | |
840 | + goto finish; | |
841 | + } | |
842 | + } | |
843 | + | |
844 | + r = (int) l; | |
845 | + | |
846 | +finish: | |
847 | + if (unset_environment) { | |
848 | + unsetenv("LISTEN_PID"); | |
849 | + unsetenv("LISTEN_FDS"); | |
850 | + } | |
851 | + | |
852 | + return r; | |
853 | +} | |
854 | + | |
855 | +int netsnmp_sd_is_fifo(int fd, const char *path) { | |
856 | + struct stat st_fd; | |
857 | + | |
858 | + if (fd < 0) | |
859 | + return -EINVAL; | |
860 | + | |
861 | + memset(&st_fd, 0, sizeof(st_fd)); | |
862 | + if (fstat(fd, &st_fd) < 0) | |
863 | + return -errno; | |
864 | + | |
865 | + if (!S_ISFIFO(st_fd.st_mode)) | |
866 | + return 0; | |
867 | + | |
868 | + if (path) { | |
869 | + struct stat st_path; | |
870 | + | |
871 | + memset(&st_path, 0, sizeof(st_path)); | |
872 | + if (stat(path, &st_path) < 0) { | |
873 | + | |
874 | + if (errno == ENOENT || errno == ENOTDIR) | |
875 | + return 0; | |
876 | + | |
877 | + return -errno; | |
878 | + } | |
879 | + | |
880 | + return | |
881 | + st_path.st_dev == st_fd.st_dev && | |
882 | + st_path.st_ino == st_fd.st_ino; | |
883 | + } | |
884 | + | |
885 | + return 1; | |
886 | +} | |
887 | + | |
888 | +int netsnmp_sd_is_special(int fd, const char *path) { | |
889 | + struct stat st_fd; | |
890 | + | |
891 | + if (fd < 0) | |
892 | + return -EINVAL; | |
893 | + | |
894 | + if (fstat(fd, &st_fd) < 0) | |
895 | + return -errno; | |
896 | + | |
897 | + if (!S_ISREG(st_fd.st_mode) && !S_ISCHR(st_fd.st_mode)) | |
898 | + return 0; | |
899 | + | |
900 | + if (path) { | |
901 | + struct stat st_path; | |
902 | + | |
903 | + if (stat(path, &st_path) < 0) { | |
904 | + | |
905 | + if (errno == ENOENT || errno == ENOTDIR) | |
906 | + return 0; | |
907 | + | |
908 | + return -errno; | |
909 | + } | |
910 | + | |
911 | + if (S_ISREG(st_fd.st_mode) && S_ISREG(st_path.st_mode)) | |
912 | + return | |
913 | + st_path.st_dev == st_fd.st_dev && | |
914 | + st_path.st_ino == st_fd.st_ino; | |
915 | + else if (S_ISCHR(st_fd.st_mode) && S_ISCHR(st_path.st_mode)) | |
916 | + return st_path.st_rdev == st_fd.st_rdev; | |
917 | + else | |
918 | + return 0; | |
919 | + } | |
920 | + | |
921 | + return 1; | |
922 | +} | |
923 | + | |
924 | +static int sd_is_socket_internal(int fd, int type, int listening) { | |
925 | + struct stat st_fd; | |
926 | + | |
927 | + if (fd < 0 || type < 0) | |
928 | + return -EINVAL; | |
929 | + | |
930 | + if (fstat(fd, &st_fd) < 0) | |
931 | + return -errno; | |
932 | + | |
933 | + if (!S_ISSOCK(st_fd.st_mode)) | |
934 | + return 0; | |
935 | + | |
936 | + if (type != 0) { | |
937 | + int other_type = 0; | |
938 | + socklen_t l = sizeof(other_type); | |
939 | + | |
940 | + if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &other_type, &l) < 0) | |
941 | + return -errno; | |
942 | + | |
943 | + if (l != sizeof(other_type)) | |
944 | + return -EINVAL; | |
945 | + | |
946 | + if (other_type != type) | |
947 | + return 0; | |
948 | + } | |
949 | + | |
950 | + if (listening >= 0) { | |
951 | + int accepting = 0; | |
952 | + socklen_t l = sizeof(accepting); | |
953 | + | |
954 | + if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting, &l) < 0) | |
955 | + return -errno; | |
956 | + | |
957 | + if (l != sizeof(accepting)) | |
958 | + return -EINVAL; | |
959 | + | |
960 | + if (!accepting != !listening) | |
961 | + return 0; | |
962 | + } | |
963 | + | |
964 | + return 1; | |
965 | +} | |
966 | + | |
967 | +union sockaddr_union { | |
968 | + struct sockaddr sa; | |
969 | + struct sockaddr_in in4; | |
970 | + struct sockaddr_in6 in6; | |
971 | + struct sockaddr_un un; | |
972 | + struct sockaddr_storage storage; | |
973 | +}; | |
974 | + | |
975 | +int netsnmp_sd_is_socket(int fd, int family, int type, int listening) { | |
976 | + int r; | |
977 | + | |
978 | + if (family < 0) | |
979 | + return -EINVAL; | |
980 | + | |
981 | + if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) | |
982 | + return r; | |
983 | + | |
984 | + if (family > 0) { | |
985 | + union sockaddr_union sockaddr; | |
986 | + socklen_t l; | |
987 | + | |
988 | + memset(&sockaddr, 0, sizeof(sockaddr)); | |
989 | + l = sizeof(sockaddr); | |
990 | + | |
991 | + if (getsockname(fd, &sockaddr.sa, &l) < 0) | |
992 | + return -errno; | |
993 | + | |
994 | + if (l < sizeof(sa_family_t)) | |
995 | + return -EINVAL; | |
996 | + | |
997 | + return sockaddr.sa.sa_family == family; | |
998 | + } | |
999 | + | |
1000 | + return 1; | |
1001 | +} | |
1002 | + | |
1003 | +int netsnmp_sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) { | |
1004 | + union sockaddr_union sockaddr; | |
1005 | + socklen_t l; | |
1006 | + int r; | |
1007 | + | |
1008 | + if (family != 0 && family != AF_INET && family != AF_INET6) | |
1009 | + return -EINVAL; | |
1010 | + | |
1011 | + if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) | |
1012 | + return r; | |
1013 | + | |
1014 | + memset(&sockaddr, 0, sizeof(sockaddr)); | |
1015 | + l = sizeof(sockaddr); | |
1016 | + | |
1017 | + if (getsockname(fd, &sockaddr.sa, &l) < 0) | |
1018 | + return -errno; | |
1019 | + | |
1020 | + if (l < sizeof(sa_family_t)) | |
1021 | + return -EINVAL; | |
1022 | + | |
1023 | + if (sockaddr.sa.sa_family != AF_INET && | |
1024 | + sockaddr.sa.sa_family != AF_INET6) | |
1025 | + return 0; | |
1026 | + | |
1027 | + if (family > 0) | |
1028 | + if (sockaddr.sa.sa_family != family) | |
1029 | + return 0; | |
1030 | + | |
1031 | + if (port > 0) { | |
1032 | + if (sockaddr.sa.sa_family == AF_INET) { | |
1033 | + if (l < sizeof(struct sockaddr_in)) | |
1034 | + return -EINVAL; | |
1035 | + | |
1036 | + return htons(port) == sockaddr.in4.sin_port; | |
1037 | + } else { | |
1038 | + if (l < sizeof(struct sockaddr_in6)) | |
1039 | + return -EINVAL; | |
1040 | + | |
1041 | + return htons(port) == sockaddr.in6.sin6_port; | |
1042 | + } | |
1043 | + } | |
1044 | + | |
1045 | + return 1; | |
1046 | +} | |
1047 | + | |
1048 | +int netsnmp_sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) { | |
1049 | + union sockaddr_union sockaddr; | |
1050 | + socklen_t l; | |
1051 | + int r; | |
1052 | + | |
1053 | + if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) | |
1054 | + return r; | |
1055 | + | |
1056 | + memset(&sockaddr, 0, sizeof(sockaddr)); | |
1057 | + l = sizeof(sockaddr); | |
1058 | + | |
1059 | + if (getsockname(fd, &sockaddr.sa, &l) < 0) | |
1060 | + return -errno; | |
1061 | + | |
1062 | + if (l < sizeof(sa_family_t)) | |
1063 | + return -EINVAL; | |
1064 | + | |
1065 | + if (sockaddr.sa.sa_family != AF_UNIX) | |
1066 | + return 0; | |
1067 | + | |
1068 | + if (path) { | |
1069 | + if (length <= 0) | |
1070 | + length = strlen(path); | |
1071 | + | |
1072 | + if (length <= 0) | |
1073 | + /* Unnamed socket */ | |
1074 | + return l == offsetof(struct sockaddr_un, sun_path); | |
1075 | + | |
1076 | + if (path[0]) | |
1077 | + /* Normal path socket */ | |
1078 | + return | |
1079 | + (l >= offsetof(struct sockaddr_un, sun_path) + length + 1) && | |
1080 | + memcmp(path, sockaddr.un.sun_path, length+1) == 0; | |
1081 | + else | |
1082 | + /* Abstract namespace socket */ | |
1083 | + return | |
1084 | + (l == offsetof(struct sockaddr_un, sun_path) + length) && | |
1085 | + memcmp(path, sockaddr.un.sun_path, length) == 0; | |
1086 | + } | |
1087 | + | |
1088 | + return 1; | |
1089 | +} | |
1090 | + | |
1091 | +int netsnmp_sd_notify(int unset_environment, const char *state) { | |
1092 | + int fd = -1, r; | |
1093 | + struct msghdr msghdr; | |
1094 | + struct iovec iovec; | |
1095 | + union sockaddr_union sockaddr; | |
1096 | + const char *e; | |
1097 | + | |
1098 | + if (!state) { | |
1099 | + r = -EINVAL; | |
1100 | + goto finish; | |
1101 | + } | |
1102 | + | |
1103 | + if (!(e = getenv("NOTIFY_SOCKET"))) | |
1104 | + return 0; | |
1105 | + | |
1106 | + /* Must be an abstract socket, or an absolute path */ | |
1107 | + if ((e[0] != '@' && e[0] != '/') || e[1] == 0) { | |
1108 | + r = -EINVAL; | |
1109 | + goto finish; | |
1110 | + } | |
1111 | + | |
1112 | + if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0) { | |
1113 | + r = -errno; | |
1114 | + goto finish; | |
1115 | + } | |
1116 | + | |
1117 | + memset(&sockaddr, 0, sizeof(sockaddr)); | |
1118 | + sockaddr.sa.sa_family = AF_UNIX; | |
1119 | + strncpy(sockaddr.un.sun_path, e, sizeof(sockaddr.un.sun_path)); | |
1120 | + | |
1121 | + if (sockaddr.un.sun_path[0] == '@') | |
1122 | + sockaddr.un.sun_path[0] = 0; | |
1123 | + | |
1124 | + memset(&iovec, 0, sizeof(iovec)); | |
1125 | + iovec.iov_base = (char *)state; | |
1126 | + iovec.iov_len = strlen(state); | |
1127 | + | |
1128 | + memset(&msghdr, 0, sizeof(msghdr)); | |
1129 | + msghdr.msg_name = &sockaddr; | |
1130 | + msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(e); | |
1131 | + | |
1132 | + if (msghdr.msg_namelen > sizeof(struct sockaddr_un)) | |
1133 | + msghdr.msg_namelen = sizeof(struct sockaddr_un); | |
1134 | + | |
1135 | + msghdr.msg_iov = &iovec; | |
1136 | + msghdr.msg_iovlen = 1; | |
1137 | + | |
1138 | + if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) { | |
1139 | + r = -errno; | |
1140 | + goto finish; | |
1141 | + } | |
1142 | + | |
1143 | + r = 1; | |
1144 | + | |
1145 | +finish: | |
1146 | + if (unset_environment) | |
1147 | + unsetenv("NOTIFY_SOCKET"); | |
1148 | + | |
1149 | + if (fd >= 0) | |
1150 | + close(fd); | |
1151 | + | |
1152 | + return r; | |
1153 | +} | |
1154 | + | |
1155 | +int netsnmp_sd_notifyf(int unset_environment, const char *format, ...) { | |
1156 | + va_list ap; | |
1157 | + char *p = NULL; | |
1158 | + int r; | |
1159 | + | |
1160 | + va_start(ap, format); | |
1161 | + r = vasprintf(&p, format, ap); | |
1162 | + va_end(ap); | |
1163 | + | |
1164 | + if (r < 0 || !p) | |
1165 | + return -ENOMEM; | |
1166 | + | |
1167 | + r = netsnmp_sd_notify(unset_environment, p); | |
1168 | + free(p); | |
1169 | + | |
1170 | + return r; | |
1171 | +} | |
1172 | + | |
1173 | +int netsnmp_sd_booted(void) { | |
1174 | + struct stat a, b; | |
1175 | + | |
1176 | + /* We simply test whether the systemd cgroup hierarchy is | |
1177 | + * mounted */ | |
1178 | + | |
1179 | + if (lstat("/sys/fs/cgroup", &a) < 0) | |
1180 | + return 0; | |
1181 | + | |
1182 | + if (lstat("/sys/fs/cgroup/systemd", &b) < 0) | |
1183 | + return 0; | |
1184 | + | |
1185 | + return a.st_dev != b.st_dev; | |
1186 | +} | |
1187 | + | |
1188 | +/* End of original sd-daemon.c from systemd sources */ | |
1189 | + | |
1190 | +int | |
1191 | +netsnmp_sd_find_inet_socket(int family, int type, int listening, int port) | |
1192 | +{ | |
1193 | + int count, fd; | |
1194 | + | |
1195 | + count = netsnmp_sd_listen_fds(0); | |
1196 | + if (count <= 0) { | |
1197 | + DEBUGMSGTL(("systemd:find_inet_socket", "No LISTEN_FDS found.\n")); | |
1198 | + return 0; | |
1199 | + } | |
1200 | + DEBUGMSGTL(("systemd:find_inet_socket", "LISTEN_FDS reports %d sockets.\n", | |
1201 | + count)); | |
1202 | + | |
1203 | + for (fd = 3; fd < 3+count; fd++) { | |
1204 | + int rc = netsnmp_sd_is_socket_inet(fd, family, type, listening, port); | |
1205 | + if (rc < 0) | |
1206 | + DEBUGMSGTL(("systemd:find_inet_socket", | |
1207 | + "sd_is_socket_inet error: %d\n", rc)); | |
1208 | + if (rc > 0) { | |
1209 | + DEBUGMSGTL(("systemd:find_inet_socket", | |
1210 | + "Found the socket in LISTEN_FDS\n")); | |
1211 | + return fd; | |
1212 | + } | |
1213 | + } | |
1214 | + DEBUGMSGTL(("systemd:find_inet_socket", "Socket not found in LISTEN_FDS\n")); | |
1215 | + return 0; | |
1216 | +} | |
1217 | + | |
1218 | +int | |
1219 | +netsnmp_sd_find_unix_socket(int type, int listening, const char *path) | |
1220 | +{ | |
1221 | + int count, fd; | |
1222 | + | |
1223 | + count = netsnmp_sd_listen_fds(0); | |
1224 | + if (count <= 0) { | |
1225 | + DEBUGMSGTL(("systemd:find_unix_socket", "No LISTEN_FDS found.\n")); | |
1226 | + return 0; | |
1227 | + } | |
1228 | + DEBUGMSGTL(("systemd:find_unix_socket", "LISTEN_FDS reports %d sockets.\n", | |
1229 | + count)); | |
1230 | + | |
1231 | + for (fd = 3; fd < 3+count; fd++) { | |
1232 | + int rc = netsnmp_sd_is_socket_unix(fd, type, listening, path, 0); | |
1233 | + if (rc < 0) | |
1234 | + DEBUGMSGTL(("systemd:find_unix_socket", | |
1235 | + "netsnmp_sd_is_socket_unix error: %d\n", rc)); | |
1236 | + if (rc > 0) { | |
1237 | + DEBUGMSGTL(("systemd:find_unix_socket", | |
1238 | + "Found the socket in LISTEN_FDS\n")); | |
1239 | + return fd; | |
1240 | + } | |
1241 | + } | |
1242 | + DEBUGMSGTL(("systemd:find_unix_socket", "Socket not found in LISTEN_FDS\n")); | |
1243 | + return 0; | |
1244 | +} | |
1245 | + | |
1246 | +#endif /* ! NETSNMP_NO_SYSTEMD */ | |
1247 | diff -up net-snmp-5.7.2/snmplib/transports/snmpTCPDomain.c.systemd net-snmp-5.7.2/snmplib/transports/snmpTCPDomain.c | |
1248 | --- net-snmp-5.7.2/snmplib/transports/snmpTCPDomain.c.systemd 2012-10-10 00:28:58.000000000 +0200 | |
1249 | +++ net-snmp-5.7.2/snmplib/transports/snmpTCPDomain.c 2012-11-12 10:19:41.767217067 +0100 | |
1250 | @@ -43,6 +43,10 @@ | |
1251 | #include <net-snmp/library/snmpTCPBaseDomain.h> | |
1252 | #include <net-snmp/library/tools.h> | |
1253 | ||
1254 | +#ifndef NETSNMP_NO_SYSTEMD | |
1255 | +#include <net-snmp/library/sd-daemon.h> | |
1256 | +#endif | |
1257 | + | |
1258 | /* | |
1259 | * needs to be in sync with the definitions in snmplib/snmpUDPDomain.c | |
1260 | * and perl/agent/agent.xs | |
1261 | @@ -149,6 +153,7 @@ netsnmp_tcp_transport(struct sockaddr_in | |
1262 | netsnmp_transport *t = NULL; | |
1263 | netsnmp_udp_addr_pair *addr_pair = NULL; | |
1264 | int rc = 0; | |
1265 | + int socket_initialized = 0; | |
1266 | ||
1267 | #ifdef NETSNMP_NO_LISTEN_SUPPORT | |
1268 | if (local) | |
1269 | @@ -178,7 +183,19 @@ netsnmp_tcp_transport(struct sockaddr_in | |
1270 | t->domain_length = | |
1271 | sizeof(netsnmp_snmpTCPDomain) / sizeof(netsnmp_snmpTCPDomain[0]); | |
1272 | ||
1273 | - t->sock = socket(PF_INET, SOCK_STREAM, 0); | |
1274 | +#ifndef NETSNMP_NO_SYSTEMD | |
1275 | + /* | |
1276 | + * Maybe the socket was already provided by systemd... | |
1277 | + */ | |
1278 | + if (local) { | |
1279 | + t->sock = netsnmp_sd_find_inet_socket(PF_INET, SOCK_STREAM, 1, | |
1280 | + ntohs(addr->sin_port)); | |
1281 | + if (t->sock) | |
1282 | + socket_initialized = 1; | |
1283 | + } | |
1284 | +#endif | |
1285 | + if (!socket_initialized) | |
1286 | + t->sock = socket(PF_INET, SOCK_STREAM, 0); | |
1287 | if (t->sock < 0) { | |
1288 | netsnmp_transport_free(t); | |
1289 | return NULL; | |
1290 | @@ -215,11 +232,13 @@ netsnmp_tcp_transport(struct sockaddr_in | |
1291 | setsockopt(t->sock, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, | |
1292 | sizeof(opt)); | |
1293 | ||
1294 | - rc = bind(t->sock, (struct sockaddr *)addr, sizeof(struct sockaddr)); | |
1295 | - if (rc != 0) { | |
1296 | - netsnmp_socketbase_close(t); | |
1297 | - netsnmp_transport_free(t); | |
1298 | - return NULL; | |
1299 | + if (!socket_initialized) { | |
1300 | + rc = bind(t->sock, (struct sockaddr *)addr, sizeof(struct sockaddr)); | |
1301 | + if (rc != 0) { | |
1302 | + netsnmp_socketbase_close(t); | |
1303 | + netsnmp_transport_free(t); | |
1304 | + return NULL; | |
1305 | + } | |
1306 | } | |
1307 | ||
1308 | /* | |
1309 | @@ -235,12 +254,13 @@ netsnmp_tcp_transport(struct sockaddr_in | |
1310 | /* | |
1311 | * Now sit here and wait for connections to arrive. | |
1312 | */ | |
1313 | - | |
1314 | - rc = listen(t->sock, NETSNMP_STREAM_QUEUE_LEN); | |
1315 | - if (rc != 0) { | |
1316 | - netsnmp_socketbase_close(t); | |
1317 | - netsnmp_transport_free(t); | |
1318 | - return NULL; | |
1319 | + if (!socket_initialized) { | |
1320 | + rc = listen(t->sock, NETSNMP_STREAM_QUEUE_LEN); | |
1321 | + if (rc != 0) { | |
1322 | + netsnmp_socketbase_close(t); | |
1323 | + netsnmp_transport_free(t); | |
1324 | + return NULL; | |
1325 | + } | |
1326 | } | |
1327 | ||
1328 | /* | |
1329 | diff -up net-snmp-5.7.2/snmplib/transports/snmpTCPIPv6Domain.c.systemd net-snmp-5.7.2/snmplib/transports/snmpTCPIPv6Domain.c | |
1330 | --- net-snmp-5.7.2/snmplib/transports/snmpTCPIPv6Domain.c.systemd 2012-10-10 00:28:58.000000000 +0200 | |
1331 | +++ net-snmp-5.7.2/snmplib/transports/snmpTCPIPv6Domain.c 2012-11-12 10:20:32.019078971 +0100 | |
1332 | @@ -49,6 +49,10 @@ | |
1333 | #include <net-snmp/library/snmpTCPBaseDomain.h> | |
1334 | #include <net-snmp/library/tools.h> | |
1335 | ||
1336 | +#ifndef NETSNMP_NO_SYSTEMD | |
1337 | +#include <net-snmp/library/sd-daemon.h> | |
1338 | +#endif | |
1339 | + | |
1340 | #include "inet_ntop.h" | |
1341 | ||
1342 | oid netsnmp_TCPIPv6Domain[] = { TRANSPORT_DOMAIN_TCP_IPV6 }; | |
1343 | @@ -140,6 +144,7 @@ netsnmp_tcp6_transport(struct sockaddr_i | |
1344 | { | |
1345 | netsnmp_transport *t = NULL; | |
1346 | int rc = 0; | |
1347 | + int socket_initialized = 0; | |
1348 | ||
1349 | #ifdef NETSNMP_NO_LISTEN_SUPPORT | |
1350 | if (local) | |
1351 | @@ -174,7 +179,19 @@ netsnmp_tcp6_transport(struct sockaddr_i | |
1352 | t->domain = netsnmp_TCPIPv6Domain; | |
1353 | t->domain_length = sizeof(netsnmp_TCPIPv6Domain) / sizeof(oid); | |
1354 | ||
1355 | - t->sock = socket(PF_INET6, SOCK_STREAM, 0); | |
1356 | +#ifndef NETSNMP_NO_SYSTEMD | |
1357 | + /* | |
1358 | + * Maybe the socket was already provided by systemd... | |
1359 | + */ | |
1360 | + if (local) { | |
1361 | + t->sock = netsnmp_sd_find_inet_socket(PF_INET6, SOCK_STREAM, 1, | |
1362 | + ntohs(addr->sin6_port)); | |
1363 | + if (t->sock) | |
1364 | + socket_initialized = 1; | |
1365 | + } | |
1366 | +#endif | |
1367 | + if (!socket_initialized) | |
1368 | + t->sock = socket(PF_INET6, SOCK_STREAM, 0); | |
1369 | if (t->sock < 0) { | |
1370 | netsnmp_transport_free(t); | |
1371 | return NULL; | |
1372 | @@ -220,12 +237,14 @@ netsnmp_tcp6_transport(struct sockaddr_i | |
1373 | ||
1374 | setsockopt(t->sock, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, sizeof(opt)); | |
1375 | ||
1376 | - rc = bind(t->sock, (struct sockaddr *) addr, | |
1377 | - sizeof(struct sockaddr_in6)); | |
1378 | - if (rc != 0) { | |
1379 | - netsnmp_socketbase_close(t); | |
1380 | - netsnmp_transport_free(t); | |
1381 | - return NULL; | |
1382 | + if (!socket_initialized) { | |
1383 | + rc = bind(t->sock, (struct sockaddr *) addr, | |
1384 | + sizeof(struct sockaddr_in6)); | |
1385 | + if (rc != 0) { | |
1386 | + netsnmp_socketbase_close(t); | |
1387 | + netsnmp_transport_free(t); | |
1388 | + return NULL; | |
1389 | + } | |
1390 | } | |
1391 | ||
1392 | /* | |
1393 | @@ -242,11 +261,13 @@ netsnmp_tcp6_transport(struct sockaddr_i | |
1394 | * Now sit here and wait for connections to arrive. | |
1395 | */ | |
1396 | ||
1397 | - rc = listen(t->sock, NETSNMP_STREAM_QUEUE_LEN); | |
1398 | - if (rc != 0) { | |
1399 | - netsnmp_socketbase_close(t); | |
1400 | - netsnmp_transport_free(t); | |
1401 | - return NULL; | |
1402 | + if (!socket_initialized) { | |
1403 | + rc = listen(t->sock, NETSNMP_STREAM_QUEUE_LEN); | |
1404 | + if (rc != 0) { | |
1405 | + netsnmp_socketbase_close(t); | |
1406 | + netsnmp_transport_free(t); | |
1407 | + return NULL; | |
1408 | + } | |
1409 | } | |
1410 | ||
1411 | /* | |
1412 | diff -up net-snmp-5.7.2/snmplib/transports/snmpUDPIPv4BaseDomain.c.systemd net-snmp-5.7.2/snmplib/transports/snmpUDPIPv4BaseDomain.c | |
1413 | --- net-snmp-5.7.2/snmplib/transports/snmpUDPIPv4BaseDomain.c.systemd 2012-10-10 00:28:58.000000000 +0200 | |
1414 | +++ net-snmp-5.7.2/snmplib/transports/snmpUDPIPv4BaseDomain.c 2012-11-12 10:22:30.279750750 +0100 | |
1415 | @@ -40,6 +40,10 @@ | |
1416 | ||
1417 | #include <net-snmp/library/snmpSocketBaseDomain.h> | |
1418 | ||
1419 | +#ifndef NETSNMP_NO_SYSTEMD | |
1420 | +#include <net-snmp/library/sd-daemon.h> | |
1421 | +#endif | |
1422 | + | |
1423 | #if (defined(linux) && defined(IP_PKTINFO)) \ | |
1424 | || defined(IP_RECVDSTADDR) && HAVE_STRUCT_MSGHDR_MSG_CONTROL \ | |
1425 | && HAVE_STRUCT_MSGHDR_MSG_FLAGS | |
1426 | @@ -67,6 +71,7 @@ netsnmp_udpipv4base_transport(struct soc | |
1427 | char *client_socket = NULL; | |
1428 | netsnmp_indexed_addr_pair addr_pair; | |
1429 | socklen_t local_addr_len; | |
1430 | + int socket_initialized = 0; | |
1431 | ||
1432 | #ifdef NETSNMP_NO_LISTEN_SUPPORT | |
1433 | if (local) | |
1434 | @@ -91,7 +96,20 @@ netsnmp_udpipv4base_transport(struct soc | |
1435 | free(str); | |
1436 | } | |
1437 | ||
1438 | - t->sock = socket(PF_INET, SOCK_DGRAM, 0); | |
1439 | +#ifndef NETSNMP_NO_SYSTEMD | |
1440 | + /* | |
1441 | + * Maybe the socket was already provided by systemd... | |
1442 | + */ | |
1443 | + if (local) { | |
1444 | + t->sock = netsnmp_sd_find_inet_socket(PF_INET, SOCK_DGRAM, -1, | |
1445 | + ntohs(addr->sin_port)); | |
1446 | + if (t->sock) | |
1447 | + socket_initialized = 1; | |
1448 | + } | |
1449 | +#endif | |
1450 | + if (!socket_initialized) | |
1451 | + t->sock = socket(PF_INET, SOCK_DGRAM, 0); | |
1452 | + | |
1453 | DEBUGMSGTL(("UDPBase", "openned socket %d as local=%d\n", t->sock, local)); | |
1454 | if (t->sock < 0) { | |
1455 | netsnmp_transport_free(t); | |
1456 | @@ -141,13 +159,15 @@ netsnmp_udpipv4base_transport(struct soc | |
1457 | DEBUGMSGTL(("netsnmp_udp", "set IP_RECVDSTADDR\n")); | |
1458 | } | |
1459 | #endif | |
1460 | - rc = bind(t->sock, (struct sockaddr *) addr, | |
1461 | - sizeof(struct sockaddr)); | |
1462 | - if (rc != 0) { | |
1463 | - netsnmp_socketbase_close(t); | |
1464 | - netsnmp_transport_free(t); | |
1465 | - return NULL; | |
1466 | - } | |
1467 | + if (!socket_initialized) { | |
1468 | + rc = bind(t->sock, (struct sockaddr *) addr, | |
1469 | + sizeof(struct sockaddr)); | |
1470 | + if (rc != 0) { | |
1471 | + netsnmp_socketbase_close(t); | |
1472 | + netsnmp_transport_free(t); | |
1473 | + return NULL; | |
1474 | + } | |
1475 | + } | |
1476 | t->data = NULL; | |
1477 | t->data_length = 0; | |
1478 | #else /* NETSNMP_NO_LISTEN_SUPPORT */ | |
1479 | diff -up net-snmp-5.7.2/snmplib/transports/snmpUDPIPv6Domain.c.systemd net-snmp-5.7.2/snmplib/transports/snmpUDPIPv6Domain.c | |
1480 | --- net-snmp-5.7.2/snmplib/transports/snmpUDPIPv6Domain.c.systemd 2012-10-10 00:28:58.000000000 +0200 | |
1481 | +++ net-snmp-5.7.2/snmplib/transports/snmpUDPIPv6Domain.c 2012-11-12 10:23:19.713603003 +0100 | |
1482 | @@ -67,6 +67,10 @@ static const struct in6_addr in6addr_any | |
1483 | #include <net-snmp/library/snmpSocketBaseDomain.h> | |
1484 | #include <net-snmp/library/tools.h> | |
1485 | ||
1486 | +#ifndef NETSNMP_NO_SYSTEMD | |
1487 | +#include <net-snmp/library/sd-daemon.h> | |
1488 | +#endif | |
1489 | + | |
1490 | #include "inet_ntop.h" | |
1491 | #include "inet_pton.h" | |
1492 | ||
1493 | @@ -190,6 +194,7 @@ netsnmp_udp6_transport(struct sockaddr_i | |
1494 | { | |
1495 | netsnmp_transport *t = NULL; | |
1496 | int rc = 0; | |
1497 | + int socket_initialized = 0; | |
1498 | ||
1499 | #ifdef NETSNMP_NO_LISTEN_SUPPORT | |
1500 | if (local) | |
1501 | @@ -217,7 +222,19 @@ netsnmp_udp6_transport(struct sockaddr_i | |
1502 | t->domain_length = | |
1503 | sizeof(netsnmp_UDPIPv6Domain) / sizeof(netsnmp_UDPIPv6Domain[0]); | |
1504 | ||
1505 | - t->sock = socket(PF_INET6, SOCK_DGRAM, 0); | |
1506 | +#ifndef NETSNMP_NO_SYSTEMD | |
1507 | + /* | |
1508 | + * Maybe the socket was already provided by systemd... | |
1509 | + */ | |
1510 | + if (local) { | |
1511 | + t->sock = netsnmp_sd_find_inet_socket(PF_INET6, SOCK_DGRAM, -1, | |
1512 | + ntohs(addr->sin6_port)); | |
1513 | + if (t->sock) | |
1514 | + socket_initialized = 1; | |
1515 | + } | |
1516 | +#endif | |
1517 | + if (!socket_initialized) | |
1518 | + t->sock = socket(PF_INET6, SOCK_DGRAM, 0); | |
1519 | if (t->sock < 0) { | |
1520 | netsnmp_transport_free(t); | |
1521 | return NULL; | |
1522 | @@ -242,13 +259,14 @@ netsnmp_udp6_transport(struct sockaddr_i | |
1523 | } | |
1524 | } | |
1525 | #endif | |
1526 | - | |
1527 | - rc = bind(t->sock, (struct sockaddr *) addr, | |
1528 | - sizeof(struct sockaddr_in6)); | |
1529 | - if (rc != 0) { | |
1530 | - netsnmp_socketbase_close(t); | |
1531 | - netsnmp_transport_free(t); | |
1532 | - return NULL; | |
1533 | + if (!socket_initialized) { | |
1534 | + rc = bind(t->sock, (struct sockaddr *) addr, | |
1535 | + sizeof(struct sockaddr_in6)); | |
1536 | + if (rc != 0) { | |
1537 | + netsnmp_socketbase_close(t); | |
1538 | + netsnmp_transport_free(t); | |
1539 | + return NULL; | |
1540 | + } | |
1541 | } | |
1542 | t->local = (unsigned char*)malloc(18); | |
1543 | if (t->local == NULL) { | |
1544 | diff -up net-snmp-5.7.2/snmplib/transports/snmpUnixDomain.c.systemd net-snmp-5.7.2/snmplib/transports/snmpUnixDomain.c | |
1545 | --- net-snmp-5.7.2/snmplib/transports/snmpUnixDomain.c.systemd 2012-10-10 00:28:58.000000000 +0200 | |
1546 | +++ net-snmp-5.7.2/snmplib/transports/snmpUnixDomain.c 2012-11-12 10:24:02.803466358 +0100 | |
1547 | @@ -37,6 +37,10 @@ | |
1548 | #include <net-snmp/library/system.h> /* mkdirhier */ | |
1549 | #include <net-snmp/library/tools.h> | |
1550 | ||
1551 | +#ifndef NETSNMP_NO_SYSTEMD | |
1552 | +#include <net-snmp/library/sd-daemon.h> | |
1553 | +#endif | |
1554 | + | |
1555 | netsnmp_feature_child_of(transport_unix_socket_all, transport_all) | |
1556 | netsnmp_feature_child_of(unix_socket_paths, transport_unix_socket_all) | |
1557 | ||
1558 | @@ -295,6 +299,7 @@ netsnmp_unix_transport(struct sockaddr_u | |
1559 | netsnmp_transport *t = NULL; | |
1560 | sockaddr_un_pair *sup = NULL; | |
1561 | int rc = 0; | |
1562 | + int socket_initialized = 0; | |
1563 | ||
1564 | #ifdef NETSNMP_NO_LISTEN_SUPPORT | |
1565 | /* SPECIAL CIRCUMSTANCE: We still want AgentX to be able to operate, | |
1566 | @@ -333,7 +338,18 @@ netsnmp_unix_transport(struct sockaddr_u | |
1567 | t->data_length = sizeof(sockaddr_un_pair); | |
1568 | sup = (sockaddr_un_pair *) t->data; | |
1569 | ||
1570 | - t->sock = socket(PF_UNIX, SOCK_STREAM, 0); | |
1571 | +#ifndef NETSNMP_NO_SYSTEMD | |
1572 | + /* | |
1573 | + * Maybe the socket was already provided by systemd... | |
1574 | + */ | |
1575 | + if (local) { | |
1576 | + t->sock = netsnmp_sd_find_unix_socket(SOCK_STREAM, 1, addr->sun_path); | |
1577 | + if (t->sock) | |
1578 | + socket_initialized = 1; | |
1579 | + } | |
1580 | +#endif | |
1581 | + if (!socket_initialized) | |
1582 | + t->sock = socket(PF_UNIX, SOCK_STREAM, 0); | |
1583 | if (t->sock < 0) { | |
1584 | netsnmp_transport_free(t); | |
1585 | return NULL; | |
1586 | @@ -357,25 +373,26 @@ netsnmp_unix_transport(struct sockaddr_u | |
1587 | ||
1588 | t->flags |= NETSNMP_TRANSPORT_FLAG_LISTEN; | |
1589 | ||
1590 | - unlink(addr->sun_path); | |
1591 | - rc = bind(t->sock, (struct sockaddr *) addr, SUN_LEN(addr)); | |
1592 | - | |
1593 | - if (rc != 0 && errno == ENOENT && create_path) { | |
1594 | - rc = mkdirhier(addr->sun_path, create_mode, 1); | |
1595 | + if (!socket_initialized) { | |
1596 | + unlink(addr->sun_path); | |
1597 | + rc = bind(t->sock, (struct sockaddr *) addr, SUN_LEN(addr)); | |
1598 | + if (rc != 0 && errno == ENOENT && create_path) { | |
1599 | + rc = mkdirhier(addr->sun_path, create_mode, 1); | |
1600 | + if (rc != 0) { | |
1601 | + netsnmp_unix_close(t); | |
1602 | + netsnmp_transport_free(t); | |
1603 | + return NULL; | |
1604 | + } | |
1605 | + rc = bind(t->sock, (struct sockaddr *) addr, SUN_LEN(addr)); | |
1606 | + } | |
1607 | if (rc != 0) { | |
1608 | + DEBUGMSGTL(("netsnmp_unix_transport", | |
1609 | + "couldn't bind \"%s\", errno %d (%s)\n", | |
1610 | + addr->sun_path, errno, strerror(errno))); | |
1611 | netsnmp_unix_close(t); | |
1612 | netsnmp_transport_free(t); | |
1613 | return NULL; | |
1614 | } | |
1615 | - rc = bind(t->sock, (struct sockaddr *) addr, SUN_LEN(addr)); | |
1616 | - } | |
1617 | - if (rc != 0) { | |
1618 | - DEBUGMSGTL(("netsnmp_unix_transport", | |
1619 | - "couldn't bind \"%s\", errno %d (%s)\n", | |
1620 | - addr->sun_path, errno, strerror(errno))); | |
1621 | - netsnmp_unix_close(t); | |
1622 | - netsnmp_transport_free(t); | |
1623 | - return NULL; | |
1624 | } | |
1625 | ||
1626 | /* | |
1627 | @@ -391,16 +408,17 @@ netsnmp_unix_transport(struct sockaddr_u | |
1628 | * Now sit here and listen for connections to arrive. | |
1629 | */ | |
1630 | ||
1631 | - rc = listen(t->sock, NETSNMP_STREAM_QUEUE_LEN); | |
1632 | - if (rc != 0) { | |
1633 | - DEBUGMSGTL(("netsnmp_unix_transport", | |
1634 | - "couldn't listen to \"%s\", errno %d (%s)\n", | |
1635 | - addr->sun_path, errno, strerror(errno))); | |
1636 | - netsnmp_unix_close(t); | |
1637 | - netsnmp_transport_free(t); | |
1638 | - return NULL; | |
1639 | + if (!socket_initialized) { | |
1640 | + rc = listen(t->sock, NETSNMP_STREAM_QUEUE_LEN); | |
1641 | + if (rc != 0) { | |
1642 | + DEBUGMSGTL(("netsnmp_unix_transport", | |
1643 | + "couldn't listen to \"%s\", errno %d (%s)\n", | |
1644 | + addr->sun_path, errno, strerror(errno))); | |
1645 | + netsnmp_unix_close(t); | |
1646 | + netsnmp_transport_free(t); | |
1647 | + return NULL; | |
1648 | + } | |
1649 | } | |
1650 | - | |
1651 | } else { | |
1652 | t->remote = (u_char *)malloc(strlen(addr->sun_path)); | |
1653 | if (t->remote == NULL) { |