def unpack (cls, data, negotiated): nlris = [] # -- Reading AFI/SAFI afi,safi = unpack('!HB',data[:3]) offset = 3 # we do not want to accept unknown families if negotiated and (afi,safi) not in negotiated.families: raise Notify(3,0,'presented a non-negotiated family %d/%d' % (afi,safi)) # -- Reading length of next-hop len_nh = ord_(data[offset]) offset += 1 rd = 0 # check next-hop size if afi == AFI.ipv4: if safi in (SAFI.unicast,SAFI.multicast): if len_nh != 4: raise Notify(3,0,'invalid ipv4 unicast/multicast next-hop length %d expected 4' % len_nh) elif safi in (SAFI.mpls_vpn,): if len_nh != 12: raise Notify(3,0,'invalid ipv4 mpls_vpn next-hop length %d expected 12' % len_nh) rd = 8 elif safi in (SAFI.flow_ip,): if len_nh not in (0,4): raise Notify(3,0,'invalid ipv4 flow_ip next-hop length %d expected 4' % len_nh) elif safi in (SAFI.flow_vpn,): if len_nh not in (0,4): raise Notify(3,0,'invalid ipv4 flow_vpn next-hop length %d expected 4' % len_nh) elif safi in (SAFI.rtc,): if len_nh not in (4,16): raise Notify(3,0,'invalid ipv4 rtc next-hop length %d expected 4' % len_nh) elif afi == AFI.ipv6: if safi in (SAFI.unicast,): if len_nh not in (16,32): raise Notify(3,0,'invalid ipv6 unicast next-hop length %d expected 16 or 32' % len_nh) elif safi in (SAFI.mpls_vpn,): if len_nh not in (24,40): raise Notify(3,0,'invalid ipv6 mpls_vpn next-hop length %d expected 24 or 40' % len_nh) rd = 8 elif safi in (SAFI.flow_ip,): if len_nh not in (0,16,32): raise Notify(3,0,'invalid ipv6 flow_ip next-hop length %d expected 0, 16 or 32' % len_nh) elif safi in (SAFI.flow_vpn,): if len_nh not in (0,16,32): raise Notify(3,0,'invalid ipv6 flow_vpn next-hop length %d expected 0, 16 or 32' % len_nh) elif afi == AFI.l2vpn: if len_nh != 4: Notify(3,0,'invalid l2vpn next-hop length %d expected 4' % len_nh) elif afi == AFI.bgpls: if len_nh != 4: Notify(3,0,'invalid bgpls next-hop length %d expected 4' % len_nh) size = len_nh - rd # XXX: FIXME: GET IT FROM CACHE HERE ? nhs = data[offset+rd:offset+rd+size] nexthops = [nhs[pos:pos+16] for pos in range(0,len(nhs),16)] # chech the RD is well zero if rd and sum([int(ord_(_)) for _ in data[offset:8]]) != 0: raise Notify(3,0,"MP_REACH_NLRI next-hop's route-distinguisher must be zero") offset += len_nh # Skip a reserved bit as somone had to bug us ! reserved = ord_(data[offset]) offset += 1 if reserved != 0: raise Notify(3,0,'the reserved bit of MP_REACH_NLRI is not zero') # Is the peer going to send us some Path Information with the route (AddPath) addpath = negotiated.addpath.receive(afi,safi) # Reading the NLRIs data = data[offset:] if not data: raise Notify(3,0,'No data to decode in an MPREACHNLRI but it is not an EOR %d/%d' % (afi,safi)) while data: if nexthops: for nexthop in nexthops: nlri,left = NLRI.unpack_nlri(afi,safi,data,IN.ANNOUNCED,addpath) nlri.nexthop = NextHop.unpack(nexthop) nlris.append(nlri) else: nlri,left = NLRI.unpack_nlri(afi,safi,data,IN.ANNOUNCED,addpath) nlris.append(nlri) if left == data: raise RuntimeError("sub-calls should consume data") # logger.parser(LazyFormat("parsed announce mp nlri %s payload " % nlri,data[:length])) data = left return cls(afi,safi,nlris)
def unpack(cls, data, negotiated): nlris = [] # -- Reading AFI/SAFI _afi, _safi = unpack('!HB', data[:3]) afi, safi = AFI.create(_afi), SAFI.create(_safi) offset = 3 nh_afi = afi # we do not want to accept unknown families if negotiated and (afi, safi) not in negotiated.families: raise Notify( 3, 0, 'presented a non-negotiated family %s/%s' % (afi, safi)) # -- Reading length of next-hop len_nh = ordinal(data[offset]) offset += 1 if (afi, safi) not in Family.size: raise Notify(3, 0, 'unsupported %s %s' % (afi, safi)) length, rd = Family.size[(afi, safi)] if negotiated.nexthop: if len_nh in (16, 32): nh_afi = AFI.ipv6 elif len_nh in (4, ): nh_afi = AFI.ipv4 else: raise Notify( 3, 0, 'unsupported family %s %s with extended next-hop capability enabled' % (afi, safi)) length, _ = Family.size[(nh_afi, safi)] if len_nh not in length: raise Notify( 3, 0, 'invalid %s %s next-hop length %d expected %s' % (afi, safi, len_nh, ' or '.join(str(_) for _ in length))) size = len_nh - rd # XXX: FIXME: GET IT FROM CACHE HERE ? nhs = data[offset + rd:offset + rd + size] nexthops = [nhs[pos:pos + 16] for pos in range(0, len(nhs), 16)] # chech the RD is well zero if rd and sum([int(ordinal(_)) for _ in data[offset:8]]) != 0: raise Notify( 3, 0, "MP_REACH_NLRI next-hop's route-distinguisher must be zero") offset += len_nh # Skip a reserved bit as somone had to bug us ! reserved = ordinal(data[offset]) offset += 1 if reserved != 0: raise Notify(3, 0, 'the reserved bit of MP_REACH_NLRI is not zero') # Is the peer going to send us some Path Information with the route (AddPath) addpath = negotiated.addpath.receive(afi, safi) # Reading the NLRIs data = data[offset:] if not data: raise Notify( 3, 0, 'No data to decode in an MPREACHNLRI but it is not an EOR %d/%d' % (afi, safi)) while data: if nexthops: for nexthop in nexthops: nlri, left = NLRI.unpack_nlri(afi, safi, data, IN.ANNOUNCED, addpath) # allow unpack_nlri to return none for "treat as withdraw" controlled by NLRI.unpack_nlri if nlri: nlri.nexthop = NextHop.unpack(nexthop) nlris.append(nlri) else: nlri, left = NLRI.unpack_nlri(afi, safi, data, IN.ANNOUNCED, addpath) # allow unpack_nlri to return none for "treat as withdraw" controlled by NLRI.unpack_nlri if nlri: nlris.append(nlri) if left == data: raise RuntimeError("sub-calls should consume data") data = left return cls(afi, safi, nlris)
def unpack (cls, data, negotiated): nlris = [] # -- Reading AFI/SAFI _afi,_safi = unpack('!HB',data[:3]) afi,safi = AFI.create(_afi),SAFI.create(_safi) offset = 3 # we do not want to accept unknown families if negotiated and (afi,safi) not in negotiated.families: raise Notify(3,0,'presented a non-negotiated family %s/%s' % (afi,safi)) # -- Reading length of next-hop len_nh = ordinal(data[offset]) offset += 1 if (afi,safi) not in Family.size: raise Notify(3,0,'unsupported %s %s' % (afi,safi)) length,rd = Family.size[(afi,safi)] if len_nh not in length: raise Notify(3,0,'invalid %s %s next-hop length %d expected %s' % (afi,safi,len_nh,' or '.join(str(_) for _ in length))) size = len_nh - rd # XXX: FIXME: GET IT FROM CACHE HERE ? nhs = data[offset+rd:offset+rd+size] nexthops = [nhs[pos:pos+16] for pos in range(0,len(nhs),16)] # chech the RD is well zero if rd and sum([int(ordinal(_)) for _ in data[offset:8]]) != 0: raise Notify(3,0,"MP_REACH_NLRI next-hop's route-distinguisher must be zero") offset += len_nh # Skip a reserved bit as somone had to bug us ! reserved = ordinal(data[offset]) offset += 1 if reserved != 0: raise Notify(3,0,'the reserved bit of MP_REACH_NLRI is not zero') # Is the peer going to send us some Path Information with the route (AddPath) addpath = negotiated.addpath.receive(afi,safi) # Reading the NLRIs data = data[offset:] if not data: raise Notify(3,0,'No data to decode in an MPREACHNLRI but it is not an EOR %d/%d' % (afi,safi)) while data: if nexthops: for nexthop in nexthops: nlri,left = NLRI.unpack_nlri(afi,safi,data,IN.ANNOUNCED,addpath) nlri.nexthop = NextHop.unpack(nexthop) nlris.append(nlri) else: nlri,left = NLRI.unpack_nlri(afi,safi,data,IN.ANNOUNCED,addpath) nlris.append(nlri) if left == data: raise RuntimeError("sub-calls should consume data") data = left return cls(afi,safi,nlris)
def unpack(cls, data, negotiated): nlris = [] # -- Reading AFI/SAFI afi, safi = unpack('!HB', data[:3]) offset = 3 # we do not want to accept unknown families if negotiated and (afi, safi) not in negotiated.families: raise Notify( 3, 0, 'presented a non-negotiated family %d/%d' % (afi, safi)) # -- Reading length of next-hop len_nh = ordinal(data[offset]) offset += 1 rd = 0 # check next-hop size if afi == AFI.ipv4: if safi in (SAFI.unicast, SAFI.multicast): if len_nh != 4: raise Notify( 3, 0, 'invalid ipv4 unicast/multicast next-hop length %d expected 4' % len_nh) elif safi in (SAFI.mpls_vpn, ): if len_nh != 12: raise Notify( 3, 0, 'invalid ipv4 mpls_vpn next-hop length %d expected 12' % len_nh) rd = 8 elif safi in (SAFI.flow_ip, ): if len_nh not in (0, 4): raise Notify( 3, 0, 'invalid ipv4 flow_ip next-hop length %d expected 4' % len_nh) elif safi in (SAFI.flow_vpn, ): if len_nh not in (0, 4): raise Notify( 3, 0, 'invalid ipv4 flow_vpn next-hop length %d expected 4' % len_nh) elif safi in (SAFI.rtc, ): if len_nh not in (4, 16): raise Notify( 3, 0, 'invalid ipv4 rtc next-hop length %d expected 4' % len_nh) elif afi == AFI.ipv6: if safi in (SAFI.unicast, ): if len_nh not in (16, 32): raise Notify( 3, 0, 'invalid ipv6 unicast next-hop length %d expected 16 or 32' % len_nh) elif safi in (SAFI.mpls_vpn, ): if len_nh not in (24, 40): raise Notify( 3, 0, 'invalid ipv6 mpls_vpn next-hop length %d expected 24 or 40' % len_nh) rd = 8 elif safi in (SAFI.flow_ip, ): if len_nh not in (0, 16, 32): raise Notify( 3, 0, 'invalid ipv6 flow_ip next-hop length %d expected 0, 16 or 32' % len_nh) elif safi in (SAFI.flow_vpn, ): if len_nh not in (0, 16, 32): raise Notify( 3, 0, 'invalid ipv6 flow_vpn next-hop length %d expected 0, 16 or 32' % len_nh) elif afi == AFI.l2vpn: if len_nh != 4: Notify(3, 0, 'invalid l2vpn next-hop length %d expected 4' % len_nh) elif afi == AFI.bgpls: if len_nh != 4: Notify(3, 0, 'invalid bgpls next-hop length %d expected 4' % len_nh) size = len_nh - rd # XXX: FIXME: GET IT FROM CACHE HERE ? nhs = data[offset + rd:offset + rd + size] nexthops = [nhs[pos:pos + 16] for pos in range(0, len(nhs), 16)] # chech the RD is well zero if rd and sum([int(ordinal(_)) for _ in data[offset:8]]) != 0: raise Notify( 3, 0, "MP_REACH_NLRI next-hop's route-distinguisher must be zero") offset += len_nh # Skip a reserved bit as somone had to bug us ! reserved = ordinal(data[offset]) offset += 1 if reserved != 0: raise Notify(3, 0, 'the reserved bit of MP_REACH_NLRI is not zero') # Is the peer going to send us some Path Information with the route (AddPath) addpath = negotiated.addpath.receive(afi, safi) # Reading the NLRIs data = data[offset:] if not data: raise Notify( 3, 0, 'No data to decode in an MPREACHNLRI but it is not an EOR %d/%d' % (afi, safi)) while data: if nexthops: for nexthop in nexthops: nlri, left = NLRI.unpack_nlri(afi, safi, data, IN.ANNOUNCED, addpath) nlri.nexthop = NextHop.unpack(nexthop) nlris.append(nlri) else: nlri, left = NLRI.unpack_nlri(afi, safi, data, IN.ANNOUNCED, addpath) nlris.append(nlri) if left == data: raise RuntimeError("sub-calls should consume data") # logger.parser(LazyFormat("parsed announce mp nlri %s payload " % nlri,data[:length])) data = left return cls(afi, safi, nlris)