Get Address Family from Socket. Linux

Get address family from socket. Linux

Damn. Searched about half an hour. Now after posting this question I found immiediately the answer.

getsockopt([...]) with option SO_DOMAIN (see socket options)

Query an existing socket's address family in Python

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.

(How) Can I determine the socket family from the socket file descriptor

See getsockname(2). You then inspect the struct sockaddr for the family.

EDIT: As a side note, its sometimes useful to query info as well, in this case info libc sockets

EDIT:

You really can't know without looking it up every time. It can't be simply cached, as the socket number can be reused by closing and reopening it. I just looked into the glibc code and it seems getsockname is simply a syscall, which could be nasty performance-wise.

But my suggestion is to use some sort of object-oriented concepts. Make the user pass a pointer to a struct you had previously returned to him, i.e. have him register/open sockets with your API. Then you can cache whatever you want about that socket.

Address family of socket is mentioned in structure and socket creation why?

socket() creates a new socket. It needs to know what its address family is so it knows what kind of addresses it is allowed to work with, whether that be IPv4, IPv6, IPX, NetLink, etc. The address family dictates the layout and format for its address values. For instance, AF_INET only allows IPv4 addresses, whereas AF_INET6 allows IPv6 addresses (and IPv4 addresses if the socket is set to dual-stack mode on platforms that support that feature).

Every sockaddr_... structure has a family field. sockaddr_... structures can be passed around to various functions, which need to know what type of address they are receiving as input, and can specify what type of address they are returning as output.

The sockaddr_in structure is specific to IPv4 addresses only, where its sin_addr field specifies the IPv4 address as a 32bit integer in network byte order. The same is not true of other sockaddr_... structures.

There is a special sockaddr_storage structure that is typically used when writing code that works with multiple addresses families, especially when calling functions that can accept multiple sockaddr_... types.

So it is important not only for the socket to be told what its address family is, but it is also important for individual addresses to specify their own types as well. Typically, these values will match each other (except in the case of dual-stack sockets).

What is Address Family?

Members of AF_INET address family are IPv4 addresses.

Members of AF_INET6 address family are IPv6 addresses.

Members of AF_UNIX address family are names of Unix domain sockets (/var/run/mysqld/mysqld.sock is an example).

Members of AF_IPX address family are IPX addresses, and so on. I don't think you really need to distinguish between family and type here. They are merely synonyms, except that family looks like more specialized, well-suited for this purpose, whilst type is a too much general word.

How can I get the address and port of a client in C sockets (sys/socket.h)?

You can extract it from a struct sockaddr_in (or sockaddr_in6).

struct sockaddr_in {
sa_family_t sin_family; /* address family: AF_INET */
in_port_t sin_port; /* port in network byte order */
struct in_addr sin_addr; /* internet address */
};

/* Internet address. */
struct in_addr {
uint32_t s_addr; /* address in network byte order */
};

See the man page: http://man7.org/linux/man-pages/man7/ip.7.html

Also, you can see my DNS-server code as a practical example (there is extracted IPV6 address sin6.sin6_addr).



Related Topics



Leave a reply



Submit