Beispiel #1
0
    def test3_IPVPNHashEqual(self):
        '''
        Two VPN NLRI distinct only by their *action* should
        hash to the same value, and be equal
        '''

        packedPrefix, mask = prefixToPackedIPMask("1.1.1.1/32")

        nlri1 = IPVPN.new(AFI(AFI.ipv4), SAFI(SAFI.mpls_vpn),
                          packedPrefix, mask,
                          Labels([42], True),
                          RouteDistinguisher.fromElements("42.42.42.42", 5),
                          IP.pton("45.45.45.45"),
                          OUT.ANNOUNCE)

        nlri2 = IPVPN.new(AFI(AFI.ipv4), SAFI(SAFI.mpls_vpn),
                          packedPrefix, mask,
                          Labels([42], True),
                          RouteDistinguisher.fromElements("42.42.42.42", 5),
                          IP.pton("45.45.45.45"),
                          OUT.WITHDRAW)

        self.assertEqual(hash(nlri1), hash(nlri2))
        self.assertTrue(nlri1.eq(nlri2))
        self.assertEqual(nlri1, nlri2)
Beispiel #2
0
    def test101_EVPNHashEqual_somefieldsvary(self):
        '''
        Two EVPN MAC NLRIs differing by their ESI or label or RD,
        or nexthop, but otherwise identical should hash to the same value,
        and be equal
        '''

        nlri0 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42",
                                                        5), ESI(),
                        EthernetTag(111), MAC("01:02:03:04:05:06"), 6 * 8,
                        Labels([42], True), IP.create("1.1.1.1"))

        # Esi
        nlri1 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5),
                        ESI(['1' for _ in range(0, 10)]), EthernetTag(111),
                        MAC("01:02:03:04:05:06"), 6 * 8, Labels([42], True),
                        IP.create("1.1.1.1"))

        # label
        nlri2 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42",
                                                        5), ESI(),
                        EthernetTag(111), MAC("01:02:03:04:05:06"), 6 * 8,
                        Labels([4444], True), IP.create("1.1.1.1"))

        # IP: different IPs, but same MACs: different route
        nlri3 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42",
                                                        5), ESI(),
                        EthernetTag(111), MAC("01:02:03:04:05:06"), 6 * 8,
                        Labels([42], True), IP.create("2.2.2.2"))

        # with a next hop...
        nlri4 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42",
                                                        5), ESI(),
                        EthernetTag(111), MAC("01:02:03:04:05:06"), 6 * 8,
                        Labels([42], True), IP.create("1.1.1.1"),
                        IP.pton("10.10.10.10"))
        nlri5 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42",
                                                        5), ESI(),
                        EthernetTag(111), MAC("01:02:03:04:05:06"), 6 * 8,
                        Labels([42], True), IP.create("1.1.1.1"),
                        IP.pton("11.11.11.11"))

        self.assertEqual(hash(nlri0), hash(nlri1))
        self.assertEqual(hash(nlri0), hash(nlri2))
        self.assertEqual(hash(nlri0), hash(nlri4))
        self.assertEqual(nlri0, nlri1)
        self.assertEqual(nlri0, nlri2)
        self.assertEqual(nlri0, nlri4)
        self.assertEqual(nlri1, nlri2)
        self.assertEqual(nlri1, nlri4)
        self.assertEqual(nlri2, nlri4)
        self.assertEqual(nlri4, nlri5)

        self.assertNotEqual(hash(nlri0), hash(nlri3))
        self.assertNotEqual(nlri0, nlri3)
        self.assertNotEqual(nlri1, nlri3)
        self.assertNotEqual(nlri2, nlri3)
        self.assertNotEqual(nlri3, nlri4)
Beispiel #3
0
def destination(tokeniser):
    data = tokeniser()
    if data.count('.') == 3 and data.count(':') == 0:
        ip, netmask = data.split('/')
        raw = b''.join(bytes([int(_)]) for _ in ip.split('.'))
        yield Flow4Destination(raw, int(netmask))
    elif data.count('/') == 1:
        ip, netmask = data.split('/')
        offset = 0
        yield Flow6Destination(IP.pton(ip), int(netmask), int(offset))
    else:
        ip, netmask, offset = data.split('/')
        yield Flow6Destination(IP.pton(ip), int(netmask), int(offset))
Beispiel #4
0
def source(tokeniser):
    data = tokeniser()
    if data.count('.') == 3 and data.count(':') == 0:
        ip, netmask = data.split('/')
        raw = ''.join(chr(int(_)) for _ in ip.split('.'))
        yield Flow4Source(raw, int(netmask))
    elif data.count('/') == 1:
        ip, netmask = data.split('/')
        offset = 0
        yield Flow6Source(IP.pton(ip), int(netmask), int(offset))
    else:
        ip, netmask, offset = data.split('/')
        yield Flow6Source(IP.pton(ip), int(netmask), int(offset))
Beispiel #5
0
def destination(tokeniser):
    data = tokeniser()
    if data.count('.') == 3 and data.count(':') == 0:
        ip, netmask = data.split('/')
        raw = concat_bytes_i(character(int(_)) for _ in ip.split('.'))
        yield Flow4Destination(raw, int(netmask))
    elif data.count('/') == 1:
        ip, netmask = data.split('/')
        offset = 0
        yield Flow6Destination(IP.pton(ip), int(netmask), int(offset))
    else:
        ip, netmask, offset = data.split('/')
        yield Flow6Destination(IP.pton(ip), int(netmask), int(offset))
Beispiel #6
0
def destination (tokeniser):
	data = tokeniser()
	if data.count('.') == 3 and data.count(':') == 0:
		ip,netmask = data.split('/')
		raw = concat_bytes_i(character(int(_)) for _ in ip.split('.'))
		yield Flow4Destination(raw,int(netmask))
	elif data.count('/') == 1:
		ip,netmask = data.split('/')
		offset = 0
		yield Flow6Destination(IP.pton(ip),int(netmask),int(offset))
	else:
		ip,netmask,offset = data.split('/')
		yield Flow6Destination(IP.pton(ip),int(netmask),int(offset))
Beispiel #7
0
 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
Beispiel #8
0
    def test200_IPVPNCreatePackUnpack(self):
        '''Test pack/unpack for IPVPN routes'''
        nlri = IPVPN.new(
            AFI.ipv4,
            SAFI.mpls_vpn,
            IP.pton("1.2.3.0"),
            24,
            Labels([42], True),
            RouteDistinguisher.fromElements("42.42.42.42", 5),
        )

        packed = nlri.pack()
        unpacked, leftover = IPVPN.unpack_nlri(AFI.ipv4, SAFI.mpls_vpn, packed,
                                               OUT.UNSET, None)

        self.assertEqual(0, len(leftover))

        # TODO: compare packed with a reference encoding verified
        # as conformant with RFC4364

        self.assertTrue(isinstance(unpacked, IPVPN))

        self.assertEqual("1.2.3.0/24", unpacked.cidr.prefix())
        self.assertEqual(1, len(unpacked.labels.labels))
        self.assertEqual(42, unpacked.labels.labels[0])
        self.assertEqual("42.42.42.42:5", unpacked.rd._str())
Beispiel #9
0
	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
Beispiel #10
0
 def pack(self):
     t = pack('!B', self.TLV)
     l = pack('!H', self.LENGTH)
     r0 = pack('!B', 0)
     r1 = pack('!H', 0)
     val = IP.pton(self.v6sid)
     return concat_bytes(t, l, r0, r1, val)
Beispiel #11
0
	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
Beispiel #12
0
	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
Beispiel #13
0
	def pack (self):
		return concat_bytes(
			pack('!B', self.TLV),
			pack('!H', self.LENGTH),
			pack('!B', 0),
			pack('!H', 0),
			IP.pton(self.v6sid)
		)
Beispiel #14
0
def source (tokeniser):
	data = tokeniser()
	if data.count('/') == 1:
		ip,netmask = data.split('/')
		raw = ''.join(chr(int(_)) for _ in ip.split('.'))
		yield Flow4Source(raw,int(netmask))
	else:
		ip,netmask,offset = data.split('/')
		yield Flow6Source(IP.pton(ip),int(netmask),int(offset))
Beispiel #15
0
def destination(tokeniser):
    data = tokeniser()
    if data.count('/') == 1:
        ip, netmask = data.split('/')
        raw = ''.join(chr(int(_)) for _ in ip.split('.'))
        yield Flow4Destination(raw, int(netmask))
        return
    else:
        ip, netmask, offset = data.split('/')
        yield Flow6Destination(IP.pton(ip), int(netmask), int(offset))
Beispiel #16
0
 def pack(self):
     return (
         pack('!B', self.TLV)
         + pack('!H', self.LENGTH)
         + pack('!B', 0)
         + IP.pton(self.l3vpnsid)
         + pack('!B', 0)
         + pack('!H', 0xFFFF)
         + pack('!B', 0)
     )
Beispiel #17
0
    def test0_IPVPNHashEqual(self):
        '''
        Two indistinct VPN NLRIs should
        hash to the same value, and be equal
        '''
        rd = RouteDistinguisher.fromElements("42.42.42.42", 5)

        packedPrefix, mask = prefixToPackedIPMask("1.1.1.1/32")

        nlri1 = IPVPN.new(AFI(AFI.ipv4), SAFI(SAFI.mpls_vpn),
                          packedPrefix, mask, Labels([42], True), rd,
                          IP.pton("45.45.45.45"), OUT.ANNOUNCE)

        nlri2 = IPVPN.new(AFI(AFI.ipv4), SAFI(SAFI.mpls_vpn),
                          packedPrefix, mask, Labels([42], True), rd,
                          IP.pton("45.45.45.45"), OUT.ANNOUNCE)

        self.assertEqual(hash(nlri1), hash(nlri2))
        self.assertEqual(nlri1, nlri2)
Beispiel #18
0
def prefix(tokeniser):
    # XXX: could raise
    ip = tokeniser()
    try:
        ip, mask = ip.split('/')
        mask = int(mask)
    except ValueError:
        mask = 32

    return Range(ip, IP.pton(ip), mask)
Beispiel #19
0
	def pack (self):
		return concat_bytes(
			pack('!B', self.TLV),
			pack('!H', self.LENGTH),
			pack('!B', 0),
			IP.pton(self.l3vpnsid),
			pack('!B', 0),
			pack('!H', 0xffff),
			pack('!B', 0),
		)
Beispiel #20
0
def prefix(tokeniser):
    # XXX: could raise
    ip = tokeniser()
    try:
        ip, mask = ip.split("/")
        mask = int(mask)
    except ValueError:
        mask = 32

    return Range(ip, IP.pton(ip), mask)
Beispiel #21
0
def destination (tokeniser):
	data = tokeniser()
	if data.count('/') == 1:
		ip,netmask = data.split('/')
		raw = ''.join(chr(int(_)) for _ in ip.split('.'))
		yield Flow4Destination(raw,int(netmask))
		return
	else:
		ip,netmask,offset = data.split('/')
		yield Flow6Destination(IP.pton(ip),int(netmask),int(offset))
Beispiel #22
0
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)
Beispiel #23
0
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)
Beispiel #24
0
    def test2_IPVPNHashEqual(self):
        '''
        Two VPN NLRI distinct only by their *nexthop* should
        hash to the same value, and be equal
        '''
        packedPrefix, mask = prefixToPackedIPMask("1.1.1.1/32")

        nlri1 = IPVPN.new(AFI(AFI.ipv4), SAFI(SAFI.mpls_vpn), packedPrefix,
                          mask, Labels([42], True),
                          RouteDistinguisher.fromElements("42.42.42.42", 5),
                          IP.pton("45.45.45.45"), OUT.ANNOUNCE)

        nlri2 = IPVPN.new(AFI(AFI.ipv4), SAFI(SAFI.mpls_vpn), packedPrefix,
                          mask, Labels([42], True),
                          RouteDistinguisher.fromElements("42.42.42.42", 5),
                          IP.pton("77.77.77.77"), OUT.ANNOUNCE)

        self.assertEqual(hash(nlri1), hash(nlri2))
        self.assertTrue(nlri1.eq(nlri2))
        self.assertNotEqual(nlri1, nlri2)
Beispiel #25
0
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()
	)
Beispiel #26
0
    def test0_IPVPNHashEqual(self):
        '''
        Two indistinct VPN NLRIs should
        hash to the same value, and be equal
        '''
        rd = RouteDistinguisher.fromElements("42.42.42.42", 5)

        packedPrefix, mask = prefixToPackedIPMask("1.1.1.1/32")

        nlri1 = IPVPN.new(AFI(AFI.ipv4), SAFI(SAFI.mpls_vpn),
                          packedPrefix, mask,
                          Labels([42], True), rd,
                          IP.pton("45.45.45.45"),
                          OUT.ANNOUNCE)

        nlri2 = IPVPN.new(AFI(AFI.ipv4), SAFI(SAFI.mpls_vpn),
                          packedPrefix, mask,
                          Labels([42], True), rd,
                          IP.pton("45.45.45.45"),
                          OUT.ANNOUNCE)

        self.assertEqual(hash(nlri1), hash(nlri2))
        self.assertEqual(nlri1, nlri2)
Beispiel #27
0
    def test2_MPLSVPNHashEqual(self):
        '''
        Two VPN NLRI distinct only by their *nexthop* should
        hash to the same value, and be equal
        '''
        packedPrefix, mask = prefixToPackedIPMask("1.1.1.1/32")

        nlri1 = MPLSVPN(AFI(AFI.ipv4), SAFI(SAFI.mpls_vpn),
                        packedPrefix, mask,
                        Labels([42], True),
                        RouteDistinguisher.fromElements("42.42.42.42", 5),
                        IP.pton("45.45.45.45"),
                        OUT.ANNOUNCE)

        nlri2 = MPLSVPN(AFI(AFI.ipv4), SAFI(SAFI.mpls_vpn),
                        packedPrefix, mask,
                        Labels([42], True),
                        RouteDistinguisher.fromElements("42.42.42.42", 5),
                        IP.pton("77.77.77.77"),
                        OUT.ANNOUNCE)

        self.assertEqual(hash(nlri1), hash(nlri2))
        self.assertEqual(nlri1, nlri2)
Beispiel #28
0
	def source (self, scope, name, command, tokens):
		try:
			data = tokens.pop(0)
			if data.count('/') == 1:
				ip,netmask = data.split('/')
				raw = ''.join(chr(int(_)) for _ in ip.split('.'))

				if not scope[-1]['announce'][-1].nlri.add(Flow4Source(raw,int(netmask))):
					return self.error.set('Flow can only have one destination')

			else:
				ip,netmask,offset = data.split('/')
				change = scope[-1]['announce'][-1]
				change.nlri.afi = AFI(AFI.ipv6)
				if not change.nlri.add(Flow6Source(IP.pton(ip),int(netmask),int(offset))):
					return self.error.set('Flow can only have one destination')
			return True

		except (IndexError,ValueError):
			return self.error.set(self.syntax)
Beispiel #29
0
    def test200_IPVPNCreatePackUnpack(self):
        '''Test pack/unpack for IPVPN routes'''
        nlri = IPVPN.new(AFI(AFI.ipv4), SAFI(SAFI.mpls_vpn),
                         IP.pton("1.2.3.0"), 24,
                         Labels([42], True), 
                         RouteDistinguisher.fromElements("42.42.42.42", 5))

        packed = nlri.pack()
        unpacked,leftover = IPVPN.unpack_nlri(AFI(AFI.ipv4), SAFI(SAFI.mpls_vpn),
                                              packed, OUT.UNSET, None)

        self.assertEqual(0, len(leftover))

        # TODO: compare packed with a reference encoding verified 
        # as conformant with RFC4364

        self.assertTrue(isinstance(unpacked, IPVPN))

        self.assertEqual("1.2.3.0/24", unpacked.cidr.prefix())
        self.assertEqual(1, len(unpacked.labels.labels))
        self.assertEqual(42, unpacked.labels.labels[0])
        self.assertEqual("42.42.42.42:5", unpacked.rd._str())
Beispiel #30
0
    def source(self, scope, name, command, tokens):
        try:
            data = tokens.pop(0)
            if data.count('/') == 1:
                ip, netmask = data.split('/')
                raw = ''.join(chr(int(_)) for _ in ip.split('.'))

                if not scope[-1]['announce'][-1].nlri.add(
                        Flow4Source(raw, int(netmask))):
                    return self.error.set('Flow can only have one destination')

            else:
                ip, netmask, offset = data.split('/')
                change = scope[-1]['announce'][-1]
                change.nlri.afi = AFI(AFI.ipv6)
                if not change.nlri.add(
                        Flow6Source(IP.pton(ip), int(netmask), int(offset))):
                    return self.error.set('Flow can only have one destination')
            return True

        except (IndexError, ValueError):
            return self.error.set(self.syntax)
Beispiel #31
0
    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
Beispiel #32
0
def prefixToPackedIPMask(prefix):
    ipString, mask = prefix.split("/")
    return (IP.pton(ipString), int(mask))
Beispiel #33
0
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)
 def pack(self):
     return concat_bytes(pack('!B', self.TLV), pack('!H', self.LENGTH),
                         pack('!B', 0), pack('!H', 0), IP.pton(self.v6sid))
Beispiel #35
0
def prefixToPackedIPMask(prefix):
    ipString, mask = prefix.split("/")
    return (IP.pton(ipString), int(mask))
Beispiel #36
0
    def test101_EVPNHashEqual_somefieldsvary(self):
        '''
        Two EVPN MAC NLRIs differing by their ESI or label or RD,
        or nexthop, but otherwise identical should hash to the same value,
        and be equal
        '''

        nlri0 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5),
                        ESI(0),
                        EthernetTag(111),
                        MAC("01:02:03:04:05:06"), 6*8,
                        Labels([42], True),
                        IP.create("1.1.1.1"))

        # Esi
        nlri1 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5),
                        ESI(1),
                        EthernetTag(111),
                        MAC("01:02:03:04:05:06"), 6*8,
                        Labels([42], True),
                        IP.create("1.1.1.1"))

        # label
        nlri2 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5),
                        ESI(0),
                        EthernetTag(111),
                        MAC("01:02:03:04:05:06"), 6*8,
                        Labels([4444], True),
                        IP.create("1.1.1.1"))

        # IP: different IPs, but same MACs: different route
        nlri3 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5),
                        ESI(0),
                        EthernetTag(111),
                        MAC("01:02:03:04:05:06"), 6*8,
                        Labels([42], True),
                        IP.create("2.2.2.2"))

        # with a next hop...
        nlri4 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5),
                        ESI(0),
                        EthernetTag(111),
                        MAC("01:02:03:04:05:06"), 6*8,
                        Labels([42], True),
                        IP.create("1.1.1.1"),
                        IP.pton("10.10.10.10"))
        nlri5 = EVPNMAC(RouteDistinguisher.fromElements("42.42.42.42", 5),
                        ESI(0),
                        EthernetTag(111),
                        MAC("01:02:03:04:05:06"), 6*8,
                        Labels([42], True),
                        IP.create("1.1.1.1"),
                        IP.pton("11.11.11.11"))

        self.assertEqual(hash(nlri0), hash(nlri1))
        self.assertEqual(hash(nlri0), hash(nlri2))
        self.assertEqual(hash(nlri0), hash(nlri4))
        self.assertEqual(nlri0, nlri1)
        self.assertEqual(nlri0, nlri2)
        self.assertEqual(nlri0, nlri4)
        self.assertEqual(nlri1, nlri2)
        self.assertEqual(nlri1, nlri4)
        self.assertEqual(nlri2, nlri4)
        self.assertEqual(nlri4, nlri5)

        self.assertNotEqual(hash(nlri0), hash(nlri3))
        self.assertNotEqual(nlri0, nlri3)
        self.assertNotEqual(nlri1, nlri3)
        self.assertNotEqual(nlri2, nlri3)
        self.assertNotEqual(nlri3, nlri4)
Beispiel #37
0
 def pack(self):
     return pack('!B', self.TLV) + pack('!H', self.LENGTH) + pack(
         '!B', 0) + pack('!H', 0) + IP.pton(self.v6sid)
Beispiel #38
0
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)