I'm playing around with Python sockets, and decided to see if I could implement a very basic name server (i.e. a lookup table for a domain name to an IP address). So I've set up my server so far to just dump the received data.
#!/usr/bin/python
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
host = ''
port = 53
size = 512
s.bind((host, port))
while True:
data, addr = s.recvfrom(size)
print repr(data)
When I run the above code and point my DNS to 127.0.0.1 I get something akin to the following:
'Y\x04\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03www\x06google\x03com\x00\x00\x01\x00\x01'
'J\xaa\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03www\x06google\x03com\x00\x00\x1c\x00\x01'
'Y\x04\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03www\x06google\x03com\x00\x00\x01\x00\x01'
I'm assuming that it is something to do with the DNS question packet structure, but I'm not to sure.
A) Are the above escape characters? A specific text encoding? Or simply just bytes?
B) How can I interpret the data and work with it?
EDIT: Changing the socket to take raw instead of datagrams results in the following:
'E\x00$\x00\xe4\x96\x00\x00#\x01\x00\x00\x7f\x00\x00\x01\x7f\x00\x00\x01\x03\x03X\xb6\x00\x00\x00\x00E\x00V\x00m\x82\x00\x00\xff\x11\x00\x00\x7f\x00\x00\x01\x7f\x00\x00\x01\xf3\xe1\x005\x00B\x00\x00'
You could start with something like this:
#!/usr/bin/env python
import pprint
import socket
import struct
def decode_labels(message, offset):
labels = []
while True:
length, = struct.unpack_from("!B", message, offset)
if (length & 0xC0) == 0xC0:
pointer, = struct.unpack_from("!H", message, offset)
offset += 2
return labels + decode_labels(message, pointer & 0x3FFF), offset
if (length & 0xC0) != 0x00:
raise StandardError("unknown label encoding")
offset += 1
if length == 0:
return labels, offset
labels.append(*struct.unpack_from("!%ds" % length, message, offset))
offset += length
DNS_QUERY_SECTION_FORMAT = struct.Struct("!2H")
def decode_question_section(message, offset, qdcount):
questions = []
for _ in range(qdcount):
qname, offset = decode_labels(message, offset)
qtype, qclass = DNS_QUERY_SECTION_FORMAT.unpack_from(message, offset)
offset += DNS_QUERY_SECTION_FORMAT.size
question = {"domain_name": qname,
"query_type": qtype,
"query_class": qclass}
questions.append(question)
return questions, offset
DNS_QUERY_MESSAGE_HEADER = struct.Struct("!6H")
def decode_dns_message(message):
id, misc, qdcount, ancount, nscount, arcount = DNS_QUERY_MESSAGE_HEADER.unpack_from(message)
qr = (misc & 0x8000) != 0
opcode = (misc & 0x7800) >> 11
aa = (misc & 0x0400) != 0
tc = (misc & 0x200) != 0
rd = (misc & 0x100) != 0
ra = (misc & 0x80) != 0
z = (misc & 0x70) >> 4
rcode = misc & 0xF
offset = DNS_QUERY_MESSAGE_HEADER.size
questions, offset = decode_question_section(message, offset, qdcount)
result = {"id": id,
"is_response": qr,
"opcode": opcode,
"is_authoritative": aa,
"is_truncated": tc,
"recursion_desired": rd,
"recursion_available": ra,
"reserved": z,
"response_code": rcode,
"question_count": qdcount,
"answer_count": ancount,
"authority_count": nscount,
"additional_count": arcount,
"questions": questions}
return result
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
host = ''
port = 53
size = 512
s.bind((host, port))
while True:
data, addr = s.recvfrom(size)
pprint.pprint(decode_dns_message(data))
And then fill in the decoding functions for the remaining records.
Here's an example to send and receive dns packets using socket and dnslib:
import socket
from dnslib import DNSRecord
forward_addr = ("8.8.8.8", 53) # dns and port
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
qname = "duckgo.com" # query
q = DNSRecord.question(qname)
client.sendto(bytes(q.pack()), forward_addr)
data, _ = client.recvfrom(1024)
d = DNSRecord.parse(data)
print("r", str(d.rr[0].rdata)) # prints the A record of duckgo.com
Related
I have a problem with running a python code in pox controller...
I have a code that use ping3 to ping between a pox controller and two servers.
However, every time the ping returns (None) as a result and I can't figure out why.
I have tried to go through the code of the icmp pinger and I find out that this line:
whatReady = select.select([mySocket], [], [], timeLeft)
always return this result: [],[],[]
and because of this ping always return (None) instead of numerical number.
The icmp pinger code:
from socket import *
import socket
import os
import sys
import struct
import time
import select
import binascii
ICMP_ECHO_REQUEST = 8
def checksum(str):
csum = 0
countTo = (len(str) / 2) * 2
count = 0
while count < countTo:
thisVal = ord(str[count+1]) * 256 + ord(str[count])
csum = csum + thisVal
csum = csum & 0xffffffffL
count = count + 2
if countTo < len(str):
csum = csum + ord(str[len(str) - 1])
csum = csum & 0xffffffffL
csum = (csum >> 16) + (csum & 0xffff)
csum = csum + (csum >> 16)
answer = ~csum
answer = answer & 0xffff
answer = answer >> 8 | (answer << 8 & 0xff00)
return answer
def receiveOnePing(mySocket, ID, timeout, destAddr):
timeLeft = timeout
while 1:
startedSelect = time.time()
whatReady = select.select([mySocket], [], [], timeLeft)
howLongInSelect = (time.time() - startedSelect)
if whatReady[0] == []: #Timeout
return "Request timed out."
timeReceived = time.time()
recPacket, addr = mySocket.recvfrom(1024)
#Fill in start
#Fetch the ICMP header from the IP packet
ICMPHeader = recPacket[20:28]
Type, Code, Checksum, packetID, Sequence = struct.unpack('bbHHh', ICMPHeader)
if packetID == ID:
BytesInDouble = struct.calcsize('d')
timeSent = struct.unpack('d',recPacket[28:28 + BytesInDouble])[0]
return timeReceived - timeSent
else:
return 'Different ID'
#Fill in end
timeLeft = timeLeft - howLongInSelect
if timeLeft <= 0:
return "Request timed out"
def sendOnePing(mySocket, destAddr, ID):
# Header is type (8), code (8), checksum (16), id (16), sequence (16)
myChecksum = 0
# Make a dummy header with a 0 checksum
# struct -- Interpret strings as packed binary data
header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, myChecksum, ID, 1)
data = struct.pack("d", time.time())
# Calculate the checksum on the data and the dummy header.
myChecksum = checksum(header + data)
# Get the right checksum, and put in the header
if sys.platform == 'darwin':
myChecksum = socket.htons(myChecksum) & 0xffff
#Convert 16-bit integers from host to network byte order.
else:
myChecksum = socket.htons(myChecksum)
header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, myChecksum, ID, 1)
packet = header + data
mySocket.sendto(packet, (destAddr, 1)) # AF_INET address must be tuple, not str
#Both LISTS and TUPLES consist of a number of objects
#which can be referenced by their position within the object
def doOnePing(destAddr, timeout):
icmp = socket.getprotobyname("icmp")
#SOCK_RAW is a powerful socket type. For more details see: http://sock-raw.ord/papers/sock_raw
#Fill in start
#Create Socket here
try:
mySocket = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp)
except socket.error, (errno, msg):
if errno == 1:
raise socket.error(msg)
#Fill in end
myID = os.getpid() & 0xFFFF #Return the current process i
sendOnePing(mySocket, destAddr, myID)
delay = receiveOnePing(mySocket, myID, timeout, destAddr)
mySocket.close()
return delay
ping("www.google.com") # USA - North America
# ping('www.china.org.cn') # China - Asia
# ping('www.thepiratebay.se') # Sweden - Europe
Can anyone help to understand what is the actual problem and how I can fix it...
I am trying to make a network proxy which will forward packets to another IP. I can sniff a packet, unpack it, and view, print, and manipulate its contents. But when I want to pack the bytes to forward it to some other IP, it gives this error:
struct.error: required argument is not an integer
The error is raised on this line of code:
ip_header = struct.pack('!BBHHHBBH4s4s' ,version_IHL, TOS, totalLength, ID,flags, TTL,protocolNR, checksum,sourceAddress,destinationAddress)
Here is the code. Bold stuff in code are comments in my code.
import socket
import sys
import struct
import re
import logging
import struct
from scapy.all import *
import Functions
logging.basicConfig(filename='example.log',level=logging.DEBUG)
hold = "192.168.0.125"
print ("\n\t\t\t**************************")
print ("\t\t\t*****SettingUp Server*****")
print ("\t\t\t**************************\n\n")
print("\t*****Implementing DHKE")
print ("\t*****Generating server public & private keypairs now . . .")
(e,n), private = Functions.generate_keypair(7, 11)
print ("*****Public Key: {} , {} ", e,n)
print ("*****Private key: {} ", private)
public = (e,n)
ip = '192.168.0.125'
port = 5001
# the public network interface
#HOST = socket.gethostbyname(socket.gethostname())
#..............................................................................................
# create a raw socket and bind it to the public interface
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP)
s.bind(('192.168.0.117',5001))
# Include IP headers
s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
logging.basicConfig(format='%(asctime)s %(message)s')
logging.warning('format=%(asctime)s %(message)s')
# receive all packages
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
#..............................................................................................
data = Functions.recievedata(s)
logging.info('**Packet Recieved')
print("Packet Recieved")
#function_data = tuple(struct.unpack(data))
unpacked_data = struct.unpack('!BBHHHBBH4s4s',data[:20])
listunpacked = list(unpacked_data)
logging.info('--> Unpacking packet')
version_IHL = unpacked_data[0]
version = version_IHL >>4
IHL = version_IHL & 0xF
TOS = unpacked_data[1]
totalLength = unpacked_data[2]
ID = unpacked_data[3]
flags = unpacked_data[4]
fragmentOffset = unpacked_data[4] & 0x1FFF
TTL = unpacked_data[5]
protocolNR = unpacked_data[6]
checksum = unpacked_data[7]
sourceAddress = socket.inet_ntoa(unpacked_data[8])
destinationAddress = socket.inet_ntoa(unpacked_data[9])
#..............................................................................................
print("An IP packet with the size %i is captured.", (totalLength))
print("Raw data: "+ str(data))
print("\nParsed data")
print("Version:\t\t"+ str(version))
print("Header length:\t\t"+ str(IHL*4)+'bytes')
print("Type of service:\t\t" + str(Functions.getTOS(TOS)))
print("Length:\t\t\t"+str(totalLength))
print("ID:\t\t\t"+str(hex(ID)) + ' {' + str(ID) + '}')
print("Flags:\t\t\t" + Functions.getFlags(flags))
print("Fragment offset:\t" + str(fragmentOffset))
print( "TTL:\t\t\t"+str(TTL))
print("Protocol:\t\t" + Functions.getProtocol(protocolNR))
print("Checksum:\t\t" + str(checksum))
print("Source:\t\t\t" + sourceAddress)
print("Destination:\t\t" + destinationAddress)
print("Payload:\n"+str(data[20:]))
# receive a package
#print(s.recvfrom(65565))
#IP = input("Enter IP address to send: ")
#port = int(input("Port: "))
#..............................................................................................
print("\tOld Destination: "+ destinationAddress)
listunpacked[9] = hold
unpacked_data = tuple(listunpacked)
print("\n\t\tNew Address is: "+ unpacked_data[9])
print()
#s.inet_aton(unpacked_data[9]) = hold
#unpacked_data = tuple(listunpacked)
#unpacked_data = bytes(unpacked_data)
#destinationAddress = socket.inet_ntoa(unpacked_data[9])
#..............................................................................................
# tcp header fields
tcp_source = 80 # source port
tcp_dest = 5001 # destination port
tcp_seq = 454
tcp_ack_seq = 0
tcp_doff = 5 # 4 bit field, size of tcp header, 5 * 4 = 20 bytes
# tcp flags
tcp_fin = 0
tcp_syn = 1
tcp_rst = 0
tcp_psh = 0
tcp_ack = 0
tcp_urg = 0
tcp_window = socket.htons(5840) # maximum allowed window size
tcp_check = 0
tcp_urg_ptr = 0
tcp_offset_res = (tcp_doff << 4) + 0
tcp_flags = tcp_fin + (tcp_syn << 1) + (tcp_rst << 2) + (tcp_psh << 3) + (tcp_ack << 4) + (tcp_urg << 5)
# the ! in the pack format string means network order
tcp_header = tuple(struct.pack('!HHLLBBHHH', tcp_source, tcp_dest, tcp_seq, tcp_ack_seq, tcp_offset_res, tcp_flags, tcp_window,tcp_check, tcp_urg_ptr))
#p =(data+tcp_header)
#hold = bytes(hold,"utf-8")
#hold = socket.inet_aton ( hold )
#checksum = bytes(checksum,"utf-8")
#destinationAddress = c_int(listunpacked[9])
checksum = bytes(str(checksum),"utf-8")
#ip_header = struct.pack('!BBHHHBBH4s4s' , version_IHL, TOS, totalLength, ID,flags, TTL,protocolNR, checksum,sourceAddress,destinationAddress)
#tcp_header = struct.pack('!HHLLBBH' , tcp_source, tcp_dest, tcp_seq, tcp_ack_seq, tcp_offset_res, tcp_flags, tcp_window) + struct.pack('H' , tcp_check) + struct.pack('!H' , tcp_urg_ptr)
#packet = ip_header + tcp_header + str(data[20:])
message = "How are you"
#data = bytes(unpacked_data,"utf-8") + tcp_header + message
ip_header = struct.pack('!BBHHHBBH4s4s' ,version_IHL, TOS, totalLength, ID,flags, TTL,protocolNR, checksum,sourceAddress,destinationAddress)
data = bytes(unpacked_data) + data[20:]
s.sendto(data, ("192.168.0.125" , 5001))
print("Packet sent")
# disabled promiscuous mode
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
ip_header = struct.pack('!BBHHHBBH4s4s' ,version_IHL, TOS, totalLength, ID,flags, TTL,protocolNR, checksum,sourceAddress,destinationAddress)
Both the B and H formats require integer arguments (or non-integer objects that implement the __index__ method) (see Format Characters).
The checksum argument is now of type bytes because you set it here before packing:
checksum = bytes(str(checksum),"utf-8")
And bytes objects do not implement the __index__ method.
You can check this using dir(checksum).
That's why you're getting the struct.error exception.
When packing a value x using one of the integer formats ('b', 'B',
'h', 'H', 'i', 'I', 'l', 'L', 'q', 'Q'), if x is outside the valid
range for that format then struct.error is raised.
Either:
Use a different variable for the bytes(str(checksum),"utf-8") output
Pass an int type object for the checksum value
I am using raw sockets in python to send SYN packets repeatedly at high rate for a project. I am able to send SYN at a rate of 120 Mb/S using below python Script. Is there a way to optimize it to increase the rate of the packets?
I think CPU is the bottleneck, as my NIC supports upto 1 Gbps. I am even constructing the packet once and just resending it repeatedly.
# some imports
import thread
import socket, sys
from struct import *
import time
import datetime as dt
def sendFunc(s, packet, dest_ip, sizeOfPacket):
start_time = time.time()
i = 0
while(1):
time_diff = time.time() - start_time
i = i + 1
if time_diff > 1:
start_time = time.time()
print i*sizeOfPacket
i = 0
s.sendto(packet, (dest_ip , 0 )) # put this in a loop if you want to flood the target
# checksum functions needed for calculation checksum
def checksum(msg):
s = 0
# loop taking 2 characters at a time
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 + (s >> 16);
#complement and mask to 4 byte short
s = ~s & 0xffff
return s
#create a raw socket
try:
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)
except socket.error , msg:
print 'Socket could not be created. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
sys.exit()
# tell kernel not to put in headers, since we are providing it
s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
# now start constructing the packet
packet = '';
source_ip = 'x.x.x.x'
dest_ip = 'y.y.y.y' # or socket.gethostbyname('www.google.com')
# ip header fields
ihl = 5
version = 4
tos = 0
tot_len = 20 + 20 # python seems to correctly fill the total length, dont know how ??
id = 54321 #Id of this packet
frag_off = 0
ttl = 255
protocol = socket.IPPROTO_TCP
check = 10 # python seems to correctly fill the checksum
saddr = socket.inet_aton ( source_ip ) #Spoof the source ip address if you want to
daddr = socket.inet_aton ( dest_ip )
ihl_version = (version << 4) + ihl
# the ! in the pack format string means network order
ip_header = pack('!BBHHHBBH4s4s' , ihl_version, tos, tot_len, id, frag_off, ttl, protocol, check, saddr, daddr)
# tcp header fields
source = 1234 # source port
dest = 80 # destination port
seq = 0
ack_seq = 0
doff = 5 #4 bit field, size of tcp header, 5 * 4 = 20 bytes
#tcp flags
fin = 0
syn = 1
rst = 0
psh = 0
ack = 0
urg = 0
window = socket.htons (5840) # maximum allowed window size
check = 0
urg_ptr = 0
offset_res = (doff << 4) + 0
tcp_flags = fin + (syn << 1) + (rst << 2) + (psh <<3) + (ack << 4) + (urg << 5)
# the ! in the pack format string means network order
tcp_header = pack('!HHLLBBHHH' , source, dest, seq, ack_seq, offset_res, tcp_flags, window, check, urg_ptr)
# pseudo header fields
source_address = socket.inet_aton( source_ip )
dest_address = socket.inet_aton(dest_ip)
placeholder = 0
protocol = socket.IPPROTO_TCP
tcp_length = len(tcp_header)
psh = pack('!4s4sBBH' , source_address , dest_address , placeholder , protocol , tcp_length);
psh = psh + tcp_header;
tcp_checksum = checksum(psh)
# make the tcp header again and fill the correct checksum
tcp_header = pack('!HHLLBBHHH' , source, dest, seq, ack_seq, offset_res, tcp_flags, window, tcp_checksum , urg_ptr)
# final full packet - syn packets dont have any data
packet = ip_header + tcp_header
#Send the packet finally - the port specified has no effect
print "size of packet", len(packet)
sendFunc(s, packet, dest_ip, len(packet))
So, I have a problem where when I use s.sendto(). Once I arrange all the information to be put into the packet and I try to send it, it ends up telling me there is something wrong with my arguments.
The code below is the code I'm using (admittedly from this website).
# some imports
import socket, sys
from struct import *
# checksum functions needed for calculation checksum
def checksum(msg):
s = 0
# loop taking 2 characters at a time
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 + (s >> 16);
#complement and mask to 4 byte short
s = ~s & 0xffff
return s
#create a raw socket
try:
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)
except socket.error , msg:
print 'Socket could not be created. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
sys.exit()
# tell kernel not to put in headers, since we are providing it
s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
# now start constructing the packet
packet = '';
source_ip = '192.168.0.13'
dest_ip = '192.168.0.1' # or socket.gethostbyname('www.google.com')
# ip header fields
ihl = 5
version = 4
tos = 0
tot_len = 20 + 20 # python seems to correctly fill the total length, dont know how ??
id = 54321 #Id of this packet
frag_off = 0
ttl = 255
protocol = socket.IPPROTO_TCP
check = 10 # python seems to correctly fill the checksum
saddr = socket.inet_aton ( source_ip ) #Spoof the source ip address if you want to
daddr = socket.inet_aton ( dest_ip )
ihl_version = (version << 4) + ihl
# the ! in the pack format string means network order
ip_header = pack('!BBHHHBBH4s4s' , ihl_version, tos, tot_len, id, frag_off, ttl, protocol, check, saddr, daddr)
# tcp header fields
source = 1234 # source port
dest = 80 # destination port
seq = 0
ack_seq = 0
doff = 5 #4 bit field, size of tcp header, 5 * 4 = 20 bytes
#tcp flags
fin = 0
syn = 1
rst = 0
psh = 0
ack = 0
urg = 0
window = socket.htons (5840) # maximum allowed window size
check = 0
urg_ptr = 0
offset_res = (doff << 4) + 0
tcp_flags = fin + (syn << 1) + (rst << 2) + (psh <<3) + (ack << 4) + (urg << 5)
# the ! in the pack format string means network order
tcp_header = pack('!HHLLBBHHH' , source, dest, seq, ack_seq, offset_res, tcp_flags, window, check, urg_ptr)
# pseudo header fields
source_address = socket.inet_aton( source_ip )
dest_address = socket.inet_aton(dest_ip)
placeholder = 0
protocol = socket.IPPROTO_TCP
tcp_length = len(tcp_header)
psh = pack('!4s4sBBH' , source_address , dest_address , placeholder , protocol , tcp_length);
psh = psh + tcp_header;
tcp_checksum = checksum(psh)
# make the tcp header again and fill the correct checksum
tcp_header = pack('!HHLLBBHHH' , source, dest, seq, ack_seq, offset_res, tcp_flags, window, tcp_checksum , urg_ptr)
# final full packet - syn packets dont have any data
packet = ip_header + tcp_header
#Send the packet finally - the port specified has no effect
while True:
s.sendto(packet, (dest_ip , 80))
And when I run it, I get this error:
File "tcp-syn.py", line 98, in <module>
s.sendto(packet, (dest_ip , 80))
socket.error: [Errno 22] Invalid argument
Any help would be appreciated!
The following code is for simulating a Modbus interface on an embedded device. Unfortunely, it has an older Python (2.4.3). The code works on 2.7, but not 2.4.3 because the the version Python I am using does not support struct.pack_into, only struct.pack. Could I get some advice on how to fix this? I think I need to use a string maybe and convert to a byte buffer. This talks to non-Python code, so pickle can not be used I believe.
import socket
import sys
import array
import struct
def hexdump(src, length=16):
FILTER = ''.join([(len(repr(chr(x))) == 3) and chr(x) or '.' for x in range(256)])
lines = []
for c in xrange(0, len(src), length):
chars = src[c:c+length]
hex = ' '.join(["%02x" % ord(x) for x in chars])
printable = ''.join(["%s" % ((ord(x) <= 127 and FILTER[ord(x)]) or '.') for x in chars])
lines.append("%04x %-*s %s\n" % (c, length*3, hex, printable))
return ''.join(lines)
HOST = '192.168.1.187'
PORT = 502
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind((HOST,PORT))
s.listen(1)
conn, addr = s.accept()
data = []
datatran = array.array('B', '\x00' * 14)
data = conn.recv(1024)
print 'Connect by', addr
while (data):
sys.stdout.write(hexdump(data))
TransID , ProtoColID, PacketLength, UnitID, FC, StartAddress, RegisterCount = struct.unpack_from(">hhhBBhh", data)
print TransID, ProtoColID, PacketLength, UnitID
print FC, StartAddress, RegisterCount
struct.pack_into(">hhhBBBh", datatran, 0, TransID , ProtoColID, PacketLength+2, UnitID, FC, 2, 51)
conn.sendall(datatran)
data = conn.recv(1024)
conn.close()
s.close()
Thanks
With a bit of size calculation it should be possible to use pack and unpack instead:
import socket
import sys
import array
import struct
def hexdump(src, length=16):
FILTER = ''.join([(len(repr(chr(x))) == 3) and chr(x) or '.' for x in range(256)])
lines = []
for c in xrange(0, len(src), length):
chars = src[c:c+length]
hex = ' '.join(["%02x" % ord(x) for x in chars])
printable = ''.join(["%s" % ((ord(x) <= 127 and FILTER[ord(x)]) or '.') for x in chars])
lines.append("%04x %-*s %s\n" % (c, length*3, hex, printable))
return ''.join(lines)
HOST = '192.168.1.187'
PORT = 502
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind((HOST,PORT))
s.listen(1)
conn, addr = s.accept()
datatranStruct = '>hhhBBBh'
datatranStructSize = struct.calcsize(datatranStruct)
datatranFormat = '%s%dx' % (datatranStruct, 14 - datatranStructSize)
recvStruct = '>hhhBBhh'
recvStructSize = struct.calcsize(recvStruct)
data = conn.recv(1024)
print 'Connect by', addr
while (data):
sys.stdout.write(hexdump(data))
recvFormat = '%s%dx' % (recvStruct, len(data) - recvStructSize)
TransID , ProtoColID, PacketLength, UnitID, FC, StartAddress, RegisterCount = struct.unpack(recvFormat, data)
print TransID, ProtoColID, PacketLength, UnitID
print FC, StartAddress, RegisterCount
datatran = struct.pack(datatranFormat, TransID , ProtoColID, PacketLength+2, UnitID, FC, 2, 51)
conn.sendall(datatran)
data = conn.recv(1024)
conn.close()
s.close()