guard against race between socket(AF_PACKET) and bind()

An AF_PACKET socket will immediately receive packets of _all_ interfaces
until it is bound to one specific interface.  This introduces a race
condition between the socket() and the bind() syscall.

Let's use the ifindex passed for each packet in recvmsg() to drop
any packets received for other interfaces.

Change-Id: Icd0b23eb1d6f75ca3a05e5dd1a569fa389903fdf
This commit is contained in:
Harald Welte 2020-12-10 21:27:45 +01:00
parent f42a8ae5c4
commit cd698095c7
1 changed files with 10 additions and 1 deletions

View File

@ -118,14 +118,23 @@ void AF__PACKET__PT_PROVIDER::Handle_Fd_Event(int fd, boolean is_readable, boole
return;
if (is_readable) {
struct sockaddr_ll sll;
socklen_t sll_len = sizeof(sll);
int rc;
rc = read(fd, mRxBuf, sizeof(mRxBuf));
rc = recvfrom(fd, mRxBuf, sizeof(mRxBuf), 0, (struct sockaddr *)&sll, &sll_len);
if (rc < 0)
TTCN_error("Error reading from socket: %s", strerror(errno));
if (rc == 0)
TTCN_error("Dead socket: %s", strerror(errno));
/* ignore any packets that we might have received for a different interface, between
* the socket() and the bind() call */
if (sll.sll_ifindex != mIfindex)
return;
/* TODO: report the other meta-data fields like sll_pkttype via the port */
incoming_message(AF__PACKET__Unitdata(OCTETSTRING(rc, mRxBuf)));
}
}