Пример #1
0
 def handle_error(self, *info):
     exc_info = sys.exc_info()
     log.msg('%s: error: %s' % (self, exc_info[1]))
     if exc_info and not isinstance(exc_info[1], socket.error):
         for line in traceback.format_exception(*exc_info):
             log.msg(line.replace('\n', ';'))
     self.handle_close()
Пример #2
0
    def handle_read(self):
        chunk = self.recv(65535)
        if not chunk:
            self.handle_close()
        self.__input += chunk
        while self.__input:
            msgId, contentId, msg, self.__input = protocol.prepareDataElements(
                self.__input, self.__secret)
            if msgId is None:
                if self.__pendingCounter > 5:
                    log.msg(
                        'incomplete message pending for too long, closing connection with %s'
                        % (self, ))
                    self.close()
                    return
                else:
                    self.__pendingCounter += 1
                return

            self.__pendingCounter = 0

            if contentId == 0:  # request
                self.__dataCbFun(self, msgId, msg)
            elif contentId == 1:  # response
                if msgId in self.__pendingReqs:
                    cbFun, cbCtx = self.__pendingReqs.pop(msgId)
                    cbFun(msg, cbCtx)
            else:
                log.msg('unknown message content-id %s from %s ignored' %
                        (contentId, self))
Пример #3
0
 def handle_error(self, *info):
     exc_info = sys.exc_info()
     log.msg('connection with %s broken: %s' %
             (self.__remoteEndpoint, exc_info[1]))
     if exc_info and not isinstance(exc_info[1], socket.error):
         for line in traceback.format_exception(*exc_info):
             log.msg(line.replace('\n', ';'))
     self.handle_close()
Пример #4
0
    def __proxyDataCbFun(self, connection, msgId, msg):
        if connection in self.__runningServersConnMap:
            trunkId = self.__runningServersConnMap[connection]
        elif connection in self.__runningClientsConnMap:
            trunkId = self.__runningClientsConnMap[connection]
        else:
            log.msg('data message from unknown connection %s ignored' %
                    connection)
            return

        self.__dataCbFun(trunkId, msgId, msg)
Пример #5
0
    def handle_connect(self):
        if self.isUp:
            return
        self.isUp = True

        if self.__announcementData:
            self.send(self.__announcementData)
            self.__announcementData = null
            log.msg('trunking client %s sent trunk announcement' % self)

        log.msg('trunk client %s is now connected' % self)
Пример #6
0
    def processCommandResponse(self, pluginId, snmpEngine, pdu, **context):
        if pluginId not in self.__plugins:
            log.msg('WARNING: skipping non-existing plugin %s' % pluginId)
            return NEXT, pdu

        if 'processCommandResponse' not in self.__plugins[pluginId]:
            return NEXT, pdu

        return self.__plugins[pluginId]['processCommandResponse'](pluginId,
                                                                  snmpEngine,
                                                                  pdu,
                                                                  **context)
Пример #7
0
    def handle_accept(self):
        try:
            sock, remoteEndpoint = self.accept()
        except socket.error:
            log.msg('%s accept() failed: %s' % (self, sys.exc_info()[1]))
            return

        log.msg('%s new connection from %s' %
                (self, ':'.join([str(x) for x in remoteEndpoint])))

        TrunkingServer(sock, self.__localEndpoint, remoteEndpoint,
                       self.__secret, self.__dataCbFun, self.__ctlCbFun)
Пример #8
0
    def __ctlCbFun(self, connection, msg=None):
        if msg:
            trunkId = str(msg['trunk-id'])
            if trunkId in self.__runningServersTrunkMap or \
                    trunkId in self.__runningClientsTrunkMap:
                log.msg('duplicate trunk %s during negotiation with %s' %
                        (trunkId, connection))
                connection.close()
                return

            log.msg('registering connection %s as trunk %s' %
                    (connection, trunkId))
            self.__runningServersTrunkMap[trunkId] = connection
            self.__runningServersConnMap[connection] = trunkId

        else:
            if connection in self.__runningServersConnMap:
                trunkId = self.__runningServersConnMap[connection]
            else:
                log.msg('control message from unknown connection %s ignored' %
                        connection)
                return

            log.msg('unregistering connection %s (trunk %s)' %
                    (self.__runningServersTrunkMap[trunkId], trunkId))
            del self.__runningServersTrunkMap[trunkId]
            del self.__runningServersConnMap[connection]
Пример #9
0
    def handleMgmtOperation(self, snmpEngine, stateReference, contextName, PDU,
                            acInfo):
        trunkReq = gCurrentRequestContext['request']

        logMsg = '(SNMP request %s), matched keys: %s' % (', '.join([
            x == 'snmp-pdu' and 'snmp-var-binds=%s' %
            prettyVarBinds(trunkReq['snmp-pdu']) or '%s=%s' %
            (x, isinstance(trunkReq[x], int) and trunkReq[x]
             or rfc1902.OctetString(trunkReq[x]).prettyPrint())
            for x in trunkReq
        ]), ', '.join([
            '%s=%s' % (k, gCurrentRequestContext[k])
            for k in gCurrentRequestContext if k[-2:] == 'id'
        ]))

        usedPlugins = []
        pluginIdList = gCurrentRequestContext['plugins-list']
        snmpReqInfo = gCurrentRequestContext['request'].copy()
        for pluginId in pluginIdList:
            usedPlugins.append((pluginId, snmpReqInfo))

            st, PDU = pluginManager.processCommandRequest(
                pluginId, snmpEngine, PDU, **snmpReqInfo)
            if st == status.BREAK:
                break
            elif st == status.DROP:
                log.msg('plugin %s muted request %s' % (pluginId, logMsg))
                self.releaseStateInformation(stateReference)
                return
            elif st == status.RESPOND:
                log.msg('plugin %s forced immediate response %s' %
                        (pluginId, logMsg))
                self.sendPdu(snmpEngine, stateReference, PDU)
                self.releaseStateInformation(stateReference)
                return

        # pass query to trunk

        trunkReq['snmp-pdu'] = PDU
        trunkIdList = gCurrentRequestContext['trunk-id-list']
        if trunkIdList is None:
            log.msg('no route configured %s' % logMsg)
            self.releaseStateInformation(stateReference)
            return

        for trunkId in trunkIdList:
            log.msg('received SNMP message (%s), sending through trunk %s' %
                    (', '.join([
                        x == 'snmp-pdu' and 'snmp-var-binds=%s' %
                        prettyVarBinds(trunkReq['snmp-pdu']) or '%s=%s' %
                        (x, isinstance(trunkReq[x], int) and trunkReq[x]
                         or rfc1902.OctetString(trunkReq[x]).prettyPrint())
                        for x in trunkReq
                    ]), trunkId))

            cbCtx = usedPlugins, trunkId, trunkReq, snmpEngine, stateReference

            trunkingManager.sendReq(trunkId, trunkReq, self.__recvCb, cbCtx)
Пример #10
0
    def __init__(self, localEndpoint, secret, dataCbFun, ctlCbFun):
        self.__localEndpoint = localEndpoint
        self.__secret = secret
        self.__dataCbFun = dataCbFun
        self.__ctlCbFun = ctlCbFun
        asyncore.dispatcher.__init__(self)

        try:
            self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 65535)
            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65535)
            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            self.bind(localEndpoint)
            self.listen(10)
        except socket.error:
            raise error.SnmpfwdError('%s socket error: %s' %
                                     (self, sys.exc_info()[1]))
            log.msg('%s: listening...' % self)
Пример #11
0
def __rspCbFun(snmpEngine, sendRequestHandle, errorIndication, rspPDU, cbCtx):
    trunkId, msgId, trunkReq = cbCtx

    trunkRsp = {}

    if errorIndication:
        log.msg(
            'SNMP error returned for message ID %s received from trunk %s: %s'
            % (msgId, trunkId, errorIndication))
        trunkRsp['error-indication'] = errorIndication

    trunkRsp['snmp-pdu'] = rspPDU

    log.msg(
        'received SNMP %s message, sending trunk message #%s to trunk %s, original SNMP peer address %s:%s received at %s:%s, var-binds: %s'
        % (errorIndication and 'error' or 'response', msgId, trunkId,
           trunkReq['snmp-peer-address'], trunkReq['snmp-peer-port'],
           trunkReq['snmp-bind-address'], trunkReq['snmp-bind-port'],
           prettyVarBinds(rspPDU)))

    trunkingManager.sendRsp(trunkId, msgId, trunkRsp)
Пример #12
0
    def __recvCb(self, trunkRsp, cbCtx):
        pluginIdList, trunkId, trunkReq, snmpEngine, stateReference = cbCtx

        if trunkRsp['error-indication']:
            log.msg(
                'received trunk message through trunk %s, remote end reported error-indication %s, NOT sending response to peer address %s:%s from %s:%s'
                % (trunkId, trunkRsp['error-indication'],
                   trunkReq['snmp-peer-address'], trunkReq['snmp-peer-port'],
                   trunkReq['snmp-bind-address'], trunkReq['snmp-bind-port']))
        else:
            PDU = trunkRsp['snmp-pdu']
            for pluginId, snmpReqInfo in pluginIdList:
                st, PDU = pluginManager.processCommandResponse(
                    pluginId, snmpEngine, PDU, **snmpReqInfo)

                if st == status.BREAK:
                    break
                elif st == status.DROP:
                    log.msg(
                        'received trunk message through trunk %s, snmp-var-binds=%s, plugin %s muted response'
                        % (trunkId, prettyVarBinds(PDU), pluginId))
                    self.releaseStateInformation(stateReference)
                    return

            log.msg(
                'received trunk message through trunk %s, sending SNMP response to peer address %s:%s from %s:%s, snmp-var-binds=%s'
                % (trunkId, trunkReq['snmp-peer-address'],
                   trunkReq['snmp-peer-port'], trunkReq['snmp-bind-address'],
                   trunkReq['snmp-bind-port'], prettyVarBinds(PDU)))

            self.sendPdu(snmpEngine, stateReference, PDU)

        self.releaseStateInformation(stateReference)
Пример #13
0
    def __init__(self, sock, localEndpoint, remoteEndpoint, secret, dataCbFun,
                 ctlCbFun):
        self.__localEndpoint = localEndpoint
        self.__remoteEndpoint = remoteEndpoint
        self.__secret = secret
        self.__dataCbFun = dataCbFun
        self.__ctlCbFun = ctlCbFun
        self.__pendingReqs = {}
        self.__pendingCounter = 0
        self.__input = null
        self.socket = None  # asyncore strangeness
        asyncore.dispatcher_with_send.__init__(self, sock)

        try:
            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 65535)
            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65535)
            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
        except socket.error:
            raise error.SnmpfwdError('%s socket error: %s' %
                                     (self, sys.exc_info()[1]))
        else:
            log.msg('%s: serving new connection...' % (self, ))
Пример #14
0
    def __init__(self, localEndpoint, remoteEndpoint, secret, dataCbFun):
        self.__localEndpoint = localEndpoint
        self.__remoteEndpoint = remoteEndpoint
        self.__secret = secret
        self.__dataCbFun = dataCbFun
        self.__pendingReqs = {}
        self.__pendingCounter = 0
        self.__input = null
        self.__announcementData = null
        asyncore.dispatcher_with_send.__init__(self)

        try:
            self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 65535)
            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65535)
            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
            self.bind(localEndpoint)
            self.connect(remoteEndpoint)
        except socket.error:
            raise error.SnmpfwdError('%s socket error: %s' %
                                     (self, sys.exc_info()[1]))
        log.msg('initiated trunk client connection from %s to %s...' %
                (localEndpoint, remoteEndpoint))
Пример #15
0
 def handle_close(self):
     self.isUp = False
     log.msg('trunk client connection with %s:%s closed' %
             self.__remoteEndpoint)
     self.close()
Пример #16
0
def dataCbFun(trunkId, msgId, msg):
    log.msg('message ID %s received from trunk %s' % (msgId, trunkId))
Пример #17
0
        except SnmpfwdError:
            sys.stderr.write('%s\r\n%s\r\n' % (sys.exc_info()[1], helpMessage))
            sys.exit(-1)
    elif opt[0] == '--config-file':
        cfgFile = opt[1]

log.setLogger(programName, 'stderr')

try:
    cfgTree = cparser.Config().load(cfgFile)
except SnmpfwdError:
    sys.stderr.write('ERROR: %s\r\n%s\r\n' % (sys.exc_info()[1], helpMessage))
    sys.exit(-1)

if cfgTree.getAttrValue('program-name', '', default=None) != programName:
    log.msg('ERROR: config file %s does not match program name %s' %
            (cfgFile, programName))
    sys.exit(-1)

if cfgTree.getAttrValue('config-version', '', default=None) != configVersion:
    log.msg(
        'ERROR: config file %s version is not compatible with program version %s'
        % (cfgFile, configVersion))
    sys.exit(-1)

random.seed()

#
# SNMPv3 CommandGenerator implementation
#

gCurrentRequestContext = {}
Пример #18
0
def dataCbFun(trunkId, msgId, msg):
    k = [
        str(x)
        for x in (msg['snmp-engine-id'], msg['snmp-transport-domain'],
                  msg['snmp-peer-address'] + ':' + str(msg['snmp-peer-port']),
                  msg['snmp-bind-address'] + ':' + str(msg['snmp-bind-port']),
                  msg['snmp-security-model'], msg['snmp-security-level'],
                  msg['snmp-security-name'], msg['snmp-context-engine-id'],
                  msg['snmp-context-name'])
    ]
    k.append(snmpPduTypesMap.get(msg['snmp-pdu'].tagSet, '?'))
    k.append('|'.join(
        [str(x[0]) for x in v2c.apiPDU.getVarBinds(msg['snmp-pdu'])]))
    k = '#'.join(k)

    for x, y in origCredIdList:
        if y.match(k):
            origPeerId = macro.expandMacros(x, msg)
            break
    else:
        origPeerId = None

    errorIndication = None

    peerIdList = routingMap.get((origPeerId, macro.expandMacros(trunkId, msg)))
    if not peerIdList:
        log.msg(
            'unroutable trunk message #%s from trunk %s, orig-peer-id %s (original SNMP info: %s)'
            % (msgId, trunkId, origPeerId or '<none>', ', '.join([
                x == 'snmp-pdu' and 'snmp-var-binds=%s' %
                prettyVarBinds(msg['snmp-pdu']) or '%s=%s' %
                (x, msg[x].prettyPrint()) for x in msg
            ])))
        errorIndication = 'no route to SNMP peer configured'

    cbCtx = trunkId, msgId, msg

    if errorIndication:
        __rspCbFun(None, None, errorIndication, None, cbCtx)
        return

    for peerId in peerIdList:
        peerId = macro.expandMacros(peerId, msg)

        snmpEngine, contextEngineId, contextName, \
            bindAddr, bindAddrMacro, \
            peerAddr, peerAddrMacro = peerIdMap[peerId]

        if bindAddrMacro:
            bindAddr = macro.expandMacros(bindAddrMacro, msg), 0
        if bindAddr:
            q.append(bindAddr)

        if peerAddrMacro:
            peerAddr = macro.expandMacros(peerAddrMacro, msg), 161
        if peerAddr:
            q.append(peerAddr)

        log.msg(
            'received trunk message #%s from trunk %s, sending SNMP message to peer ID %s, bind-address %s, peer-address %s (original SNMP info: %s)'
            % (msgId, trunkId, peerId, bindAddr[0] or '<default>', peerAddr[0]
               or '<default>', ', '.join([
                   x == 'snmp-pdu' and 'snmp-var-binds=%s' %
                   prettyVarBinds(msg['snmp-pdu']) or '%s=%s' %
                   (x, msg[x].prettyPrint()) for x in msg
               ])))

        commandGenerator.sendPdu(snmpEngine, peerId,
                                 macro.expandMacros(contextEngineId, msg),
                                 macro.expandMacros(contextName, msg),
                                 msg['snmp-pdu'], __rspCbFun, cbCtx)
Пример #19
0
    def loadPlugin(self, pluginId, pluginModuleName, pluginOptions):
        if pluginId in self.__plugins:
            raise error.SnmpfwdError('duplicate plugin ID %s' % pluginId)

        for pluginModulesDir in self.__path:
            log.msg('scanning "%s" directory for plugin modules...' %
                    pluginModulesDir)
            if not os.path.exists(pluginModulesDir):
                log.msg('directory "%s" does not exist' % pluginModulesDir)
                continue

            mod = os.path.join(pluginModulesDir, pluginModuleName + '.py')
            if not os.path.exists(mod):
                log.msg('Variation module "%s" not found' % mod)
                continue

            ctx = {
                'modulePath': mod,
                'moduleContext': {},
                'moduleOptions': pluginOptions
            }

            try:
                if sys.version_info[0] > 2:
                    exec(compile(open(mod).read(), mod, 'exec'), ctx)
                else:
                    execfile(mod, ctx)

            except Exception:
                raise error.SnmpfwdError(
                    'plugin module "%s" execution failure: %s' %
                    (mod, sys.exc_info()[1]))

            else:
                pluginModule = ctx
                try:
                    if self.__progId not in pluginModule['hostProgs']:
                        log.msg(
                            'ignoring plugin module "%s" (unmatched program ID)'
                            % mod)
                        continue

                    if self.__apiVer not in pluginModule['apiVersions']:
                        log.msg(
                            'ignoring plugin module "%s" (incompatible API version)'
                            % mod)
                        continue
                except KeyError:
                    log.msg(
                        'ignoring plugin module "%s" (missing versioning info)'
                        % mod)
                    continue

                self.__plugins[pluginId] = pluginModule

                log.msg('plugin module "%s" loaded' % mod)
                break

        else:
            raise error.SnmpfwdError('plugin module "%s" not found' %
                                     pluginModuleName)
Пример #20
0
pluginManager = PluginManager(cfgTree.getAttrValue('plugin-modules-path-list',
                                                   '',
                                                   default=[],
                                                   vector=True),
                              progId=programName,
                              apiVer=pluginApiVersion)

for pluginCfgPath in cfgTree.getPathsToAttr('plugin-id'):
    pluginId = cfgTree.getAttrValue('plugin-id', *pluginCfgPath)
    pluginMod = cfgTree.getAttrValue('plugin-module', *pluginCfgPath)
    pluginOptions = cfgTree.getAttrValue('plugin-options', *pluginCfgPath,
                                         **dict(default=''))

    log.msg(
        'configuring plugin ID %s (at %s) from module %s with options %s...' %
        (pluginId, '.'.join(pluginCfgPath), pluginMod, pluginOptions
         or '<none>'))
    try:
        pluginManager.loadPlugin(pluginId, pluginMod, pluginOptions)
    except SnmpfwdError:
        log.msg('ERROR: plugin %s not loaded: %s' %
                (pluginId, sys.exc_info()[1]))
        sys.exit(-1)

for configEntryPath in cfgTree.getPathsToAttr('snmp-credentials-id'):
    credId = cfgTree.getAttrValue('snmp-credentials-id', *configEntryPath)
    configKey = []
    log.msg('configuring snmp-credentials %s (at %s)...' %
            (credId, '.'.join(configEntryPath)))

    engineId = cfgTree.getAttrValue('snmp-engine-id', *configEntryPath)
Пример #21
0
    method = config.get('general', 'method')
    if method == 'file':
        rotation = config.get('file', 'rotation')
        if rotation == 'timed':
            handler = handlers.TimedRotatingFileHandler(
                config.get('file', 'destination'),
                config.get('file', 'timescale'),
                int(config.get('file', 'interval')),
                int(config.get('file', 'backupcount')))
        else:
            raise SnmpfwdError('logger: unknown rotation method' % rotation)
    else:
        raise SnmpfwdError('logger: unknown logging method' % method)

    msg('logger: using %s logging method' % method)

    logger.setLevel(logging.INFO)

    pdus = config.get('content', 'pdus')
    for pdu in pdus.split():
        try:
            pduMap[getattr(v2c, pdu + 'PDU').tagSet] = pdu
        except AttributeError:
            raise SnmpfwdError('logger: unknown PDU %s' % pdu)
        else:
            msg('logger: PDU ACL includes %s' % pdu)

    handler.setFormatter(
        logging.Formatter(config.get('content', 'format').replace('-', '_')))
Пример #22
0
 def handle_close(self):
     log.msg('%s: connection closed' % (self, ))
     self.__ctlCbFun(self)
     self.close()