赞
踩
man socket(7)里对该选项的描述:
- SO_BINDTODEVICE
- Bind this socket to a particular device like “eth0”, as speci‐
- fied in the passed interface name. If the name is an empty
- string or the option length is zero, the socket device binding
- is removed. The passed option is a variable-length null-ter‐
- minated interface name string with the maximum size of IFNAM‐
- SIZ. If a socket is bound to an interface, only packets
- received from that particular interface are processed by the
- socket. Note that this works only for some socket types, par‐
- ticularly AF_INET sockets. It is not supported for packet
- sockets (use normal bind(2) there).
-
- Before Linux 3.8, this socket option could be set, but could
- not retrieved with getsockopt(2). Since Linux 3.8, it is
- readable. The optlen argument should contain the buffer size
- available to receive the device name and is recommended to be
- IFNAMSIZ bytes. The real device name length is reported back
- in the optlen argument.
-
- 将套接字绑定到指定接口,例如eth0等。如果绑定了接口,这个套接字只能处理由该接口收到的数据。
- 注意,并不是所有套接字类型都有这个选项。AF_INET套接字支持,但是packet 套接字不支持(不过,可以使用bind函数绑定地址)

如果有多个接口,例如eth0, eth1, ethx......,就可以在创建套接字的时候绑定相应的接口发送数据,例如我的电脑里有两个接口 :
在创建套接字的时候就可以绑定相应的接口发送数据,demo:
- /*
- * Desrciption : 套接字选项SO_BINDTODEVICE使用,需要root权限执行
- * Author : mason
- * Date : 201809
- */
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <net/if.h>
- #include <errno.h>
-
-
- int main()
- {
- int sock;
- struct sockaddr_in addr, raddr;
- char buffer[] = "hello world";
-
- /* 指定接口 */
- struct ifreq nif;
- char *inface = "eth0";
- strcpy(nif.ifr_name, inface);
-
- /* 创建套接字 */
- sock = socket(AF_INET, SOCK_DGRAM, 0);
- if (-1 == sock)
- {
- printf("create socket fail \r\n");
- return;
- }
- else
- {
- printf("create socket success \r\n");
- }
-
-
- if (inet_aton("192.168.80.129", &addr.sin_addr) != 1)
- {
- printf("addr convert fail \r\n");
- close(sock);
- return;
- }
- addr.sin_family = AF_INET;
- addr.sin_port = htons(8000);
-
- if (inet_aton("192.168.80.1", &raddr.sin_addr) != 1)
- {
- printf("addr convert fail \r\n");
- close(sock);
- return;
- }
- raddr.sin_family = AF_INET;
- raddr.sin_port = htons(8000);
-
- #if 0 //绑定地址
- if (bind(sock, (struct sockadd *)&addr, sizeof(addr)) != 0)
- {
- printf("bind fail \r\n");
- close(sock);
- return ;
- }
- else
- {
- printf("bind success \r\n");
- }
- #endif
-
- /* 绑定接口 */
- if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, (char *)&nif, sizeof(nif)) < 0)
- {
- close(sock);
- printf("bind interface fail, errno: %d \r\n", errno);
- return ;
- }
- else
- {
- printf("bind interface success \r\n");
- }
-
- /* 发送 */
- sendto(sock, buffer, sizeof(buffer), 0, ((struct sockadd *)&raddr),sizeof(raddr));
-
- close(sock);
- return;
- }
-

分别绑定eth0, eth1发送数据,抓包如下图,可以看到有不同的源地址发送。
程序执行的时候需要使用sudo权限,不然会提示绑定接口失败。
感觉类似的功能完全可以由bind接口实现,即绑定指定IP地址。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。