Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/ax_interface/constants.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from enum import Enum, unique

AGENTX_SOCKET_PATH = '/var/agentx/master'
SNMPD_CONFIG_FILE = '/etc/snmp/snmpd.conf'

# https://tools.ietf.org/html/rfc2741#section-6.1 -- PDU Header definition
# Headers are fixed at 20 bytes.
Expand Down
72 changes: 68 additions & 4 deletions src/ax_interface/socket_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"""
import asyncio
import logging
import re

from . import logger, constants
from .protocol import AgentX
Expand All @@ -25,6 +26,27 @@ def __init__(self, mib_table, run_event, loop):

self.transport = self.ax_socket = None

self.ax_socket_path = constants.AGENTX_SOCKET_PATH

# The following code reads the snmp config file to see if the Agentx Socket path has been redefined
# from the default RFC value '/var/agentx/master'. We do not implement reading the SNMP daemon's
# command line to check if it has been redefined there, this should be an effort for the future
# perhaps via a psutil().cmdline() call

# open the snmpd config file and search for a agentx socket redefinition. Exceptions will be raised
# if the constants.SNMPD_CONFIG_FILE or the file in itself do not exist
pattern = re.compile("^agentxsocket\s+(.*)$", re.IGNORECASE)
try :
with open(constants.SNMPD_CONFIG_FILE,'rt') as config_file:
for line in config_file:
match = pattern.search(line)
if match:
self.ax_socket_path = match.group(1)
except:
logger.warning("SNMPD config file not found, using default agentx file socket")

logger.info("Using agentx socket " + self.ax_socket_path)

async def connection_loop(self):
"""
Try/Retry connection coroutine to attach the socket.
Expand All @@ -37,10 +59,52 @@ async def connection_loop(self):
try:
logger.info("Attempting AgentX socket bind...".format())

connection_routine = self.loop.create_unix_connection(
protocol_factory=lambda: AgentX(self.mib_table, self.loop),
path=constants.AGENTX_SOCKET_PATH,
sock=self.ax_socket)
# Open the connection to the Agentx socket, we check the socket string to
# either open a tcp socket or a Unix domain socket
if '/' in self.ax_socket_path:
# This looks like a filesystem path so lets open it as a domain socket
# but first lets remove 'unix' if it's in the spec
if self.ax_socket_path.startswith('unix'):
self.ax_socket_path = self.ax_socket_path.split(':')[1]
connection_routine = self.loop.create_unix_connection(
protocol_factory=lambda: AgentX(self.mib_table, self.loop),
path=self.ax_socket_path,
sock=self.ax_socket)
elif self.ax_socket_path.startswith('tcp'):
# This looks like a tcp connection
myhost = self.ax_socket_path.split(':')[1]
myport = self.ax_socket_path.split(':')[2]
connection_routine = self.loop.create_connection(
protocol_factory=lambda: AgentX(self.mib_table, self.loop),
host=myhost,
port=myport,
sock=self.ax_socket)
elif self.ax_socket_path.startswith('udp'):
# This looks like a udp connection
myhost = self.ax_socket_path.split(':')[1]
myport = self.ax_socket_path.split(':')[2]
connection_routine = self.loop.create_datagram_endpoint(
protocol_factory=lambda: AgentX(self.mib_table, self.loop),
host=myhost,
port=myport,
sock=self.ax_socket)
elif self.ax_socket_path.isdigit():
# if the socket path is just a number then it is treated as a udp port on localhost
myhost = 'localhost'
myport = self.ax_socket_path
connection_routine = self.loop.create_datagram_endpoint(
protocol_factory=lambda: AgentX(self.mib_table, self.loop),
host=myhost,
port=myport,
sock=self.ax_socket)
else:
# We do not support 'ssh', 'dtlsudp', 'ipx', or 'aal5pvc' (ATM lol...) methods
# default to the snmp default /var/agentx/master and log a warning
logger.warning("Socket type " + self.ax_socket_path + " not supported, using default agentx file socket")
connection_routine = self.loop.create_unix_connection(
protocol_factory=lambda: AgentX(self.mib_table, self.loop),
path=constants.AGENTX_SOCKET_PATH,
sock=self.ax_socket)

# Initiate the socket connection
self.transport, protocol = await connection_routine
Expand Down