adding new address families (AF_xxx) - network-programming

I came across the kernel driver code implementing some sort of IGMP snooping backend and as part of its functionalilty it creates a new socket address family, AF_IGMPSNOOP, but actually implements just a few operations for this type of socket:
static struct proto_ops igmp_snoop_ops = {
family: AF_IGMP_SNOOP,
release: _igmp_snoop_sock_release,
bind: sock_no_bind,
connect: sock_no_connect,
socketpair: sock_no_socketpair,
accept: sock_no_accept,
getname: sock_no_getname,
poll: datagram_poll,
ioctl: sock_no_ioctl,
listen: sock_no_listen,
shutdown: sock_no_shutdown,
setsockopt: _igmp_snoop_setsockopt,
getsockopt: sock_no_getsockopt,
sendmsg: _igmp_snoop_sock_sendmsg,
recvmsg: _igmp_snoop_sock_recvmsg,
mmap: sock_no_mmap,
sendpage: sock_no_sendpage,
}
However from a user space perspective a socket is created as:
fd = socket (AF_IGMPSNOOP, SOCK_RAW, IPPROTO_IGMP)
I'm wondering what is the rationale for adding a new family, while in fact a raw socket is being used to access the stack for IGMP packets? Would not it be the same to just create AF_INET raw socket and do the things?
Looking forward to hearing form you !
Thanks.
Mark

Related

How to get the remote host from a rsocket

I now receive an rsocket connection in my spring project, and then I want to get its remote address and port, how should I get it?Similar to using socket.getRemoteSocketAddress() to get the remote address of the socket.
#ConnectMapping
public void connectMapping(RSocketRequester requester) {
// there is a resockt connect, how can i get the remote host from it
RSocket rSocket = requester.rsocket();
// TODO
logger.info("host port");
}
Unfortunately, I think even if you grab the RSocketRequester in #ConnectMapping or #MessageMapping method it is an internal detail. io.rsocket.core.RSocketRequester via RequesterResponderSupport holds the DuplexConnection which represents a connection over tcp, web socket or in-process. It is not exposed via a public API.
This is a worthy request but you will need to file a feature request to get this added unless I'm missing something obvious.
It isn't clear that there is a hook in https://docs.spring.io/spring-boot/docs/2.3.0.RELEASE/api/org/springframework/boot/rsocket/server/RSocketServerCustomizer.html to let you see the DuplexConnection (tcp or web socket etc) as it's established.

Does `select` handles multiple endpoints or multiple sockets?

I am new to network programming, and I have some confusion with select function.
For a server program, we need to first create a fd to socket endpoint (server's ip and port without client's ip and port) with socket, bind and listen, then if there is a TCP connection to this socket endpoint, then accept returns the fd to the socket (server's ip, port and client's ip, port). Then we use recv on this socket's fd, and if there is no data to receive, the recv will block (for blocking socket).
I learned that select is used to handle non-blocking multiple connections. But which connection level does it handles? Does it handles multiple socket endpoints, or handles multiple sockets of one single socket endpoint?
For a normal server program, I think the socket endpoint is always single, and there are maybe hundreds of sockets connected to this endpoint. So I think handling multiple socket endpoints may be less useful to handling multiple sockets. But when talking about IO multiplexing, I find that many articles seems talking about handling multiple socket endpoints. While for handling multiple sockets to a single socket, I can't find a way to get all sockets, and put them to select's set of fds, since accept only accepts one sockets a time.
"Does it handles multiple socket endpoints or handles multiple sockets of one single socket endpoint?" -- There is no such thing as multiple sockets of a single socket endpoint. Every socket is an endpoint to the network communication. It just happens that the piece of code which deals with that socket might be different from the others. Consider the following socket descriptors:
int sock_acpt = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
listen(sock_acpt, 5);
int sock_cli = accept(sock_apt, ....);
Both the socket descriptors sock_acpt and sock_cli are the endpoints of different communications. After setting sock_acpt in passive mode by calling listen(), the socket just listens for TCP connection, and the server's TCP stack will manage any data that appears on that socket (most probably TCP Handshakes). While sock_cli is the end of an already established connection, and in general, the data on that socket is managed by the user-level application.
Now coming to select(), it is an IO Multiplexer, not a Network IO multiplexer. So any descriptor which can be viewed as an IO endpoint can be used with the select(). Referring to our socket descriptors sock_acpt and sock_cli, both are IO endpoints of different communications, so you can use both of them with select(). You generally do something like below
for ( ; ; ) {
fd_set rd_set;
FD_ZERO(&rd_set);
FD_SET(sock_acpt, &rd_set);
FD_SET(sock_cli, &rd_set);
if (select(sock_acpt > sock_cli ? sock_acpt + 1 : sock_cli + 1, \
&rd_set, NULL, NULL, NULL) <= 0) {
continue;
}
if (FD_ISSET(sock_acpt, &rd_set)) {
// Accept new connection
// accept(sock_acpt, ...);
}
if (FD_ISSET(sock_cli, &rd_set)) {
// Read from the socket
// read(sock_cli, ...);
}
}
But using select() is not limited to sockets, you can use with the file IO (fileno(stdin)), with the signal IO (signalfd()) and any other which can be viewed as IO endpoint.

TCP connection issue by using BlueSocket framework on IOS

Getting error of "Error code: -9989(0x-2705), Connection refused" by using BlueSocket framework and connecting between Mac and IOS.
Here is the logic:
I am treating Mac as a server:
// making TCP IPV4 socket
try self.listenSocket = Socket.create(family: .inet, type: .stream, proto: .tcp)
// start lisening port of 8888
try socket.listen(on: self.port)
// accept client connection when there is
let newSocket = try socket.acceptClientConnection()
// keep opening and reading data ....
iPhone as a client:
self.socket = try Socket.create(family: .inet)
try self.socket?.connect(to: ip, port: 8888)
try self.socket?.setReadTimeout(value: readWriteTimeOut)
try self.socket?.setWriteTimeout(value: readWriteTimeOut)
self.socket?.readBufferSize = Socket.SOCKET_MAXIMUM_SSL_READ_BUFFER_SIZE
client first time connect with the server works fine.
after the server receives data, client-side automatically closes the socket.
client tries to connect the server again to send back data by using same code above.
Then error displays!
I think by default when the server-side uses socket.listen, it has SO_REUSEADDR set to true
Need suggestions on how to resolve this issue. Thanks!
Just need to make sure while loop for socket.acceptClientConnection() is opening all the time....

mina server response port different from port incoming messages

I set up a server that receives messages over port xxx, but I want to respond to port yyy.
Is there a simple way to achieve this?
My server:
IoAcceptor acceptor = new NioSocketAcceptor();
acceptor.setHandler(new MessageHandler());
acceptor.getFilterChain().addLast("logger", new LoggingFilter());
acceptor.getFilterChain().addLast("codec", new protocolCodecFilter(codecFactory));
acceptor.getSessionConfig().setReadBufferSize(bufferSize);
acceptor.bind(new InetSocketAddress(port));
The encode method of my encoder:
public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
byte[] writeBytes = (byte[]) message;
IoBuffer buffer = IoBuffer.allocate(writeBytes.length).setAutoExpand(false);
buffer.put(writeBytes);
buffer.flip();
out.write(buffer);
writeMessage(session,writeBytes);
}
The msessage should be written to a different port. How do I achieve this?
If you want to response message using different tcp port, you must make another other tcp connection first, which means you have two servers and tow clients.
request
client1---------->server1
reponse
server2---------->client2

IPv6 equivalent of ETH_P_ARP

To determine if an IPv4 gateway is alive or not programatically, raw packet socket with ETH_P_ARP as the protocol, can be used as follows:
int fd = socket (PF_PACKET, SOCK_RAW, ETH_P_ARP);
I'm looking for an IPv6 equivalent of ETH_P_ARP to use to ping an IPv6 gateway along similar lines. What are the other options in which this can be achieved programmatically?
Thanks!
Using wireshark, the protocol on a ND solicitation and on advertisement is just 0x86DD, and in if_ether.h that is assigned to ETH_P_IPV6.

Resources