mirror of
https://github.com/sileht/bird-lg.git
synced 2024-11-25 00:04:42 +01:00
178 lines
4.3 KiB
Python
178 lines
4.3 KiB
Python
# -*- coding: utf-8 -*-
|
|
# vim: ts=4
|
|
###
|
|
#
|
|
# Copyright (c) 2006 Mehdi Abaakouk
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License version 3 as
|
|
# published by the Free Software Foundation
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
#
|
|
###
|
|
|
|
import socket
|
|
import sys
|
|
|
|
BUFSIZE = 4096
|
|
|
|
SUCCESS_CODES = {
|
|
"0000" : "OK",
|
|
"0001" : "Welcome",
|
|
"0002" : "Reading configuration",
|
|
"0003" : "Reconfigured",
|
|
"0004" : "Reconfiguration in progress",
|
|
"0005" : "Reconfiguration already in progress, queueing",
|
|
"0006" : "Reconfiguration ignored, shutting down",
|
|
"0007" : "Shutdown ordered",
|
|
"0008" : "Already disabled",
|
|
"0009" : "Disabled",
|
|
"0010" : "Already enabled",
|
|
"0011" : "Enabled",
|
|
"0012" : "Restarted",
|
|
"0013" : "Status report",
|
|
"0014" : "Route count",
|
|
"0015" : "Reloading",
|
|
"0016" : "Access restricted",
|
|
}
|
|
|
|
TABLES_ENTRY_CODES = {
|
|
"1000" : "BIRD version",
|
|
"1001" : "Interface list",
|
|
"1002" : "Protocol list",
|
|
"1003" : "Interface address",
|
|
"1004" : "Interface flags",
|
|
"1005" : "Interface summary",
|
|
"1006" : "Protocol details",
|
|
"1007" : "Route list",
|
|
"1008" : "Route details",
|
|
"1009" : "Static route list",
|
|
"1010" : "Symbol list",
|
|
"1011" : "Uptime",
|
|
"1012" : "Route extended attribute list",
|
|
"1013" : "Show ospf neighbors",
|
|
"1014" : "Show ospf",
|
|
"1015" : "Show ospf interface",
|
|
"1016" : "Show ospf state/topology",
|
|
"1017" : "Show ospf lsadb",
|
|
"1018" : "Show memory",
|
|
}
|
|
|
|
ERROR_CODES = {
|
|
"8000" : "Reply too long",
|
|
"8001" : "Route not found",
|
|
"8002" : "Configuration file error",
|
|
"8003" : "No protocols match",
|
|
"8004" : "Stopped due to reconfiguration",
|
|
"8005" : "Protocol is down => cannot dump",
|
|
"8006" : "Reload failed",
|
|
"8007" : "Access denied",
|
|
|
|
"9000" : "Command too long",
|
|
"9001" : "Parse error",
|
|
"9002" : "Invalid symbol type",
|
|
}
|
|
|
|
END_CODES = ERROR_CODES.keys() + SUCCESS_CODES.keys()
|
|
|
|
global bird_sockets
|
|
bird_sockets = {}
|
|
|
|
def BirdSocketSingleton(host, port):
|
|
global bird_sockets
|
|
s = bird_sockets.get((host,port), None)
|
|
if not s:
|
|
s = BirdSocket(host,port)
|
|
bird_sockets[(host,port)] = s
|
|
return s
|
|
|
|
class BirdSocket:
|
|
|
|
def __init__(self, host="", port="", file=""):
|
|
self.__file = file
|
|
self.__host = host
|
|
self.__port = port
|
|
self.__sock = None
|
|
|
|
def __connect(self):
|
|
if self.__sock: return
|
|
|
|
if not file:
|
|
self.__sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
self.__sock.settimeout(3.0)
|
|
self.__sock.connect((self.__host, self.__port))
|
|
else:
|
|
self.__sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
|
self.__sock.settimeout(3.0)
|
|
self.__sock.connect(self.__file)
|
|
|
|
# read welcome message
|
|
self.__sock.recv(1024)
|
|
self.cmd("restrict")
|
|
|
|
def close(self):
|
|
if self.__sock:
|
|
try: self.__sock.close()
|
|
except: pass
|
|
self.__sock = None
|
|
|
|
def cmd(self, cmd):
|
|
try:
|
|
self.__connect()
|
|
self.__sock.send(cmd + "\n")
|
|
data = self.__read()
|
|
return data
|
|
except socket.error:
|
|
why = sys.exc_info()[1]
|
|
self.close()
|
|
return False, "Bird connection problem: %s" % why
|
|
|
|
def __read(self):
|
|
code = "7000" # Not used in bird
|
|
parsed_string = ""
|
|
lastline = ""
|
|
|
|
while code not in END_CODES:
|
|
data = self.__sock.recv(BUFSIZE)
|
|
|
|
lines = (lastline + data).split("\n")
|
|
if len(data) == BUFSIZE:
|
|
lastline = lines[-1]
|
|
lines = lines[:-1]
|
|
|
|
for line in lines:
|
|
code = line[0:4]
|
|
|
|
if not line.strip():
|
|
continue
|
|
elif code == "0000":
|
|
return True, parsed_string
|
|
elif code in SUCCESS_CODES.keys():
|
|
return True, SUCCESS_CODES.get(code)
|
|
elif code in ERROR_CODES.keys():
|
|
return False, ERROR_CODES.get(code)
|
|
elif code[0] in [ "1", "2"] :
|
|
parsed_string += line[5:] + "\n"
|
|
elif code[0] == " ":
|
|
parsed_string += line[1:] + "\n"
|
|
elif code[0] == "+":
|
|
parsed_string += line[1:]
|
|
else:
|
|
parsed_string += "<<<unparsable_string(%s)>>>\n"%line
|
|
|
|
return True, parsed_string
|
|
|
|
|
|
__all__ = ['BirdSocketSingleton' , 'BirdSocket' ]
|
|
|
|
|
|
|