def ip_vpn(tokeniser, afi, safi): action = OUT.ANNOUNCE if tokeniser.announce else OUT.WITHDRAW ipmask = prefix(tokeniser) nlri = IPVPN(afi, safi, action) nlri.cidr = CIDR(ipmask.pack(), ipmask.mask) change = Change(nlri, Attributes()) while True: command = tokeniser() if not command: break action = AnnounceVPN.action.get(command, '') if action == 'attribute-add': change.attributes.add(AnnounceVPN.known[command](tokeniser)) elif action == 'nlri-set': change.nlri.assign(AnnounceVPN.assign[command], AnnounceVPN.known[command](tokeniser)) elif action == 'nexthop-and-attribute': nexthop, attribute = AnnounceVPN.known[command](tokeniser) change.nlri.nexthop = nexthop change.attributes.add(attribute) else: raise ValueError('unknown command "%s"' % command) if not AnnounceVPN.check(change, afi): raise ValueError( 'invalid announcement (missing next-hop, label or rd ?)') return [change]
def ip_vpn(tokeniser, afi, safi): ipmask = prefix(tokeniser) nlri = IPVPN(afi, safi, OUT.ANNOUNCE) nlri.cidr = CIDR(ipmask.pack(), ipmask.mask) change = Change(nlri, Attributes()) while True: command = tokeniser() if not command: break action = ParseVPN.action.get(command, '') if action == 'attribute-add': change.attributes.add(ParseVPN.known[command](tokeniser)) elif action == 'nlri-set': change.nlri.assign(ParseVPN.assign[command], ParseVPN.known[command](tokeniser)) elif action == 'nexthop-and-attribute': nexthop, attribute = ParseVPN.known[command](tokeniser) change.nlri.nexthop = nexthop change.attributes.add(attribute) else: raise ValueError('route: unknown command "%s"' % command) return [change]
def ip_multicast(tokeniser, afi, safi): action = OUT.ANNOUNCE if tokeniser.announce else OUT.WITHDRAW ipmask = prefix(tokeniser) nlri = INET(afi, safi, action) nlri.cidr = CIDR(ipmask.pack(), ipmask.mask) change = Change(nlri, Attributes()) while True: command = tokeniser() if not command: break action = AnnounceIP.action.get(command, '') if action == 'attribute-add': change.attributes.add(AnnounceIP.known[command](tokeniser)) elif action == 'nlri-set': change.nlri.assign(AnnounceIP.assign[command], AnnounceIP.known[command](tokeniser)) elif action == 'nexthop-and-attribute': nexthop, attribute = AnnounceIP.known[command](tokeniser) change.nlri.nexthop = nexthop change.attributes.add(attribute) else: raise ValueError('unknown command "%s"' % command) return [change]
def unpack_nlri(cls, afi, safi, bgp, action, addpath): nlri = cls(afi, safi, action) if addpath: nlri.path_info = PathInfo(bgp[:4]) bgp = bgp[4:] mask = bgp[0] bgp = bgp[1:] _, rd_size = Family.size.get((afi, safi), (0, 0)) rd_mask = rd_size * 8 if safi.has_label(): labels = [] while mask - rd_mask >= 24: label = int(unpack('!L', bytes([0]) + bgp[:3])[0]) bgp = bgp[3:] mask -= 24 # 3 bytes # The last 4 bits are the bottom of Stack # The last bit is set for the last label labels.append(label >> 4) # This is a route withdrawal if label == 0x800000 and action == IN.WITHDRAWN: break # This is a next-hop if label == 0x000000: break if label & 1: break nlri.labels = Labels(labels) if rd_size: mask -= rd_mask # the route distinguisher rd = bgp[:rd_size] bgp = bgp[rd_size:] nlri.rd = RouteDistinguisher(rd) if mask < 0: raise Notify(3, 10, 'invalid length in NLRI prefix') if not bgp and mask: raise Notify( 3, 10, 'not enough data for the mask provided to decode the NLRI') size = CIDR.size(mask) if len(bgp) < size: raise Notify( 3, 10, 'could not decode route with family %s (AFI %d) %s (SAFI %d)' % (AFI(afi), int(afi), SAFI(safi), int(safi))) network, bgp = bgp[:size], bgp[size:] nlri.cidr = CIDR(network + bytes(IP.length(afi) - size), mask) return nlri, bgp
def new(cls, afi, safi, packed, mask, labels, rd, nexthop, action): instance = cls(afi, safi, OUT.ANNOUNCE) instance.cidr = CIDR(packed, mask) instance.labels = labels instance.rd = rd instance.nexthop = NextHop(IP.ntop(nexthop), nexthop) instance.action = action return instance
def new (cls, afi, safi, packed, mask, labels, rd, nexthop=None, action=OUT.UNSET): instance = cls(afi,safi,action) instance.cidr = CIDR(packed, mask) instance.labels = labels instance.rd = rd instance.nexthop = IP.create(nexthop) if nexthop else NoNextHop instance.action = action return instance
def unpack_nlri(cls, afi, safi, bgp, action, addpath): nlri = cls(afi, safi, action) if addpath: nlri.path_info = PathInfo(bgp[:4]) bgp = bgp[4:] mask = ord(bgp[0]) bgp = bgp[1:] if cls.has_label(): labels = [] while bgp and mask >= 8: label = int(unpack('!L', chr(0) + bgp[:3])[0]) bgp = bgp[3:] mask -= 24 # 3 bytes # The last 4 bits are the bottom of Stack # The last bit is set for the last label labels.append(label >> 4) # This is a route withdrawal if label == 0x800000 and action == IN.WITHDRAWN: break # This is a next-hop if label == 0x000000: break if label & 1: break nlri.labels = Labels(labels) if cls.has_rd(): mask -= 8 * 8 # the 8 bytes of the route distinguisher rd = bgp[:8] bgp = bgp[8:] nlri.rd = RouteDistinguisher(rd) if mask < 0: raise Notify(3, 10, 'invalid length in NLRI prefix') if not bgp and mask: raise Notify( 3, 10, 'not enough data for the mask provided to decode the NLRI') size = CIDR.size(mask) if len(bgp) < size: raise Notify( 3, 10, 'could not decode route with AFI %d sand SAFI %d' % (afi, safi)) network, bgp = bgp[:size], bgp[size:] padding = '\0' * (IP.length(afi) - size) nlri.cidr = CIDR(network + padding, mask) return nlri, bgp
def split(last): if Attribute.CODE.INTERNAL_SPLIT not in last.attributes: yield last return # ignore if the request is for an aggregate, or the same size mask = last.nlri.cidr.mask cut = last.attributes[Attribute.CODE.INTERNAL_SPLIT] if mask >= cut: yield last return # calculate the number of IP in the /<size> of the new route increment = pow(2, last.nlri.afi.mask() - cut) # how many new routes are we going to create from the initial one number = pow(2, cut - last.nlri.cidr.mask) # convert the IP into a integer/long ip = 0 for c in last.nlri.cidr.ton(): ip <<= 8 ip += c afi = last.nlri.afi safi = last.nlri.safi # Really ugly klass = last.nlri.__class__ nexthop = last.nlri.nexthop if safi.has_path(): path_info = last.nlri.path_info if safi.has_label(): labels = last.nlri.labels if safi.has_rd(): rd = last.nlri.rd # XXX: Looks weird to set and then set to None, check last.nlri.cidr.mask = cut last.nlri = None # generate the new routes for _ in range(number): # update ip to the next route, this recalculate the "ip" field of the Inet class nlri = klass(afi, safi, OUT.ANNOUNCE) nlri.cidr = CIDR(pack_int(afi, ip), cut) nlri.nexthop = nexthop # nexthop can be NextHopSelf if safi.has_path(): nlri.path_info = path_info if safi.has_label(): nlri.labels = labels if safi.has_rd(): nlri.rd = rd # next ip ip += increment yield Change(nlri, last.attributes)
def __init__(self, raw, netmask, offset): self.cidr = CIDR(raw, netmask) self.offset = offset
def __init__(self, raw, netmask): self.cidr = CIDR(raw, netmask)
def __init__(self, raw, netmask): self.nlri = CIDR(raw, netmask)