it-swarm.com.de

wie man einen Socket an eine bestimmte Schnittstelle bindet

Meine Anwendung läuft unter CentOS 5.5 .. Ich benutze Raw Socket, um Daten zu senden:

sd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if (sd < 0) {
  // Error
}
const int opt_on = 1;
rc = setsockopt(m_SocketDescriptor, IPPROTO_IP, IP_HDRINCL, &opt_on, sizeof(opt_on));
if (rc < 0) {
  close(sd);
  // Error
}
struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = my_ip_address;

if (sendto(m_SocketDescriptor, DataBuffer, (size_t)TotalSize, 0, (struct sockaddr *)&sin, sizeof(struct sockaddr)) < 0)  {
  close(sd);
  // Error
}

Wie kann ich diesen Socket an eine bestimmte Netzwerkschnittstelle binden (zB eth1)?

26
Dima
const char *opt;
opt = "eth0";
const len = strnlen(opt, IFNAMSIZ);
if (len == IFNAMSIZ) {
    fprintf(stderr, "Too long iface name");
    return 1;
}
setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, opt, len);

Erste Zeile: Richten Sie Ihre Variable ein

Zweite Zeile: Teilen Sie dem Programm mit, an welche Schnittstelle es gebunden werden soll

Zeilen 3-5: Ermitteln Sie die Länge des Schnittstellennamens und prüfen Sie, ob die Größe nicht zu groß ist.

Sechs Zeilen: Legen Sie die Socket-Optionen für Socket sd fest, die an das Gerät opt bindet.

setsockopt Prototyp:

int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen);

Stellen Sie außerdem sicher, dass Sie die Headerdateien if.h, socket.h und string.h einschließen

38
Andrew Sledge

Wie bereits erwähnt, verwenden Sie struct ifreq, um den Namen der Schnittstelle anzugeben. Hier ist mein Codebeispiel.

#define SERVERPORT 5555
...
struct ifreq ifr;


/* Create the socket */
sd = socket(AF_INET, SOCK_STREAM, 0);
if (sd < 0) 
{
    printf("Error in socket() creation - %s", strerror(errno));
}

/* Bind to eth1 interface only - this is a private VLAN */
memset(&ifr, 0, sizeof(ifr));
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "eth1");
if ((rc = setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr))) < 0)
{
    perror("Server-setsockopt() error for SO_BINDTODEVICE");
    printf("%s\n", strerror(errno));
    close(sd);
    exit(-1);
}

/* bind to an address */
memset(&serveraddr, 0x00, sizeof(struct sockaddr_in));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(SERVERPORT);
serveraddr.sin_addr.s_addr = inet_addr("9.1.2.3");

int rc = bind(sd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));

Ich möchte auch hinzufügen, dass es aus Sicherheitsgründen wichtig ist, den Socket an eine Schnittstelle zu binden, aber es ist nicht sinnvoll, INADDR_ANY als abhörende IP-Adresse zu verwenden. Dadurch würde der Port in allen Netzwerkschnittstellen in netstat als offen angezeigt. 

Proto Recv-Q Send-Q Local Address    Foreign Address    State     User Inode      PID/Program name
tcp   0      0      0.0.0.0:5555     0.0.0.0:*          LISTEN    0    210898     26996/myserver  

Stattdessen habe ich eine IP-Adresse angegeben, die für die verwendete Schnittstelle spezifisch ist (privates VLAN). Die netstat-Ausgabe wurde ebenfalls korrigiert:

Proto Recv-Q Send-Q Local Address    Foreign Address    State     User Inode      PID/Program name
tcp   0      0      9.1.2.3:5555     0.0.0.0:*          LISTEN    0    210898     26996/myserver  
16
viv

Socket an bestimmte Schnittstellen-IP-Adresse binden

int bind_using_iface_ip(int fd, char *ipaddr, uint16_t port)
{
    struct sockaddr_in localaddr = {0};
    localaddr.sin_family    = AF_INET;
    localaddr.sin_port  = htons(port);
    localaddr.sin_addr.s_addr = inet_addr(ipaddr);
    return bind(fd, (struct sockaddr*) &localaddr, sizeof(struct sockaddr_in));
}

Socket an bestimmten Schnittstellennamen binden

int bind_using_iface_name(int fd, char *iface_name)
{
    return setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, iface_name, strlen(iface_name))
}

Um in bind_using_iface_ip zu binden, sollte 0 übergeben werden. Wenn auch fd ein unformatierter Socket ist, müssen Sie den Port als 0 übergeben. Dieser Bindungsmechanismus ist für alle Arten von Sockets wie raw, dgram und stream üblich.

0
rashok