def pack(cls, data, capability): try: if capability.get('asn4'): return cls(value=data, hex_value=struct.pack('!I', data[0]) + IPAddress.pack(data[1])) else: return cls(value=data, hex_value=struct.pack('!H', data[0]) + IPAddress.pack(data[1])) except: raise BGPNotification(3, 5)
def unpack_peer_header(header_raw): header_dict = dict() header_dict['type'] = str(PeerType(ord(header_raw[0:1]))) header_dict['flag'] = PeerFlag(ord(header_raw[1:2])).dict() header_dict['distinguisher'] = struct.unpack('!2I', header_raw[2:10])[0] if header_dict['flag']['V']: header_dict['addr'] = IPAddress.unpack(header_raw[10:26]) else: header_dict['addr'] = IPAddress.unpack(header_raw[22:26]) header_dict['asn'] = struct.unpack('!I', header_raw[26:30])[0] header_dict['bgp-id'] = IPAddress.unpack(header_raw[30:34]) header_dict['time'] = struct.unpack('!II', header_raw[34:42]) return header_dict
def unpack(cls, data, length, capability): open_msg = dict() try: open_msg['version'], open_msg['asn'], open_msg['hold-time'] = struct.unpack('!BHH', data[:5]) except: raise BGPNotification(1, 2) if open_msg['version'] != cls.VERSION: # BGP-4 raise BGPNotification(2, 1) if open_msg['asn'] == 0: raise BGPNotification(2, 2) if isinstance(open_msg['asn'], float): tmp = str(open_msg['asn']).split('.') open_msg['asn'] = 65536 * (int(tmp[0])) + int(tmp[1]) try: open_msg['bgp-id'] = IPAddress.unpack(data[5:9]) except: raise BGPNotification(2, 3) opt_para_len = struct.unpack('!B', data[9:10]) if opt_para_len: open_msg['capabilities'] = Capabilities.unpack(data[10:]).value return cls(value=open_msg, length=length)
def unpack(cls, data, capability): """ Parse Aggregator attributes. :param data: raw binary data """ try: if not capability.get('asn4'): asn = struct.unpack('!H', data[:2])[0] aggregator = IPAddress.unpack(data[2:]) else: asn = struct.unpack('!I', data[:4])[0] aggregator = IPAddress.unpack(data[4:]) except Exception: raise BGPNotification(3, 5) return cls(value=[asn, aggregator])
def unpack(cls, data, capability): """ Parse originator id :param data: """ if len(data) != 4: raise BGPNotification(3, 5) return cls(value=IPAddress.unpack(data))
def pack(cls, data, capability): try: return cls(value=data, hex_value=b''.join([ IPAddress.pack(cluster_id) for cluster_id in data ])) except: raise BGPNotification(3, 5)
def pack(cls, data, capability): capabilities = Capabilities.pack(data.get('capabilities')).hex_value open_header = struct.pack( '!BHH', data.get('version') or cls.VERSION, data.get('asn'), data.get('hold-time') ) + IPAddress.pack(data.get('bgp-id')) + struct.pack('!B', len(capabilities)) return cls(value=data, hex_value=open_header + capabilities)
def unpack(cls, data, capability): """ Parse BGP nexthop. :param data: raw binary data """ if len(data) % 4 == 0: next_hop = IPAddress.unpack(data) return cls(value=next_hop) else: raise BGPNotification(3, 5)
def unpack(cls, data, capability): """ Parse culster list :param data """ cluster_list = [] if len(data) % 4 != 0: raise BGPNotification(3, 5) while data: cluster_list.append(IPAddress.unpack(data[0:4])) data = data[4:] return cls(value=cluster_list)
def pack_nlri(nlri, add_path=False): """ constructs NLRI prefix list :param nlri: prefix list :param add_path: support add path or not """ nlri_raw_hex = b'' for prefix in nlri: if add_path and isinstance(prefix, dict): path_id = prefix.get('path_id') prefix = prefix.get('prefix') nlri_raw_hex += struct.pack('!I', path_id) ip, masklen = prefix.split('/') ip_hex = IPAddress.pack(ip) masklen = int(masklen) if 16 < masklen <= 24: ip_hex = ip_hex[0:3] elif 8 < masklen <= 16: ip_hex = ip_hex[0:2] elif masklen <= 8: ip_hex = ip_hex[0:1] nlri_raw_hex += struct.pack('!B', masklen) + ip_hex return nlri_raw_hex
def pack(cls, data, capability): try: return cls(data, IPAddress.pack(data)) except: raise BGPNotification(3, 5)