def arp_broken(): for v in tvlan: # broadcast the ARP packets and force other device change their gateway MAC pkt = Ether(src=mymac, dst="ff:ff:ff:ff:ff:ff") / Dot1Q( vlan=self_vlan) / Dot1Q(vlan=int(v)) / ARP( op=2, hwsrc=mymac, psrc=gateway_ip) sendp(pkt)
def embed(self, scapy_pkt): ''' Given a scapy packet, embedd the VLAN config into the packet ''' if not self.tags: return ether = scapy_pkt.getlayer(0) ether_payload = scapy_pkt.payload # single VLAN if len(self.tags) == 1: vlan = Dot1Q(vlan=self.tags[0]) vlan.payload = ether.payload ether.payload = vlan # dobule VLAN elif len(self.tags) == 2: dot1ad = Dot1AD(vlan=self.tags[0]) dot1q = Dot1Q(vlan=self.tags[1]) dot1ad.payload = dot1q dot1q.payload = ether_payload ether.payload = dot1ad
def test_bpf1(self): vid = 4090 pcp = 7 frame_match = 'ether[14:2] = 0x{:01x}{:03x}'.format(pcp << 1, vid) filter = BpfProgramFilter(frame_match) self.assertTrue(filter(str(Ether()/Dot1Q(prio=pcp, vlan=vid)))) self.assertFalse(filter(str(Ether()/Dot1Q(prio=pcp, vlan=4000))))
def test_combo_upstream_unicast_onu2(self): self.setup_all_flows() kw = dict(src='00:00:00:11:11:11', dst='00:00:00:22:22:22') in_frame = Ether(**kw) / Dot1Q(vlan=1000) / Dot1Q(vlan=129) / IP() out_frame = Ether(**kw) / Dot1Q(vlan=0) / IP() self.ingress_frame(in_frame) self.assertEqual(self.output, [(129, out_frame)])
def buildLayer(session: 'PPPoESession') -> 'Packet': packet = Ether(src=session.src_mac, dst=session.dst_mac) if session.providerVlan is not None: packet.add_payload(Dot1Q(vlan=session.clientVlan)) if session.clientVlan is not None: packet.add_payload(Dot1Q(vlan=session.clientVlan)) return packet
def packet_out(self, egress_port, msg): self.log.info('sending-packet-out', egress_port=egress_port, msg=hexify(msg)) pkt = Ether(msg) out_pkt = (Ether(src=pkt.src, dst=pkt.dst) / Dot1Q(vlan=4000) / Dot1Q(vlan=egress_port, type=pkt.type) / pkt.payload) self.io_port.send(str(out_pkt))
def add_dot1_layer(self, packet): payload = packet.payload packet.remove_payload() packet.add_payload( Dot1Q(vlan=self.outer_vlan) / Dot1Q(vlan=self.inner_vlan) / payload) packet.type = self.DOT1AD_TYPE return packet
def send_proxied_message(self, proxy_address, msg): log.info('send-proxied-message', proxy_address=proxy_address) device = self.adapter_agent.get_device(proxy_address.device_id) frame = Ether(dst=device.mac_address) / \ Dot1Q(vlan=TIBIT_MGMT_VLAN, prio=TIBIT_MGMT_PRIORITY) / \ Dot1Q(vlan=proxy_address.channel_id, prio=TIBIT_MGMT_PRIORITY) / \ msg self.io_port.send(str(frame))
def vlan_send_packet(self, outer_vid, outer_tpid=0x8100, inner_vid=-1, inner_tpid=-1): """ if vid is -1, it means send pakcage not include vlan id. """ self.tpid_ori_file = "/tmp/tpid_ori.pcap" self.tpid_new_file = "/tmp/tpid_new.pcap" self.tester.send_expect("rm -rf /tmp/tpid_ori.pcap", "# ") self.tester.send_expect("rm -rf /tmp/tpid_new.pcap", "# ") # The package stream : testTxPort->dutRxPort->dutTxport->testRxPort port = self.tester.get_local_port(dutRxPortId) self.txItf = self.tester.get_interface(port) self.smac = self.tester.get_mac(port) port = self.tester.get_local_port(dutTxPortId) self.rxItf = self.tester.get_interface(port) # the package dect mac must is dut tx port id when the port promisc is # off self.dmac = self.dut.get_mac_address(dutRxPortId) self.inst = sniff_packets(self.rxItf) pkt = [] if outer_vid < 0 or outer_tpid <= 0: pkt = [ Ether(dst="%s" % self.dmac, src="%s" % self.smac) / IP(len=46) ] wrpcap(self.tpid_new_file, pkt) else: pkt = [ Ether(dst="%s" % self.dmac, src="%s" % self.smac) / Dot1Q(vlan=1) / Dot1Q(vlan=2) / IP(len=46) ] wrpcap(self.tpid_ori_file, pkt) fmt = '1/1 "%02x"' out = self.tester.send_expect( "hexdump -ve '%s' '%s'" % (fmt, self.tpid_ori_file), "# ") if (inner_vid < 0 or inner_tpid <= 0): replace = str("%04x" % outer_tpid) + str("%04x" % outer_vid) else: replace = str("%04x" % outer_tpid) + str( "%04x" % outer_vid) + str("%04x" % inner_tpid) + str( "%04x" % inner_vid) fmt = '1/1 "%02x"' out = self.tester.send_expect( "hexdump -ve '%s' '%s' |sed 's/8100000181000002/%s/' |xxd -r -p > '%s'" % (fmt, self.tpid_ori_file, replace, self.tpid_new_file), "# ") self.tester.send_expect("scapy", ">>> ") self.tester.send_expect("pkt=rdpcap('%s')" % self.tpid_new_file, ">>> ") self.tester.send_expect("sendp(pkt, iface='%s')" % self.txItf, ">>> ") self.tester.send_expect("quit()", "# ")
def test_eapol_in(self): self.setup_all_flows() kw = dict(src='00:00:00:11:11:11', dst='00:00:00:22:22:22') in_frame = Ether(**kw) / EAPOL(type=1) out_frame1 = Ether(**kw) / Dot1Q(vlan=4000) / Dot1Q(vlan=128) / EAPOL( type=1) out_frame2 = Ether(**kw) / Dot1Q(vlan=4000) / Dot1Q(vlan=129) / EAPOL( type=1) self.ingress_frame(in_frame) self.assertEqual(self.output, [(0, out_frame1), (0, out_frame2)])
def VlanNumer(dstMac, startVlanID, endVlanID): while 1 < endVlanID: sendp( Ether(dst=dstMac) / Dot1Q(vlan=1) / Dot1Q(vlan=startVlanID) / ARP(op='who-has', psrc=psrc, pdst=pdst)) startVlanID = startVlanID + 1 if startVlanID == endVlanID: break else: continue
def test_downstream_unicast_forwarding(self): self.pon.olt_install_flows([ mk_flow_stat(match_fields=[in_port(2), vlan_vid(4096 + 1000)], actions=[pop_vlan(), output(1)]) ]) self.pon.onu_install_flows(128, [ mk_flow_stat(match_fields=[in_port(1), vlan_vid(4096 + 128)], actions=[set_field(vlan_vid(4096 + 0)), output(2)]) ]) # untagged frames shall not get through self.assert_untagged_frames_dont_pass() # incorrect single- or double-tagged frames don't pass self.assert_dont_pass(Ether() / Dot1Q(vlan=1000) / IP()) self.assert_dont_pass(Ether() / Dot1Q(vlan=128) / IP()) self.assert_dont_pass(Ether() / Dot1Q(vlan=128) / Dot1Q(vlan=1000) / IP()) self.assert_dont_pass(Ether() / Dot1Q(vlan=1000) / Dot1Q(vlan=129) / IP()) # properly tagged downstream frame gets through and pops up at port 128 # as untagged kw = dict(src='00:00:00:11:11:11', dst='00:00:00:22:22:22') in_frame = Ether(**kw) / Dot1Q(vlan=1000) / Dot1Q(vlan=128) / IP() out_frame = Ether(**kw) / Dot1Q(vlan=0) / IP() self.ingress_frame(in_frame) self.assertEqual(self.output, [(128, out_frame)])
def packet_out(self, egress_port, msg): self.log.info('sending-packet-out', egress_port=egress_port, msg=hexify(msg)) pkt = Ether(msg) out_pkt = (Ether(src=pkt.src, dst=pkt.dst) / Dot1Q(vlan=PACKET_IN_VLAN) / Dot1Q(vlan=egress_port, type=pkt.type) / pkt.payload) # TODO: Need to retrieve the correct destination onu_id self.bal.packet_out(1, egress_port, str(out_pkt))
def test_igmp_out(self): self.setup_all_flows() kw = dict(src='00:00:00:11:11:11', dst='00:00:00:22:22:22') mq = IGMPv3(type=IGMP_TYPE_MEMBERSHIP_QUERY, max_resp_code=120) in_frame1 = Ether(**kw) / Dot1Q(vlan=4000) / Dot1Q(vlan=128) /\ IP() / mq.copy() in_frame2 = Ether(**kw) / Dot1Q(vlan=4000) / Dot1Q(vlan=129) /\ IP() / mq.copy() out_frame = Ether(**kw) / Dot1Q(vlan=0) / IP() / mq.copy() self.ingress_frame(in_frame1) self.ingress_frame(in_frame2) self.assertEqual(self.output, [(128, out_frame), (129, out_frame)])
def protocol_frame(protocol, source='unicast', vlans=[]): """ Create a frame that has the minimum fields to be recognized as a determined protocol. It's not intended to be a valid PDU, only to be seen as one by the switch filter. @param protocol Protocol name. Valid options are: * stp, lldp, lacp, marker, oam, lbd, cdp, pagp, udld, vtp, pvst, dtp, gvrp, gmrp, dot1x @param source Name of the source interface, or source MAC address. * 'unicast' to use a random unicast address as source MAC. @param vlans [optional] List of VLAN Tags. List can be composed by single integer representing VLAN, or tuple (int, int) for VLAN and prio. Ex: [(100, 3), 20] will add two tags, one with VLAN 100, prio 3 and another with VLAN 20, prio 0. """ if protocol not in pdu_info: raise Exception("Unknown protocol name {0}".format(protocol)) info = pdu_info[protocol] # Define source MAC address. if "eth" in source: src_mac = str(mac_address(source)) elif source == 'unicast': src_mac = str(random_mac('unicast')) else: src_mac = str(source) if protocol == 'eaps': src_mac = "00:e0:2b:00:00:01" if 'type' in info or vlans: pdu = Ether(src=src_mac, dst=info['mac']) for v in vlans: if type(v) == int: pdu = pdu / Dot1Q(vlan=v) elif type(v) == tuple: pdu = pdu / Dot1Q(vlan=v[0], prio=v[1]) else: raise TypeError( "Expected list with int or tuple for VLANs parameter.") if 'type' in info: pdu.lastlayer().type = info['type'] else: pdu = Dot3(src=src_mac, dst=info['mac']) pdu = pdu / info['load'] # Process PDU so length field is correctly calculated. pdu = Ether(str(pdu)) # Add Padding and return. padding = 64 - len(pdu) + 4 #FCS if padding > 0: pdu = pdu / Padding(load='\0' * padding) return pdu
def add_dot1_layers(cls, i, packet): assert (type(packet) is Ether) payload = packet.payload det = cls.INT_DETAILS[i] if isinstance(det, cls.Dot1QSubint): packet.remove_payload() packet.add_payload(Dot1Q(vlan=det.sub_id) / payload) elif isinstance(det, cls.Dot1ADSubint): packet.remove_payload() packet.add_payload( Dot1Q(vlan=det.outer_vlan) / Dot1Q(vlan=det.inner_vlan) / payload) packet.type = 0x88A8
def test_bpf2(self): vid1 = 4090 pcp1 = 7 frame_match_case1 = 'ether[14:2] = 0x{:01x}{:03x}'.format( pcp1 << 1, vid1) vid2 = 4000 frame_match_case2 = '(ether[14:2] & 0xfff) = 0x{:03x}'.format(vid2) filter = BpfProgramFilter('{} or {}'.format( frame_match_case1, frame_match_case2)) self.assertTrue(filter(str(Ether()/Dot1Q(prio=pcp1, vlan=vid1)))) self.assertTrue(filter(str(Ether()/Dot1Q(vlan=vid2)))) self.assertFalse(filter(str(Ether()/Dot1Q(vlan=4001))))
def test_igmp_in(self): self.setup_all_flows() kw = dict(src='00:00:00:11:11:11', dst='00:00:00:22:22:22') mr = IGMPv3(type=IGMP_TYPE_V3_MEMBERSHIP_REPORT, max_resp_code=30, gaddr="224.0.0.1") mr.grps = [IGMPv3gr(rtype=IGMP_V3_GR_TYPE_EXCLUDE, mcaddr="228.1.1.3")] in_frame = Ether(**kw) / IP() / mr out_frame1 = Ether(**kw) / Dot1Q(vlan=4000) / Dot1Q(vlan=128) /\ in_frame.payload.copy() out_frame2 = Ether(**kw) / Dot1Q(vlan=4000) / Dot1Q(vlan=129) /\ in_frame.payload.copy() self.ingress_frame(in_frame) self.assertEqual(self.output, [(0, out_frame1), (0, out_frame2)])
def create_packet_header_IPv6_SRH_L2(self, srcaddr, sidlist, segleft, vlan=0): """Create packet header: L2 encapsulated in SRv6: IPv6 header with SRH, L2 :param int srcaddr: IPv6 source address :param list sidlist: segment list of outer IPv6 SRH :param int segleft: segments-left field of outer IPv6 SRH :param vlan: L2 vlan; if vlan!=0 then add 802.1q header IPv6 source address is set to srcaddr IPv6 destination address is set to sidlist[segleft] """ eth = Ether(src='00:11:22:33:44:55', dst='00:55:44:33:22:11') etype = 0x8137 # IPX if vlan: # add 802.1q layer eth /= Dot1Q(vlan=vlan, type=etype) else: eth.type = etype p = IPv6(src=srcaddr, dst=sidlist[segleft]) / \ IPv6ExtHdrSegmentRouting(addresses=sidlist, segleft=segleft, nh=59) / \ eth return p
def packet_out(self, egress_port, msg): self.log.info('sending-packet-out', egress_port=egress_port, msg=hexify(msg)) pkt = Ether(msg) out_pkt = (Ether(src=pkt.src, dst=pkt.dst) / Dot1Q(vlan=4000) / Dot1Q(vlan=egress_port, type=pkt.type) / pkt.payload) if self.ponsim_comm == 'grpc': # send over grpc stream stub = ponsim_pb2.PonSimStub(self.get_channel()) frame = PonSimFrame(id=self.device_id, payload=str(out_pkt)) stub.SendFrame(frame) else: # send over frameio self.io_port.send(str(out_pkt))
def receive_packet_out(self, logical_device_id, egress_port_no, msg): log.info('packet-out', logical_device_id=logical_device_id, egress_port_no=egress_port_no, msg_len=len(msg)) dev_id, logical_dev_id = self.vlan_to_device_ids[egress_port_no] if logical_dev_id != logical_device_id: raise Exception('Internal table mismatch') tmp = Ether(msg) frame = Ether(dst=tmp.dst, src=tmp.src) / \ Dot1Q(vlan=TIBIT_PACKET_OUT_VLAN) / \ Dot1Q(vlan=egress_port_no) / \ tmp.payload self.io_port.send(str(frame))
def _make_links_frame(self, mac_address): # Create a json packet json_operation_str = '{\"operation\":\"links\"}' frame = Ether(dst=mac_address) / Dot1Q( vlan=TIBIT_MGMT_VLAN, prio=TIBIT_MGMT_PRIORITY) / TBJSON( data='json %s' % json_operation_str) return str(frame)
def _raise_alarm(alarm_event, olt, egress): try: frame = Ether() / Dot1Q(vlan=4000) / IP() / TCP() / Raw(load=json.dumps(alarm_event)) egress(0, frame) except Exception as e: log.exception('failed-to-raise-alarm', e=e)
def generate_someip_based_tcp(self, s_ip, d_ip, s_port, d_port, seq=2496318543, ack=594476641, flags="PA", matrix=None): vlan = Dot1Q(vlan=4) ip = IP(src=s_ip, dst=d_ip) tcp = TCP(flags=flags, sport=s_port, dport=d_port, seq=seq, ack=ack) if flags == "PA": # PSH+ACK if matrix is None: matrix = {} srv_id = matrix.get("srv_id", 0xffff) method_id = matrix.get("method_id", 65535) session_id = matrix.get("session_id", 1) msg_type = matrix.get("msg_type", SOMEIP.TYPE_NOTIFICATION) req_data = matrix.get("req_data", []) someip = SOMEIP(srv_id=srv_id, sub_id=0x0, method_id=method_id, event_id=0, client_id=method_id, session_id=session_id, msg_type=msg_type) packet = b''.join([bytes().fromhex(i) for i in req_data]) target = ip / tcp / someip / packet elif flags == "A": # ACK target = ip / tcp else: target = ip / tcp payload_length = len(target) hex_target = hexdump(target, True) results = hex_target.split("\n") finalResult = [] for item in results: finalResult.append(item.split(" ")[1]) x = " ".join(finalResult) x_list = x.split(" ") return payload_length, x_list
def test_combo_multicast_stream4(self): self.setup_all_flows() kw = dict(src='00:00:00:11:11:11', dst='00:00:00:22:22:22') in_frame = Ether(**kw) / Dot1Q(vlan=140) / IP(dst='228.1.1.4') out_frame = Ether(**kw) / IP(dst='228.1.1.4') self.ingress_frame(in_frame) self.assertEqual(self.output, [(128, out_frame), (129, out_frame)])
def send_dhcp_packet(self, mac: MacAddress, vlan: str, state: DHCPState, dhcp_desc: DHCPDescriptor = None): """ Send DHCP packet and record state in dhcp_client_state. Args: mac: MAC address of interface state: state of DHCP packet dhcp_desc: DHCP protocol state. Returns: """ ciaddr = None # generate DHCP request packet if state == DHCPState.DISCOVER: dhcp_opts = [("message-type", "discover")] dhcp_desc = DHCPDescriptor(mac=mac, ip="", vlan=vlan, state_requested=DHCPState.DISCOVER) self._msg_xid = self._msg_xid + 1 pkt_xid = self._msg_xid elif state == DHCPState.REQUEST: dhcp_opts = [("message-type", "request"), ("requested_addr", dhcp_desc.ip), ("server_id", dhcp_desc.server_ip)] dhcp_desc.state_requested = DHCPState.REQUEST pkt_xid = dhcp_desc.xid ciaddr = dhcp_desc.ip elif state == DHCPState.RELEASE: dhcp_opts = [("message-type", "release"), ("server_id", dhcp_desc.server_ip)] dhcp_desc.state_requested = DHCPState.RELEASE self._msg_xid = self._msg_xid + 1 pkt_xid = self._msg_xid ciaddr = dhcp_desc.ip else: LOG.warning("Unknown egress request mac %s state %s", str(mac), state) return dhcp_opts.append("end") dhcp_desc.xid = pkt_xid with self._dhcp_notify: self.dhcp_client_state[mac.as_redis_key(vlan)] = dhcp_desc pkt = Ether(src=str(mac), dst="ff:ff:ff:ff:ff:ff") if vlan and vlan != "0": pkt /= Dot1Q(vlan=int(vlan)) pkt /= IP(src="0.0.0.0", dst="255.255.255.255") pkt /= UDP(sport=68, dport=67) pkt /= BOOTP(op=1, chaddr=mac.as_hex(), xid=pkt_xid, ciaddr=ciaddr) pkt /= DHCP(options=dhcp_opts) LOG.debug("DHCP pkt xmit %s", pkt.show(dump=True)) sendp(pkt, iface=self._dhcp_interface, verbose=0)
def make_ndp_grat_ndp_packet( pktlen=64, eth_dst='00:01:02:03:04:05', eth_src='00:06:07:08:09:0a', dl_vlan_enable=False, vlan_vid=0, vlan_pcp=0, ipv6_src='2001:db8:85a3::8a2e:370:7334', ipv6_dst='2001:db8:85a3::8a2e:370:7335', ipv6_tc=0, ipv6_ecn=None, ipv6_dscp=None, ipv6_hlim=255, ipv6_fl=0, ipv6_tgt='2001:db8:85a3::8a2e:370:7334', hw_tgt='00:06:07:08:09:0a', ): """ Generates a simple NDP advertisement similar to PTF testutils simple_arp_packet. Args: pktlen: length of packet eth_dst: etheret destination address. eth_src: ethernet source address dl_vlan_enable: True to add vlan header. vlan_vid: vlan ID vlan_pcp: vlan priority ipv6_src: IPv6 source address ipv6_dst: IPv6 destination address ipv6_tc: IPv6 traffic class ipv6_ecn: IPv6 traffic class ECN ipv6_dscp: IPv6 traffic class DSCP ipv6_hlim: IPv6 hop limit/ttl ipv6_fl: IPv6 flow label ipv6_tgt: ICMPv6 ND advertisement target address. hw_tgt: IPv6 ND advertisement destination link-layer address. Returns: Crafted scapy packet for using with send_packet(). """ if MINSIZE > pktlen: pktlen = MINSIZE ipv6_tc = ip_make_tos(ipv6_tc, ipv6_ecn, ipv6_dscp) pkt = Ether(dst=eth_dst, src=eth_src) if dl_vlan_enable or vlan_vid or vlan_pcp: pkt /= Dot1Q(vlan=vlan_vid, prio=vlan_pcp) pkt /= IPv6(src=ipv6_src, dst=ipv6_dst, fl=ipv6_fl, tc=ipv6_tc, hlim=ipv6_hlim) pkt /= ICMPv6ND_NA(R=0, S=0, O=1, tgt=ipv6_tgt) pkt /= ICMPv6NDOptDstLLAddr(lladdr=hw_tgt) pkt /= ("D" * (pktlen - len(pkt))) return pkt
def _make_sendp_latency(self, s, p, m, a, c): logger.info("starting sendp") while s.is_set(): e = Ether(src=RandMAC(c), dst=RandMAC()) / Dot1Q(vlan=20) i = IP(src=RandIP(a), dst=RandIP()) d = Raw(load="{}".format(time.time()).encode(encoding="utf8")) pkt = e / i / d sendp(pkt, iface=p, verbose=False)
def _clear_alarm(alarm_event, olt, egress): try: alarm_event['state'] = AlarmEventState.CLEARED frame = Ether() / Dot1Q(vlan=4000) / IP() / TCP() / Raw(load=json.dumps(alarm_event)) egress(0, frame) except Exception as e: log.exception('failed-to-clear-alarm', e=e)
def _add_tag(self, packet, vlan, tag_type): payload = packet.payload inner_type = packet.type packet.remove_payload() packet.add_payload(Dot1Q(vlan=vlan) / payload) packet.payload.type = inner_type packet.payload.vlan = vlan packet.type = tag_type return packet