How to bind to a specific ethernet interface?
-
Hey,
I would like to know how I can bind a socket to a specific ethernet interface and not only to an ip address.
The device where I am running my application has two interfaces configured (eth0 and eth0.2) and I want to send multicasts through my network using eth0.2. The interfaces use the following addresses:
eth0
IPv6: fd::1feth0.2
IPv6: fd61:xxxx:xxxx:x::1fIn my application, I have bind the socket as follows:
udpSocket->bind(QHostAddress("fd61:xxxx:xxxx:x::1f"), xxxx); qDebug() << udpSocket->state(); if(udpSocket->joinMulticastGroup(QHostAddress("ff16::02")) qDebug() << "joined multicast group";
The application itself starts automatically on boot and starts sending the mutlicasts. The interesting part is, that the source address of multicasts is "fd::1f" which is related to eth0, but the address that I use to bind the socket to is related to eth0.2. In any case, the result of state() is always "Bounded".
First I thought it could be a timing issue, which means that my applications starts earlier than all network settings are ready to use. But implementing a delay of several seconds didn't solve this problem. For test purposes I removed the address of eth0, so the only available address is found on eth0.2. Now, it all works finde but I don't have an ip address on eth0 anymore.
My guess is, that the problem is somewhere in the multicast source address selection of the ip-stack.
Anyway, since I don't know exactly where the problem comes from, I would like to bind the socket to the interface eth0.2.For plain c, I could use the BINDTODEVICE option, which looks like this:
setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, "eth0", 4);
Is there also a possibility to use something like this within Qt?
Thanks!
-
Hi
I think yes.
setsockopt(m_udpSocket->socketDescriptor(), SOL_SOCKET, SO_BINDTODEVICE, dev, sizeof(dev) )) -
Hey,
sorry for my very late response. I had to do some other stuff in between :)While trying to implement the setsockopt - function, I thought I have found a very simple solution for my problem. And I do not have to use some plain C++, because it is an build-in functionality of Qt :)
This one should do the trick:
bool QUdpSocket::joinMulticastGroup(const QHostAddress &groupAddress, const QNetworkInterface &iface)
You can define the interface that has to be used for sending the mutlicast massages. But still, I can't see the messages in the specific VLAN the udpsocket is bind to. That's weird.
So I have no choice but to use plain C/C++. I implemented the following:
#include "udpsock.h" udpSock::udpSock(QObject *parent) : QObject(parent) { qDebug() << "starting..."; int sock_fd = 0; struct ifreq interfaces; sockaddr_in6 addr; addr.sin6_family = AF_INET6; addr.sin6_addr = in6addr_any; addr.sin6_port = htons(1337); if((sock_fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { qDebug() << "cannot create socket"; exit(1); } qDebug() << "created socket: descriptor " << sock_fd; strncpy(interfaces.ifr_name, "eth0.2", IFNAMSIZ); if(setsockopt(sock_fd, SOL_SOCKET, SO_BINDTODEVICE, (char *)&interfaces, sizeof(interfaces)) < 0) { qDebug() << "failed to bind to device"; exit(1); } if((bind(sock_fd,(sockaddr*) &addr, sizeof(addr))) < 0) { qDebug() << "failed to bind to ip and port"; exit(1); } uSock = new QUdpSocket(this); if(uSock->setSocketDescriptor(sock_fd)) qDebug() << "socket descriptor accepted"; qDebug() << "state of sock: " << uSock->state(); //join multicast group if(uSock->joinMulticastGroup(QHostAddress("ff16::01"))) qDebug() << "com_NM: socket (send) joind multicast group"; else qDebug() << "com_NM: socket (send) could not join multicast group"; qDebug() << "end of code"; }
It is all working fine, except the part where the guy should join the multicast group. It just claims
QNativeSocketEngine::joinMulticastGroup() was not called in QAbstractSocket::BoundState
The qDebug (one live above the statement where to join the multicastgroup) gives me QAbstracktSocket::ConnectedState.
What am I missing?
Thanks.