Sitzung: Jeden Freitag in der Vorlesungszeit ab 16 Uhr c. t. im MAR 0.005. In der vorlesungsfreien Zeit unregelmäßig (Jemensch da?). Macht mit!

Benutzer:Grey/UDP-Testskript EN

UDP-testscript

breadboard constructions

There are different variations of breadboard constructions for FWTEST and the FWAGENT, see here: breadboard constructions

netdate-example

On the basis of an example we want to illustrate an implementation of a testscript. For example, we want to make a draft on the netdate-service of www.heise.de (we don't really to make a draft on www.heise.de, but we only simulate the traffic) for getting the actual time. Netdate exists for UDP and TCP, we take here the UDP-variation.

if we would eavesdrop the traffic with etereal or tcpdump, the packets should look like that they are real and not generated(more to this topic here: Limits of tests).

Basically we are processing following credits:

  1. creating default IP-packet(achen -> bchen)
  2. creating default IP-packet(bchen -> achen)
  3. creating default UDP-packet(achen -> bchen)
  4. creating default UDP-packet(bchen -> achen)
  5. adjusting IP-packet
  6. adjusting UDP-packet
  7. merging IP- and UDP-packets
  8. sending UDP/IP-packets via transceive-function
  9. evaluation



Now we take a closer look at the testscript, at the end will be the link to the complete source code of the netdate-script:

  • At first we have to import our wrapper-classes (with prefix fwt_) and other needed classes:
import fwt_ip      # wrapper-Klasse zum erstellen/ändern von IP-Paketen
import fwt_udp     # wrapper-Klasse zum erstellen/ändern von UDP-Paketen
import fwt_tcp     # wrapper-Klasse zum erstellen/ändern von TCP-Paketen
import posix       # TODO: Erklärung


  • After that we define two variables for debugging. dry_run is for run called dry-run, which do the packet creation, but the finally sending is skipped. The second effects, that only bchen will send their packets, packets from achen are skipped.
dry_run=0	    # if set the transceive function is skipped
response_only=0    # send time protocol response only


  • TODO Wir müssen die Beiden Agenten Achen und Bchen mit einer IP-Adresse festlegen.
ACHEN='10.000.2.2'
BCHEN='10.128.2.2'


  • TODO
FILTER_A="not tcp port 1500 and src " + BCHEN + " and dst " + ACHEN + " or icmp"
FILTER_B="not tcp port 1500 and src " + ACHEN + " and dst " + BCHEN + " or icmp"


  • As basis we need our IP-packet as we generated here. We can use our wrapper-class fwt_ip to create the default IP-packet.
ip_packet = fwt_ip.Packet(fwt_ip.defaultPacket)


  • The default IP-packet has to be modified, e.g. the correct protocol is not set. To do so, we use the set-funcition of our wrapper-class fwt_ip. All fields of the IP-packet can be set by the set-function.
ip_packet.set ({
    fwt_ip.HEADER_PROTOCOL: 17,
})


  • The next step is to calculate the IHL(Internet Header Length) and the Header Checksum. An easy way to do it is to call the FIXUP-function of our wrapper-class. THe FIXUP corrects the fields(TODO: WELCHE?) of IP-packet. Our IP-packet will be loaded later with the SourceIP and the DestinationIP.
ip_packet.fixup (fwt_ip.FIXUP_ALL)


  • Currently we have an IP-packet as basis for both UDP-packets, but be also need the UDP-packets itself. We define with our wrapper-class two UDP-packets, the one for the way from achen to bchen and one for the reversed way. Each of these UDP-packets will be the payload for the IP-packets. They also have now only the base preferences, which have to be modified.
udp_pkt_ab = fwt_udp.Packet(fwt_udp.defaultPacket)
udp_pkt_ba = fwt_udp.Packet(fwt_udp.defaultPacket)


  • The base preferences are good beginning, but the UDP-packets get to be modified now, e.g.: sourceport, destinationport. At first we modify the UDP-packet from achen to bchen...
udp_pkt_ab.set({
    fwt_udp.HEADER_CHECKSUM:      0,
    fwt_udp.HEADER_SOURCEPORT:   53,
    fwt_udp.HEADER_DESTPORT:     37,
    fwt_udp.PAYLOAD:	         '\x0a'
})
  • ...and then from bchen to achen.
udp_pkt_ba.set({
    fwt_udp.HEADER_CHECKSUM:      0,
    fwt_udp.HEADER_SOURCEPORT:   37,
    fwt_udp.HEADER_DESTPORT:     53,
    fwt_udp.PAYLOAD: '\x69\xdc\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03\x77\x77\x77\x05\x68\x65\x69\x73\x65\x02\x64\x65\x00\x00\x01\x00\x01',
})

Pay attention that you take the right Destination Port of the service you will use. The payload of the UDP-packet have to be hardcode-implemented in hex.


  • Likewise a FIXUP of both UDP-packets have to be done, like the IP-packets. So the length and the Header Checksum will be corrected or changed:
udp_pkt_ab.fixup(fwt_udp.FIXUP_ALL, ACHEN, BCHEN);
udp_pkt_ba.fixup(fwt_udp.FIXUP_ALL, BCHEN, ACHEN);


  • After we created our default IP-packet and our modified default UDP-packets, we want to merge these packets to an UDP/IP-packet froma achen to bchen and reverse. The IP-packet listed befor act as a template for the UDP/IP-packet from achen to bchen. The constructor get the IP-packet as a dictionary and retruns a UDP/IP-packet.
ip_udp_pkt_ab = fwt_ip.Packet(ip_packet.as_dict())


  • The UDP/IP-packet needs a destination- and source-IP. As the payload, mentioned above, we refer the UDP-packet(as string).
ip_udp_pkt_ab.set({
    fwt_ip.HEADER_SOURCEIP:	ACHEN,
    fwt_ip.HEADER_DESTIP:	BCHEN,
    fwt_ip.PAYLOAD: udp_pkt_ab.as_str()
})


  • Yet we have set the IP-packet with the destination- and source-IP, but the Header Checksum must be generate as once again. This will do the FIXUP.
ip_udp_pkt_ab.fixup(fwt_ip.FIXUP_ALL)


  • The same must be done for the UDP-packet from bchen to achen.
ip_udp_pkt_ba = fwt_ip.Packet(ip_packet.as_dict())
ip_udp_pkt_ba.set({
    fwt_ip.HEADER_SOURCEIP:	BCHEN,
    fwt_ip.HEADER_DESTIP:	ACHEN,
    fwt_ip.PAYLOAD: udp_pkt_ba.as_str()
})
ip_udp_pkt_ba.fixup(fwt_ip.FIXUP_ALL)


  • For printing the received packets a print-function(printResult) is needed. The function checks if achen or bchen received any packet and print it on the standard out otherwise an error(timeout) is returned.
def printResult (result):
    if result[0] is not None:
         print 'Received on A:\n%r\n' % result[0]
    if result[1] is not None:
         print 'Received on B:\n%r\n' % result[1]
    if result[0] is None and result[1] is None:
         print 'Timeout'


  • If the dry_run option is 1, the packets are printed out to the console.
if dry_run == 1:
    print 'dry_run: skip all transceive functions'
    print 'Would send IP packet a->b:\n%s\n' % repr(ip_udp_pkt_ab.as_dict())
    print 'Would send IP packet b->a:\n%s\n' % repr(ip_udp_pkt_ba.as_dict())


  • At this point it gets more serious and the packets will be send

TODO

else:
    fwt_ip.set_coarse_filter_and_arp (fwt_ip.IFACE_A, [ ("10.000.0.2", "10.127.255.255")])
    fwt_ip.set_coarse_filter_and_arp (fwt_ip.IFACE_B, [ ("10.128.0.2", "10.255.255.255")])


  • If the second variable(response_only) is 1 only the packet from bchen to achen will be send by the transceive-function, the packet from achen to bchen is skipped. The received packet is stored in result.

TODO:an welche stelle wird paket in result gespeichert?

    if response_only == 1:
         print 'Will send IP packet b->a:\n%r\n' % ip_udp_pkt_ba
         result = fwt_ip.transceive (
                        fwt_ip.IFACE_B, 
                        ip_udp_pkt_ba, 
                        filterA=FILTER_A, 
                        filterB=FILTER_B, 
                        timeoutA=500, 
                        timeoutB=0
                  )
         printResult (result)

  • Otherwise the UDP/IP-packet from achen to bchen is send and than the packet from bchen to achen. The received packet are stored again in result.
    else:
         print 'Will send IP packet a->b:\n%r\n' % ip_udp_pkt_ab
         result = fwt_ip.transceive (
                        fwt_ip.IFACE_A, 
                        ip_udp_pkt_ab,  
                        filterA=FILTER_A, 
                        filterB=FILTER_B, 
                        timeoutA=0, 
                        timeoutB=500
                  )
         printResult (result)
         if result[1] is not None:
              print 'Will send IP packet b->a:\n%r\n' % ip_udp_pkt_ba
              result = fwt_ip.transceive (
                             fwt_ip.IFACE_B, 
                             ip_udp_pkt_ba, 
                             filterA=FILTER_A, 
                             filterB=FILTER_B, 
                             timeoutA=500, 
                             timeoutB=0
                       )
              printResult (result)
         else:
              print 'Lost origin packet -- Skip sending answer'


complete code of netdate.

transceive-function

The transceive-function is mostly the core of our testscript. It is responsable for sending the packets from source to destination. For a better understanding of the transceive-function we need to answer some questions:

What does the transceive-function exactly?

TODO: Erklärung

Which parameters are expected of the transceive-function?

A typical call of the transceive-function is listed below:

result = fwt_ip.transceive (
               fwt_ip.IFACE_B, 
               ip_udp_pkt_ba, 
               filterA=FILTER_A, 
               filterB=FILTER_B, 
               timeoutA=500, 
               timeoutB=0
        )

The first parameter defines the interface from which the packet is send, followed by the complete UDP/IP-packet (here from bchen to achen or generaly from source to destination). The third and fourth defines the filters for achen and bchen, followed by the timeouts for achen and bchen.

Which result is returned by transceive?

After transceive send the packet, it returns a python-dictionary with the values of the packet received on the other side. In our netdate-example the first received packet is stored in result[1], so we can check if a packet is arrived or not by validating result[1].