2

I created a Python 3.6 script that creates a raw UDP Packet over ethernet to a system with a known MAC Address and IPv4 Address. This script is running on a Beaglebone Black (BBB) that is connected directly over ethernet to a laptop running Ubuntu 16.04. The script is also running on the Ubuntu system (with the src and dst addresses changed obviously). I am also accessing the BBB terminal by a serial connection. The BBB can successfully ping the laptop, and vice versa. When the laptop runs the Python script, the packet is shown as sent by Wireshark, the ethernet port lights flicker, and then the instance of tcpdump running on the BBB confirms that the packet was sent. However, when running the script on the BBB, the instance of tcpdump on the BBB shows that the packet is sent; but the ethernet port lights don't light up and the laptop does not receive the packet. On startup of both systems, when I run ifconfig, neither of the ethernet interfaces have IP adresses, so I had to set them to arbitrary addresses (even before I did this, the packets would sent laptop to BBB but not the other way around).

The laptop's MAC address is AX:XX:XX:XX:XX:XA and its IP is 192.168.1.XA The BBB's MAC address is BX:XX:XX:XX:XX:XB and its IP is 192.168.1.XB I'm using port 1235 for all operations.

Calling ifconfig on the laptop gives:

enp0s31f6 Link encap:Ethernet  HWaddr AX:XX:XX:XX:XX:XA  
          inet addr:192.168.1.XA  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::56ee:75ff:fece:4227/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:537 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2912 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:154829 (154.8 KB)  TX bytes:516547 (516.5 KB)
          Interrupt:16 Memory:f2200000-f2220000 

Calling ifconfig on the BBB gives:

eth0      Link encap:Ethernet  HWaddr BX:XX:XX:XX:XX:XB                        
          inet addr:192.168.1.XB  Bcast:192.168.1.255  Mask:255.255.255.0      
          inet6 addr: fe80::6a3:16ff:feba:676a%132688/64 Scope:Link             
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1                    
          RX packets:2124 errors:0 dropped:0 overruns:0 frame:0                 
          TX packets:669 errors:0 dropped:0 overruns:0 carrier:0                
          collisions:0 txqueuelen:1000                                          
          RX bytes:402654 (393.2 KiB)  TX bytes:173920 (169.8 KiB)              
          Interrupt:174  

When the script is run on the laptop, the BBB tcpdump -n udp -vv -X looks like this:

04:47:15.179497 IP (tos 0x0, ttl 64, id 52223, offset 0, flags [DF], proto UDP (17), length 33)                                                                 
    192.168.1.XA.1235 > 192.168.1.XB.1235: [no cksum] UDP, length 5           
        0x0000:  4500 0021 cbff 4000 4011 ea79 c0a8 017f  E..!..@.@..y....      
        0x0010:  c0a8 0183 04d3 04d3 000d 0000 0003 020f  ................      
        0x0020:  0f00 0000 0000 0000 0000 0000 0000       .............. 

When the script is run on the BBB, the laptop doesn't receive it, but the tcpdump -n udp -vv -X on the BBB shows that it is sent:

04:51:31.613740 IP (tos 0x0, ttl 64, id 34794, offset 0, flags [DF], proto UDP (17), length 33)
    192.168.1.XB.1235 > 192.168.1.XA.1235: [no cksum] UDP, length 5
        0x0000:  4500 0021 87ea 4000 4011 2e8f c0a8 0183  E..!..@.@.......
        0x0010:  c0a8 017f 04d3 04d3 000d 0000 0003 020f  ................
        0x0020:  0f                                       .

The python3.6 script running on the Laptop and BBB is is:

import socket
import time
import struct
import random

#the following lists are specified as [src, dst]
#The order of the elements of these two element lists are reversed for the BBB
MAC = ["AX XX XX XX XX XA", "BX XX XX XX XX XB"]
IP = ["192.168.1.XA", "192.168.1.XB"]
port = [1235, 1235]
address = (IP[1], port[1])

#iface = 'eth0' for the BBB, 'enp0s31f6' for Laptop running Ubuntu 16.04
iface = 'enp0s31f6'


def shex(str):
    result = hex(int(str))
    return result[2:].zfill(2)


def ipToHex(ip):
    a = ip.split('.')
    return '{:02X} {:02X} {:02X} {:02X}'.format(*map(int, a))


def checksum(hdr):
    hdr = "".join(hdr.split())
    hdr = " ".join(hdr[i:i + 2] for i in range(0, len(hdr), 2)).split()
    hdr = list(map(lambda x: int(x, 16), hdr))
    hdr = struct.pack("%dB" % len(hdr), *hdr)

    cksum = 0
    for i in range(0, len(hdr), 2):
        word = hdr[i] + (hdr[i + 1] << 8)
        temp = cksum + word
        cksum = (temp & 0xFFFF) + (temp >> 16)
    res = ~cksum & 0xFFFF
    return '{:04X}'.format(((res << 8) & 0xFF00) | ((res >> 8) & 0x00FF))


class EthernetPacket:
    def __init__(self, mac, payload):
        self.srcMAC = mac[0]
        self.dstMAC = mac[1]
        self.type = '{:04X}'.format(0x0800)
        self.payload = payload

    def send(self, sock):
        sock.send(bytes.fromhex(self.srcMAC + self.dstMAC + self.type + self.payload.construct()))
        time.sleep(0.005)


class IPv4Packet:
    def __init__(self, ip, payload):
        self.srcIP = ipToHex(ip[0])
        self.dstIP = ipToHex(ip[1])
        self.ver = "45 00"
        self.id = '{:04X}'.format(0xFFFF & random.randrange(0, 65536)) + " 40 00 40 11"
        self.length = payload.length + 20
        self.payload = payload
        hdr = self.ver + '{:04X}'.format(self.length) + self.id + "0000" + self.srcIP + self.dstIP
        self.checksum = checksum(hdr)

    def construct(self):
        return self.ver + '{:04X}'.format(
        self.length) + self.id + self.checksum + self.srcIP + self.dstIP + self.payload.construct()


class UDPPacket:
    def __init__(self, port, payload):
        self.srcPort = '{:04X}'.format(port[0])
        self.dstPort = '{:04X}'.format(port[1])
        self.checksum = "0000"
        self.length = len(bytes.fromhex(payload)) + 8
        self.payload = payload

    def construct(self):
        return self.srcPort + self.dstPort + '{:04X}'.format(self.length) + self.checksum + self.payload


def main():
    sock = socket.socket(socket.AF_PACKET, socket.SOCK_RAW)
    sock.bind((iface, 1235))

    msg = 0

    cmd = input("Enter Command: ")
    task = cmd.split()

    if not task:
        task = ['null']

    while task[0] != 'exit' and task[0] != 'quit' and task[0] != 'close':
        if task[0] == 'light':
            param1, param2 = shex('00') + ' ', shex('00')
        if len(task) > 1:
            param1 = shex(task[1]) + ' '
        if len(task) > 2:
            param2 = shex(task[2])
        msg = '00 03 02 ' + param1 + param2

        u = UDPPacket(port, msg)
        i = IPv4Packet(IP, u)
        e = EthernetPacket(MAC, i)
        e.send(sock)

        cmd = input("Enter Command: ")
        task = cmd.split()

    sock.close()


if __name__ == "__main__":
    main()

Any help is appreciated.

3
  • Does it work for netcat via something like nc -u -l 1235 and then echo foo | nc -i $theip 1235 ? – thrig Sep 16 '17 at 1:09
  • 1
    Perhaps your checksum calculation is wrong but gets fixed by the hardware tx interface on the laptop, but not on the bbb. Check for tx checksum offload on both with sudo ethtool --show-offload eth0. You can check out other things with ethtool, like the result of negociation. Perhaps one end is broken at half-duplex, but not the other. – meuh Sep 16 '17 at 17:28
  • @meuh I turned off tx-checksumming and rx-checksumming for both and the same problem occurs. – hsifeulbhsifder Sep 18 '17 at 18:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.