def sendRsp(self, trunkId, msgId, rsp): if trunkId in self.__runningServersTrunkMap: trunk = self.__runningServersTrunkMap[trunkId] elif trunkId in self.__runningClientsTrunkMap: trunk = self.__runningClientsTrunkMap[trunkId] else: raise error.SnmpfwdError('Unknown trunk ID %s' % trunkId) return trunk.sendRsp(msgId, rsp)
def sendReq(self, trunkId, req, cbFun, cbCtx): if trunkId in self.__runningServersTrunkMap: trunk = self.__runningServersTrunkMap[trunkId] elif trunkId in self.__runningClientsTrunkMap: trunk = self.__runningClientsTrunkMap[trunkId] else: raise error.SnmpfwdError('Unknown trunk ID %s' % trunkId) return trunk.sendReq(req, cbFun, cbCtx)
def __exit__(self, *args): if self._olduid is None or self._oldgid is None: return try: os.setegid(self._oldgid) os.seteuid(self._olduid) except Exception: raise error.SnmpfwdError( 'setegid()/seteuid() failed for %s/%s: %s' % (self._oldgid, self._olduid, sys.exc_info()[1]))
def getAttrValue(self, attr, *nodes, **kwargs): scope = nodes while scope: obj = self.traverse([self.objects], scope) if obj and attr in obj: expect = kwargs.get('expect') if 'vector' in kwargs: if expect: try: return [expect(x) for x in obj[attr]] except Exception: raise error.SnmpfwdError( '%s value casting error at scope "%s" attribute "%s"' % (self, '.'.join(nodes), attr)) else: return obj[attr] else: if obj[attr]: if expect: try: return expect(obj[attr][0]) except Exception: raise error.SnmpfwdError( '%s value casting error at scope "%s" attribute "%s"' % (self, '.'.join(nodes), attr)) else: return obj[attr][0] else: return '' scope = scope[:-1] if 'default' in kwargs: return kwargs['default'] else: raise error.SnmpfwdError( '%s non-existing attribute "%s" at scope "%s"' % (self, attr, '.'.join(nodes)))
def dropPrivileges(uname, gname): if os.getuid() != 0: if uname and uname != pwd.getpwnam(uname).pw_name or \ gname and gname != grp.getgrnam(gname).gr_name: raise error.SnmpfwdError( 'Process is running under different UID/GID') else: return else: if not uname or not gname: raise error.SnmpfwdError( 'Must drop priveleges to a non-priveleged user&group') try: runningUid = pwd.getpwnam(uname).pw_uid runningGid = grp.getgrnam(gname).gr_gid except Exception: raise error.SnmpfwdError( 'getpwnam()/getgrnam() failed for %s/%s: %s' % (uname, gname, sys.exc_info()[1])) try: os.setgroups([]) except Exception: raise error.SnmpfwdError('setgroups() failed: %s' % sys.exc_info()[1]) try: os.setgid(runningGid) os.setuid(runningUid) except Exception: raise error.SnmpfwdError( 'setgid()/setuid() failed for %s/%s: %s' % (runningGid, runningUid, sys.exc_info()[1])) os.umask(63) # 0077
def getAttrValue(self, attr, *nodes, **kwargs): scope = nodes while scope: obj = self.traverse([self.objects], scope) if obj and attr in obj: if 'vector' in kwargs: return obj[attr] else: return obj[attr] and obj[attr][0] or '' scope = scope[:-1] if 'default' in kwargs: return kwargs['default'] else: raise error.SnmpfwdError( '%s non-existing attribute "%s" at scope "%s"' % (self, attr, '.'.join(nodes)))
def load(self, filename): try: self.lines = open(filename).readlines() except OSError: raise error.SnmpfwdError('cant open config file %s: %s' % (filename, sys.exc_info()[1])) self.tokens = [] while self.lines: line = self.lines.pop(0) if line and line[0] == '#': continue tokens = re.findall(r'(?:[^\s,"]|"(?:\\.|[^"])*")+', line) for i in range(len(tokens)): if tokens[i] and tokens[i][0] == '"' and tokens[i][-1] == '"': tokens[i] = tokens[i][1:-1] if not tokens or not tokens[0] or tokens[0][0] == '#': continue for token in tokens: # Figure out the grammar type of the token if token and token[-1] == SYMBOL_OPTION: # It's an option symbol = SYMBOL_OPTION # Cut the trailing char from token token = token[:-1] elif token == '{': symbol = SYMBOL_SECTION_BEGIN elif token == '}': symbol = SYMBOL_SECTION_END else: symbol = SYMBOL_WORD # Attach read tokens to list of tokens self.tokens.append((token, symbol)) self.index = 0 self.length = len(self.tokens) return self
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)
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, ))
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))
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.info('scanning "%s" directory for plugin modules...' % pluginModulesDir) if not os.path.exists(pluginModulesDir): log.error('directory "%s" does not exist' % pluginModulesDir) continue modPath = os.path.join(pluginModulesDir, pluginModuleName + '.py') if not os.path.exists(modPath): log.error('Variation module "%s" not found' % modPath) continue ctx = { 'modulePath': modPath, 'moduleContext': {}, 'moduleOptions': pluginOptions } modData = open(modPath).read() try: exec(compile(modData, modPath, 'exec'), ctx) except Exception: raise error.SnmpfwdError( 'plugin module "%s" execution failure: %s' % (modPath, sys.exc_info()[1])) else: pluginModule = ctx try: if self.__progId not in pluginModule['hostProgs']: log.error( 'ignoring plugin module "%s" (unmatched program ID)' % modPath) continue if self.__apiVer not in pluginModule['apiVersions']: log.error( 'ignoring plugin module "%s" (incompatible API version)' % modPath) continue except KeyError: log.error( 'ignoring plugin module "%s" (missing versioning info)' % modPath) continue self.__plugins[pluginId] = pluginModule log.info('plugin module "%s" loaded' % modPath) break else: raise error.SnmpfwdError( 'plugin module "%s" not found in search path(s): %s' % (pluginModuleName, ', '.join(self.__path)))
def load_section(self): obj = {'_name': '', '_children': []} state = 'FSM_START' while 1: # Initial state if state == 'FSM_START': try: token, symbol = self.scanner.get_token() except error.EofError: state = 'FSM_STOP' continue self.scanner.unget_token() # See if it's object closure sign if symbol == SYMBOL_SECTION_END: state = 'FSM_SECTION_END' # See if it's symbol sign elif symbol == SYMBOL_OPTION: state = 'FSM_OPTION_NAME' # Default is to start from parsing up new section else: state = 'FSM_SECTION_NAME' # If object name expected elif state == 'FSM_SECTION_NAME': self.scanner.get_token() self.scanner.unget_token() # Move to next FSM state state = 'FSM_SECTION_BEGIN' # If object body delimiter expected elif state == 'FSM_SECTION_BEGIN': self.scanner.get_token() # Get section begin token, symbol = self.scanner.get_token() # Now unget these tokens to be used at the # next FSM state self.scanner.unget_token() self.scanner.unget_token() # Make sure it's object's body start sign if symbol != SYMBOL_SECTION_BEGIN: raise error.SnmpfwdError( '%s missing object beginning sign: %s' % (self, token)) state = 'FSM_CHILD_BEGIN' # If inclusive object expected elif state == 'FSM_CHILD_BEGIN': name, symbol = self.scanner.get_token() self.scanner.get_token() child_object = self.load_section() child_object['_name'] = name # Attach child object to the list of enclosed objects obj['_children'].append(child_object) state = 'FSM_CHILD_END' # If object body closure delimiter expected elif state == 'FSM_CHILD_END': # Get next token token, symbol = self.scanner.get_token() # Make sure it's object's body end sign if symbol != SYMBOL_SECTION_END: raise error.SnmpfwdError( '%s missing object closure sign: %s' % (self, token)) # Move to the beginning of FSM state = 'FSM_START' # If object body closure delimiter expected elif state == 'FSM_SECTION_END': # Get next token token, symbol = self.scanner.get_token() # Now unget token to be used at upper level FSM instance self.scanner.unget_token() # Make sure it's object's body end sign if symbol != SYMBOL_SECTION_END: raise error.SnmpfwdError( '%s missing object closure sign: %s' % (self, token)) # Move to next FSM state state = 'FSM_STOP' # If attribute name expected elif state == 'FSM_OPTION_NAME': # Get next token token, symbol = self.scanner.get_token() # See if this attribute does not yet exist if token in obj: raise error.SnmpfwdError( '%s multiple option occurrence: %s' % (self, token)) # Accept token as attribute name obj[token] = [] # Now unget token to be used at the next FSM state self.scanner.unget_token() # Move to next FSM state state = 'FSM_OPTION_VALUE' # If option value expected elif state == 'FSM_OPTION_VALUE': option, symbol = self.scanner.get_token() # Read up one or more option values while 1: try: token, symbol = self.scanner.get_token() except error.EofError: state = 'FSM_STOP' break # If it's not a plain word if symbol != SYMBOL_WORD: self.scanner.unget_token() # See if it's object begin symbol if symbol == SYMBOL_SECTION_BEGIN: # Unget section begin sign self.scanner.unget_token() # Remove previously added last value of # the list as it turned to be section name del obj[option][-1] # Move to the beginning of FSM state = 'FSM_START' break # Accept token as attribute value if token.lower()[:2] == '0x': token = str(OctetString(hexValue=token[2:])) obj[option].append(token) # If FSM is gonna stop elif state == 'FSM_STOP': # Return object loaded return obj # If this FSM state is not known else: raise error.SnmpfwdError('%s unknown FSM state: %s' % (self, state))
def unget_token(self): if not self.index: raise error.SnmpfwdError('%s nothing to unget' % self) self.index -= 1
def addClient(self, trunkId, localEndpoint, remoteEndpoint, secret): if trunkId in self.__clients or trunkId in self.__runningServersTrunkMap: raise error.SnmpfwdError('Trunk %s already registered' % trunkId) self.__clients[ trunkId] = localEndpoint, remoteEndpoint, secret, self.__proxyDataCbFun
def parse(self): try: return self.load_section() except error.EofError: raise error.SnmpfwdError( '%s premature EOF while reading config file' % self)
def daemonize(pidfile): raise error.SnmpfwdError('Windows is not inhabited with daemons!')
def daemonize(pidfile): try: pid = os.fork() if pid > 0: # exit first parent os._exit(0) except OSError: raise error.SnmpfwdError('ERROR: fork #1 failed: %s' % sys.exc_info()[1]) # decouple from parent environment try: os.chdir('/') os.setsid() except OSError: pass os.umask(0) # do second fork try: pid = os.fork() if pid > 0: # exit from second parent os._exit(0) except OSError: raise error.SnmpfwdError('ERROR: fork #2 failed: %s' % sys.exc_info()[1]) def signal_cb(s, f): raise KeyboardInterrupt for s in signal.SIGTERM, signal.SIGINT, signal.SIGHUP, signal.SIGQUIT: signal.signal(s, signal_cb) # write pidfile def atexit_cb(): try: if pidfile: os.remove(pidfile) except OSError: pass atexit.register(atexit_cb) try: if pidfile: fd, nm = tempfile.mkstemp(dir=os.path.dirname(pidfile)) os.write(fd, ('%d\n' % os.getpid()).encode('utf-8')) os.close(fd) os.rename(nm, pidfile) except Exception: raise error.SnmpfwdError('Failed to create PID file %s: %s' % (pidfile, sys.exc_info()[1])) # redirect standard file descriptors sys.stdout.flush() sys.stderr.flush() si = open(os.devnull, 'r') so = open(os.devnull, 'a+') se = open(os.devnull, 'a+') os.dup2(si.fileno(), sys.stdin.fileno()) os.dup2(so.fileno(), sys.stdout.fileno()) os.dup2(se.fileno(), sys.stderr.fileno())