def api_attribute (self, command, peers, action): # This is a quick solution which does not support next-hop self attribute,nlris = command.split('nlri') route = '%s route 0.0.0.0/0 %s' % (action, ' '.join(attribute.split()[2:])) parsed = self.api_route(peers,route) if parsed in (True,False,None): return parsed attributes = parsed[0][1].attributes nexthop = parsed[0][1].nlri.nexthop changes = [] for nlri in nlris.split(): ip,mask = nlri.split('/') klass = MPLS if 'path-information' in command else INET change = Change( klass( afi=IP.toafi(ip), safi=IP.tosafi(ip), packed=IP.pton(ip), mask=int(mask), nexthop='', # could be NextHopSelf action=action ), attributes ) change.nlri.nexthop = nexthop if action == 'withdraw': change.nlri.action = OUT.WITHDRAW else: change.nlri.action = OUT.ANNOUNCE changes.append((peers.keys(),change)) return changes
def insert_static_route (self, scope, name, command, tokens): try: ip = tokens.pop(0) except IndexError: return self.error.set(self.syntax) try: ip,mask = ip.split('/') mask = int(mask) except ValueError: mask = 32 try: if 'rd' in tokens: klass = MPLS elif 'route-distinguisher' in tokens: klass = MPLS elif 'label' in tokens: klass = MPLS else: klass = INET # nexthop must be false and its str return nothing .. an empty string does that update = Change(klass(afi=IP.toafi(ip),safi=IP.tosafi(ip),packed=IP.pton(ip),mask=mask,nexthop=None,action=OUT.ANNOUNCE),Attributes()) except ValueError: return self.error.set(self.syntax) if 'announce' not in scope[-1]: scope[-1]['announce'] = [] scope[-1]['announce'].append(update) return True
def parse_api_attribute (self,command,peers,action): # This is a quick solution which does not support next-hop self attribute,nlris = command.split('nlri') route = '%s route 0.0.0.0/0 %s' % (action, ' '.join(attribute.split()[2:])) parsed = self.parse_api_route(route,peers,action) if parsed in (True,False,None): return parsed attributes = parsed[0][1].attributes nexthop = parsed[0][1].nlri.nexthop changes = [] for nlri in nlris.split(): ip,mask = nlri.split('/') klass = Prefix if 'path-information' in command else MPLS change = Change( klass( afi=IP.toafi(ip), safi=IP.tosafi(ip), packed=IP.pton(ip), mask=int(mask), nexthop=nexthop.packed, action=action ) ,attributes ) if action == 'withdraw': change.nlri.action = OUT.withdraw else: change.nlri.action = OUT.announce changes.append((peers.keys(),change)) return changes
def route (tokeniser): ipmask = prefix(tokeniser) if 'rd' in tokeniser.tokens or 'route-distinguisher' in tokeniser.tokens: nlri = IPVPN(IP.toafi(ipmask.top()),SAFI.mpls_vpn,OUT.ANNOUNCE) elif 'label' in tokeniser.tokens: nlri = Label(IP.toafi(ipmask.top()),SAFI.nlri_mpls,OUT.ANNOUNCE) else: nlri = INET(IP.toafi(ipmask.top()),IP.tosafi(ipmask.top()),OUT.ANNOUNCE) nlri.cidr = CIDR(ipmask.pack(),ipmask.mask) change = Change( nlri, Attributes() ) while True: command = tokeniser() if not command: break if command == 'label': nlri.labels = label(tokeniser) continue if command == 'rd' or command == 'route-distinguisher': nlri.rd = route_distinguisher(tokeniser) continue action = ParseStatic.action.get(command,'') if action == 'attribute-add': change.attributes.add(ParseStatic.known[command](tokeniser)) elif action == 'nlri-set': change.nlri.assign(ParseStatic.assign[command],ParseStatic.known[command](tokeniser)) elif action == 'nexthop-and-attribute': nexthop,attribute = ParseStatic.known[command](tokeniser) change.nlri.nexthop = nexthop change.attributes.add(attribute) else: raise ValueError('route: unknown command "%s"' % command) return list(ParseStatic.split(change))
def MD5(io, ip, port, md5): if md5: os = platform.system() if os == 'FreeBSD': if md5 != 'kernel': raise MD5Error( 'FreeBSD requires that you set your MD5 key via ipsec.conf.\n' 'Something like:\n' 'flush;\n' 'add <local ip> <peer ip> tcp 0x1000 -A tcp-md5 "password";' ) try: TCP_MD5SIG = 0x10 io.setsockopt(socket.IPPROTO_TCP, TCP_MD5SIG, 1) except socket.error: raise MD5Error( 'FreeBSD requires that you rebuild your kernel to enable TCP MD5 Signatures:\n' 'options IPSEC\n' 'options TCP_SIGNATURE\n' 'device crypto\n') elif os == 'Linux': try: # __kernel_sockaddr_storage n_af = IP.toaf(ip) n_addr = IP.pton(ip) n_port = socket.htons(port) # pack 'x' is padding, so we want the struct # Do not use '!' for the pack, the network (big) endian switch in # struct.pack is fighting against inet_pton and htons (note the n) if IP.toafi(ip) == AFI.ipv4: # SS_MAXSIZE is 128 but addr_family, port and ipaddr (8 bytes total) are written independently of the padding SS_MAXSIZE_PADDING = 128 - calcsize('HH4s') # 8 sockaddr = pack('HH4s%dx' % SS_MAXSIZE_PADDING, socket.AF_INET, n_port, n_addr) else: SS_MAXSIZE_PADDING = 128 - calcsize('HI16sI') # 28 SIN6_FLOWINFO = 0 SIN6_SCOPE_ID = 0 sockaddr = pack('HHI16sI%dx' % SS_MAXSIZE_PADDING, n_af, n_port, SIN6_FLOWINFO, n_addr, SIN6_SCOPE_ID) TCP_MD5SIG_MAXKEYLEN = 80 key = pack('2xH4x%ds' % TCP_MD5SIG_MAXKEYLEN, len(md5), md5) TCP_MD5SIG = 14 io.setsockopt(socket.IPPROTO_TCP, TCP_MD5SIG, sockaddr + key) except socket.error, exc: raise MD5Error( 'This linux machine does not support TCP_MD5SIG, you can not use MD5 (%s)' % errstr(exc)) else: raise MD5Error('ExaBGP has no MD5 support for %s' % os)
def prefix (tokeniser): # XXX: could raise ip = tokeniser() try: ip,mask = ip.split('/') mask = int(mask) except ValueError: mask = 32 tokeniser.afi = IP.toafi(ip) return Range(ip,IP.pton(ip),mask)
def prefix(tokeniser): # XXX: could raise ip = tokeniser() try: ip, mask = ip.split('/') mask = int(mask) except ValueError: mask = 32 tokeniser.afi = IP.toafi(ip) return Range(ip, IP.pton(ip), mask)
def prefix(tokeniser): # XXX: could raise ip = tokeniser() try: ip, mask = ip.split('/') except ValueError: mask = '32' if ':' in ip: mask = '128' tokeniser.afi = IP.toafi(ip) return IPRange.create(ip, mask)
def prefix (tokeniser): # XXX: could raise ip = tokeniser() try: ip,mask = ip.split('/') except ValueError: mask = '32' if ':' in ip: mask = '128' tokeniser.afi = IP.toafi(ip) return IPRange.create(ip,mask)
def mpls (tokeniser): ipmask = prefix(tokeniser) mpls = IPVPN( afi=IP.toafi(ipmask.top()), safi=IP.tosafi(ipmask.top()), action=OUT.ANNOUNCE ) mpls.cidr = CIDR(ipmask.ton(),ipmask.mask) return Change( mpls, Attributes() )
def mpls (tokeniser): ipmask = prefix(tokeniser) mpls = IPVPN( afi=IP.toafi(ipmask.top()), safi=IP.tosafi(ipmask.top()), action=OUT.UNSET ) mpls.cidr = CIDR(ipmask.ton(),ipmask.mask) return Change( mpls, Attributes() )
def inet (tokeniser): ipmask = prefix(tokeniser) inet = INET( afi=IP.toafi(ipmask.top()), safi=IP.tosafi(ipmask.top()), action=OUT.UNSET ) inet.cidr = CIDR(ipmask.ton(),ipmask.mask) return Change( inet, Attributes() )
def inet (tokeniser): ipmask = prefix(tokeniser) inet = INET( afi=IP.toafi(ipmask.top()), safi=IP.tosafi(ipmask.top()), action=OUT.UNSET ) inet.cidr = CIDR(ipmask.ton(),ipmask.mask) return Change( inet, Attributes() )
def inet (tokeniser): ipmask = prefix(tokeniser) return Change( INET( afi=IP.toafi(ipmask.string), safi=IP.tosafi(ipmask.string), packed=IP.pton(ipmask.string), mask=ipmask.mask, nexthop=None, action=OUT.UNSET ), Attributes() )
def route (tokeniser): ipmask = prefix(tokeniser) if 'rd' in tokeniser.tokens or 'route-distinguisher' in tokeniser.tokens: nlri = IPVPN(IP.toafi(ipmask.top()),SAFI.mpls_vpn,OUT.ANNOUNCE) elif 'label' in tokeniser.tokens: nlri = Label(IP.toafi(ipmask.top()),SAFI.nlri_mpls,OUT.ANNOUNCE) else: nlri = INET(IP.toafi(ipmask.top()),IP.tosafi(ipmask.top()),OUT.ANNOUNCE) nlri.cidr = CIDR(ipmask.pack(),ipmask.mask) change = Change( nlri, Attributes() ) while True: command = tokeniser() if not command: break action = ParseStatic.action.get(command,'') if action == 'attribute-add': change.attributes.add(ParseStatic.known[command](tokeniser)) elif action == 'nlri-set': change.nlri.assign(ParseStatic.assign[command],ParseStatic.known[command](tokeniser)) elif action == 'nexthop-and-attribute': nexthop,attribute = ParseStatic.known[command](tokeniser) change.nlri.nexthop = nexthop change.attributes.add(attribute) else: raise ValueError('route: unknown command "%s"' % command) return list(ParseStatic.split(change))
def route (tokeniser): ipmask = prefix(tokeniser) if 'rd' in tokeniser.tokens or 'route-distinguisher' in tokeniser.tokens: klass = MPLS safi = SAFI(SAFI.mpls_vpn) elif 'label' in tokeniser.tokens: # XXX: should we create a LABEL class ? klass = MPLS safi = SAFI(SAFI.nlri_mpls) else: klass = INET safi = IP.tosafi(ipmask.string) change = Change( klass( IP.toafi(ipmask.string), safi, ipmask.pack(), ipmask.mask, '', OUT.UNSET ), Attributes() ) while True: command = tokeniser() if not command: break action = ParseStatic.action[command] if action == 'attribute-add': change.attributes.add(ParseStatic.known[command](tokeniser)) elif action == 'nlri-set': change.nlri.assign(ParseStatic.assign[command],ParseStatic.known[command](tokeniser)) elif action == 'nexthop-and-attribute': nexthop,attribute = ParseStatic.known[command](tokeniser) change.nlri.nexthop = nexthop change.attributes.add(attribute) else: raise ValueError('route: unknown command "%s"' % command) return list(ParseStatic.split(change))
def prefix(tokeniser): # XXX: could raise ip = tokeniser() try: ip, mask = ip.split('/') except ValueError: mask = '32' if ':' in ip: mask = '128' tokeniser.afi = IP.toafi(ip) iprange = IPRange.create(ip, mask) if iprange.address() & iprange.mask.hostmask() != 0: raise ValueError('invalid network %s for netmask %s' % (ip, mask)) return iprange
def insert_static_route(self, scope, name, command, tokens): try: ip = tokens.pop(0) except IndexError: return self.error.set(self.syntax) try: ip, mask = ip.split('/') mask = int(mask) except ValueError: mask = 32 try: if 'rd' in tokens: klass = MPLS elif 'route-distinguisher' in tokens: klass = MPLS elif 'label' in tokens: klass = MPLS else: klass = INET # nexthop must be false and its str return nothing .. an empty string does that update = Change( klass(afi=IP.toafi(ip), safi=IP.tosafi(ip), packed=IP.pton(ip), mask=mask, nexthop=None, action=OUT.ANNOUNCE), Attributes()) except ValueError: return self.error.set(self.syntax) if 'announce' not in scope[-1]: scope[-1]['announce'] = [] scope[-1]['announce'].append(update) return True
def attributes (tokeniser): ipmask = prefix(lambda: tokeniser.tokens[-1]) if 'rd' in tokeniser.tokens or 'route-distinguisher' in tokeniser.tokens: nlri = MPLS(IP.toafi(ipmask.top()),SAFI.mpls_vpn,OUT.ANNOUNCE) elif 'label' in tokeniser.tokens: nlri = Label(IP.toafi(ipmask.top()),SAFI.nlri_mpls,OUT.ANNOUNCE) else: nlri = INET(IP.toafi(ipmask.top()),IP.tosafi(ipmask.top()),OUT.ANNOUNCE) nlri.cidr = CIDR(ipmask.pack(),ipmask.mask) change = Change( nlri, Attributes() ) while True: command = tokeniser() if not command: return [] if command == 'nlri': break action = ParseStatic.action[command] if action == 'attribute-add': change.attributes.add(ParseStatic.known[command](tokeniser)) elif action == 'nlri-set': change.nlri.assign(ParseStatic.assign[command],ParseStatic.known[command](tokeniser)) elif action == 'nexthop-and-attribute': nexthop,attribute = ParseStatic.known[command](tokeniser) change.nlri.nexthop = nexthop change.attributes.add(attribute) else: raise ValueError('route: unknown command "%s"' % command) attributes = change.attributes nexthop = change.nlri.nexthop changes = [] while True: nlri = tokeniser.peek() if not nlri: break ipmask = prefix(tokeniser) new = Change( change.nlri.__class__( change.nlri.afi, change.nlri.safi, OUT.UNSET ), attributes ) new.nlri.cidr = CIDR(ipmask.pack(),ipmask.mask) new.nlri.nexthop = nexthop changes.append(new) return changes
def attributes (tokeniser): ipmask = prefix(lambda: tokeniser.tokens[-1]) if 'rd' in tokeniser.tokens or 'route-distinguisher' in tokeniser.tokens: nlri = IPVPN(IP.toafi(ipmask.top()),SAFI.mpls_vpn,OUT.ANNOUNCE) elif 'label' in tokeniser.tokens: nlri = Label(IP.toafi(ipmask.top()),SAFI.nlri_mpls,OUT.ANNOUNCE) else: nlri = INET(IP.toafi(ipmask.top()),IP.tosafi(ipmask.top()),OUT.ANNOUNCE) nlri.cidr = CIDR(ipmask.pack(),ipmask.mask) change = Change( nlri, Attributes() ) while True: command = tokeniser() if not command: return [] if command == 'nlri': break action = ParseStatic.action[command] if action == 'attribute-add': change.attributes.add(ParseStatic.known[command](tokeniser)) elif action == 'nlri-set': change.nlri.assign(ParseStatic.assign[command],ParseStatic.known[command](tokeniser)) elif action == 'nexthop-and-attribute': nexthop,attribute = ParseStatic.known[command](tokeniser) change.nlri.nexthop = nexthop change.attributes.add(attribute) else: raise ValueError('route: unknown command "%s"' % command) attributes = change.attributes nexthop = change.nlri.nexthop changes = [] while True: nlri = tokeniser.peek() if not nlri: break ipmask = prefix(tokeniser) new = Change( change.nlri.__class__( change.nlri.afi, change.nlri.safi, OUT.UNSET ), attributes ) new.nlri.cidr = CIDR(ipmask.pack(),ipmask.mask) new.nlri.nexthop = nexthop changes.append(new) return changes
def attributes (tokeniser): ipmask = prefix(lambda: tokeniser.tokens[-1]) if 'rd' in tokeniser.tokens or 'route-distinguisher' in tokeniser.tokens: nlri = IPVPN(IP.toafi(ipmask.top()),SAFI.mpls_vpn,OUT.ANNOUNCE) elif 'label' in tokeniser.tokens: nlri = Label(IP.toafi(ipmask.top()),SAFI.nlri_mpls,OUT.ANNOUNCE) else: nlri = INET(IP.toafi(ipmask.top()),IP.tosafi(ipmask.top()),OUT.ANNOUNCE) nlri.cidr = CIDR(ipmask.pack(),ipmask.mask) attr = Attributes() labels = None rd = None while True: command = tokeniser() if not command: return [] if command == 'nlri': break if command == 'label': labels = label(tokeniser) continue if command == 'rd' or command == 'route-distinguisher': rd = route_distinguisher(tokeniser) continue action = ParseStatic.action[command] if action == 'attribute-add': attr.add(ParseStatic.known[command](tokeniser)) elif action == 'nlri-set': nlri.assign(ParseStatic.assign[command],ParseStatic.known[command](tokeniser)) elif action == 'nexthop-and-attribute': nexthop,attribute = ParseStatic.known[command](tokeniser) nlri.nexthop = nexthop attr.add(attribute) else: raise ValueError('route: unknown command "%s"' % command) changes = [] while True: peeked_nlri = tokeniser.peek() if not peeked_nlri: break ipmask = prefix(tokeniser) new = Change( nlri.__class__( nlri.afi, nlri.safi, OUT.UNSET ), attr ) new.nlri.cidr = CIDR(ipmask.pack(),ipmask.mask) if labels: new.nlri.labels = labels if rd: new.nlri.rd = rd new.nlri.nexthop = nlri.nexthop changes.append(new) return changes
def MD5(io, ip, port, md5, md5_base64): platform_os = platform.system() if platform_os == 'FreeBSD': if md5: if md5 != 'kernel': raise MD5Error( 'FreeBSD requires that you set your MD5 key via ipsec.conf.\n' 'Something like:\n' 'flush;\n' 'add <local ip> <peer ip> tcp 0x1000 -A tcp-md5 "password";' ) try: TCP_MD5SIG = 0x10 io.setsockopt(socket.IPPROTO_TCP, TCP_MD5SIG, 1) except socket.error: raise MD5Error( 'FreeBSD requires that you rebuild your kernel to enable TCP MD5 Signatures:\n' 'options IPSEC\n' 'options TCP_SIGNATURE\n' 'device crypto\n') elif platform_os == 'Linux': try: md5_bytes = None if md5: if md5_base64 is True: try: md5_bytes = base64.b64decode(md5) except TypeError: raise MD5Error("Failed to decode base 64 encoded PSK") elif md5_base64 is None and not re.match('.*[^a-f0-9].*', md5): # auto options = [md5 + '==', md5 + '=', md5] for md5 in options: try: md5_bytes = base64.b64decode(md5) break except TypeError: pass # __kernel_sockaddr_storage n_af = IP.toaf(ip) n_addr = IP.pton(ip) n_port = socket.htons(port) # pack 'x' is padding, so we want the struct # Do not use '!' for the pack, the network (big) endian switch in # struct.pack is fighting against inet_pton and htons (note the n) if IP.toafi(ip) == AFI.ipv4: # SS_MAXSIZE is 128 but addr_family, port and ipaddr (8 bytes total) are written independently of the padding SS_MAXSIZE_PADDING = 128 - calcsize('HH4s') # 8 sockaddr = pack('HH4s%dx' % SS_MAXSIZE_PADDING, socket.AF_INET, n_port, n_addr) else: SS_MAXSIZE_PADDING = 128 - calcsize('HI16sI') # 28 SIN6_FLOWINFO = 0 SIN6_SCOPE_ID = 0 sockaddr = pack('HHI16sI%dx' % SS_MAXSIZE_PADDING, n_af, n_port, SIN6_FLOWINFO, n_addr, SIN6_SCOPE_ID) TCP_MD5SIG_MAXKEYLEN = 80 TCP_MD5SIG = 14 if md5_bytes: key = pack('2xH4x%ds' % TCP_MD5SIG_MAXKEYLEN, len(md5_bytes), md5_bytes) io.setsockopt(socket.IPPROTO_TCP, TCP_MD5SIG, sockaddr + key) elif md5: md5_bytes = bytes(md5, 'ascii') key = pack('2xH4x%ds' % TCP_MD5SIG_MAXKEYLEN, len(md5_bytes), md5_bytes) io.setsockopt(socket.IPPROTO_TCP, TCP_MD5SIG, sockaddr + key) # else: # key = pack('2xH4x%ds' % TCP_MD5SIG_MAXKEYLEN, 0, b'') # io.setsockopt(socket.IPPROTO_TCP, TCP_MD5SIG, sockaddr + key) except socket.error as exc: if exc.errno != errno.ENOENT: raise MD5Error( 'This linux machine does not support TCP_MD5SIG, you can not use MD5 (%s)' % errstr(exc)) elif md5: raise MD5Error('ExaBGP has no MD5 support for %s' % platform_os)
def attributes (tokeniser): action = OUT.ANNOUNCE if tokeniser.announce else OUT.WITHDRAW ipmask = prefix(lambda: tokeniser.tokens[-1]) tokeniser.afi = ipmask.afi if 'rd' in tokeniser.tokens or 'route-distinguisher' in tokeniser.tokens: nlri = IPVPN(IP.toafi(ipmask.top()), SAFI.mpls_vpn, action) elif 'label' in tokeniser.tokens: nlri = Label(IP.toafi(ipmask.top()), SAFI.nlri_mpls, action) else: nlri = INET(IP.toafi(ipmask.top()), IP.tosafi(ipmask.top()), action) nlri.cidr = CIDR(ipmask.pack(),ipmask.mask) attr = Attributes() labels = None rd = None while True: command = tokeniser() if not command: return [] if command == 'nlri': break if command == 'label': labels = label(tokeniser) continue if command == 'rd' or command == 'route-distinguisher': rd = route_distinguisher(tokeniser) continue action = ParseStatic.action[command] if action == 'attribute-add': attr.add(ParseStatic.known[command](tokeniser)) elif action == 'nlri-set': nlri.assign(ParseStatic.assign[command],ParseStatic.known[command](tokeniser)) elif action == 'nexthop-and-attribute': nexthop,attribute = ParseStatic.known[command](tokeniser) nlri.nexthop = nexthop attr.add(attribute) else: raise ValueError('unknown command "%s"' % command) changes = [] while True: peeked_nlri = tokeniser.peek() if not peeked_nlri: break ipmask = prefix(tokeniser) new = Change( nlri.__class__( nlri.afi, nlri.safi, OUT.UNSET ), attr ) new.nlri.cidr = CIDR(ipmask.pack(),ipmask.mask) if labels: new.nlri.labels = labels if rd: new.nlri.rd = rd new.nlri.nexthop = nlri.nexthop changes.append(new) return changes
def MD5 (io, ip, port, md5, md5_base64): platform_os = platform.system() if platform_os == 'FreeBSD': if md5: if md5 != 'kernel': raise MD5Error( 'FreeBSD requires that you set your MD5 key via ipsec.conf.\n' 'Something like:\n' 'flush;\n' 'add <local ip> <peer ip> tcp 0x1000 -A tcp-md5 "password";' ) try: TCP_MD5SIG = 0x10 io.setsockopt(socket.IPPROTO_TCP, TCP_MD5SIG, 1) except socket.error: raise MD5Error( 'FreeBSD requires that you rebuild your kernel to enable TCP MD5 Signatures:\n' 'options IPSEC\n' 'options TCP_SIGNATURE\n' 'device crypto\n' ) elif platform_os == 'Linux': try: if md5: md5_bytes = None if md5_base64 is True: try: md5_bytes = base64.b64decode(md5) except TypeError: raise MD5Error("Failed to decode base 64 encoded PSK") elif md5_base64 is None and not re.match('.*[^a-f0-9].*', md5): # auto options = [md5+'==', md5+'=', md5] for md5 in options: try: md5_bytes = base64.b64decode(md5) break except TypeError: pass # __kernel_sockaddr_storage n_af = IP.toaf(ip) n_addr = IP.pton(ip) n_port = socket.htons(port) # pack 'x' is padding, so we want the struct # Do not use '!' for the pack, the network (big) endian switch in # struct.pack is fighting against inet_pton and htons (note the n) if IP.toafi(ip) == AFI.ipv4: # SS_MAXSIZE is 128 but addr_family, port and ipaddr (8 bytes total) are written independently of the padding SS_MAXSIZE_PADDING = 128 - calcsize('HH4s') # 8 sockaddr = pack('HH4s%dx' % SS_MAXSIZE_PADDING, socket.AF_INET, n_port, n_addr) else: SS_MAXSIZE_PADDING = 128 - calcsize('HI16sI') # 28 SIN6_FLOWINFO = 0 SIN6_SCOPE_ID = 0 sockaddr = pack('HHI16sI%dx' % SS_MAXSIZE_PADDING, n_af, n_port, SIN6_FLOWINFO, n_addr, SIN6_SCOPE_ID) TCP_MD5SIG_MAXKEYLEN = 80 TCP_MD5SIG = 14 if md5_bytes: key = pack('2xH4x%ds' % TCP_MD5SIG_MAXKEYLEN, len(md5_bytes), md5_bytes) io.setsockopt(socket.IPPROTO_TCP, TCP_MD5SIG, sockaddr + key) elif md5: md5_bytes = bytes_ascii(md5) key = pack('2xH4x%ds' % TCP_MD5SIG_MAXKEYLEN, len(md5_bytes), md5_bytes) io.setsockopt(socket.IPPROTO_TCP, TCP_MD5SIG, sockaddr + key) # else: # key = pack('2xH4x%ds' % TCP_MD5SIG_MAXKEYLEN, 0, b'') # io.setsockopt(socket.IPPROTO_TCP, TCP_MD5SIG, sockaddr + key) except socket.error as exc: if exc.errno != errno.ENOENT: raise MD5Error('This linux machine does not support TCP_MD5SIG, you can not use MD5 (%s)' % errstr(exc)) elif md5: raise MD5Error('ExaBGP has no MD5 support for %s' % platform_os)