aboutsummaryrefslogtreecommitdiffstats
path: root/meta-networking/recipes-protocols/net-snmp
diff options
context:
space:
mode:
authorPaul Eggleton <paul.eggleton@linux.intel.com>2013-04-22 08:45:45 +0000
committerMartin Jansa <Martin.Jansa@gmail.com>2013-04-26 10:00:32 +0200
commit9e7327e446d16a8bd70f93d5d68cdf267e3d2106 (patch)
treec7b80ce3e0389f561ca0ac18accd544a34d2c28f /meta-networking/recipes-protocols/net-snmp
parent9d68ba4fc2b2f862bfb9619f74e082c88ab68604 (diff)
downloadmeta-openembedded-contrib-9e7327e446d16a8bd70f93d5d68cdf267e3d2106.tar.gz
net-snmp: move to meta-networking and tweak
* Set SUMMARY instead of DESCRIPTION * Move SRC_URI checksums under SRC_URI * Move packaging definitions to the end Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com> Signed-off-by: Martin Jansa <Martin.Jansa@gmail.com>
Diffstat (limited to 'meta-networking/recipes-protocols/net-snmp')
-rw-r--r--meta-networking/recipes-protocols/net-snmp/files/ifmib.patch66
-rwxr-xr-xmeta-networking/recipes-protocols/net-snmp/files/init63
-rw-r--r--meta-networking/recipes-protocols/net-snmp/files/snmpd.conf422
-rw-r--r--meta-networking/recipes-protocols/net-snmp/files/snmptrapd.conf18
-rw-r--r--meta-networking/recipes-protocols/net-snmp/net-snmp/snmpd.service13
-rw-r--r--meta-networking/recipes-protocols/net-snmp/net-snmp/snmptrapd.service13
-rw-r--r--meta-networking/recipes-protocols/net-snmp/net-snmp/systemd-support.patch1616
-rw-r--r--meta-networking/recipes-protocols/net-snmp/net-snmp_5.7.2.bb118
8 files changed, 2329 insertions, 0 deletions
diff --git a/meta-networking/recipes-protocols/net-snmp/files/ifmib.patch b/meta-networking/recipes-protocols/net-snmp/files/ifmib.patch
new file mode 100644
index 0000000000..859c52c3e3
--- /dev/null
+++ b/meta-networking/recipes-protocols/net-snmp/files/ifmib.patch
@@ -0,0 +1,66 @@
+Signed-off-by: Jack Mitchell <jack@embed.me.uk>
+Upstream-Status: Pending
+Bug-Report: http://sourceforge.net/p/net-snmp/bugs/2449/
+
+diff --git a/agent/mibgroup/if-mib/data_access/interface_linux.c b/agent/mibgroup/if-mib/data_access/interface_linux.c
+index 3419811..d6eb91a 100644
+--- a/agent/mibgroup/if-mib/data_access/interface_linux.c
++++ b/agent/mibgroup/if-mib/data_access/interface_linux.c
+@@ -18,7 +18,31 @@ netsnmp_feature_require(interface_ioctl_flags_set)
+
+ #ifdef HAVE_PCI_LOOKUP_NAME
+ #include <pci/pci.h>
++#include <setjmp.h>
+ static struct pci_access *pci_access;
++
++/* Avoid letting libpci call exit(1) when no PCI bus is available. */
++static int do_longjmp =0;
++static jmp_buf err_buf;
++static void
++netsnmp_pci_error(char *msg, ...)
++{
++ va_list args;
++ char *buf;
++ int buflen;
++
++ va_start(args, msg);
++ buflen = strlen("pcilib: ")+strlen(msg)+2;
++ buf = malloc(buflen);
++ snprintf(buf, buflen, "pcilib: %s\n", msg);
++ snmp_vlog(LOG_ERR, buf, args);
++ free(buf);
++ va_end(args);
++ if (do_longjmp)
++ longjmp(err_buf, 1);
++ else
++ exit(1);
++}
+ #endif
+
+ #ifdef HAVE_LINUX_ETHTOOL_H
+@@ -147,10 +171,22 @@ netsnmp_arch_interface_init(void)
+
+ #ifdef HAVE_PCI_LOOKUP_NAME
+ pci_access = pci_alloc();
+- if (pci_access)
++ if (!pci_access) {
++ snmp_log(LOG_ERR, "pcilib: pci_alloc failed\n");
++ return;
++ }
++
++ pci_access->error = netsnmp_pci_error;
++
++ do_longjmp = 1;
++ if (setjmp(err_buf)) {
++ pci_cleanup(pci_access);
++ snmp_log(LOG_ERR, "pcilib: pci_init failed\n");
++ pci_access = NULL;
++ }
++ else if (pci_access)
+ pci_init(pci_access);
+- else
+- snmp_log(LOG_ERR, "Unable to create pci access method\n");
++ do_longjmp = 0;
+ #endif
+ }
+
diff --git a/meta-networking/recipes-protocols/net-snmp/files/init b/meta-networking/recipes-protocols/net-snmp/files/init
new file mode 100755
index 0000000000..434b2fa3f2
--- /dev/null
+++ b/meta-networking/recipes-protocols/net-snmp/files/init
@@ -0,0 +1,63 @@
+#! /bin/sh
+# /etc/init.d/snmpd: start snmp daemon.
+
+test -x /usr/sbin/snmpd || exit 0
+test -x /usr/sbin/snmptrapd || exit 0
+
+# Defaults
+export MIBDIRS=/usr/share/snmp/mibs
+SNMPDRUN=yes
+SNMPDOPTS='-Lsd -Lf /dev/null -p /var/run/snmpd.pid'
+TRAPDRUN=no
+TRAPDOPTS='-Lsd -p /var/run/snmptrapd.pid'
+
+# Cd to / before starting any daemons.
+cd /
+
+case "$1" in
+ start)
+ echo -n "Starting network management services:"
+ if [ "$SNMPDRUN" = "yes" -a -f /etc/snmp/snmpd.conf ]; then
+ start-stop-daemon -S -x /usr/sbin/snmpd \
+ -- $SNMPDOPTS
+ echo -n " snmpd"
+ fi
+ if [ "$TRAPDRUN" = "yes" -a -f /etc/snmp/snmptrapd.conf ]; then
+ start-stop-daemon -S -x /usr/sbin/snmptrapd \
+ -- $TRAPDOPTS
+ echo -n " snmptrapd"
+ fi
+ echo "."
+ ;;
+ stop)
+ echo -n "Stopping network management services:"
+ start-stop-daemon -K -x /usr/sbin/snmpd
+ echo -n " snmpd"
+ start-stop-daemon -K -x /usr/sbin/snmptrapd
+ echo -n " snmptrapd"
+ echo "."
+ ;;
+ restart|reload|force-reload)
+ echo -n "Restarting network management services:"
+ start-stop-daemon -K -x /usr/sbin/snmpd
+ start-stop-daemon -K -x /usr/sbin/snmptrapd
+ # Allow the daemons time to exit completely.
+ sleep 2
+ if [ "$SNMPDRUN" = "yes" -a -f /etc/snmp/snmpd.conf ]; then
+ start-stop-daemon -S -x /usr/sbin/snmpd -- $SNMPDOPTS
+ echo -n " snmpd"
+ fi
+ if [ "$TRAPDRUN" = "yes" -a -f /etc/snmp/snmptrapd.conf ]; then
+ # Allow snmpd time to start up.
+ sleep 1
+ start-stop-daemon -S -x /usr/sbin/snmptrapd -- $TRAPDOPTS
+ echo -n " snmptrapd"
+ fi
+ echo "."
+ ;;
+ *)
+ echo "Usage: /etc/init.d/snmpd {start|stop|restart|reload|force-reload}"
+ exit 1
+esac
+
+exit 0
diff --git a/meta-networking/recipes-protocols/net-snmp/files/snmpd.conf b/meta-networking/recipes-protocols/net-snmp/files/snmpd.conf
new file mode 100644
index 0000000000..728171c427
--- /dev/null
+++ b/meta-networking/recipes-protocols/net-snmp/files/snmpd.conf
@@ -0,0 +1,422 @@
+###############################################################################
+#
+# EXAMPLE.conf:
+# An example configuration file for configuring the ucd-snmp snmpd agent.
+#
+###############################################################################
+#
+# This file is intended to only be an example. If, however, you want
+# to use it, it should be placed in /etc/snmp/snmpd.conf.
+# When the snmpd agent starts up, this is where it will look for it.
+#
+# You might be interested in generating your own snmpd.conf file using
+# the "snmpconf" program (perl script) instead. It's a nice menu
+# based interface to writing well commented configuration files. Try it!
+#
+# Note: This file is automatically generated from EXAMPLE.conf.def.
+# Do NOT read the EXAMPLE.conf.def file! Instead, after you have run
+# configure & make, and then make sure you read the EXAMPLE.conf file
+# instead, as it will tailor itself to your configuration.
+
+# All lines beginning with a '#' are comments and are intended for you
+# to read. All other lines are configuration commands for the agent.
+
+#
+# PLEASE: read the snmpd.conf(5) manual page as well!
+#
+
+
+###############################################################################
+# Access Control
+###############################################################################
+
+# YOU SHOULD CHANGE THE "COMMUNITY" TOKEN BELOW TO A NEW KEYWORD ONLY
+# KNOWN AT YOUR SITE. YOU *MUST* CHANGE THE NETWORK TOKEN BELOW TO
+# SOMETHING REFLECTING YOUR LOCAL NETWORK ADDRESS SPACE.
+
+# By far, the most common question I get about the agent is "why won't
+# it work?", when really it should be "how do I configure the agent to
+# allow me to access it?"
+#
+# By default, the agent responds to the "public" community for read
+# only access, if run out of the box without any configuration file in
+# place. The following examples show you other ways of configuring
+# the agent so that you can change the community names, and give
+# yourself write access as well.
+#
+# The following lines change the access permissions of the agent so
+# that the COMMUNITY string provides read-only access to your entire
+# NETWORK (EG: 10.10.10.0/24), and read/write access to only the
+# localhost (127.0.0.1, not its real ipaddress).
+#
+# For more information, read the FAQ as well as the snmpd.conf(5)
+# manual page.
+
+####
+# First, map the community name (COMMUNITY) into a security name
+# (local and mynetwork, depending on where the request is coming
+# from):
+
+# sec.name source community
+com2sec paranoid default public
+#com2sec readonly default public
+#com2sec readwrite default private
+
+####
+# Second, map the security names into group names:
+
+# sec.model sec.name
+group MyROSystem v1 paranoid
+group MyROSystem v2c paranoid
+group MyROSystem usm paranoid
+group MyROGroup v1 readonly
+group MyROGroup v2c readonly
+group MyROGroup usm readonly
+group MyRWGroup v1 readwrite
+group MyRWGroup v2c readwrite
+group MyRWGroup usm readwrite
+
+####
+# Third, create a view for us to let the groups have rights to:
+
+# incl/excl subtree mask
+view all included .1 80
+view system included .iso.org.dod.internet.mgmt.mib-2.system
+
+####
+# Finally, grant the 2 groups access to the 1 view with different
+# write permissions:
+
+# context sec.model sec.level match read write notif
+access MyROSystem "" any noauth exact system none none
+access MyROGroup "" any noauth exact all none none
+access MyRWGroup "" any noauth exact all all none
+
+# -----------------------------------------------------------------------------
+
+
+###############################################################################
+# System contact information
+#
+
+# It is also possible to set the sysContact and sysLocation system
+# variables through the snmpd.conf file. **PLEASE NOTE** that setting
+# the value of these objects here makes these objects READ-ONLY
+# (regardless of any access control settings). Any attempt to set the
+# value of an object whose value is given here will fail with an error
+# status of notWritable.
+
+syslocation Unknown (configure /etc/snmp/snmpd.local.conf)
+syscontact Root <root@localhost> (configure /etc/snmp/snmpd.local.conf)
+
+# Example output of snmpwalk:
+# % snmpwalk -v 1 -c public localhost system
+# system.sysDescr.0 = "SunOS name sun4c"
+# system.sysObjectID.0 = OID: enterprises.ucdavis.ucdSnmpAgent.sunos4
+# system.sysUpTime.0 = Timeticks: (595637548) 68 days, 22:32:55
+# system.sysContact.0 = "Me <me@somewhere.org>"
+# system.sysName.0 = "name"
+# system.sysLocation.0 = "Right here, right now."
+# system.sysServices.0 = 72
+
+
+# -----------------------------------------------------------------------------
+
+
+###############################################################################
+# Process checks.
+#
+# The following are examples of how to use the agent to check for
+# processes running on the host. The syntax looks something like:
+#
+# proc NAME [MAX=0] [MIN=0]
+#
+# NAME: the name of the process to check for. It must match
+# exactly (ie, http will not find httpd processes).
+# MAX: the maximum number allowed to be running. Defaults to 0.
+# MIN: the minimum number to be running. Defaults to 0.
+
+#
+# Examples:
+#
+
+# Make sure mountd is running
+#proc mountd
+
+# Make sure there are no more than 4 ntalkds running, but 0 is ok too.
+#proc ntalkd 4
+
+# Make sure at least one sendmail, but less than or equal to 10 are running.
+#proc sendmail 10 1
+
+# A snmpwalk of the prTable would look something like this:
+#
+# % snmpwalk -v 1 -c public localhost .1.3.6.1.4.1.2021.2
+# enterprises.ucdavis.procTable.prEntry.prIndex.1 = 1
+# enterprises.ucdavis.procTable.prEntry.prIndex.2 = 2
+# enterprises.ucdavis.procTable.prEntry.prIndex.3 = 3
+# enterprises.ucdavis.procTable.prEntry.prNames.1 = "mountd"
+# enterprises.ucdavis.procTable.prEntry.prNames.2 = "ntalkd"
+# enterprises.ucdavis.procTable.prEntry.prNames.3 = "sendmail"
+# enterprises.ucdavis.procTable.prEntry.prMin.1 = 0
+# enterprises.ucdavis.procTable.prEntry.prMin.2 = 0
+# enterprises.ucdavis.procTable.prEntry.prMin.3 = 1
+# enterprises.ucdavis.procTable.prEntry.prMax.1 = 0
+# enterprises.ucdavis.procTable.prEntry.prMax.2 = 4
+# enterprises.ucdavis.procTable.prEntry.prMax.3 = 10
+# enterprises.ucdavis.procTable.prEntry.prCount.1 = 0
+# enterprises.ucdavis.procTable.prEntry.prCount.2 = 0
+# enterprises.ucdavis.procTable.prEntry.prCount.3 = 1
+# enterprises.ucdavis.procTable.prEntry.prErrorFlag.1 = 1
+# enterprises.ucdavis.procTable.prEntry.prErrorFlag.2 = 0
+# enterprises.ucdavis.procTable.prEntry.prErrorFlag.3 = 0
+# enterprises.ucdavis.procTable.prEntry.prErrMessage.1 = "No mountd process running."
+# enterprises.ucdavis.procTable.prEntry.prErrMessage.2 = ""
+# enterprises.ucdavis.procTable.prEntry.prErrMessage.3 = ""
+# enterprises.ucdavis.procTable.prEntry.prErrFix.1 = 0
+# enterprises.ucdavis.procTable.prEntry.prErrFix.2 = 0
+# enterprises.ucdavis.procTable.prEntry.prErrFix.3 = 0
+#
+# Note that the errorFlag for mountd is set to 1 because one is not
+# running (in this case an rpc.mountd is, but thats not good enough),
+# and the ErrMessage tells you what's wrong. The configuration
+# imposed in the snmpd.conf file is also shown.
+#
+# Special Case: When the min and max numbers are both 0, it assumes
+# you want a max of infinity and a min of 1.
+#
+
+
+# -----------------------------------------------------------------------------
+
+
+###############################################################################
+# Executables/scripts
+#
+
+#
+# You can also have programs run by the agent that return a single
+# line of output and an exit code. Here are two examples.
+#
+# exec NAME PROGRAM [ARGS ...]
+#
+# NAME: A generic name.
+# PROGRAM: The program to run. Include the path!
+# ARGS: optional arguments to be passed to the program
+
+# a simple hello world
+#exec echotest /bin/echo hello world
+
+# Run a shell script containing:
+#
+# #!/bin/sh
+# echo hello world
+# echo hi there
+# exit 35
+#
+# Note: this has been specifically commented out to prevent
+# accidental security holes due to someone else on your system writing
+# a /tmp/shtest before you do. Uncomment to use it.
+#
+#exec shelltest /bin/sh /tmp/shtest
+
+# Then,
+# % snmpwalk -v 1 -c public localhost .1.3.6.1.4.1.2021.8
+# enterprises.ucdavis.extTable.extEntry.extIndex.1 = 1
+# enterprises.ucdavis.extTable.extEntry.extIndex.2 = 2
+# enterprises.ucdavis.extTable.extEntry.extNames.1 = "echotest"
+# enterprises.ucdavis.extTable.extEntry.extNames.2 = "shelltest"
+# enterprises.ucdavis.extTable.extEntry.extCommand.1 = "/bin/echo hello world"
+# enterprises.ucdavis.extTable.extEntry.extCommand.2 = "/bin/sh /tmp/shtest"
+# enterprises.ucdavis.extTable.extEntry.extResult.1 = 0
+# enterprises.ucdavis.extTable.extEntry.extResult.2 = 35
+# enterprises.ucdavis.extTable.extEntry.extOutput.1 = "hello world."
+# enterprises.ucdavis.extTable.extEntry.extOutput.2 = "hello world."
+# enterprises.ucdavis.extTable.extEntry.extErrFix.1 = 0
+# enterprises.ucdavis.extTable.extEntry.extErrFix.2 = 0
+
+# Note that the second line of the /tmp/shtest shell script is cut
+# off. Also note that the exit status of 35 was returned.
+
+# -----------------------------------------------------------------------------
+
+
+###############################################################################
+# disk checks
+#
+
+# The agent can check the amount of available disk space, and make
+# sure it is above a set limit.
+
+# disk PATH [MIN=DEFDISKMINIMUMSPACE]
+#
+# PATH: mount path to the disk in question.
+# MIN: Disks with space below this value will have the Mib's errorFlag set.
+# Default value = DEFDISKMINIMUMSPACE.
+
+# Check the / partition and make sure it contains at least 10 megs.
+
+#disk / 10000
+
+# % snmpwalk -v 1 -c public localhost .1.3.6.1.4.1.2021.9
+# enterprises.ucdavis.diskTable.dskEntry.diskIndex.1 = 0
+# enterprises.ucdavis.diskTable.dskEntry.diskPath.1 = "/" Hex: 2F
+# enterprises.ucdavis.diskTable.dskEntry.diskDevice.1 = "/dev/dsk/c201d6s0"
+# enterprises.ucdavis.diskTable.dskEntry.diskMinimum.1 = 10000
+# enterprises.ucdavis.diskTable.dskEntry.diskTotal.1 = 837130
+# enterprises.ucdavis.diskTable.dskEntry.diskAvail.1 = 316325
+# enterprises.ucdavis.diskTable.dskEntry.diskUsed.1 = 437092
+# enterprises.ucdavis.diskTable.dskEntry.diskPercent.1 = 58
+# enterprises.ucdavis.diskTable.dskEntry.diskErrorFlag.1 = 0
+# enterprises.ucdavis.diskTable.dskEntry.diskErrorMsg.1 = ""
+
+# -----------------------------------------------------------------------------
+
+
+###############################################################################
+# load average checks
+#
+
+# load [1MAX=DEFMAXLOADAVE] [5MAX=DEFMAXLOADAVE] [15MAX=DEFMAXLOADAVE]
+#
+# 1MAX: If the 1 minute load average is above this limit at query
+# time, the errorFlag will be set.
+# 5MAX: Similar, but for 5 min average.
+# 15MAX: Similar, but for 15 min average.
+
+# Check for loads:
+#load 12 14 14
+
+# % snmpwalk -v 1 -c public localhost .1.3.6.1.4.1.2021.10
+# enterprises.ucdavis.loadTable.laEntry.loadaveIndex.1 = 1
+# enterprises.ucdavis.loadTable.laEntry.loadaveIndex.2 = 2
+# enterprises.ucdavis.loadTable.laEntry.loadaveIndex.3 = 3
+# enterprises.ucdavis.loadTable.laEntry.loadaveNames.1 = "Load-1"
+# enterprises.ucdavis.loadTable.laEntry.loadaveNames.2 = "Load-5"
+# enterprises.ucdavis.loadTable.laEntry.loadaveNames.3 = "Load-15"
+# enterprises.ucdavis.loadTable.laEntry.loadaveLoad.1 = "0.49" Hex: 30 2E 34 39
+# enterprises.ucdavis.loadTable.laEntry.loadaveLoad.2 = "0.31" Hex: 30 2E 33 31
+# enterprises.ucdavis.loadTable.laEntry.loadaveLoad.3 = "0.26" Hex: 30 2E 32 36
+# enterprises.ucdavis.loadTable.laEntry.loadaveConfig.1 = "12.00"
+# enterprises.ucdavis.loadTable.laEntry.loadaveConfig.2 = "14.00"
+# enterprises.ucdavis.loadTable.laEntry.loadaveConfig.3 = "14.00"
+# enterprises.ucdavis.loadTable.laEntry.loadaveErrorFlag.1 = 0
+# enterprises.ucdavis.loadTable.laEntry.loadaveErrorFlag.2 = 0
+# enterprises.ucdavis.loadTable.laEntry.loadaveErrorFlag.3 = 0
+# enterprises.ucdavis.loadTable.laEntry.loadaveErrMessage.1 = ""
+# enterprises.ucdavis.loadTable.laEntry.loadaveErrMessage.2 = ""
+# enterprises.ucdavis.loadTable.laEntry.loadaveErrMessage.3 = ""
+
+# -----------------------------------------------------------------------------
+
+
+###############################################################################
+# Extensible sections.
+#
+
+# This alleviates the multiple line output problem found in the
+# previous executable mib by placing each mib in its own mib table:
+
+# Run a shell script containing:
+#
+# #!/bin/sh
+# echo hello world
+# echo hi there
+# exit 35
+#
+# Note: this has been specifically commented out to prevent
+# accidental security holes due to someone else on your system writing
+# a /tmp/shtest before you do. Uncomment to use it.
+#
+# exec .1.3.6.1.4.1.2021.50 shelltest /bin/sh /tmp/shtest
+
+# % snmpwalk -v 1 -c public localhost .1.3.6.1.4.1.2021.50
+# enterprises.ucdavis.50.1.1 = 1
+# enterprises.ucdavis.50.2.1 = "shelltest"
+# enterprises.ucdavis.50.3.1 = "/bin/sh /tmp/shtest"
+# enterprises.ucdavis.50.100.1 = 35
+# enterprises.ucdavis.50.101.1 = "hello world."
+# enterprises.ucdavis.50.101.2 = "hi there."
+# enterprises.ucdavis.50.102.1 = 0
+
+# Now the Output has grown to two lines, and we can see the 'hi
+# there.' output as the second line from our shell script.
+#
+# Note that you must alter the mib.txt file to be correct if you want
+# the .50.* outputs above to change to reasonable text descriptions.
+
+# Other ideas:
+#
+# exec .1.3.6.1.4.1.2021.51 ps /bin/ps
+# exec .1.3.6.1.4.1.2021.52 top /usr/local/bin/top
+# exec .1.3.6.1.4.1.2021.53 mailq /usr/bin/mailq
+
+# -----------------------------------------------------------------------------
+
+
+###############################################################################
+# Pass through control.
+#
+
+# Usage:
+# pass MIBOID EXEC-COMMAND
+#
+# This will pass total control of the mib underneath the MIBOID
+# portion of the mib to the EXEC-COMMAND.
+#
+# Note: You'll have to change the path of the passtest script to your
+# source directory or install it in the given location.
+#
+# Example: (see the script for details)
+# (commented out here since it requires that you place the
+# script in the right location. (its not installed by default))
+
+# pass .1.3.6.1.4.1.2021.255 /bin/sh /usr/local/passtest
+
+# % snmpwalk -v 1 -c public localhost .1.3.6.1.4.1.2021.255
+# enterprises.ucdavis.255.1 = "life the universe and everything"
+# enterprises.ucdavis.255.2.1 = 42
+# enterprises.ucdavis.255.2.2 = OID: 42.42.42
+# enterprises.ucdavis.255.3 = Timeticks: (363136200) 42 days, 0:42:42
+# enterprises.ucdavis.255.4 = IpAddress: 127.0.0.1
+# enterprises.ucdavis.255.5 = 42
+# enterprises.ucdavis.255.6 = Gauge: 42
+#
+# % snmpget -v 1 -c public localhost .1.3.6.1.4.1.2021.255.5
+# enterprises.ucdavis.255.5 = 42
+#
+# % snmpset -v 1 -c public localhost .1.3.6.1.4.1.2021.255.1 s "New string"
+# enterprises.ucdavis.255.1 = "New string"
+#
+
+# For specific usage information, see the man/snmpd.conf.5 manual page
+# as well as the local/passtest script used in the above example.
+
+###############################################################################
+# Subagent control
+#
+
+# The agent can support subagents using a number of extension mechanisms.
+# From the 4.2.1 release, AgentX support is being compiled in by default.
+# However, this is still experimental code, so should not be used on
+# critical production systems.
+# Please see the file README.agentx for more details.
+#
+# If having read, marked, learnt and inwardly digested this information,
+# you decide that you do wish to make use of this mechanism, simply
+# uncomment the following directive.
+#
+# master agentx
+#
+# I repeat - this is *NOT* regarded as suitable for front-line production
+# systems, though it is probably stable enough for day-to-day use.
+# Probably.
+#
+# No refunds will be given.
+
+###############################################################################
+# Further Information
+#
+# See the snmpd.conf manual page, and the output of "snmpd -H".
+# MUCH more can be done with the snmpd.conf than is shown as an
+# example here.
diff --git a/meta-networking/recipes-protocols/net-snmp/files/snmptrapd.conf b/meta-networking/recipes-protocols/net-snmp/files/snmptrapd.conf
new file mode 100644
index 0000000000..8d2e4375ef
--- /dev/null
+++ b/meta-networking/recipes-protocols/net-snmp/files/snmptrapd.conf
@@ -0,0 +1,18 @@
+###############################################################################
+#
+# EXAMPLE.conf:
+# An example configuration file for configuring the ucd-snmp snmptrapd agent.
+#
+###############################################################################
+#
+# This file is intended to only be an example. If, however, you want
+# to use it, it should be placed in /etc/snmp/snmptrapd.conf.
+# When the snmptrapd agent starts up, this is where it will look for it.
+#
+# All lines beginning with a '#' are comments and are intended for you
+# to read. All other lines are configuration commands for the agent.
+
+#
+# PLEASE: read the snmptrapd.conf(5) manual page as well!
+#
+
diff --git a/meta-networking/recipes-protocols/net-snmp/net-snmp/snmpd.service b/meta-networking/recipes-protocols/net-snmp/net-snmp/snmpd.service
new file mode 100644
index 0000000000..10a1eb2128
--- /dev/null
+++ b/meta-networking/recipes-protocols/net-snmp/net-snmp/snmpd.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=Simple Network Management Protocol (SNMP) Daemon.
+After=syslog.target network.target
+
+[Service]
+Type=notify
+Environment=OPTIONS="-LS0-6d"
+EnvironmentFile=-/etc/default/snmpd
+ExecStart=/usr/sbin/snmpd $OPTIONS -f
+ExecReload=/bin/kill -HUP $MAINPID
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta-networking/recipes-protocols/net-snmp/net-snmp/snmptrapd.service b/meta-networking/recipes-protocols/net-snmp/net-snmp/snmptrapd.service
new file mode 100644
index 0000000000..951f9f2707
--- /dev/null
+++ b/meta-networking/recipes-protocols/net-snmp/net-snmp/snmptrapd.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=Simple Network Management Protocol (SNMP) Trap Daemon.
+After=syslog.target network.target
+
+[Service]
+Type=notify
+Environment=OPTIONS="-Lsd"
+EnvironmentFile=-/etc/default/snmptrapd
+ExecStart=/usr/sbin/snmptrapd $OPTIONS -f
+ExecReload=/bin/kill -HUP $MAINPID
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta-networking/recipes-protocols/net-snmp/net-snmp/systemd-support.patch b/meta-networking/recipes-protocols/net-snmp/net-snmp/systemd-support.patch
new file mode 100644
index 0000000000..18955f29ee
--- /dev/null
+++ b/meta-networking/recipes-protocols/net-snmp/net-snmp/systemd-support.patch
@@ -0,0 +1,1616 @@
+Systemd support backported from the master branch as of 23/04/2012 (post 5.7.1, pre 5.8).
+
+The following commits have been cherry-picked:
+
+19499c3c90bf9d7b2b9e5d08baa26cc6bba28a11
+fef6cddfdb94da1a6b1fb768af62918b80f11fd3
+0641e43c694c485cbbffef0556efc4641bd3ff50
+76530a89f1c8bbd0b63acce63e10d5d4812a1a16 (conflict resolved)
+bf108d7f1354f6276fc43c129963f2c49b9fc242
+74412748067c685e1d8ab6ed3bcc3ca9c2774844
+86132e3f1e6ef7b4e0b96d8fa24e37c81b71b0e0
+63557cf8986a33dba1d4429b583a901361052c4f
+
+Upstream-Status: Backport
+
+diff --git a/README.systemd b/README.systemd
+new file mode 100644
+index 0000000..f731851
+--- /dev/null
++++ b/README.systemd
+@@ -0,0 +1,41 @@
++README.systemd
++--------------
++Net-SNMP provides two daemons, which support systemd system manager.
++See http://www.freedesktop.org/wiki/Software/systemd to learn how
++systemd works. Both socket activation and notification is supported by these
++daemons.
++
++To enable systemd support, the sources must be compiled with
++--with-systemd configure option.
++
++snmpd - The SNMP agent
++----------------------
++Socket activation od snmpd daemon is implemented, but it's discouraged.
++The reason is simple - snmpd not only listens and processes SNMP requests
++from network, but also gathers system statistics counters, sends traps and
++communicates with subagents. It even opens few netlink sockets.
++
++In other words, snmpd should run from system start to properly work.
++This can be done in two ways:
++1) either as snmpd service unit with 'Type=notification' and without a socket
++ unit
++2) or as snmpd service unit with 'Type=simple', appropriate socket socket unit
++ and the snmpd service enabled. This way systemd creates the snmpd listening
++ socket early during boot and passes the sockets to snmpd slightly later
++ (but still during machine boot). This way systemd can paralelize start of
++ services, which depend on snmpd. Admins must adjust the socket file manually,
++ depending if the snmpd support AgentX, IPv6, SMUX etc.
++
++snmpd should be started with '-f' command line parameter to disable forking -
++systemd does that for us automatically.
++
++
++snmptrapd - The trap processing daemon
++--------------------------------------
++snmptrapd supports full socket activation and also notification (if needed).
++Both 'Type=simple' (with appropriate socket unit) and 'Type=notify' services
++will work. Again, '-f' parameter should be provided on snmptrapd command line.
++
++If integration with SNMP agent using AgentX protocol is enabled, snmptrapd should
++start during boot and not after first SNMP trap arrives. Same rules as for snmpd
++applies then.
+\ No newline at end of file
+diff --git a/agent/snmpd.c b/agent/snmpd.c
+index b177d5b..08bdfc7 100644
+--- a/agent/snmpd.c
++++ b/agent/snmpd.c
+@@ -164,6 +164,10 @@ typedef long fd_mask;
+
+ #endif
+
++#ifndef NETSNMP_NO_SYSTEMD
++#include <net-snmp/library/sd-daemon.h>
++#endif
++
+ netsnmp_feature_want(logging_file)
+ netsnmp_feature_want(logging_stdio)
+ netsnmp_feature_want(logging_syslog)
+@@ -441,18 +445,28 @@ main(int argc, char *argv[])
+ int agent_mode = -1;
+ char *pid_file = NULL;
+ char option_compatability[] = "-Le";
++#ifndef WIN32
++ int prepared_sockets = 0;
++#endif
+ #if HAVE_GETPID
+ int fd;
+ FILE *PID;
+ #endif
+
+ #ifndef WIN32
++#ifndef NETSNMP_NO_SYSYSTEMD
++ /* check if systemd has sockets for us and don't close them */
++ prepared_sockets = netsnmp_sd_listen_fds(0);
++#endif /* NETSNMP_NO_SYSYSTEMD */
++
+ /*
+ * close all non-standard file descriptors we may have
+ * inherited from the shell.
+ */
+- for (i = getdtablesize() - 1; i > 2; --i) {
+- (void) close(i);
++ if (!prepared_sockets) {
++ for (i = getdtablesize() - 1; i > 2; --i) {
++ (void) close(i);
++ }
+ }
+ #endif /* #WIN32 */
+
+@@ -1100,6 +1114,19 @@ main(int argc, char *argv[])
+ netsnmp_addrcache_initialise();
+
+ /*
++ * Let systemd know we're up.
++ */
++#ifndef NETSNMP_NO_SYSTEMD
++ netsnmp_sd_notify(1, "READY=1\n");
++ if (prepared_sockets)
++ /*
++ * Clear the environment variable, we already processed all the sockets
++ * by now.
++ */
++ netsnmp_sd_listen_fds(1);
++#endif
++
++ /*
+ * Forever monitor the dest_port for incoming PDUs.
+ */
+ DEBUGMSGTL(("snmpd/main", "We're up. Starting to process data.\n"));
+diff --git a/apps/snmptrapd.c b/apps/snmptrapd.c
+index 1a52080..0857ae1 100644
+--- a/apps/snmptrapd.c
++++ b/apps/snmptrapd.c
+@@ -125,6 +125,10 @@ SOFTWARE.
+
+ #include <net-snmp/net-snmp-features.h>
+
++#ifndef NETSNMP_NO_SYSTEMD
++#include <net-snmp/library/sd-daemon.h>
++#endif
++
+ #ifndef BSD4_3
+ #define BSD4_2
+ #endif
+@@ -655,15 +659,24 @@ main(int argc, char *argv[])
+ int agentx_subagent = 1;
+ #endif
+ netsnmp_trapd_handler *traph;
++#ifndef WIN32
++ int prepared_sockets = 0;
++#endif
+
+
+ #ifndef WIN32
++#ifndef NETSNMP_NO_SYSTEMD
++ /* check if systemd has sockets for us and don't close them */
++ prepared_sockets = netsnmp_sd_listen_fds(0);
++#endif
+ /*
+ * close all non-standard file descriptors we may have
+ * inherited from the shell.
+ */
+- for (i = getdtablesize() - 1; i > 2; --i) {
+- (void) close(i);
++ if (!prepared_sockets) {
++ for (i = getdtablesize() - 1; i > 2; --i) {
++ (void) close(i);
++ }
+ }
+ #endif /* #WIN32 */
+
+@@ -1311,6 +1324,19 @@ main(int argc, char *argv[])
+ #endif
+ #endif
+
++ /*
++ * Let systemd know we're up.
++ */
++#ifndef NETSNMP_NO_SYSTEMD
++ netsnmp_sd_notify(1, "READY=1\n");
++ if (prepared_sockets)
++ /*
++ * Clear the environment variable, we already processed all the sockets
++ * by now.
++ */
++ netsnmp_sd_listen_fds(1);
++#endif
++
+ #ifdef WIN32SERVICE
+ trapd_status = SNMPTRAPD_RUNNING;
+ #endif
+diff --git a/configure.d/config_modules_lib b/configure.d/config_modules_lib
+index b6609c1..5849072 100644
+--- a/configure.d/config_modules_lib
++++ b/configure.d/config_modules_lib
+@@ -53,6 +53,14 @@ if test "x$PARTIALTARGETOS" = "xmingw32" -o "x$PARTIALTARGETOS" = "xmingw32msvc"
+ other_ftobjs_list="$other_ftobjs_list winpipe.ft"
+ fi
+
++# Linux systemd
++if test "x$with_systemd" == "xyes"; then
++ other_src_list="$other_src_list sd-daemon.c"
++ other_objs_list="$other_objs_list sd-daemon.o"
++ other_lobjs_list="$other_lobjs_list sd-daemon.lo"
++ other_ftobjs_list="$other_ftobjs_list sd-daemon.ft"
++fi
++
+ AC_SUBST(other_src_list)
+ AC_SUBST(other_objs_list)
+ AC_SUBST(other_lobjs_list)
+diff --git a/configure.d/config_project_with_enable b/configure.d/config_project_with_enable
+index 8b46ad2..59d6d5c 100644
+--- a/configure.d/config_project_with_enable
++++ b/configure.d/config_project_with_enable
+@@ -689,6 +689,15 @@ if test "x$with_dummy_values" != "xyes"; then
+ data for])
+ fi
+
++NETSNMP_ARG_WITH(systemd,
++[ --with-systemd Provide systemd support. See README.systemd
++ for details.])
++# Define unless specifically suppressed (i.e., option defaults to false).
++if test "x$with_systemd" != "xyes"; then
++ AC_DEFINE(NETSNMP_NO_SYSTEMD, 1,
++ [If you don't want to integrate with systemd.])
++fi
++
+ NETSNMP_ARG_ENABLE(set-support,
+ [ --disable-set-support Do not allow SNMP set requests.])
+ if test "x$enable_set_support" = "xno"; then
+diff --git a/dist/snmpd.service b/dist/snmpd.service
+new file mode 100644
+index 0000000..31391e5
+--- /dev/null
++++ b/dist/snmpd.service
+@@ -0,0 +1,18 @@
++#
++# SNMP agent service file for systemd
++#
++#
++# The service should be enabled, i.e. snmpd should start during machine boot.
++# Socket activation shall not be used. See README.systemd for details.
++
++[Unit]
++Description=Simple Network Management Protocol (SNMP) daemon.
++After=syslog.target network.target
++
++[Service]
++# Type=notify is also supported. It should be set when snmpd.socket is not used.
++Type=simple
++ExecStart=/usr/sbin/snmpd -f
++
++[Install]
++WantedBy=multi-user.target
+diff --git a/dist/snmpd.socket b/dist/snmpd.socket
+new file mode 100644
+index 0000000..7f3a2d9
+--- /dev/null
++++ b/dist/snmpd.socket
+@@ -0,0 +1,17 @@
++[Unit]
++Description=Socket listening for SNMP and AgentX messages
++
++[Socket]
++ListenDatagram=0.0.0.0:161
++# Uncomment other listening addresses as needed - TCP, UDP6, TCP6.
++# It must match listening addresses/ports defined in snmpd.service
++# or snmpd.conf.
++# ListenStream=0.0.0.0:161
++# ListenDatagram=[::]:161
++# ListenStream=[::]:161
++#
++# Uncomment AgentX socket if snmpd.conf enables AgentX protocol.
++# ListenStream=/var/agentx/master
++
++[Install]
++WantedBy=sockets.target
+diff --git a/dist/snmptrapd.service b/dist/snmptrapd.service
+new file mode 100644
+index 0000000..e88a5b4
+--- /dev/null
++++ b/dist/snmptrapd.service
+@@ -0,0 +1,16 @@
++#
++# SNMP trap-processing service file for systemd
++#
++
++[Unit]
++Description=Simple Network Management Protocol (SNMP) Trap daemon.
++After=syslog.target network.target
++
++[Service]
++# Type=notify is also supported. It should be set when snmptrapd.socket is not
++# used.
++Type=simple
++ExecStart=/usr/sbin/snmptrapd -f
++
++[Install]
++WantedBy=multi-user.target
+diff --git a/dist/snmptrapd.socket b/dist/snmptrapd.socket
+new file mode 100644
+index 0000000..0fc8a7c
+--- /dev/null
++++ b/dist/snmptrapd.socket
+@@ -0,0 +1,14 @@
++[Unit]
++Description=Socket listening for SNMP trap messages
++
++[Socket]
++ListenDatagram=0.0.0.0:162
++# Uncomment other listening addresses as needed - TCP, UDP6, TCP6.
++# It must match listening addresses/ports defined in snmptrapd.service
++# or snmptrapd.conf.
++# ListenStream=0.0.0.0:162
++# ListenDatagram=[::]:162
++# ListenStream=[::]:162
++
++[Install]
++WantedBy=sockets.target
+diff --git a/include/net-snmp/library/sd-daemon.h b/include/net-snmp/library/sd-daemon.h
+new file mode 100644
+index 0000000..85274c9
+--- /dev/null
++++ b/include/net-snmp/library/sd-daemon.h
+@@ -0,0 +1,290 @@
++/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
++
++#ifndef SNMPD_SD_DAEMON_H
++#define SNMPD_SD_DAEMON_H
++
++/***
++ Copyright 2010 Lennart Poettering
++
++ Permission is hereby granted, free of charge, to any person
++ obtaining a copy of this software and associated documentation files
++ (the "Software"), to deal in the Software without restriction,
++ including without limitation the rights to use, copy, modify, merge,
++ publish, distribute, sublicense, and/or sell copies of the Software,
++ and to permit persons to whom the Software is furnished to do so,
++ subject to the following conditions:
++
++ The above copyright notice and this permission notice shall be
++ included in all copies or substantial portions of the Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ SOFTWARE.
++***/
++
++#ifdef HAVE_SYS_TYPES_H
++#include <sys/types.h>
++#endif
++#ifdef HAVE_INTTYPES_H
++#include <inttypes.h>
++#endif
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/*
++ Reference implementation of a few systemd related interfaces for
++ writing daemons. These interfaces are trivial to implement. To
++ simplify porting we provide this reference implementation.
++ Applications are welcome to reimplement the algorithms described
++ here if they do not want to include these two source files.
++
++ The following functionality is provided:
++
++ - Support for logging with log levels on stderr
++ - File descriptor passing for socket-based activation
++ - Daemon startup and status notification
++ - Detection of systemd boots
++
++ You may compile this with -DDISABLE_SYSTEMD to disable systemd
++ support. This makes all those calls NOPs that are directly related to
++ systemd (i.e. only sd_is_xxx() will stay useful).
++
++ Since this is drop-in code we don't want any of our symbols to be
++ exported in any case. Hence we declare hidden visibility for all of
++ them.
++
++ You may find an up-to-date version of these source files online:
++
++ http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.h
++ http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.c
++
++ This should compile on non-Linux systems, too, but with the
++ exception of the sd_is_xxx() calls all functions will become NOPs.
++
++ See sd-daemon(7) for more information.
++*/
++
++#ifndef _sd_printf_attr_
++#if __GNUC__ >= 4
++#define _sd_printf_attr_(a,b) __attribute__ ((format (printf, a, b)))
++#else
++#define _sd_printf_attr_(a,b)
++#endif
++#endif
++
++/*
++ Log levels for usage on stderr:
++
++ fprintf(stderr, SD_NOTICE "Hello World!\n");
++
++ This is similar to printk() usage in the kernel.
++*/
++#define SD_EMERG "<0>" /* system is unusable */
++#define SD_ALERT "<1>" /* action must be taken immediately */
++#define SD_CRIT "<2>" /* critical conditions */
++#define SD_ERR "<3>" /* error conditions */
++#define SD_WARNING "<4>" /* warning conditions */
++#define SD_NOTICE "<5>" /* normal but significant condition */
++#define SD_INFO "<6>" /* informational */
++#define SD_DEBUG "<7>" /* debug-level messages */
++
++/* The first passed file descriptor is fd 3 */
++#define SD_LISTEN_FDS_START 3
++
++/*
++ Returns how many file descriptors have been passed, or a negative
++ errno code on failure. Optionally, removes the $LISTEN_FDS and
++ $LISTEN_PID file descriptors from the environment (recommended, but
++ problematic in threaded environments). If r is the return value of
++ this function you'll find the file descriptors passed as fds
++ SD_LISTEN_FDS_START to SD_LISTEN_FDS_START+r-1. Returns a negative
++ errno style error code on failure. This function call ensures that
++ the FD_CLOEXEC flag is set for the passed file descriptors, to make
++ sure they are not passed on to child processes. If FD_CLOEXEC shall
++ not be set, the caller needs to unset it after this call for all file
++ descriptors that are used.
++
++ See sd_listen_fds(3) for more information.
++*/
++int netsnmp_sd_listen_fds(int unset_environment);
++
++/*
++ Helper call for identifying a passed file descriptor. Returns 1 if
++ the file descriptor is a FIFO in the file system stored under the
++ specified path, 0 otherwise. If path is NULL a path name check will
++ not be done and the call only verifies if the file descriptor
++ refers to a FIFO. Returns a negative errno style error code on
++ failure.
++
++ See sd_is_fifo(3) for more information.
++*/
++int netsnmp_sd_is_fifo(int fd, const char *path);
++
++/*
++ Helper call for identifying a passed file descriptor. Returns 1 if
++ the file descriptor is a special character device on the file
++ system stored under the specified path, 0 otherwise.
++ If path is NULL a path name check will not be done and the call
++ only verifies if the file descriptor refers to a special character.
++ Returns a negative errno style error code on failure.
++
++ See sd_is_special(3) for more information.
++*/
++int netsnmp_sd_is_special(int fd, const char *path);
++
++/*
++ Helper call for identifying a passed file descriptor. Returns 1 if
++ the file descriptor is a socket of the specified family (AF_INET,
++ ...) and type (SOCK_DGRAM, SOCK_STREAM, ...), 0 otherwise. If
++ family is 0 a socket family check will not be done. If type is 0 a
++ socket type check will not be done and the call only verifies if
++ the file descriptor refers to a socket. If listening is > 0 it is
++ verified that the socket is in listening mode. (i.e. listen() has
++ been called) If listening is == 0 it is verified that the socket is
++ not in listening mode. If listening is < 0 no listening mode check
++ is done. Returns a negative errno style error code on failure.
++
++ See sd_is_socket(3) for more information.
++*/
++int netsnmp_sd_is_socket(int fd, int family, int type, int listening);
++
++/*
++ Helper call for identifying a passed file descriptor. Returns 1 if
++ the file descriptor is an Internet socket, of the specified family
++ (either AF_INET or AF_INET6) and the specified type (SOCK_DGRAM,
++ SOCK_STREAM, ...), 0 otherwise. If version is 0 a protocol version
++ check is not done. If type is 0 a socket type check will not be
++ done. If port is 0 a socket port check will not be done. The
++ listening flag is used the same way as in sd_is_socket(). Returns a
++ negative errno style error code on failure.
++
++ See sd_is_socket_inet(3) for more information.
++*/
++int netsnmp_sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port);
++
++/*
++ Helper call for identifying a passed file descriptor. Returns 1 if
++ the file descriptor is an AF_UNIX socket of the specified type
++ (SOCK_DGRAM, SOCK_STREAM, ...) and path, 0 otherwise. If type is 0
++ a socket type check will not be done. If path is NULL a socket path
++ check will not be done. For normal AF_UNIX sockets set length to
++ 0. For abstract namespace sockets set length to the length of the
++ socket name (including the initial 0 byte), and pass the full
++ socket path in path (including the initial 0 byte). The listening
++ flag is used the same way as in sd_is_socket(). Returns a negative
++ errno style error code on failure.
++
++ See sd_is_socket_unix(3) for more information.
++*/
++int netsnmp_sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length);
++
++/*
++ Informs systemd about changed daemon state. This takes a number of
++ newline separated environment-style variable assignments in a
++ string. The following variables are known:
++
++ READY=1 Tells systemd that daemon startup is finished (only
++ relevant for services of Type=notify). The passed
++ argument is a boolean "1" or "0". Since there is
++ little value in signaling non-readiness the only
++ value daemons should send is "READY=1".
++
++ STATUS=... Passes a single-line status string back to systemd
++ that describes the daemon state. This is free-from
++ and can be used for various purposes: general state
++ feedback, fsck-like programs could pass completion
++ percentages and failing programs could pass a human
++ readable error message. Example: "STATUS=Completed
++ 66% of file system check..."
++
++ ERRNO=... If a daemon fails, the errno-style error code,
++ formatted as string. Example: "ERRNO=2" for ENOENT.
++
++ BUSERROR=... If a daemon fails, the D-Bus error-style error
++ code. Example: "BUSERROR=org.freedesktop.DBus.Error.TimedOut"
++
++ MAINPID=... The main pid of a daemon, in case systemd did not
++ fork off the process itself. Example: "MAINPID=4711"
++
++ Daemons can choose to send additional variables. However, it is
++ recommended to prefix variable names not listed above with X_.
++
++ Returns a negative errno-style error code on failure. Returns > 0
++ if systemd could be notified, 0 if it couldn't possibly because
++ systemd is not running.
++
++ Example: When a daemon finished starting up, it could issue this
++ call to notify systemd about it:
++
++ sd_notify(0, "READY=1");
++
++ See sd_notifyf() for more complete examples.
++
++ See sd_notify(3) for more information.
++*/
++int netsnmp_sd_notify(int unset_environment, const char *state);
++
++/*
++ Similar to sd_notify() but takes a format string.
++
++ Example 1: A daemon could send the following after initialization:
++
++ sd_notifyf(0, "READY=1\n"
++ "STATUS=Processing requests...\n"
++ "MAINPID=%lu",
++ (unsigned long) getpid());
++
++ Example 2: A daemon could send the following shortly before
++ exiting, on failure:
++
++ sd_notifyf(0, "STATUS=Failed to start up: %s\n"
++ "ERRNO=%i",
++ strerror(errno),
++ errno);
++
++ See sd_notifyf(3) for more information.
++*/
++int netsnmp_sd_notifyf(int unset_environment, const char *format, ...) _sd_printf_attr_(2,3);
++
++/*
++ Returns > 0 if the system was booted with systemd. Returns < 0 on
++ error. Returns 0 if the system was not booted with systemd. Note
++ that all of the functions above handle non-systemd boots just
++ fine. You should NOT protect them with a call to this function. Also
++ note that this function checks whether the system, not the user
++ session is controlled by systemd. However the functions above work
++ for both user and system services.
++
++ See sd_booted(3) for more information.
++*/
++int netsnmp_sd_booted(void);
++
++/**
++ * Find an socket with given parameters. See man sd_is_socket_inet for
++ * description of the arguments.
++ *
++ * Returns the file descriptor if it is found, 0 otherwise.
++ */
++int netsnmp_sd_find_inet_socket(int family, int type, int listening, int port);
++
++/**
++ * Find an unix socket with given parameters. See man sd_is_socket_unix for
++ * description of the arguments.
++ *
++ * Returns the file descriptor if it is found, 0 otherwise.
++ */
++int
++netsnmp_sd_find_unix_socket(int type, int listening, const char *path);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* SNMPD_SD_DAEMON_H */
+diff --git a/snmplib/sd-daemon.c b/snmplib/sd-daemon.c
+new file mode 100644
+index 0000000..42dba29
+--- /dev/null
++++ b/snmplib/sd-daemon.c
+@@ -0,0 +1,532 @@
++/*
++ * Systemd integration parts.
++ *
++ * Most of this file is directly copied from systemd sources.
++ * Changes:
++ * - all functions were renamed to have netsnmp_ prefix
++ * - includes were changed to match Net-SNMP style.
++ * - removed gcc export macros
++ * - removed POSIX message queues
++ */
++
++#include <net-snmp/net-snmp-config.h>
++#include <net-snmp/net-snmp-features.h>
++#include <net-snmp/types.h>
++#include <net-snmp/library/snmp_debug.h>
++
++#ifndef NETSNMP_NO_SYSTEMD
++
++/***
++ Copyright 2010 Lennart Poettering
++
++ Permission is hereby granted, free of charge, to any person
++ obtaining a copy of this software and associated documentation files
++ (the "Software"), to deal in the Software without restriction,
++ including without limitation the rights to use, copy, modify, merge,
++ publish, distribute, sublicense, and/or sell copies of the Software,
++ and to permit persons to whom the Software is furnished to do so,
++ subject to the following conditions:
++
++ The above copyright notice and this permission notice shall be
++ included in all copies or substantial portions of the Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ SOFTWARE.
++***/
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE
++#endif
++
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <sys/socket.h>
++#include <sys/un.h>
++#include <sys/fcntl.h>
++#include <netinet/in.h>
++#include <stdlib.h>
++#include <errno.h>
++#include <unistd.h>
++#include <string.h>
++#include <stdarg.h>
++#include <stdio.h>
++#include <stddef.h>
++#include <limits.h>
++
++#include <net-snmp/library/sd-daemon.h>
++
++int netsnmp_sd_listen_fds(int unset_environment) {
++
++ int r, fd;
++ const char *e;
++ char *p = NULL;
++ unsigned long l;
++
++ if (!(e = getenv("LISTEN_PID"))) {
++ r = 0;
++ goto finish;
++ }
++
++ errno = 0;
++ l = strtoul(e, &p, 10);
++
++ if (errno != 0) {
++ r = -errno;
++ goto finish;
++ }
++
++ if (!p || *p || l <= 0) {
++ r = -EINVAL;
++ goto finish;
++ }
++
++ /* Is this for us? */
++ if (getpid() != (pid_t) l) {
++ r = 0;
++ goto finish;
++ }
++
++ if (!(e = getenv("LISTEN_FDS"))) {
++ r = 0;
++ goto finish;
++ }
++
++ errno = 0;
++ l = strtoul(e, &p, 10);
++
++ if (errno != 0) {
++ r = -errno;
++ goto finish;
++ }
++
++ if (!p || *p) {
++ r = -EINVAL;
++ goto finish;
++ }
++
++ for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + (int) l; fd ++) {
++ int flags;
++
++ if ((flags = fcntl(fd, F_GETFD)) < 0) {
++ r = -errno;
++ goto finish;
++ }
++
++ if (flags & FD_CLOEXEC)
++ continue;
++
++ if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) {
++ r = -errno;
++ goto finish;
++ }
++ }
++
++ r = (int) l;
++
++finish:
++ if (unset_environment) {
++ unsetenv("LISTEN_PID");
++ unsetenv("LISTEN_FDS");
++ }
++
++ return r;
++}
++
++int netsnmp_sd_is_fifo(int fd, const char *path) {
++ struct stat st_fd;
++
++ if (fd < 0)
++ return -EINVAL;
++
++ memset(&st_fd, 0, sizeof(st_fd));
++ if (fstat(fd, &st_fd) < 0)
++ return -errno;
++
++ if (!S_ISFIFO(st_fd.st_mode))
++ return 0;
++
++ if (path) {
++ struct stat st_path;
++
++ memset(&st_path, 0, sizeof(st_path));
++ if (stat(path, &st_path) < 0) {
++
++ if (errno == ENOENT || errno == ENOTDIR)
++ return 0;
++
++ return -errno;
++ }
++
++ return
++ st_path.st_dev == st_fd.st_dev &&
++ st_path.st_ino == st_fd.st_ino;
++ }
++
++ return 1;
++}
++
++int netsnmp_sd_is_special(int fd, const char *path) {
++ struct stat st_fd;
++
++ if (fd < 0)
++ return -EINVAL;
++
++ if (fstat(fd, &st_fd) < 0)
++ return -errno;
++
++ if (!S_ISREG(st_fd.st_mode) && !S_ISCHR(st_fd.st_mode))
++ return 0;
++
++ if (path) {
++ struct stat st_path;
++
++ if (stat(path, &st_path) < 0) {
++
++ if (errno == ENOENT || errno == ENOTDIR)
++ return 0;
++
++ return -errno;
++ }
++
++ if (S_ISREG(st_fd.st_mode) && S_ISREG(st_path.st_mode))
++ return
++ st_path.st_dev == st_fd.st_dev &&
++ st_path.st_ino == st_fd.st_ino;
++ else if (S_ISCHR(st_fd.st_mode) && S_ISCHR(st_path.st_mode))
++ return st_path.st_rdev == st_fd.st_rdev;
++ else
++ return 0;
++ }
++
++ return 1;
++}
++
++static int sd_is_socket_internal(int fd, int type, int listening) {
++ struct stat st_fd;
++
++ if (fd < 0 || type < 0)
++ return -EINVAL;
++
++ if (fstat(fd, &st_fd) < 0)
++ return -errno;
++
++ if (!S_ISSOCK(st_fd.st_mode))
++ return 0;
++
++ if (type != 0) {
++ int other_type = 0;
++ socklen_t l = sizeof(other_type);
++
++ if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &other_type, &l) < 0)
++ return -errno;
++
++ if (l != sizeof(other_type))
++ return -EINVAL;
++
++ if (other_type != type)
++ return 0;
++ }
++
++ if (listening >= 0) {
++ int accepting = 0;
++ socklen_t l = sizeof(accepting);
++
++ if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting, &l) < 0)
++ return -errno;
++
++ if (l != sizeof(accepting))
++ return -EINVAL;
++
++ if (!accepting != !listening)
++ return 0;
++ }
++
++ return 1;
++}
++
++union sockaddr_union {
++ struct sockaddr sa;
++ struct sockaddr_in in4;
++ struct sockaddr_in6 in6;
++ struct sockaddr_un un;
++ struct sockaddr_storage storage;
++};
++
++int netsnmp_sd_is_socket(int fd, int family, int type, int listening) {
++ int r;
++
++ if (family < 0)
++ return -EINVAL;
++
++ if ((r = sd_is_socket_internal(fd, type, listening)) <= 0)
++ return r;
++
++ if (family > 0) {
++ union sockaddr_union sockaddr;
++ socklen_t l;
++
++ memset(&sockaddr, 0, sizeof(sockaddr));
++ l = sizeof(sockaddr);
++
++ if (getsockname(fd, &sockaddr.sa, &l) < 0)
++ return -errno;
++
++ if (l < sizeof(sa_family_t))
++ return -EINVAL;
++
++ return sockaddr.sa.sa_family == family;
++ }
++
++ return 1;
++}
++
++int netsnmp_sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) {
++ union sockaddr_union sockaddr;
++ socklen_t l;
++ int r;
++
++ if (family != 0 && family != AF_INET && family != AF_INET6)
++ return -EINVAL;
++
++ if ((r = sd_is_socket_internal(fd, type, listening)) <= 0)
++ return r;
++
++ memset(&sockaddr, 0, sizeof(sockaddr));
++ l = sizeof(sockaddr);
++
++ if (getsockname(fd, &sockaddr.sa, &l) < 0)
++ return -errno;
++
++ if (l < sizeof(sa_family_t))
++ return -EINVAL;
++
++ if (sockaddr.sa.sa_family != AF_INET &&
++ sockaddr.sa.sa_family != AF_INET6)
++ return 0;
++
++ if (family > 0)
++ if (sockaddr.sa.sa_family != family)
++ return 0;
++
++ if (port > 0) {
++ if (sockaddr.sa.sa_family == AF_INET) {
++ if (l < sizeof(struct sockaddr_in))
++ return -EINVAL;
++
++ return htons(port) == sockaddr.in4.sin_port;
++ } else {
++ if (l < sizeof(struct sockaddr_in6))
++ return -EINVAL;
++
++ return htons(port) == sockaddr.in6.sin6_port;
++ }
++ }
++
++ return 1;
++}
++
++int netsnmp_sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) {
++ union sockaddr_union sockaddr;
++ socklen_t l;
++ int r;
++
++ if ((r = sd_is_socket_internal(fd, type, listening)) <= 0)
++ return r;
++
++ memset(&sockaddr, 0, sizeof(sockaddr));
++ l = sizeof(sockaddr);
++
++ if (getsockname(fd, &sockaddr.sa, &l) < 0)
++ return -errno;
++
++ if (l < sizeof(sa_family_t))
++ return -EINVAL;
++
++ if (sockaddr.sa.sa_family != AF_UNIX)
++ return 0;
++
++ if (path) {
++ if (length <= 0)
++ length = strlen(path);
++
++ if (length <= 0)
++ /* Unnamed socket */
++ return l == offsetof(struct sockaddr_un, sun_path);
++
++ if (path[0])
++ /* Normal path socket */
++ return
++ (l >= offsetof(struct sockaddr_un, sun_path) + length + 1) &&
++ memcmp(path, sockaddr.un.sun_path, length+1) == 0;
++ else
++ /* Abstract namespace socket */
++ return
++ (l == offsetof(struct sockaddr_un, sun_path) + length) &&
++ memcmp(path, sockaddr.un.sun_path, length) == 0;
++ }
++
++ return 1;
++}
++
++int netsnmp_sd_notify(int unset_environment, const char *state) {
++ int fd = -1, r;
++ struct msghdr msghdr;
++ struct iovec iovec;
++ union sockaddr_union sockaddr;
++ const char *e;
++
++ if (!state) {
++ r = -EINVAL;
++ goto finish;
++ }
++
++ if (!(e = getenv("NOTIFY_SOCKET")))
++ return 0;
++
++ /* Must be an abstract socket, or an absolute path */
++ if ((e[0] != '@' && e[0] != '/') || e[1] == 0) {
++ r = -EINVAL;
++ goto finish;
++ }
++
++ if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0) {
++ r = -errno;
++ goto finish;
++ }
++
++ memset(&sockaddr, 0, sizeof(sockaddr));
++ sockaddr.sa.sa_family = AF_UNIX;
++ strncpy(sockaddr.un.sun_path, e, sizeof(sockaddr.un.sun_path));
++
++ if (sockaddr.un.sun_path[0] == '@')
++ sockaddr.un.sun_path[0] = 0;
++
++ memset(&iovec, 0, sizeof(iovec));
++ iovec.iov_base = (char *)state;
++ iovec.iov_len = strlen(state);
++
++ memset(&msghdr, 0, sizeof(msghdr));
++ msghdr.msg_name = &sockaddr;
++ msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(e);
++
++ if (msghdr.msg_namelen > sizeof(struct sockaddr_un))
++ msghdr.msg_namelen = sizeof(struct sockaddr_un);
++
++ msghdr.msg_iov = &iovec;
++ msghdr.msg_iovlen = 1;
++
++ if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
++ r = -errno;
++ goto finish;
++ }
++
++ r = 1;
++
++finish:
++ if (unset_environment)
++ unsetenv("NOTIFY_SOCKET");
++
++ if (fd >= 0)
++ close(fd);
++
++ return r;
++}
++
++int netsnmp_sd_notifyf(int unset_environment, const char *format, ...) {
++ va_list ap;
++ char *p = NULL;
++ int r;
++
++ va_start(ap, format);
++ r = vasprintf(&p, format, ap);
++ va_end(ap);
++
++ if (r < 0 || !p)
++ return -ENOMEM;
++
++ r = netsnmp_sd_notify(unset_environment, p);
++ free(p);
++
++ return r;
++}
++
++int netsnmp_sd_booted(void) {
++ struct stat a, b;
++
++ /* We simply test whether the systemd cgroup hierarchy is
++ * mounted */
++
++ if (lstat("/sys/fs/cgroup", &a) < 0)
++ return 0;
++
++ if (lstat("/sys/fs/cgroup/systemd", &b) < 0)
++ return 0;
++
++ return a.st_dev != b.st_dev;
++}
++
++/* End of original sd-daemon.c from systemd sources */
++
++int
++netsnmp_sd_find_inet_socket(int family, int type, int listening, int port)
++{
++ int count, fd;
++
++ count = netsnmp_sd_listen_fds(0);
++ if (count <= 0) {
++ DEBUGMSGTL(("systemd:find_inet_socket", "No LISTEN_FDS found.\n"));
++ return 0;
++ }
++ DEBUGMSGTL(("systemd:find_inet_socket", "LISTEN_FDS reports %d sockets.\n",
++ count));
++
++ for (fd = 3; fd < 3+count; fd++) {
++ int rc = netsnmp_sd_is_socket_inet(fd, family, type, listening, port);
++ if (rc < 0)
++ DEBUGMSGTL(("systemd:find_inet_socket",
++ "sd_is_socket_inet error: %d\n", rc));
++ if (rc > 0) {
++ DEBUGMSGTL(("systemd:find_inet_socket",
++ "Found the socket in LISTEN_FDS\n"));
++ return fd;
++ }
++ }
++ DEBUGMSGTL(("systemd:find_inet_socket", "Socket not found in LISTEN_FDS\n"));
++ return 0;
++}
++
++int
++netsnmp_sd_find_unix_socket(int type, int listening, const char *path)
++{
++ int count, fd;
++
++ count = netsnmp_sd_listen_fds(0);
++ if (count <= 0) {
++ DEBUGMSGTL(("systemd:find_unix_socket", "No LISTEN_FDS found.\n"));
++ return 0;
++ }
++ DEBUGMSGTL(("systemd:find_unix_socket", "LISTEN_FDS reports %d sockets.\n",
++ count));
++
++ for (fd = 3; fd < 3+count; fd++) {
++ int rc = netsnmp_sd_is_socket_unix(fd, type, listening, path, 0);
++ if (rc < 0)
++ DEBUGMSGTL(("systemd:find_unix_socket",
++ "netsnmp_sd_is_socket_unix error: %d\n", rc));
++ if (rc > 0) {
++ DEBUGMSGTL(("systemd:find_unix_socket",
++ "Found the socket in LISTEN_FDS\n"));
++ return fd;
++ }
++ }
++ DEBUGMSGTL(("systemd:find_unix_socket", "Socket not found in LISTEN_FDS\n"));
++ return 0;
++}
++
++#endif /* ! NETSNMP_NO_SYSTEMD */
+diff --git a/snmplib/transports/snmpTCPDomain.c b/snmplib/transports/snmpTCPDomain.c
+index b8bdba4..ab7f3a1 100644
+--- a/snmplib/transports/snmpTCPDomain.c
++++ b/snmplib/transports/snmpTCPDomain.c
+@@ -43,6 +43,10 @@
+ #include <net-snmp/library/snmpTCPBaseDomain.h>
+ #include <net-snmp/library/tools.h>
+
++#ifndef NETSNMP_NO_SYSTEMD
++#include <net-snmp/library/sd-daemon.h>
++#endif
++
+ /*
+ * needs to be in sync with the definitions in snmplib/snmpUDPDomain.c
+ * and perl/agent/agent.xs
+@@ -149,6 +153,7 @@ netsnmp_tcp_transport(struct sockaddr_in *addr, int local)
+ netsnmp_transport *t = NULL;
+ netsnmp_udp_addr_pair *addr_pair = NULL;
+ int rc = 0;
++ int socket_initialized = 0;
+
+ #ifdef NETSNMP_NO_LISTEN_SUPPORT
+ if (local)
+@@ -178,7 +183,19 @@ netsnmp_tcp_transport(struct sockaddr_in *addr, int local)
+ t->domain_length =
+ sizeof(netsnmp_snmpTCPDomain) / sizeof(netsnmp_snmpTCPDomain[0]);
+
+- t->sock = socket(PF_INET, SOCK_STREAM, 0);
++#ifndef NETSNMP_NO_SYSTEMD
++ /*
++ * Maybe the socket was already provided by systemd...
++ */
++ if (local) {
++ t->sock = netsnmp_sd_find_inet_socket(PF_INET, SOCK_STREAM, 1,
++ ntohs(addr->sin_port));
++ if (t->sock)
++ socket_initialized = 1;
++ }
++#endif
++ if (!socket_initialized)
++ t->sock = socket(PF_INET, SOCK_STREAM, 0);
+ if (t->sock < 0) {
+ netsnmp_transport_free(t);
+ return NULL;
+@@ -215,11 +232,13 @@ netsnmp_tcp_transport(struct sockaddr_in *addr, int local)
+ setsockopt(t->sock, SOL_SOCKET, SO_REUSEADDR, (void *)&opt,
+ sizeof(opt));
+
+- rc = bind(t->sock, (struct sockaddr *)addr, sizeof(struct sockaddr));
+- if (rc != 0) {
+- netsnmp_socketbase_close(t);
+- netsnmp_transport_free(t);
+- return NULL;
++ if (!socket_initialized) {
++ rc = bind(t->sock, (struct sockaddr *)addr, sizeof(struct sockaddr));
++ if (rc != 0) {
++ netsnmp_socketbase_close(t);
++ netsnmp_transport_free(t);
++ return NULL;
++ }
+ }
+
+ /*
+@@ -235,12 +254,13 @@ netsnmp_tcp_transport(struct sockaddr_in *addr, int local)
+ /*
+ * Now sit here and wait for connections to arrive.
+ */
+-
+- rc = listen(t->sock, NETSNMP_STREAM_QUEUE_LEN);
+- if (rc != 0) {
+- netsnmp_socketbase_close(t);
+- netsnmp_transport_free(t);
+- return NULL;
++ if (!socket_initialized) {
++ rc = listen(t->sock, NETSNMP_STREAM_QUEUE_LEN);
++ if (rc != 0) {
++ netsnmp_socketbase_close(t);
++ netsnmp_transport_free(t);
++ return NULL;
++ }
+ }
+
+ /*
+diff --git a/snmplib/transports/snmpTCPIPv6Domain.c b/snmplib/transports/snmpTCPIPv6Domain.c
+index 3c96856..305a861 100644
+--- a/snmplib/transports/snmpTCPIPv6Domain.c
++++ b/snmplib/transports/snmpTCPIPv6Domain.c
+@@ -49,6 +49,10 @@
+ #include <net-snmp/library/snmpTCPBaseDomain.h>
+ #include <net-snmp/library/tools.h>
+
++#ifndef NETSNMP_NO_SYSTEMD
++#include <net-snmp/library/sd-daemon.h>
++#endif
++
+ #include "inet_ntop.h"
+
+ oid netsnmp_TCPIPv6Domain[] = { TRANSPORT_DOMAIN_TCP_IPV6 };
+@@ -140,6 +144,8 @@ netsnmp_tcp6_transport(struct sockaddr_in6 *addr, int local)
+ {
+ netsnmp_transport *t = NULL;
+ int rc = 0;
++ char *str = NULL;
++ int socket_initialized = 0;
+
+ #ifdef NETSNMP_NO_LISTEN_SUPPORT
+ if (local)
+@@ -174,7 +180,19 @@ netsnmp_tcp6_transport(struct sockaddr_in6 *addr, int local)
+ t->domain = netsnmp_TCPIPv6Domain;
+ t->domain_length = sizeof(netsnmp_TCPIPv6Domain) / sizeof(oid);
+
+- t->sock = socket(PF_INET6, SOCK_STREAM, 0);
++#ifndef NETSNMP_NO_SYSTEMD
++ /*
++ * Maybe the socket was already provided by systemd...
++ */
++ if (local) {
++ t->sock = netsnmp_sd_find_inet_socket(PF_INET6, SOCK_STREAM, 1,
++ ntohs(addr->sin6_port));
++ if (t->sock)
++ socket_initialized = 1;
++ }
++#endif
++ if (!socket_initialized)
++ t->sock = socket(PF_INET6, SOCK_STREAM, 0);
+ if (t->sock < 0) {
+ netsnmp_transport_free(t);
+ return NULL;
+@@ -220,12 +238,14 @@ netsnmp_tcp6_transport(struct sockaddr_in6 *addr, int local)
+
+ setsockopt(t->sock, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, sizeof(opt));
+
+- rc = bind(t->sock, (struct sockaddr *) addr,
+- sizeof(struct sockaddr_in6));
+- if (rc != 0) {
+- netsnmp_socketbase_close(t);
+- netsnmp_transport_free(t);
+- return NULL;
++ if (!socket_initialized) {
++ rc = bind(t->sock, (struct sockaddr *) addr,
++ sizeof(struct sockaddr_in6));
++ if (rc != 0) {
++ netsnmp_socketbase_close(t);
++ netsnmp_transport_free(t);
++ return NULL;
++ }
+ }
+
+ /*
+@@ -242,11 +262,13 @@ netsnmp_tcp6_transport(struct sockaddr_in6 *addr, int local)
+ * Now sit here and wait for connections to arrive.
+ */
+
+- rc = listen(t->sock, NETSNMP_STREAM_QUEUE_LEN);
+- if (rc != 0) {
+- netsnmp_socketbase_close(t);
+- netsnmp_transport_free(t);
+- return NULL;
++ if (!socket_initialized) {
++ rc = listen(t->sock, NETSNMP_STREAM_QUEUE_LEN);
++ if (rc != 0) {
++ netsnmp_socketbase_close(t);
++ netsnmp_transport_free(t);
++ return NULL;
++ }
+ }
+
+ /*
+diff --git a/snmplib/transports/snmpUDPIPv4BaseDomain.c b/snmplib/transports/snmpUDPIPv4BaseDomain.c
+index c67427b..428e6d6 100644
+--- a/snmplib/transports/snmpUDPIPv4BaseDomain.c
++++ b/snmplib/transports/snmpUDPIPv4BaseDomain.c
+@@ -40,6 +40,10 @@
+
+ #include <net-snmp/library/snmpSocketBaseDomain.h>
+
++#ifndef NETSNMP_NO_SYSTEMD
++#include <net-snmp/library/sd-daemon.h>
++#endif
++
+ #if (defined(linux) && defined(IP_PKTINFO)) \
+ || defined(IP_RECVDSTADDR) && HAVE_STRUCT_MSGHDR_MSG_CONTROL \
+ && HAVE_STRUCT_MSGHDR_MSG_FLAGS
+@@ -67,6 +71,7 @@ netsnmp_udpipv4base_transport(struct sockaddr_in *addr, int local)
+ char *client_socket = NULL;
+ netsnmp_indexed_addr_pair addr_pair;
+ socklen_t local_addr_len;
++ int socket_initialized = 0;
+
+ #ifdef NETSNMP_NO_LISTEN_SUPPORT
+ if (local)
+@@ -91,7 +96,19 @@ netsnmp_udpipv4base_transport(struct sockaddr_in *addr, int local)
+ free(str);
+ }
+
+- t->sock = socket(PF_INET, SOCK_DGRAM, 0);
++#ifndef NETSNMP_NO_SYSTEMD
++ /*
++ * Maybe the socket was already provided by systemd...
++ */
++ if (local) {
++ t->sock = netsnmp_sd_find_inet_socket(PF_INET, SOCK_DGRAM, -1,
++ ntohs(addr->sin_port));
++ if (t->sock)
++ socket_initialized = 1;
++ }
++#endif
++ if (!socket_initialized)
++ t->sock = socket(PF_INET, SOCK_DGRAM, 0);
+ DEBUGMSGTL(("UDPBase", "openned socket %d as local=%d\n", t->sock, local));
+ if (t->sock < 0) {
+ netsnmp_transport_free(t);
+@@ -141,12 +158,14 @@ netsnmp_udpipv4base_transport(struct sockaddr_in *addr, int local)
+ DEBUGMSGTL(("netsnmp_udp", "set IP_RECVDSTADDR\n"));
+ }
+ #endif
+- rc = bind(t->sock, (struct sockaddr *) addr,
+- sizeof(struct sockaddr));
+- if (rc != 0) {
+- netsnmp_socketbase_close(t);
+- netsnmp_transport_free(t);
+- return NULL;
++ if (!socket_initialized) {
++ rc = bind(t->sock, (struct sockaddr *) addr,
++ sizeof(struct sockaddr));
++ if (rc != 0) {
++ netsnmp_socketbase_close(t);
++ netsnmp_transport_free(t);
++ return NULL;
++ }
+ }
+ t->data = NULL;
+ t->data_length = 0;
+diff --git a/snmplib/transports/snmpUDPIPv6Domain.c b/snmplib/transports/snmpUDPIPv6Domain.c
+index b3eaae4..35b617f 100644
+--- a/snmplib/transports/snmpUDPIPv6Domain.c
++++ b/snmplib/transports/snmpUDPIPv6Domain.c
+@@ -67,6 +67,10 @@ static const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
+ #include <net-snmp/library/snmpSocketBaseDomain.h>
+ #include <net-snmp/library/tools.h>
+
++#ifndef NETSNMP_NO_SYSTEMD
++#include <net-snmp/library/sd-daemon.h>
++#endif
++
+ #include "inet_ntop.h"
+ #include "inet_pton.h"
+
+@@ -190,6 +194,8 @@ netsnmp_udp6_transport(struct sockaddr_in6 *addr, int local)
+ {
+ netsnmp_transport *t = NULL;
+ int rc = 0;
++ char *str = NULL;
++ int socket_initialized = 0;
+
+ #ifdef NETSNMP_NO_LISTEN_SUPPORT
+ if (local)
+@@ -217,7 +223,19 @@ netsnmp_udp6_transport(struct sockaddr_in6 *addr, int local)
+ t->domain_length =
+ sizeof(netsnmp_UDPIPv6Domain) / sizeof(netsnmp_UDPIPv6Domain[0]);
+
+- t->sock = socket(PF_INET6, SOCK_DGRAM, 0);
++#ifndef NETSNMP_NO_SYSTEMD
++ /*
++ * Maybe the socket was already provided by systemd...
++ */
++ if (local) {
++ t->sock = netsnmp_sd_find_inet_socket(PF_INET6, SOCK_DGRAM, -1,
++ ntohs(addr->sin6_port));
++ if (t->sock)
++ socket_initialized = 1;
++ }
++#endif
++ if (!socket_initialized)
++ t->sock = socket(PF_INET6, SOCK_DGRAM, 0);
+ if (t->sock < 0) {
+ netsnmp_transport_free(t);
+ return NULL;
+@@ -242,13 +260,14 @@ netsnmp_udp6_transport(struct sockaddr_in6 *addr, int local)
+ }
+ }
+ #endif
+-
+- rc = bind(t->sock, (struct sockaddr *) addr,
+- sizeof(struct sockaddr_in6));
+- if (rc != 0) {
+- netsnmp_socketbase_close(t);
+- netsnmp_transport_free(t);
+- return NULL;
++ if (!socket_initialized) {
++ rc = bind(t->sock, (struct sockaddr *) addr,
++ sizeof(struct sockaddr_in6));
++ if (rc != 0) {
++ netsnmp_socketbase_close(t);
++ netsnmp_transport_free(t);
++ return NULL;
++ }
+ }
+ t->local = (unsigned char*)malloc(18);
+ if (t->local == NULL) {
+diff --git a/snmplib/transports/snmpUnixDomain.c b/snmplib/transports/snmpUnixDomain.c
+index 674dc2b..9f3d3cb 100644
+--- a/snmplib/transports/snmpUnixDomain.c
++++ b/snmplib/transports/snmpUnixDomain.c
+@@ -37,6 +37,10 @@
+ #include <net-snmp/library/system.h> /* mkdirhier */
+ #include <net-snmp/library/tools.h>
+
++#ifndef NETSNMP_NO_SYSTEMD
++#include <net-snmp/library/sd-daemon.h>
++#endif
++
+ netsnmp_feature_child_of(transport_unix_socket_all, transport_all)
+ netsnmp_feature_child_of(unix_socket_paths, transport_unix_socket_all)
+
+@@ -295,6 +299,8 @@ netsnmp_unix_transport(struct sockaddr_un *addr, int local)
+ netsnmp_transport *t = NULL;
+ sockaddr_un_pair *sup = NULL;
+ int rc = 0;
++ char *string = NULL;
++ int socket_initialized = 0;
+
+ #ifdef NETSNMP_NO_LISTEN_SUPPORT
+ /* SPECIAL CIRCUMSTANCE: We still want AgentX to be able to operate,
+@@ -333,7 +339,18 @@ netsnmp_unix_transport(struct sockaddr_un *addr, int local)
+ t->data_length = sizeof(sockaddr_un_pair);
+ sup = (sockaddr_un_pair *) t->data;
+
+- t->sock = socket(PF_UNIX, SOCK_STREAM, 0);
++#ifndef NETSNMP_NO_SYSTEMD
++ /*
++ * Maybe the socket was already provided by systemd...
++ */
++ if (local) {
++ t->sock = netsnmp_sd_find_unix_socket(SOCK_STREAM, 1, addr->sun_path);
++ if (t->sock)
++ socket_initialized = 1;
++ }
++#endif
++ if (!socket_initialized)
++ t->sock = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (t->sock < 0) {
+ netsnmp_transport_free(t);
+ return NULL;
+@@ -357,25 +374,26 @@ netsnmp_unix_transport(struct sockaddr_un *addr, int local)
+
+ t->flags |= NETSNMP_TRANSPORT_FLAG_LISTEN;
+
+- unlink(addr->sun_path);
+- rc = bind(t->sock, (struct sockaddr *) addr, SUN_LEN(addr));
+-
+- if (rc != 0 && errno == ENOENT && create_path) {
+- rc = mkdirhier(addr->sun_path, create_mode, 1);
++ if (!socket_initialized) {
++ unlink(addr->sun_path);
++ rc = bind(t->sock, (struct sockaddr *) addr, SUN_LEN(addr));
++ if (rc != 0 && errno == ENOENT && create_path) {
++ rc = mkdirhier(addr->sun_path, create_mode, 1);
++ if (rc != 0) {
++ netsnmp_unix_close(t);
++ netsnmp_transport_free(t);
++ return NULL;
++ }
++ rc = bind(t->sock, (struct sockaddr *) addr, SUN_LEN(addr));
++ }
+ if (rc != 0) {
++ DEBUGMSGTL(("netsnmp_unix_transport",
++ "couldn't bind \"%s\", errno %d (%s)\n",
++ addr->sun_path, errno, strerror(errno)));
+ netsnmp_unix_close(t);
+ netsnmp_transport_free(t);
+ return NULL;
+ }
+- rc = bind(t->sock, (struct sockaddr *) addr, SUN_LEN(addr));
+- }
+- if (rc != 0) {
+- DEBUGMSGTL(("netsnmp_unix_transport",
+- "couldn't bind \"%s\", errno %d (%s)\n",
+- addr->sun_path, errno, strerror(errno)));
+- netsnmp_unix_close(t);
+- netsnmp_transport_free(t);
+- return NULL;
+ }
+
+ /*
+@@ -391,16 +409,17 @@ netsnmp_unix_transport(struct sockaddr_un *addr, int local)
+ * Now sit here and listen for connections to arrive.
+ */
+
+- rc = listen(t->sock, NETSNMP_STREAM_QUEUE_LEN);
+- if (rc != 0) {
+- DEBUGMSGTL(("netsnmp_unix_transport",
+- "couldn't listen to \"%s\", errno %d (%s)\n",
+- addr->sun_path, errno, strerror(errno)));
+- netsnmp_unix_close(t);
+- netsnmp_transport_free(t);
+- return NULL;
++ if (!socket_initialized) {
++ rc = listen(t->sock, NETSNMP_STREAM_QUEUE_LEN);
++ if (rc != 0) {
++ DEBUGMSGTL(("netsnmp_unix_transport",
++ "couldn't listen to \"%s\", errno %d (%s)\n",
++ addr->sun_path, errno, strerror(errno)));
++ netsnmp_unix_close(t);
++ netsnmp_transport_free(t);
++ return NULL;
++ }
+ }
+-
+ } else {
+ t->remote = (u_char *)malloc(strlen(addr->sun_path));
+ if (t->remote == NULL) {
+diff --git a/win32/libsnmp/Makefile.in b/win32/libsnmp/Makefile.in
+index 98d83c8..dd5689b 100644
+--- a/win32/libsnmp/Makefile.in
++++ b/win32/libsnmp/Makefile.in
+@@ -42,6 +42,7 @@ LIB32_OBJS= \
+ "$(INTDIR)\read_config.obj" \
+ "$(INTDIR)\readdir.obj" \
+ "$(INTDIR)\scapi.obj" \
++ "$(INTDIR)\sd-daemon.obj" \
+ "$(INTDIR)\snmp-tc.obj" \
+ "$(INTDIR)\snmp.obj" \
+ "$(INTDIR)\snmpCallbackDomain.obj" \
+@@ -307,6 +308,12 @@ SOURCE=..\..\snmplib\scapi.c
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
++SOURCE=..\..\snmplib\sd-daemon.c
++
++"$(INTDIR)\sd-daemon.obj" : $(SOURCE) "$(INTDIR)"
++ $(CPP) $(CPP_PROJ) $(SOURCE)
++
++
+ SOURCE="..\..\snmplib\snmp-tc.c"
+
+ "$(INTDIR)\snmp-tc.obj" : $(SOURCE) "$(INTDIR)"
+diff --git a/win32/net-snmp/net-snmp-config.h b/win32/net-snmp/net-snmp-config.h
+index 7791ee0..1eccf42 100644
+--- a/win32/net-snmp/net-snmp-config.h
++++ b/win32/net-snmp/net-snmp-config.h
+@@ -1705,6 +1705,8 @@ enum {
+ #define DMALLOC_FUNC_CHECK
+ #endif
+
++#define NETSNMP_NO_SYSTEMD
++
+ /* #undef NETSNMP_ENABLE_LOCAL_SMUX */
+
+ /* define if agentx transport is to use domain sockets only */
+diff --git a/win32/net-snmp/net-snmp-config.h.in b/win32/net-snmp/net-snmp-config.h.in
+index 5215865..1607bfa 100644
+--- a/win32/net-snmp/net-snmp-config.h.in
++++ b/win32/net-snmp/net-snmp-config.h.in
+@@ -1705,6 +1705,8 @@ enum {
+ #define DMALLOC_FUNC_CHECK
+ #endif
+
++#define NETSNMP_NO_SYSTEMD
++
+ /* #undef NETSNMP_ENABLE_LOCAL_SMUX */
+
+ /* define if agentx transport is to use domain sockets only */
diff --git a/meta-networking/recipes-protocols/net-snmp/net-snmp_5.7.2.bb b/meta-networking/recipes-protocols/net-snmp/net-snmp_5.7.2.bb
new file mode 100644
index 0000000000..4c3939a7e4
--- /dev/null
+++ b/meta-networking/recipes-protocols/net-snmp/net-snmp_5.7.2.bb
@@ -0,0 +1,118 @@
+SUMMARY = "Various tools relating to the Simple Network Management Protocol"
+HOMEPAGE = "http://www.net-snmp.org/"
+LICENSE = "BSD"
+
+LIC_FILES_CHKSUM = "file://README;beginline=3;endline=8;md5=7f7f00ba639ac8e8deb5a622ea24634e"
+
+DEPENDS = "openssl libnl pciutils"
+
+SRC_URI = "${SOURCEFORGE_MIRROR}/net-snmp/net-snmp-${PV}.tar.gz \
+ file://init \
+ file://snmpd.conf \
+ file://snmptrapd.conf \
+ file://systemd-support.patch \
+ file://snmpd.service \
+ file://snmptrapd.service \
+ file://ifmib.patch \
+"
+
+SRC_URI[md5sum] = "5bddd02e2f82b62daa79f82717737a14"
+SRC_URI[sha256sum] = "09ed31b4cc1f3c0411ef9a16eff79ef3b30d89c32ca46d5a01a41826c4ceb816"
+
+inherit autotools update-rc.d siteinfo systemd
+
+EXTRA_OEMAKE = "INSTALL_PREFIX=${D}"
+
+PARALLEL_MAKE = ""
+CCACHE = ""
+
+TARGET_CC_ARCH += "${LDFLAGS}"
+
+EXTRA_OECONF = "--disable-embedded-perl \
+ --with-perl-modules=no \
+ --enable-shared \
+ --disable-manuals \
+ --with-defaults \
+ ${@base_conditional('SITEINFO_ENDIANNESS', 'le', '--with-endianness=little', '--with-endianness=big', d)}"
+
+do_install_append() {
+ install -d ${D}${sysconfdir}/snmp
+ install -d ${D}${sysconfdir}/init.d
+ install -m 755 ${WORKDIR}/init ${D}${sysconfdir}/init.d/snmpd
+ install -m 644 ${WORKDIR}/snmpd.conf ${D}${sysconfdir}/snmp/
+ install -m 644 ${WORKDIR}/snmptrapd.conf ${D}${sysconfdir}/snmp/
+ install -d ${STAGING_BINDIR}
+ install -m 0755 ${D}${bindir}/net-snmp-config ${STAGING_BINDIR}/
+ sed -e "s@-I/usr/include@@g" \
+ -e "s@^prefix=.*@prefix=${STAGING_DIR_HOST}@g" \
+ -e "s@^exec_prefix=.*@exec_prefix=${STAGING_DIR_HOST}@g" \
+ -e "s@^includedir=.*@includedir=${STAGING_INCDIR}@g" \
+ -e "s@^libdir=.*@libdir=${STAGING_LIBDIR}@g" \
+ -i ${STAGING_BINDIR}/net-snmp-config
+ install -d ${D}${systemd_unitdir}/system
+ install -m 0644 ${WORKDIR}/snmpd.service ${D}${systemd_unitdir}/system
+ install -m 0644 ${WORKDIR}/snmptrapd.service ${D}${systemd_unitdir}/system
+}
+
+PACKAGES = "${PN}-dbg ${PN}-doc ${PN}-dev ${PN}-staticdev ${PN}-static ${PN}-libs \
+ ${PN}-mibs ${PN}-server ${PN}-client ${PN}-server-snmpd ${PN}-server-snmptrapd"
+
+ALLOW_EMPTY_${PN}-server = "1"
+
+FILES_${PN}-libs = "${libdir}/lib*${SOLIBS}"
+FILES_${PN}-mibs = "${datadir}/snmp/mibs"
+FILES_${PN}-server-snmpd = "${sbindir}/snmpd \
+ ${sysconfdir}/snmp/snmpd.conf \
+ ${sysconfdir}/init.d \
+ ${systemd_unitdir}/system/snmpd.service \
+"
+
+FILES_${PN}-server-snmptrapd = "${sbindir}/snmptrapd \
+ ${sysconfdir}/snmp/snmptrapd.conf \
+ ${systemd_unitdir}/system/snmptrapd.service \
+"
+
+FILES_${PN}-client = "${bindir}/* ${datadir}/snmp/"
+FILES_${PN}-dbg += "${libdir}/.debug/ ${sbindir}/.debug/ ${bindir}/.debug/"
+FILES_${PN}-dev += "${bindir}/net-snmp-config ${bindir}/mib2c ${bindir}/mib2c-update"
+
+CONFFILES_${PN}-server-snmpd = "${sysconfdir}/snmp/snmpd.conf"
+CONFFILES_${PN}-server-snmptrapd = "${sysconfdir}/snmp/snmptrapd.conf"
+
+INITSCRIPT_PACKAGES = "${PN}-server"
+INITSCRIPT_NAME_${PN}-server = "snmpd"
+INITSCRIPT_PARAMS_${PN}-server = "defaults"
+
+EXTRA_OECONF += "${@base_contains('DISTRO_FEATURES', 'systemd', '--with-systemd', '--without-systemd', d)}"
+
+SYSTEMD_PACKAGES = "${PN}-server-snmpd \
+ ${PN}-server-snmptrapd"
+
+SYSTEMD_SERVICE_${PN}-server-snmpd = "snmpd.service"
+SYSTEMD_SERVICE_${PN}-server-snmptrapd = "snmptrapd.service"
+
+RDEPENDS_${PN}-server-snmpd += "net-snmp-mibs"
+RDEPENDS_${PN}-server-snmptrapd += "net-snmp-server-snmpd"
+RDEPENDS_${PN}-server += "net-snmp-server-snmpd net-snmp-server-snmptrapd"
+RDEPENDS_${PN}-client += "net-snmp-mibs"
+RDEPENDS_${PN}-dev = "net-snmp-client (= ${EXTENDPKGV}) net-snmp-server (= ${EXTENDPKGV})"
+RRECOMMENDS_${PN}-dbg = "net-snmp-client (= ${EXTENDPKGV}) net-snmp-server (= ${EXTENDPKGV})"
+
+RPROVIDES_${PN}-server-snmpd += "${PN}-server-snmpd-systemd"
+RREPLACES_${PN}-server-snmpd += "${PN}-server-snmpd-systemd"
+RCONFLICTS_${PN}-server-snmpd += "${PN}-server-snmpd-systemd"
+
+RPROVIDES_${PN}-server-snmptrapd += "${PN}-server-snmptrapd-systemd"
+RREPLACES_${PN}-server-snmptrapd += "${PN}-server-snmptrapd-systemd"
+RCONFLICTS_${PN}-server-snmptrapd += "${PN}-server-snmptrapd-systemd"
+
+LEAD_SONAME = "libnetsnmp.so"
+
+pkg_postrm_${PN}-server() {
+ if test "x$D" != "x"; then
+ OPT="-r $D "
+ else
+ OPT=""
+ /etc/init.d/snmpd stop
+ fi
+}