I'm passing a socket file descriptor using a UNIX domain socket to a Python 3 program. I would like to query the socket and determine its address family.
In this answer the getsockname system call is used to achieve the same result in C. However, Python's socket.getsockname function doesn't return the address family, instead assuming the caller already knows it. Furthermore, it only works on sockets, not on file descriptors, and creating a socket object from a file descriptor requires passing the address family as well.
Is there a way to query the address family from Python?
EDIT: I want to emphasize that I am looking for the address family of an already open socket, for which I have the file descriptor.
You just pass the file descriptor to socket.socket, giving it as the fileno= keyword attribute. The socket class figures out the type of socket corresponding to the file descriptor. You can then find the family as @klaus suggested: with s.family.
import socket
s = socket.socket()
print("original socket", s)
desc = s.fileno()
print("file descriptor", type(desc), desc)
new_s = socket.socket(fileno=desc)
print("new socket", new_s.family, int(new_s.family))
Here I'm creating a socket in python, but then extracting the file descriptor from the socket object (producing an ordinary int containing the descriptor number) so as to demonstrate putting it back into a new socket object. Running the above produces:
original socket <socket.socket fd=3, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('0.0.0.0', 0)>
file descriptor <class 'int'> 3
new socket AddressFamily.AF_INET 2
EDIT
Hmm... the above method does not seem to work with AF_INET6 sockets, at least in my python 3.5.2 version.
s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
new_s = socket.socket(fileno=s.fileno())
print(new_s)
<socket.socket fd=3, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('::%1', 0, 0, 1)>
That seems like a clear bug to me. The documentation says:
If fileno is specified, the values for family, type, and proto are auto-detected from the specified file descriptor.
You may need to examine new_s.laddr and heuristically determine the family. (For AF_INET6, laddr will be a 4-tuple, whereas AF_INET uses a 2-tuple). If you expect AF_UNIX or other families, you might need to extend that.
You can query a socket's address family in python checking the .family attribute. There are other attributes saved in the sock object also
import socket
import sys
# Create a TCP/IP socket
sock = socket.create_connection(('www.stackoverflow.com', 80))
print(sock)
print(sock.family)
The output is
<socket.socket fd=3, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('x.x.x.x', y), raddr=('x.x.x.x', 80)>
AddressFamily.AF_INET
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With