def __init__(self,afi,safi,packed,mask,nexthop,action): self.labels = Labels.NOLABEL self.rd = RouteDistinguisher.NORD self.nexthop = IP.unpack(nexthop) if nexthop else NoIP self.action = action NLRI.__init__(self,afi,safi) CIDR.__init__(self,packed,mask)
def __init__ (self, afi, safi, packed, mask, nexthop, action,path=None): self.path_info = PathInfo.NOPATH if path is None else path self.labels = Labels.NOLABEL self.rd = RouteDistinguisher.NORD self.nexthop = IP.unpack(nexthop) if nexthop else NoNextHop self.action = action NLRI.__init__(self,afi,safi) CIDR.__init__(self,packed,mask)
def pack (self, addpath=None): if not self.has_label(): if addpath: return self.path_info.pack() + CIDR.pack(self) return CIDR.pack(self) length = len(self.labels)*8 + len(self.rd)*8 + self.mask if addpath: return self.path_info.pack() + chr(length) + self.labels.pack() + self.rd.pack() + CIDR.packed_ip(self) return chr(length) + self.labels.pack() + self.rd.pack() + CIDR.packed_ip(self)
def __eq__ (self, other): return \ NLRI.__eq__(self, other) and \ CIDR.__eq__(self, other) and \ self.path_info == other.path_info and \ self.labels == other.labels and \ self.rd == other.rd and \ self.nexthop == other.nexthop and \ self.action == other.action
def __eq__(self, other): # Note: BaGPipe needs an advertise and a withdraw for the same # RD:prefix to result in objects that are equal for Python, # this is why the test below does not look at self.labels nor # self.nexthop or self.action return \ NLRI.__eq__(self, other) and \ CIDR.__eq__(self, other) and \ self.path_info == other.path_info and \ self.rd == other.rd
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 = ordinal(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',character(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 AFI %d and SAFI %d' % (afi,safi)) network,bgp = bgp[:size],bgp[size:] nlri.cidr = CIDR(network + padding(IP.length(afi)-size),mask) return nlri,bgp
def _nlri (afi, safi, bgp, action, addpath): labels = [] rd = '' if addpath: path_identifier = bgp[:4] bgp = bgp[4:] else: path_identifier = None mask = ord(bgp[0]) bgp = bgp[1:] if SAFI(safi).has_label(): 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 if SAFI(safi).has_rd(): mask -= 8*8 # the 8 bytes of the route distinguisher rd = bgp[:8] bgp = bgp[8:] 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) prefix = network + padding return labels,rd,path_identifier,mask,size,prefix,bgp
class IPrefix4 (IPrefix,IComponent,IPv4): # not used, just present for simplying the nlri generation operations = 0x0 # NAME def __init__ (self,raw,netmask): self.nlri = CIDR(raw,netmask) def pack (self): raw = self.nlri.pack() return "%s%s" % (chr(self.ID),raw) def __str__ (self): return str(self.nlri)
class IPrefix6 (IPrefix,IComponent,IPv6): # not used, just present for simplying the nlri generation operations = 0x0 # NAME def __init__ (self,raw,netmask,offset): self.nlri = CIDR(raw,netmask) self.offset = offset def pack (self): raw = self.nlri.packed_ip() return "%s%s%s%s" % (chr(self.ID),chr(self.nlri.mask),chr(self.offset),raw) def __str__ (self): return "%s/%s" % (self.nlri,self.offset)
def _nlri(afi, safi, bgp, action): labels = [] rd = "" mask = ord(bgp[0]) bgp = bgp[1:] if SAFI(safi).has_label(): 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 if SAFI(safi).has_rd(): mask -= 8 * 8 # the 8 bytes of the route distinguisher rd = bgp[:8] bgp = bgp[8:] 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) prefix = network + padding return labels, rd, mask, size, prefix, bgp
class IPrefix4 (IPrefix,IComponent,IPv4): # Must be defined in subclasses CODE = -1 NAME = '' # not used, just present for simplying the nlri generation operations = 0x0 def __init__ (self, raw, netmask): self.nlri = CIDR(raw,netmask) def pack (self): raw = self.nlri.pack() # ID is defined in subclasses return "%s%s" % (chr(self.ID),raw) # pylint: disable=E1101 def __str__ (self): return str(self.nlri)
class IPrefix6 (IPrefix,IComponent,IPv6): # Must be defined in subclasses CODE = -1 NAME = '' # not used, just present for simplying the nlri generation operations = 0x0 def __init__ (self, raw, netmask, offset): self.nlri = CIDR(raw,netmask) self.offset = offset def pack (self): # ID is defined in subclasses return "%s%s%s%s" % (chr(self.ID),chr(self.nlri.mask),chr(self.offset),self.nlri.classless()) # pylint: disable=E1101 def __str__ (self): return "%s/%s" % (self.nlri,self.offset)
class IPrefix4 (IPrefix,IComponent,IPv4): # Must be defined in subclasses CODE = -1 NAME = '' # not used, just present for simplying the nlri generation operations = 0x0 def __init__ (self, raw, netmask): self.cidr = CIDR(raw,netmask) def pack (self): raw = self.cidr.pack_nlri() # ID is defined in subclasses return "%s%s" % (chr(self.ID),raw) # pylint: disable=E1101 def __str__ (self): return str(self.cidr) @classmethod def make (cls, bgp): prefix,mask = CIDR.decode(AFI.ipv4,bgp) return cls(prefix,mask), bgp[CIDR.size(mask)+1:]
class IPrefix6 (IPrefix,IComponent,IPv6): # Must be defined in subclasses CODE = -1 NAME = '' # not used, just present for simplying the nlri generation operations = 0x0 def __init__ (self, raw, netmask, offset): self.cidr = CIDR(raw,netmask) self.offset = offset def pack (self): # ID is defined in subclasses return "%s%s%s%s" % (chr(self.ID),chr(self.cidr.mask),chr(self.offset),self.cidr.pack_ip()) # pylint: disable=E1101 def __str__ (self): return "%s/%s" % (self.cidr,self.offset) @classmethod def make (cls, bgp): offset = ord(bgp[1]) prefix,mask = CIDR.decode(AFI.ipv6,bgp[0]+bgp[2:]) return cls(prefix,mask,offset), bgp[CIDR.size(mask)+2:]
def __init__ (self, afi, safi, packed, mask, nexthop, action,path=None): self.path_info = PathInfo.NOPATH if path is None else path self.nexthop = IP.unpack(nexthop) if nexthop else NoIP NLRI.__init__(self,afi,safi) CIDR.__init__(self,packed,mask) self.action = action
def __init__ (self, raw, netmask): self.cidr = CIDR(raw,netmask)
def make (cls, bgp): prefix,mask = CIDR.decode(AFI.ipv4,bgp) return cls(prefix,mask), bgp[CIDR.size(mask)+1:]
def make(cls, bgp): offset = ordinal(bgp[1]) prefix, mask = CIDR.decode(AFI.ipv6, bgp[0:1] + bgp[2:]) return cls(prefix, mask, offset), bgp[CIDR.size(mask) + 2:]
def __init__ (self, afi, safi, packed, mask, nexthop, action): self.path_info = PathInfo.NOPATH self.nexthop = IP.unpack(nexthop) if nexthop else NoNextHop NLRI.__init__(self,afi,safi) CIDR.__init__(self,packed,mask) self.action = action
def __init__(self, raw, netmask, offset): self.cidr = CIDR(raw, netmask) self.offset = offset
def pack (self, addpath): return self.path_info.pack() + CIDR.pack(self) if addpath else CIDR.pack(self)
def make (cls, bgp): offset = ord(bgp[1]) prefix,mask = CIDR.decode(AFI.ipv6,bgp[0]+bgp[2:]) return cls(prefix,mask,offset), bgp[CIDR.size(mask)+2:]
def prefix (self): return "%s/%s%s" % (CIDR.getip(self),self.mask,str(self.path_info) if self.path_info is not PathInfo.NOPATH else '')
def __len__ (self): return CIDR.__len__(self) + len(self.labels) + len(self.rd)
def __init__ (self,raw,netmask): self.nlri = CIDR(raw,netmask)
def make(cls, bgp): prefix, mask = CIDR.decode(AFI.ipv4, bgp) return cls(prefix, mask), bgp[CIDR.size(mask) + 1:]
def __init__ (self,raw,netmask,offset): self.nlri = CIDR(raw,netmask) self.offset = offset
def __len__ (self): return CIDR.__len__(self) + len(self.path_info)
def pack (self, addpath): if addpath or True: return self.path_info.pack() + CIDR.pack(self) if addpath else CIDR.pack(self) return CIDR.pack(self) if addpath else CIDR.pack(self)
def __eq__ (self, other): return \ NLRI.__eq__(self, other) and \ CIDR.__eq__(self, other) and \ self.path_info == other.path_info and \ self.nexthop == other.nexthop
def json (self): return '"%s/%s": { %s }' % (CIDR.getip(self),self.mask,self.path_info.json())
def __init__(self, raw, netmask): self.cidr = CIDR(raw, netmask)