去掉Socket绑定设备权限检查

为了在Linux手机上支持多个PDP,允许不同应用数据包走不同路由,文章介绍了通过修改Kernel代码去除Socket绑定设备权限检查的方法,以避免路由表混乱。详细展示了修改Kernel的sock.c文件和使用setsockopt进行网卡绑定的示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

为了让Linux手机可以支持多个PDP,需要让不同的应用的数据包走不同的路由/网卡,可以通过两种方式实现:

  • 为每个应用增加特定路由,或
  • 让应用可以绑定网卡(Net Device)

在路由表中增加特定路由的方式很繁琐,而且容易出错,导致路由表混乱。而绑定网卡方式,很清晰而且不受路由表限制。

 

Linux Kernel的默认代码,会检查调用者是否有CAP_NET_RAW能力,如果没有该能力,绑定网卡的时候,系统会返回错误-EPERM。我们需要做的是:任何应用能绑定网卡。因此需要对内核代码sock_bindtodevice()函数进行简单的修改,如下:以Linux 2.6.32为例

 

 

修改Kernel以后,Native应用就可以通过调用setsockopt来绑定网卡了,示例代下:

 

 

 

#include <stdio.h> #include <winsock2.h> #include <conio.h> // 新增:用于非阻塞输入检测 #include <process.h> // 新增:用于多线程 #define PORT 8888 #define BUFFER_SIZE 2000 unsigned __stdcall SendThread(void* param); SOCKET client_socket; // 改为全局变量便于线程访问 /* 新增发送线程函数 / unsigned __stdcall SendThread(void param) { char message[BUFFER_SIZE]; while (1) { printf("输入要发送的消息 (输入exit退出): "); fgets(message, BUFFER_SIZE, stdin); message[strcspn(message, “\n”)] = ‘\0’; // 去除换行符 if (strcmp(message, "exit") == 0) break; if (send(client_socket, message, strlen(message), 0) < 0) { puts("发送失败"); break; } } return 0; } int main() { WSADATA wsa; SOCKET server_socket; struct sockaddr_in server, client; int c; // 初始化Winsock(保持不变) if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) { printf("WSAStartup失败. 错误代码: %d", WSAGetLastError()); return 1; } // 创建Socket(保持不变) if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { printf("创建socket失败: %d", WSAGetLastError()); return 1; } // 配置&绑定&监听(保持不变) server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons(PORT); if (bind(server_socket, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) { printf("绑定失败: %d", WSAGetLastError()); closesocket(server_socket); return 1; } listen(server_socket, 3); printf("等待连接...\n"); // 接受连接(保持不变) c = sizeof(struct sockaddr_in); if ((client_socket = accept(server_socket, (struct sockaddr*)&client, &c)) == INVALID_SOCKET) { printf("接受连接失败: %d", WSAGetLastError()); return 1; } /* 新增:创建发送线程 */ HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, SendThread, NULL, 0, NULL); // 接收循环 while (1) { char client_message[BUFFER_SIZE]; int recv_size; if ((recv_size = recv(client_socket, client_message, BUFFER_SIZE, 0)) > 0) { client_message[recv_size] = '\0'; printf("\n收到客户端消息: %s\n", client_message); } else { // 连接断开处理 printf("\n连接已断开\n"); break; } } // 清理资源 closesocket(client_socket); closesocket(server_socket); WSACleanup(); return 0; }这个程序发送的消息在正常情况下能被安卓上的客户端接受到吗
最新发布
03-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值