python ioctl creating ifreq struct - python

I am very new to system programming. I am trying to query some NIC information using Python with ioctl, I easily got the code but having some difficulty in understanding
Python code to get the ip address
nic = "eth1"
# Create socket object
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# **How did they conclude the formate to be 16sH14s and why 14 times \x00 ? Please advice**
ifreq = struct.pack('16sH14s', nic, socket.AF_INET, '\x00'*14)
result = fcntl.ioctl(fd, SIOCGIFADDR, ifreq)
# My wild guess **unpack format would be same as pack**. But I am wrong
ip = struct.unpack('16sH2x4s8x', result)[2]
print socket.inet_ntoa(ip)
Can somebody advice how to decide upon the format and why/how to decide upon number of null characters ?
This link seemed to be almost same question as mine but couldn't find my answer
http://www.unix.com/programming/148374-python-struct-pack.html
I found another way of creating ifreq.. ifreq = struct.pack('256s', self.iface). If possible please help me understand the difference.

Related

How to get only COMx in Serial.Tools.List (Python)?

I created a program, which sorts all connected Devices (Serials). I only want the List to get COMx Ports instead of their description.
import serial.tools.list_ports
ports = serial.tools.list_ports.comports()
List1 = []
for port in sorted(ports):
List1.append(port)
print(*List1)
It always shows the description too, and i don't know what to do?
Can anyone help me to solve this problem? Any Ideas?
I also read the pyserial documentation and tried to divide results into port, desc, hwid, didn't work...
If you are on Windows, you will be able to list only the COM port names with one of the following:
List1.append(port.name)
or
List1.append(port.device)
If you stick to the string named COMx, you can change comports() to:
ports = serial.tools.list_ports.grep("COM[1-9][0-9]*")
serial.tools.list_ports
classserial.tools.list_ports.ListPortInfo
device
Full device name/path, e.g. /dev/ttyUSB0. This is also the information returned as first element when accessed by index.
name
Short device name, e.g. ttyUSB0.

Python socket receive bufsize parameter value

I am new to programming and started with Python about 2 weeks ago using a course on FCC, I am currently in the networking chapter.
The exercise was about creating a program which counts the maximum number of characters in a document of a website and only display the first 3000 characters of that document using the socket library in Python. The next exercise was to do the same with the urllib library. I have noticed that, when using socket, I was sometimes missing some letters in the file when the bufsize parameter of the sock.recv(bufsize,[flag]) method wasn't set to the total length of received bytes from the document. For example when I used 1024 as the value for bufsize, there were some letters missing here and there from the retrieved document, but when I put the bufsize to 95000 (exact number of bytelength of that document), I got all the letters and everything worked fine.
Please don't be too harsh on me with the code, I am just starting to write something, but here is my example:
import socket
import re
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
while True:
userinp = input("Enter a URL: ")
try:
if userinp.startswith("http"):
url = userinp.split("/")[2]
#print(url)
sock.connect((url, 80))
#print("http start connected")
break
elif userinp.startswith("www"):
url = userinp.split("/")[0]
#print(url)
sock.connect((url, 80))
#print("www start connected")
break
else:
url = userinp.split("/")[0]
#print(url)
sock.connect((url, 80))
#print("else start connected")
break
except:
print("Please enter a valid URL")
continue
if userinp.startswith("http:"):
cmd0 = "GET " + userinp + " HTTP/1.0\r\n\r\n"
cmd = cmd0.encode()
#print("http bytes: ", cmd)
elif userinp.startswith("https:"):
cmd0 = "GET " + userinp + " HTTP/1.1\r\nHost: " + url + "\r\n\r\n"
cmd = cmd0.encode()
#print("https bytes: ", cmd)
else:
cmd0 = "GET http://" + userinp + " HTTP/1.0\r\n\r\n"
cmd = cmd0.encode()
sock.send(cmd)
#print("cmd request sent")
count = 0
str = ""
while True:
data = sock.recv(95000) ##536 magic number in romeo.txt, 95000 in mbox-short.txt
if len(data) < 1: ##http://data.pr4e.org/mbox-short.txt
break
#print("Byte length:", len(data))
data = data.decode()
pos = data.find("\r\n\r\n") + 4
for each in data[pos:]:
count += 1
if count <= 3000:
str += each
print(str, "Total characters:", count, len(str))
sock.shutdown(socket.SHUT_RDWR)
sock.close()
The first if statements are meant for the first exercise in the chapter, which was handling userinput URLs using the socket library. On many websites I have some problems with that too, since it often says
301: Moved Permanently
But the location specified in the document says it moved to the exact same location.\
So my questions are:
Why do I have to set the bufsize parameter to the exact bytelength of the retrieved document in order to get all letters out of it? Is there a way around this using the socket library?
Why do some websites specify that they are moved permanently, but show the exact same location of the website?
With the urllib library it is much easier, since it does "all the stuff" for me, but I would like to know how I need to write the program with the socket library too, just to get a better understanding of it.
I'm sorry for the noob questions, but I've read that beginner questions are welcome aswell! I hope you can help me with my problem, thank you in advance! :)
Actually, before HTTP/1.1, Content-Length header is SHOULD on RFC1945, of course this means the header was not required. How did application distinguish end of file, closing of TCP connection was regarded as it. Therefore, there are files of which we can't know
size before downloading even now. This story is about HTTP, layer 7, application layer in OSI model.
Sockets which you use belong TCP, layer 5 and 4. TCP doesn't have how to know size of files. It just manages connections and sends bytes only. It doesn't think any other thing. If TCPs work correctly each other, other layers are guaranteed to work. This is same as HTTP too.
How network works? is itself able theme to be written a thick book. If you are interested in, I recommend to read some books about network.
If anyone is interested in the answer to this question (probably not, because it is a complete beginner question):
I played around with the program a little and added print statements basically everywhere to be able to see what it is doing at what point exactly. The received data every time in the sock.recv is set to 512, so it sends 512 bytes worth of information per iteration of that loop. Then those 512 bytes of information will be used by the for loop after decoding it to a string, iterating through every character of the string but only up to the end of those 512 bytes of information, which in this case (romeo.txt) ends with the "s" in the last line of the poem. Then the sock.recv starts receiving the rest of the information of the document and the for loop starts iterating through the rest again, but this time because of the "data[pos:]" (initially used to remove the header) it starts at the beginning position of those remaining bytes + 4. So with this I would have 3 letters less for each iteration of the loops.

Get all FQDN for an IP address in Python

I've the following problem : I'm actually making a script for an ovirt server to automatically delete virtual machine which include unregister them from the DNS. But for some very specific virtual machine there is multiple FQDN for an IP address example:
myfirstfqdn.com IN A 10.10.10.10
mysecondfqdn.com IN A 10.10.10.10
I've tried to do it with socket in Python but it return only one answer, I've also tried python with dnspython but I failed.
the goal is to count the number of type A record on the dns server
Anyone have an idea to do stuff like this?
That's outright impossible. If I am in the right mood, I could add an entry to my DNS server pointing to your IP address. Generally, you cannot find it out (except for some hints in some protocols like http(s)).
Given a zone file in the above format, you could do something like...
from collections import defaultdict
zone_file = """myfirstfqdn.com IN A 10.10.10.10
mysecondfqdn.com IN A 10.10.10.10"""
# Build mapping for lookups
ip_fqdn_mapping = defaultdict(list)
for record in zone_file.split("\n"):
fqdn, record_class, record_type, ip_address = record.split()
ip_fqdn_mapping[ip_address].append(fqdn)
# Lookup
ip_address_to_lookup = "10.10.10.10"
fqdns = ip_fqdn_mapping[ip_address_to_lookup]
print(fqdns)
Note: Using socket can be done like so - Python lookup hostname from IP with 1 second timeout
However this does require that DNS server that you are querying has correctly configured PTR reverse records.
https://www.cloudns.net/wiki/article/40/

meaning of python socket address info output

I'm tring to understand the meaning of the python socket address info output.
import socket
rawSocket = socket.socket(socket.PF_PACKET, socket.SOCK_RAW, socket.htons(0x0800))
pkt = rawSocket.recvfrom(2048)
print pkt[1]
('ens33', 2048, 1, 1, 'HE \xfd\x12h')
ens33 is the interface sending the data.
I guess that 2048 is the buffer size.
I have no idea what the first "1" is. Sometimes it's "0".
I noticed the second "1" relates to the interface (i.e. "772" for "lo")
'HE \xfd\x12h' : Reverting the converted hex values, we get '\x48\x45\x20\xfd\x12\x68', it gives the mac address of host machine in a VM bridged connection.
So, the main question is for #3. What 1 or 0 means here ?
In short, the third 1 means it's a broadcast packet. 0 would mean it was a packet addressed to the machine running the Python code. Details follow.
This is based on Python 3.6, but the answer should be similar for other Py2 or Py3 versions. The answer is split between the source for the socket module, the packet(7) man page, and the Linux source.
The Python library includes function makesockaddr(). For PF_PACKET sockets (same as AF_PACKET), the relevant portion gives you the following order of fields. Explanations from the man page are italicized.
ifname (e.g., ens33) (the interface name, as you noted)
sll_protocol (e.g., 2048) Physical-layer protocol
sll_pkttype (e.g., 1) Packet type
sll_hatype (e.g., 1) ARP hardware type
sll_addr (e.g., the MAC address, as you noted above) Physical-layer address
The Linux source gives the various values for packet type. In that list, 1 is PACKET_BROADCAST. 0 is PACKET_HOST, explained as "To us".

Python and Netbios

I have been toying with a few ideas and would like to use Netbios to do some checks on the network. So after some research decided pysmb's nmb.Netbios was a good place to start.
I have constructed a simple queryName function that I was hoping would return an ip address. But it seems after checking some wireshark pcap dumps it isnt even broadcasting.
Ive found an example in the pysmb docs but that doesnt seem to broadcast either. Below is my test function, any pointers would be appreciated.
from nmb.NetBIOS import NetBIOS
def queryNam(name):
n = NetBIOS(broadcast=True, listen_port=0)
ip = n.queryName(name, timeout=30)
return ip
name = "Computer-Name"
ip = queryNam(name)
print ip
I worked out the issue myself. Initially I wasnt using the correct computername as NetBios Broadcasts seem to broadcast the name in uppercase. I was presenting a lowercase so the system was not responding.
So supplying the value in uppercase resolved the problem. (Even though a hostname check on the client showed an Uppercase followed by lowercase characters.

Categories

Resources