コード例 #1
0
def build_ip_header():
    ihl = 5
    ver = 4
    tos = 0

    id_of_ip_pkt = 54321
    fragm_off = 0
    ttl = 225
    protocol = socket.IPPROTO_TCP
    checksum_for_ip = 0

    source_add_for_ip = socket.inet_aton(global_data.get_value("local_ip"))
    dest_add_for_ip = socket.inet_aton(global_data.get_value("server_ip"))

    ihl_ver = (ver << 4) + ihl
    tot_length = 4 * ihl + len(global_data.get_value("tcp_header"))

    ip_header = struct.pack('!BBHHHBBH4s4s', ihl_ver, tos, tot_length,
                            id_of_ip_pkt, fragm_off, ttl, protocol,
                            checksum_for_ip, source_add_for_ip,
                            dest_add_for_ip)

    checksum = util.ip_checksum(ip_header)
    """ add checksum into ip header """
    ip_header = struct.pack('!BBHHHBBH4s4s', ihl_ver, tos, tot_length,
                            id_of_ip_pkt, fragm_off, ttl, protocol, checksum,
                            source_add_for_ip, dest_add_for_ip)

    ip_header = ''.join([ip_header, global_data.get_value("tcp_header")])
    global_data.set_value("ip_header", ip_header)
def get_gateway_mac_binary():
    interface = global_data.get_value("interface")
    main_socket = global_data.get_value("main_socket")

    # simulate a broadcast address to find the gateway mac address
    arp_header = ethernet.build_arp_header()
    ethernet_header = ethernet.build_ethernet_header_for_arp()
    ethernet_packet = ''.join([ethernet_header, arp_header])

    # bind with interface
    main_socket.bind((interface, socket.SOCK_RAW))
    # send ethernet packet, so that MAC address of gateway can be retrieved from its response.
    main_socket.send(ethernet_packet)

    # we store the size of struct, will be used while unpacking the packets, corresponding to the given format.
    ethernet_header_length = struct.calcsize('!6s6sH')
    arp_header_length = struct.calcsize('!HHBBH6s4s6s4s')

    while True:
        packet = main_socket.recv(65565)
        # unpack the ethernet_packet
        fields = struct.unpack('!6s6sH', packet[:ethernet_header_length])

        if fields[2] == 2054:
            break

    # unpack arp packet from eth packet
    arp_fields = struct.unpack(
        '!HHBBH6s4s6s4s', packet[ethernet_header_length:][:arp_header_length])
    gateway_mac_binary = arp_fields[5]
    print "gateway_mac_binary:", gateway_mac_binary
    return gateway_mac_binary
コード例 #3
0
def send_ack_to_server(seq_no):
    http.build_empty_http_header()
    tcp.build_tcp_header(global_data.get_value("local_port"), 80,
                         1 + global_data.get_value("http_request_length"),
                         seq_no + 1, 5, 0, 0, 0, 0, 1)
    ip.build_ip_header()
    ethernet.build_ethernet_header_for_ip()
    send_packet_to_server()
コード例 #4
0
def handshake_step_three():
    http.build_empty_http_header()
    tcp.build_tcp_header(global_data.get_value("local_port"), 80, 1,
                         global_data.get_value("sequence_number") + 1, 5, 0, 0,
                         0, 0, 1)
    ip.build_ip_header()
    ethernet.build_ethernet_header_for_ip()
    data_transfer.send_packet_to_server()
def build_tcp_header(source_of_tcp_p, dest_of_tcp_p, seq_of_tcp_p,
                     ack_seq_of_tcp_p, d_off_tcp_p, fin_p, syn_p, rst_p, psh_p,
                     ack_p):
    # TCP Header Section
    # source port
    source_port = source_of_tcp_p
    # destination port
    destination_port = dest_of_tcp_p

    seq_num = seq_of_tcp_p
    ack_num = ack_seq_of_tcp_p
    d_offset = 5

    # flags
    fin = fin_p
    syn = syn_p
    rst = rst_p
    psh = psh_p
    ack = ack_p
    urg = 0
    #   size of max allowed window size
    window_size = socket.htons(5840)
    checksum = 0
    urg_pointer = 0

    offset_res_of_tcp = (d_offset << 4) + 0
    flags = fin + (syn << 1) + (rst << 2) + (psh << 3) + (ack << 4) + (
        urg << 5)

    tcp_header_p = struct.pack("!HHLLBBHHH", source_port, destination_port,
                               seq_num, ack_num, offset_res_of_tcp, flags,
                               window_size, checksum, urg_pointer)

    source_address = socket.inet_aton(global_data.get_value("local_ip"))

    dest_address = socket.inet_aton(global_data.get_value("server_ip"))

    placeholder = 0

    protocol = socket.IPPROTO_TCP
    tcp_length = len(tcp_header_p) + len(global_data.get_value("http_request"))

    psh = struct.pack('!4s4sBBH', source_address, dest_address, placeholder,
                      protocol, tcp_length)

    psh = psh + tcp_header_p + global_data.get_value("http_request")

    checksum = util.tcp_checksum(psh)

    # add correct tcp header checksum
    tcp_header = struct.pack(
        '!HHLLBBH', source_port, destination_port, seq_num,
        ack_num, offset_res_of_tcp, flags, window_size) + struct.pack(
            'H', checksum) + struct.pack('!H', urg_pointer)
    tcp_header = ''.join([tcp_header, global_data.get_value("http_request")])

    # save into global data value
    global_data.set_value("tcp_header", tcp_header)
コード例 #6
0
def send_fin_ack_to_server():
    http.build_empty_http_header()
    tcp.build_tcp_header(global_data.get_value("local_port"), 80,
                         global_data.get_value("acknowledge_number"),
                         int(global_data.get_value("sequence_number")) + 1, 5,
                         1, 0, 0, 0, 1)
    ip.build_ip_header()
    ethernet.build_ethernet_header_for_ip()
    send_packet_to_server()
コード例 #7
0
def send_data_to_server():
    """
    send http request to server
    """
    http.build_http_header()
    tcp.build_tcp_header(global_data.get_value("local_port"), 80, 1,
                         int(global_data.get_value("sequence_number")), 5, 0,
                         0, 0, 1, 1)
    ip.build_ip_header()
    ethernet.build_ethernet_header_for_ip()
    send_packet_to_server()
def build_arp_header():
    hardware_type = 1
    protocol_type = 2048
    hardware_length = 6
    protocol_length = 4
    broadcast_mac_address = struct.pack('!6B', 255, 255, 255, 255, 255, 255)

    operation = 1
    arp_pkt = struct.pack('!HHBBH6s4s6s4s', hardware_type, protocol_type, hardware_length, protocol_length, operation,
                          global_data.get_value("local_mac_binary"), global_data.get_value("local_ip_binary"), broadcast_mac_address,
                          global_data.get_value("gateway_ip_binary"))
    return arp_pkt
def build_ethernet_header_for_arp():
    ether_type = 2054  # 0x0806
    broadcast_mac_address = struct.pack('!6B', 255, 255, 255, 255, 255, 255)
    header_of_eth = struct.pack('!6s6sH', broadcast_mac_address, global_data.get_value("local_mac_binary"), ether_type)

    eth_pkt = header_of_eth
    return eth_pkt
コード例 #10
0
def handshake_step_one():
    http.build_empty_http_header()
    tcp.build_tcp_header(global_data.get_value("local_port"), 80, 0, 0, 5, 0,
                         1, 0, 0, 0)
    ip.build_ip_header()
    ethernet.build_ethernet_header_for_ip()
    data_transfer.send_packet_to_server()
コード例 #11
0
def build_http_header():
    http_header = "GET " + global_data.get_value("url") + " HTTP/1.0\r\n\r\n"
    http_request = http_header
    global_data.set_value("http_request", http_request)

    http_request_length = len(http_header)
    global_data.set_value("http_request_length", http_request_length)
コード例 #12
0
def send_packet_to_server():
    global_data.get_value("main_socket").bind(
        (global_data.get_value("interface"), 0))
    global_data.get_value("main_socket").send(
        global_data.get_value("eth_header"))
    last_packet_sent_time = time.time()
    global_data.set_value("last_packet_sent_time", last_packet_sent_time)
def build_ethernet_header_for_ip():
    ether_type = 2048
    header_of_eth = struct.pack('!6s6sH', global_data.get_value("gateway_mac_binary"), global_data.get_value("local_mac_binary"), ether_type)
    eth_header = ''.join([header_of_eth, global_data.get_value("ip_header")])
    global_data.set_value("eth_header", eth_header)
def get_local_ip_binary():
    local_ip = global_data.get_value("local_ip")
    local_ip_binary = socket.inet_aton(local_ip)
    print "local_ip_binary:", local_ip_binary
    return local_ip_binary
コード例 #15
0
def receive_data_from_server():
    """
    receive data from the server, for three way handshake and for receive http response data
    """
    downloaded_file_name = global_data.get_value("downloaded_file_name")
    main_socket = global_data.get_value("main_socket")
    local_port = global_data.get_value("local_port")
    server_ip = global_data.get_value("server_ip")
    local_ip = global_data.get_value("local_ip")

    f = open(downloaded_file_name, 'a')
    while True:
        if (time.time() -
                global_data.get_value("last_packet_sent_time")) > 180:
            print "Program, rawhttpget, does not receive any data from the remote server for three minutes. Please retry again."
            sys.exit(0)

        packet = main_socket.recvfrom(65565)
        packet = packet[0]

        ethernet_header_length = struct.calcsize('!6s6sH')

        ip_header = packet[ethernet_header_length:ethernet_header_length + 20]
        global_data.set_value("ip_header", ip_header)
        iph = struct.unpack('!BBHHHBBH4s4s', ip_header)
        version_ihl = iph[0]
        ihl = version_ihl & 0xF
        iph_length = ihl * 4
        server_as_source_address = socket.inet_ntoa(iph[8])
        local_as_destination_address = socket.inet_ntoa(iph[9])
        tcp_header = packet[ethernet_header_length +
                            iph_length:ethernet_header_length + iph_length +
                            20]
        global_data.set_value("tcp_header", tcp_header)

        tcph = struct.unpack('!HHLLBBHHH', tcp_header)
        server_as_source_port = tcph[0]
        local_as_destination_port = tcph[1]
        sequence_number = tcph[2]
        global_data.set_value("sequence_number", sequence_number)
        acknowledge_number = tcph[3]
        global_data.set_value("acknowledge_number", acknowledge_number)
        data_offset_reserved = tcph[4]
        tcp_flags = tcph[5]

        flag_fin = tcp_flags & int(hex(1), 16)
        flag_syn = (tcp_flags >> 1) & int(hex(1), 16)
        flag_ack = (tcp_flags >> 4) & int(hex(1), 16)

        tcph_length = data_offset_reserved >> 4
        header_size = ethernet_header_length + iph_length + tcph_length * 4
        data_size = len(packet) - header_size
        data = packet[header_size:]

        if local_as_destination_port != local_port or server_as_source_port != 80 \
                or server_as_source_address != server_ip or local_as_destination_address != local_ip:
            continue
        else:
            if flag_ack == 1 and flag_syn == 1:
                old_sequence_number = sequence_number + 1
                global_data.set_value("old_sequence_number",
                                      old_sequence_number)
                break

            if data_size > 6 and global_data.get_value(
                    "current_cwnd_size") <= 1000:
                if global_data.get_value("old_sequence_number") + global_data.get_value("old_data_length") == \
                        global_data.get_value("sequence_number") and util.tcp_checksum(global_data.get_value("ip_header")) == 0:
                    if (time.time() -
                            global_data.get_value("last_packet_sent_time")
                        ) < 60:
                        if data.split('\r\n\r\n')[0] == data:
                            """ directly write data into file """
                            f.write(data)
                        else:
                            data_containing_header = data.split('\r\n\r\n')[0]
                            http_status = data_containing_header.split(' ')[1]
                            if http_status == "200":
                                f.write(data.split('\r\n\r\n')[1])
                            else:
                                print "Only 200 will be considered!"
                                break

                        old_sequence_number = global_data.get_value(
                            "sequence_number")
                        global_data.set_value("old_sequence_number",
                                              old_sequence_number)
                        old_data_length = data_size
                        global_data.set_value("old_data_length",
                                              old_data_length)
                        """ solve the retransmit packet needs to be ACK """
                        if global_data.get_value(
                                "number_of_retransmit_packet_to_be_ACK") > 0:
                            new_number_of_retransmit_packet_to_be_ACK = global_data.get_value(
                                "number_of_retransmit_packet_to_be_ACK") - 1
                            global_data.set_value(
                                "number_of_retransmit_packet_to_be_ACK",
                                new_number_of_retransmit_packet_to_be_ACK)
                        """ normal cwnd size """
                        if 0 < global_data.get_value(
                                "current_cwnd_size") + 1 < 1000:
                            new_current_cwnd_size = global_data.get_value(
                                "current_cwnd_size") + 1
                            global_data.set_value("current_cwnd_size",
                                                  new_current_cwnd_size)
                        else:
                            new_current_cwnd_size = 1
                            global_data.set_value("current_cwnd_size",
                                                  new_current_cwnd_size)

                        send_ack_to_server(
                            global_data.get_value("sequence_number"))
                    else:
                        print "retransmit because the 60 seconds limit"
                        send_ack_retransmit_to_server(
                            global_data.get_value("old_sequence_number"))
                else:
                    if global_data.get_value(
                            "current_cwnd_size"
                    ) + 1 <= 0 or global_data.get_value(
                            "current_cwnd_size") + 1 >= 1000:
                        new_current_cwnd_size = 1
                        global_data.set_value("current_cwnd_size",
                                              new_current_cwnd_size)
                    else:
                        new_current_cwnd_size = global_data.get_value(
                            "current_cwnd_size") + 1
                        global_data.set_value("current_cwnd_size",
                                              new_current_cwnd_size)
                    new_number_of_retransmit_packet_to_be_ACK = 1
                    global_data.set_value(
                        "number_of_retransmit_packet_to_be_ACK",
                        new_number_of_retransmit_packet_to_be_ACK)
                    print "retransmit because sequence number or checksum error"
                    send_ack_retransmit_to_server(
                        global_data.get_value("old_sequence_number"))

            if flag_fin == 1 and global_data.get_value(
                    "number_of_retransmit_packet_to_be_ACK") == 0:
                f.close()
                send_fin_ack_to_server()
                break
                sys.exit(0)