Frage

Wenn ein Socket an IN6ADDR_ANY oder INADDR_ANY gebunden ist und Sie einen Anruf wie recvfrom() Nachrichten auf dem Sockel zu empfangen. Gibt es eine Möglichkeit, um herauszufinden, welche Schnittstelle die Nachricht kam?

Im Fall von IPv6-Link-scope-Nachrichten, ich habe gehofft, dass der von Argumente von recvfrom() das scope_id Feld an der Schnittstelle Id initialisiert haben würde. Leider ist es gesetzt in meinem Testprogramm 0.

Jeder weiß von einem Weg, um diese Informationen zu erhalten?

War es hilfreich?

Lösung

Neben jede Schnittstelle aus der Bindung, bin ich eine Art und Weise nicht bewusst mit IPv4, per se.

IPv6 hat die IPV6_PKTINFO Socket-Option hinzugefügt, um diesen Mangel zu beheben. Mit dieser Option in der Tat wird ein struct in6_pktinfo als Zusatzdaten zurückgegeben werden.

Andere Tipps

dwc richtig ist, wird IPV6_PKTINFO für IPv6 unter Linux arbeiten.

Darüber hinaus IP_PKTINFO wird für IPv4 arbeiten - Sie Details in manpage ip sehen (7)

Ich habe ein Beispiel konstruiert, dass die Quelle extrahiert, Ziel und Interface-Adressen. Der Kürze halber wird keine Fehlerprüfung vorgesehen. Schau dir das Duplikat. Get Zieladresse eines Pakets empfangenen UDP

// sock is bound AF_INET socket, usually SOCK_DGRAM
// include struct in_pktinfo in the message "ancilliary" control data
setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt));
// the control data is dumped here
char cmbuf[0x100];
// the remote/source sockaddr is put here
struct sockaddr_in peeraddr;
// if you want access to the data you need to init the msg_iovec fields
struct msghdr mh = {
    .msg_name = &peeraddr,
    .msg_namelen = sizeof(peeraddr),
    .msg_control = cmbuf,
    .msg_controllen = sizeof(cmbuf),
};
recvmsg(sock, &mh, 0);
for ( // iterate through all the control headers
    struct cmsghdr *cmsg = CMSG_FIRSTHDR(&mh);
    cmsg != NULL;
    cmsg = CMSG_NXTHDR(&mh, cmsg))
{
    // ignore the control headers that don't match what we want
    if (cmsg->cmsg_level != IPPROTO_IP ||
        cmsg->cmsg_type != IP_PKTINFO)
    {
        continue;
    }
    struct in_pktinfo *pi = CMSG_DATA(cmsg);
    // at this point, peeraddr is the source sockaddr
    // pi->ipi_spec_dst is the destination in_addr
    // pi->ipi_addr is the receiving interface in_addr
}

Es ist eine Weile her, seit ich habe C / C ++ getan TCP / IP-Codierung, aber soweit ich auf jede Nachricht (oder abgeleitet Buchse) Erinnern Sie sich in die IP-Header Informationen erhalten. Diese Header sollten die Empfängeradresse enthalten, die die IP-Adresse der Schnittstelle werden Sie fragen.

Außerhalb der Verwendung eine separate Buchse an jeder Schnittstelle geöffnet wird, wie Glomek vorgeschlagen, den einzigen Weg, ich weiß, das auf Windows endgültig zu tun ist, eine Raw-Socket zu verwenden, z. B.

  SOCKET s = socket(AF_INET, SOCK_RAW, IPPROTO_IP);

erhalten Jede dieser Buchse wird ein IP-Paket sein, was sowohl den Quellen- und Zieladressen. Das Programm, das ich auf Arbeit verlangt, dass ich die Buchse im Promiscuous-Modus zu versetzen, die SIO_RCVALL Option. Dadurch bedeutet, dass ich jedes IP-Paket die Schnittstelle „sieht“ im Netzwerk erhalten. So extrahieren Pakete ausdrücklich für meine Anwendung erfordert mir die Daten unter Verwendung der Adressen und Ports im IP und TCP / UDP-Header zu filtern. Offensichtlich, das ist wahrscheinlich mehr Aufwand als Sie interessiert sind kann ich nur erwähnen, das zu sagen -. Ich habe nie einen Raw-Socket, ohne sie in der Promiscuous-Modus. Also ich bin nicht sicher, ob Sie binden kann es INADDR_ANY und es einfach verwenden wie eine normale Steckdose von diesem Punkt an ist oder nicht. Es scheint mir, dass Sie können; Ich habe nur noch nie versucht.

EDIT: Lesen Sie diesen Artikel rel="nofollow für Einschränkungen in Bezug auf raw Sockets unter Windows. Die größte Hürde ich an meinem Projekt konfrontiert war, dass ein Mitglied der Gruppe Administratoren sein, hat einen Raw-Socket auf Windows 2000 und später zu öffnen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top