diff options
author | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2014-07-01 02:36:00 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2014-07-01 02:36:00 +0900 |
commit | fdce89a0def2b20d5dffda541207e2d482e2b652 (patch) | |
tree | aa617d0a109be7e49f43923be357614feaaff11c | |
parent | b984c15f68c24d32d974f3af90aa55db50e0246b (diff) |
bgp: support md5 authentication for re-active sessions
For now, only Linux is supported.
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r-- | ryu/services/protocols/bgp/base.py | 63 | ||||
-rw-r--r-- | ryu/services/protocols/bgp/core.py | 24 |
2 files changed, 71 insertions, 16 deletions
diff --git a/ryu/services/protocols/bgp/base.py b/ryu/services/protocols/bgp/base.py index 87060cd6..ef175db0 100644 --- a/ryu/services/protocols/bgp/base.py +++ b/ryu/services/protocols/bgp/base.py @@ -330,22 +330,16 @@ class Activity(object): addr, port = sock.getsockname()[:2] return (self._canonicalize_ip(addr), str(port)) - def _listen_tcp(self, loc_addr, conn_handle): - """Creates a TCP server socket which listens on `port` number. - - For each connection `server_factory` starts a new protocol. - """ - if ':' in loc_addr[0]: - server = hub.listen(loc_addr, family=socket.AF_INET6) - else: - server = hub.listen(loc_addr) - - server_name = self.name + '_server@' + str(loc_addr) - self._asso_socket_map[server_name] = server - - # We now wait for connection requests from client. + def _create_listen_socket(self, family, loc_addr): + s = socket.socket(family) + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + s.bind(loc_addr) + s.listen(1) + return s + + def _listen_socket_loop(self, s, conn_handle): while True: - sock, client_address = server.accept() + sock, client_address = s.accept() client_address, port = self.get_remotename(sock) LOG.debug('Connect request received from client for port' ' %s:%s' % (client_address, port)) @@ -353,6 +347,45 @@ class Activity(object): self._asso_socket_map[client_name] = sock self._spawn(client_name, conn_handle, sock) + def _listen_tcp(self, loc_addr, conn_handle): + """Creates a TCP server socket which listens on `port` number. + + For each connection `server_factory` starts a new protocol. + """ + info = socket.getaddrinfo(None, loc_addr[1], socket.AF_UNSPEC, + socket.SOCK_STREAM, 0, socket.AI_PASSIVE) + listen_sockets = {} + for res in info: + af, socktype, proto, cannonname, sa = res + sock = None + try: + sock = socket.socket(af, socktype, proto) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + if af == socket.AF_INET6: + sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1) + + sock.bind(sa) + sock.listen(50) + listen_sockets[sa] = sock + except socket.error: + if sock: + sock.close() + + count = 0 + server = None + for sa in listen_sockets.keys(): + name = self.name + '_server@' + str(sa[0]) + if count == 0: + import eventlet + server = eventlet.spawn(self._listen_socket_loop, + listen_sockets[sa], conn_handle) + + count += 1 + else: + self._spawn(name, self._listen_socket_loop, + listen_sockets[sa], conn_handle) + return server, listen_sockets + def _connect_tcp(self, peer_addr, conn_handler, time_out=None, bind_address=None, password=None): """Creates a TCP connection to given peer address. diff --git a/ryu/services/protocols/bgp/core.py b/ryu/services/protocols/bgp/core.py index fa9ee184..27eae15e 100644 --- a/ryu/services/protocols/bgp/core.py +++ b/ryu/services/protocols/bgp/core.py @@ -21,6 +21,7 @@ """ import logging import netaddr +import socket from ryu.lib.packet.bgp import BGP_ERROR_CEASE from ryu.lib.packet.bgp import BGP_ERROR_SUB_CONNECTION_RESET @@ -40,6 +41,7 @@ from ryu.services.protocols.bgp.signals.emit import BgpSignalBus from ryu.services.protocols.bgp.speaker import BgpProtocol from ryu.services.protocols.bgp.utils.rtfilter import RouteTargetManager from ryu.services.protocols.bgp.utils import stats +from ryu.lib import sockopt LOG = logging.getLogger('bgpspeaker.core') @@ -221,7 +223,9 @@ class CoreService(Factory, Activity): server_addr = (CORE_IP, self._common_config.bgp_server_port) waiter = kwargs.pop('waiter') waiter.set() - server_thread = self._listen_tcp(server_addr, self.start_protocol) + server_thread, sockets = self._listen_tcp(server_addr, + self.start_protocol) + self.listen_sockets = sockets server_thread.wait() processor_thread.wait() @@ -358,7 +362,21 @@ class CoreService(Factory, Activity): out_route = FlexinetOutgoingRoute(path, route_dist) sink.enque_outgoing_msg(out_route) + def _set_password(self, address, password): + if netaddr.valid_ipv4(address): + family = socket.AF_INET + else: + family = socket.AF_INET6 + + for sock in self.listen_sockets.values(): + if sock.family == family: + sockopt.set_tcp_md5sig(sock, address, password) + def on_peer_added(self, peer): + if peer._neigh_conf.password: + self._set_password(peer._neigh_conf.ip_address, + peer._neigh_conf.password) + if self.started: self._spawn_activity( peer, self.start_protocol @@ -372,6 +390,10 @@ class CoreService(Factory, Activity): ) def on_peer_removed(self, peer): + if peer._neigh_conf.password: + # seting zero length key means deleting the key + self._set_password(peer._neigh_conf.ip_address, '') + if peer.rtc_as != self.asn: self._spawn( 'OLD_RTC_AS_HANDLER %s' % peer.rtc_as, |