0

I have implemented this code to communicate with my device from pc. It get a several packets then it hangs on recvfrom() in while loop ?

import socket, sys, random
from struct import *
import struct
import select
import codecs
import base64
import time
import pdb

def checksum(msg):
    s = 0
    for i in range(0, len(msg), 2):
        w = (ord(msg[i]) <<8) + (ord(msg[i+1]) )
        s = s + w

    s = (s>>16) + (s & 0xffff);
    s = ~s & 0xffff
    return s

def create_socket(source_ip,dest_ip):
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)            
    except socket.error , msg:
        print 'Socket could not be created.  Error: ',str(msg[0]),' Message: ',msg[1]
        sys.exit()
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
    return s

def create_ip_header(source_ip, dest_ip):
    packet = ''
    headerlen = 5
    version = 4
    tos = 0
    tot_len = 20 + 20
    id = random.randrange(18000,65535,1)
    flags = 2
    frag_off = 0
    ttl = 255
    protocol = socket.IPPROTO_TCP
    check = 10
    saddr = socket.inet_aton ( source_ip )
    daddr = socket.inet_aton ( dest_ip )
    hl_version = (version << 4) + headerlen
    flags = (flags << 13) + frag_off
    ip_header = pack('!BBHHHBBH4s4s', hl_version, tos, tot_len, id, flags, ttl, protocol, check, saddr, daddr)
    return ip_header    

def create_tcp_syn_header(source_ip, source, dest_ip, dest_port, syn_flag, ack_num, ack_flag, seq_num, psh_flag, user_data):
    seq = seq_num
    ack_seq = ack_num
    doff = 5
    # tcp flags
    fin = 0
    syn = syn_flag
    rst = 0
    psh = psh_flag
    ack = ack_flag
    urg = 0
    window = socket.htons(19253500)
    check = 0
    urg_ptr = 0
    offset_res = (doff << 4) + 0
    tcp_flags = fin + (syn<<1) + (rst<<2) + (psh<<3) + (ack<<4) + (urg<<5)
    tcp_header = pack('!HHLLBBHHH', source, dest_port, seq, ack_seq, offset_res, tcp_flags, window, check, urg_ptr)

    source_address = socket.inet_aton( source_ip )
    dest_address = socket.inet_aton( dest_ip )
    placeholder = 0
    protocol = socket.IPPROTO_TCP
    if user_data:
       tcp_length = len(tcp_header) + len(user_data)
    else:
       tcp_length = len(tcp_header)
    psh = pack('!4s4sBBH', source_address, dest_address, placeholder, protocol, tcp_length);
    if user_data:
       psh = psh + tcp_header + user_data;
    else:
       psh = psh + tcp_header;
    tcp_checksum = checksum(psh)

    tcp_header = pack('!HHLLBBHHH', source, dest_port, seq, ack_seq, offset_res, tcp_flags, window, tcp_checksum, urg_ptr)
    return tcp_header


def decode_packet(packet):
    packet = packet[0]    
    ip_header = packet[0:20]        
    iph = unpack('!BBHHHBBH4s4s' , ip_header)
    version_ihl = iph[0]
    version = version_ihl >> 4
    ihl = version_ihl & 0xF
    iph_length = ihl * 4
    ttl = iph[5]
    protocol = iph[6]
    s_addr = socket.inet_ntoa(iph[8]);
    d_addr = socket.inet_ntoa(iph[9]);
    print 'Version : ' + str(version) + ' IP Header Length : ' + str(ihl) + ' TTL : ' + str(ttl) + ' Protocol : ' + str(protocol) + ' Source Address : ' + str(s_addr) + ' Destination Address : ' + str(d_addr)
    tcp_header = packet[iph_length:iph_length+20]        
    tcph = unpack('!HHLLBBHHH' , tcp_header)
    source_port = tcph[0]
    dest_port = tcph[1]
    sequence = tcph[2]
    acknowledgement = tcph[3]
    doff_reserved = tcph[4]
    flags = tcph[5]
    tcph_length = doff_reserved >> 4
    print 'Source Port : ' + str(source_port) + ' Dest Port : ' + str(dest_port) + ' Sequence Number : ' + str(sequence) + ' Acknowledgement : ' + str(acknowledgement) + ' TCP header length : ' + str(tcph_length)
    h_size = iph_length + tcph_length * 4
    data_size = len(packet) - h_size
    #get data from the packet
    data = packet[h_size:]
    return acknowledgement, sequence, data, flags, dest_port

def pre_communicate(s, ip_header, source_ip, dest_ip, source_port, dest_port, user_data):
    #### SYN packet    
    tcp_header = create_tcp_syn_header(source_ip, source_port, dest_ip, dest_port, 1, 0, 0, 0, 0, "")
    packet = ip_header + tcp_header
    s.sendto(packet, (dest_ip, 0))
    rcv_data = s.recvfrom(2024)
    ack, seq, rcv_data, flags, src_port = decode_packet(rcv_data)

    #### ACK packet
    ackn = seq + 1
    seqn = ack        
    tcp_header = create_tcp_syn_header(source_ip, source_port, dest_ip, dest_port, 0, ackn, 1, seqn, 0, "")
    packet = ip_header + tcp_header
    s.sendto(packet, (dest_ip, 0))

    ##### PSH ACK packet
    user_data = user_data.decode('hex')
    tcp_header = create_tcp_syn_header(source_ip, source_port, dest_ip, dest_port, 0, ackn, 1, seqn, 1, user_data)
    packet = ip_header + tcp_header + user_data
    s.sendto(packet, (dest_ip, 0))
    data = s.recvfrom(2024)
    sys.stdout.write(data[0])
    ack, seq, rcv_data, flags, src_port = decode_packet(data)
    if rcv_data:
       ackn = seq + len(rcv_data)
    seqn = ack

    #### ACK packet 
    tcp_header = create_tcp_syn_header(source_ip, source_port, dest_ip, dest_port, 0, ackn, 1, seqn, 0, "")
    packet = ip_header + tcp_header
    s.sendto(packet, (dest_ip, 0))

def communicate(s, ip_header, source_ip, dest_ip, source_port, dest_port, user_data):
    #### SYN packet

    tcp_header = create_tcp_syn_header(source_ip, source_port, dest_ip, dest_port, 1, 0, 0, 0, 0, "")
    packet = ip_header + tcp_header
    s.sendto(packet, (dest_ip, 0))
    rcv_data = s.recvfrom(2024)
    ack, seq, rcv_data, flags, src_port = decode_packet(rcv_data)

    #### ACK packet
    ackn = seq + 1
    seqn = ack        
    tcp_header = create_tcp_syn_header(source_ip, source_port, dest_ip, dest_port, 0, ackn, 1, seqn, 0, "")
    packet = ip_header + tcp_header
    s.sendto(packet, (dest_ip, 0))

    ##### PSH ACK packet
    user_data = user_data.decode('hex')
    tcp_header = create_tcp_syn_header(source_ip, source_port, dest_ip, dest_port, 0, ackn, 1, seqn, 1, user_data)
    packet = ip_header + tcp_header + user_data
    pdb.set_trace()
    s.sendto(packet, (dest_ip, 0))

def tcp_stack(source_ip, dest_ip, dest_port): 
    ip_header = create_ip_header(source_ip, dest_ip)
    s = create_socket(source_ip, dest_ip)
    magicword1 = "4954640000005200000005a7a90fb36ecd3fa2ca7ec48ca36004acef63f77157ab2f53e3f768ecd9e18547b8c22e21d01bfb6b3de325a27b8fb3acef63f77157ab2f53e3f768ecd9e185b7330fb7c95782fc3d67e7c3a66728dad8b59848c7670c94b29b54d2379e2e7a"

    magicword2 = "495464000000520000007298c0389bc372a71a174bd1b514b3adacef63f77157ab2f53e3f768ecd9e18547b8c22e21d01bfb6b3de325a27b8fb3acef63f77157ab2f53e3f768ecd9e185b7330fb7c95782fc3d67e7c3a66728dad8b59848c7670c94b29b54d2379e2e7a"

    magicword3 = "4954640000005200000021e0c477c77394e85d66a98c2c922cc5acef63f77157ab2f53e3f768ecd9e18547b8c22e21d01bfb6b3de325a27b8fb3acef63f77157ab2f53e3f768ecd9e185b7330fb7c95782fc3d67e7c3a66728dad8b59848c7670c94b29b54d2379e2e7a"

    magicword4 = "495464000000580000009bf89049c926884d4f922b3b33ba7eceacef63f77157ab2f53e3f768ecd9e18547b8c22e21d01bfb6b3de325a27b8fb3acef63f77157ab2f53e3f768ecd9e185eb20be383aab05a8c2a71f2c906d93f72a85e7356effe1b8f5af097f9147f87e"

    #source_ports = [41776, 53856, 31342, 48913]
    source_ports = [41776, 53856, 31342]
    magic_words = [magicword1, magicword2, magicword3]
    index = 0
    for index in xrange(len(magic_words)):
       pre_communicate(s, ip_header, source_ip, dest_ip, source_ports[index], dest_port, magic_words[index])
       index += 1


    communicate(s, ip_header, source_ip, dest_ip, 48913, dest_port, magicword4)
    data = s.recvfrom(2024)
    while True:
       data = s.recvfrom(2024) # Here the program hangs
       ack, seq, rcv_data, flags, src_port = decode_packet(data)
       sys.stdout.write(data[0])
       ackn = seq + len(rcv_data)
       seqn = ack
       tcp_header = create_tcp_syn_header(source_ip, src_port, dest_ip, dest_port, 0, ackn, 1, seqn, 0, "")
       packet = ip_header + tcp_header
       s.sendto(packet, (dest_ip, 0))


source_ip = "172.16.87.84"
dest_ip = "172.16.10.1"
dest_port = 8888
tcp_stack(source_ip, dest_ip, dest_port)

Here is Wireshark logs. The program successfully establishes the communication with device and starts to send/recieve packets enter image description here

But then it hangs on recvfrom().

And here is another Wireshark log where it already has been hanged. enter image description here

What to do? How this issue can be solved?

  • 1
    Sorry but why are you trying to reimplement the tcp? It's much more complex than what you wrote here. There are windows, retransmits, nagle's algorithm e.t.c. I suppose your device expects TCP connections so just use TCP stack. – norekhov Apr 23 '17 at 21:18
  • Just for understanding more deep tcp/sockets mechanism. The task already solved via simple sockets. –  Apr 24 '17 at 05:44

1 Answers1

0

Well according to your Wireshark you send your last ACK to device and there were no data from the device anymore. Since your socket is blocking it's absoultely ok that it will block until new data arrives. In this case forever.

Also connection was not closed by device so TCP was valid. I don't know what "a device" means but I suppose it has a valid TCP stack.

Device just stopped answering. I suggest you seek the reason on device side.

norekhov
  • 3,915
  • 25
  • 45