- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我编写了一个用户空间程序,应该在路由表中安装一个新路由。我注意到的是,如果 bytes sendmsg
fn 返回是正确的,但程序无法安装新路由。当我尝试在 Linux 内核上使用 gdb 诊断问题时,我发现垃圾数据正在从用户空间发送到内核 netlink 套接字。
输出
[root@localhost rtnetlink]# ./netlink_add_route.exe
bytes send = 52
分享代码:
typedef struct _request
{
struct nlmsghdr netlink_header;
struct rtmsg rt_message;
char buffer[1024];
} req_t;
int addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int alen)
{
/* alen is the length of the data. Add sizeof(struct rtattr) to it to accomodate
type, length, value format for rtattr */
int len = RTA_LENGTH(alen); // (RTA_ALIGN(sizeof(struct rtattr)) + (len))
struct rtattr *rta;
/* size of request should not be violated*/
if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen)
return -1;
/* go to end of buffer in request data structure*/
rta = (struct rtattr*)(((char*)n) + NLMSG_ALIGN(n->nlmsg_len));
/* specify attribute using TLV format*/
rta->rta_type = type;
rta->rta_len = len;
memcpy(RTA_DATA(rta), data, alen);
/* increase the nlmsg_len to accomodate the added new attribute*/
n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len;
return 0;
}
static void
initialisation(){
/* initialise the request structure*/
int index = 3,
gw = 3232236545/*192.168.4.1*/,
dst = 3232235776/*192.168.1.0*/;
memset(&request, 0, sizeof(request));
/* set the nlmsg_len = nl header + underlying structure*/
request.netlink_header.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); /*NLMSG_HDRLEN + sizeof(struct rtmsg);*/
/* set the flags that facilitates adding a route in routing table*/
request.netlink_header.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE;
/* note that inet_rtm_newroute() is the fn in kernel which will be eventually called to add a new route in routing table*/
request.netlink_header.nlmsg_type = RTM_NEWROUTE;
/* Now filling the rtmsg*/
request.rt_message.rtm_family = AF_INET;
request.rt_message.rtm_table = RT_TABLE_MAIN;
request.rt_message.rtm_protocol = RTPROT_BOOT;/*Route installed during boot*/
request.rt_message.rtm_scope = RT_SCOPE_UNIVERSE;
request.rt_message.rtm_type = RTN_UNICAST; /*Gateway or direct route */
/* Add routing info*/
addattr_l(&request.netlink_header, sizeof(request), RTA_GATEWAY, &gw, sizeof(gw));
addattr_l(&request.netlink_header, sizeof(request), RTA_DST, &dst, sizeof(dst));
addattr_l(&request.netlink_header, sizeof(request), RTA_OIF, &index, sizeof(index));
/* For adding a route, the gateway, destination address and the interface
will suffice, now the netlink packet is all set to go to the kernel*/
}
static void
send_request(int fd){
int rc = 0;
struct msghdr msg;
struct sockaddr_nl nladdr;
struct iovec iov;
iov.iov_base = (void*)&request.netlink_header;
iov.iov_len = request.netlink_header.nlmsg_len ;/* Total length : from request start to end of last attribute*/
memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK;
nladdr.nl_pid = 0; /* For Linux Kernel */
nladdr.nl_groups = 0;
msg.msg_name = (void *)&nladdr;
msg.msg_namelen = sizeof(nladdr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
rc = sendmsg(fd, &msg, 0);
printf("bytes send = %d\n", rc);
}
int
main(int argc, char *argv[])
{
struct sockaddr_nl la;
int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if(fd < 0){
printf("socket creation failed\n");
return -1;
}
bzero(&la, sizeof(la));
la.nl_family = AF_NETLINK;
la.nl_pid = getpid();
la.nl_groups = 0;
if(bind(fd, (struct sockaddr*) &la, sizeof(la)) < 0){
printf("Bind failed\n");
return -1;
}
initialisation();
send_request(fd);
close(fd);
}
gdb 输出
Breakpoint 1, inet_rtm_newroute (skb=0xbb53f20, nlh=0xb96ed00) at net/ipv4/fib_frontend.c:732
732 {
(gdb) bt
#0 inet_rtm_newroute (skb=0xbb53f20, nlh=0xb96ed00) at net/ipv4/fib_frontend.c:732
#1 0x081f1b28 in rtnetlink_rcv_msg (skb=0xbb53f20, nlh=0xb96ed00) at net/core/rtnetlink.c:3412
#2 0x081fcd07 in netlink_rcv_skb (skb=0xbb53f20, cb=0x81f19de <rtnetlink_rcv_msg>)
at net/netlink/af_netlink.c:3017
#3 0x081efcb9 in rtnetlink_rcv (skb=0xbb53f20) at net/core/rtnetlink.c:3418
#4 0x081fc7e4 in netlink_unicast_kernel (ssk=<optimized out>, skb=<optimized out>, sk=<optimized out>) at net/netlink/af_netlink.c:1834
#5 netlink_unicast (ssk=0xbb03000, skb=0xbb53f20, portid=0, nonblock=0) at net/netlink/af_netlink.c:1860
#6 0x081fcbf3 in netlink_sendmsg (sock=0xa50a700, msg=0xbb71e3c, len=52) at net/netlink/af_netlink.c:2511
#7 0x081cf181 in sock_sendmsg_nosec (msg=<optimized out>, sock=<optimized out>) at net/socket.c:611
#8 sock_sendmsg (sock=0xa50a700, msg=<optimized out>) at net/socket.c:621
#9 0x081cf781 in ___sys_sendmsg (sock=0xa50a700, msg=<optimized out>, msg_sys=0xbb71e3c, flags=0,
used_address=0x0) at net/socket.c:1947
#10 0x081d044f in __sys_sendmsg (fd=3, msg=0xbfd5cc40, flags=0) at net/socket.c:1981
#11 0x081d0a97 in SYSC_sendmsg (flags=<optimized out>, msg=<optimized out>, fd=<optimized out>)
at net/socket.c:1992
#12 SyS_sendmsg (flags=0, msg=-1076507584, fd=3) at net/socket.c:1988
#13 SYSC_socketcall (args=<optimized out>, call=<optimized out>) at net/socket.c:2397
#14 SyS_socketcall (call=16, args=-1076507632) at net/socket.c:2315
#15 0x0805ba59 in handle_syscall (r=0xbbab3f0) at arch/um/kernel/skas/syscall.c:37
#16 0x08069147 in handle_trap (local_using_sysemu=<optimized out>, regs=<optimized out>,
pid=<optimized out>) at arch/um/os-Linux/skas/process.c:172
#17 userspace (regs=0xbbab3f0) at arch/um/os-Linux/skas/process.c:384
#18 0x080594df in fork_handler () at arch/um/kernel/process.c:154
#19 0x00000000 in ?? ()
(gdb) f 6
#6 0x081fcbf3 in netlink_sendmsg (sock=0xa50a700, msg=0xbb71e3c, len=52) at net/netlink/af_netlink.c:2511
2511 err = netlink_unicast(sk, skb, dst_portid, msg->msg_flags&MSG_DONTWAIT);
(gdb) p msg
$1 = (struct msghdr *) 0xbb71e3c
(gdb) p *(struct msghdr *) 0xbb71e3c
$2 = {msg_name = 0xbb71d98, msg_namelen = 12, msg_iter = {type = 1, iov_offset = 0, count = 0, {
iov = 0xbb71d60, kvec = 0xbb71d60, bvec = 0xbb71d60}, nr_segs = 0}, msg_control = 0x4,
msg_controllen = 0, msg_flags = 0, msg_iocb = 0x0}
(gdb) f 10
#10 0x081d044f in __sys_sendmsg (fd=3, msg=0xbfd5cc40, flags=0) at net/socket.c:1981
1981 err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL);
(gdb) p msg
$3 = (struct user_msghdr *) 0xbfd5cc40
(gdb) p *(struct user_msghdr *) 0xbfd5cc40
Cannot access memory at address 0xbfd5cc40
正如您在上面看到的,无法访问内核中收到的消息。当我在应用程序的 sendmsg fn 上应用 gdb 并扩展发送到内核的消息时,我发现一切都很完美。是什么导致用户空间和内核之间的消息损坏?任何人都可以帮助诊断问题吗?
我使用的是内核版本 4.5.3。
如果有人想运行该程序,请共享 src 文件的链接。 https://drive.google.com/file/d/0B56H_R1fVFZXRjNWRkZ3M09pY2s/view?usp=sharing
谢谢。
最佳答案
我可以成功地让它发挥作用。问题在于添加 RTA_DST 和 RTA_GATEWAY 的方式。您需要为 dst 使用 inet_prefix。请注意 dst.data[]、dst.bytelen 和 dst.bitlen 都是一些随机值。请根据您的解决方案的需要进行初始化。 (这只是为了证明它有效!)
typedef struct
{
__u16 flags;
__u16 bytelen;
__s16 bitlen;
__u16 family;
__u32 data[8];
} inet_prefix;
inet_prefix dst;
dst.data[0] = 11;
dst.data[1] = 12;
dst.data[2] = 13;
dst.data[3] = 14;
dst.data[4] = 15;
dst.data[5] = 16;
dst.data[6] = 17;
dst.data[7] = 17;
dst.bytelen = 32;
dst.bitlen = dst.bytelen * 8;
/* mask */
request.rt_message.rtm_dst_len = 24;
//addattr_l(&request.netlink_header, sizeof(request), RTA_GATEWAY, &gw, sizeof(gw));
addattr_l(&request.netlink_header, sizeof(request), RTA_DST, &dst, sizeof(dst));
作为示例,我添加了“dst”条目并注释掉了“gw”条目。对于“gw”,您也必须遵循类似的结构 inet_prefix。
条目创建:
12.0.32.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
关于linux - 使用 rtnetlink 套接字在 linux 路由表中安装新路由,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37465768/
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?将问题更新为 on-topic对于堆栈溢出。 1年前关闭。 Improve this qu
我想了解 rtnetlink 的工作原理,所以我开始尝试构建一个小库供自己使用。 我已经到了可以正常发送/接收网络链接消息的地步。现在我正在为如何处理 RTM_GETLINK 请求的答案而苦恼。这是我
我找到了几个监听 RTNETLINK 事件的示例,既直接来自内核,也使用 libmnl。 libmnl 示例完全符合我的要求,因为它监听路由更改并报告它们。该示例已完成,可在此处找到: https:/
当我添加延迟命令时,paramiko 返回“2”作为退出状态(同时返回“0”用于带宽命令设置)。 2还好吗? (谷歌搜索对此没有帮助,我猜 2 一定是某种错误)。 我使用的命令是:- delay_cm
当我运行这个命令时: tc qdisc add dev eth0 root red limit 51200000 min 128000 max 512000 avpkt 1024 burst 200
我试图创建一个网络接口(interface)的新实例以在其上设置 DNS 服务器配置。 当我运行此命令时: ip link set enp1s0 name ens33 && ip link set e
我编写了一个用户空间程序,应该在路由表中安装一个新路由。我注意到的是,如果 bytes sendmsg fn 返回是正确的,但程序无法安装新路由。当我尝试在 Linux 内核上使用 gdb 诊断问题时
我已经使用 netlink 套接字向内核发送了一条 RTM_GETROUTE 消息。现在我正在监听内核的消息。 内核发送nlmsghdr通过 netlink 套接字回复结构。我需要知道它的消息类型 (
1. ETH=$1 2. LATENCY=$2 3. LOSS=$3 4. JITTER=$4 5. BW=$5 6. sudo /sbin/tc qdisc del dev eth0 root 7.
这是我的生成文件: delay: tc qdisc add dev eth0 root netem delay 0ms test4_s_delay:delay ./a.out 10 1
我尝试过的步骤 我正在尝试在Raspberry pi上设置Wireguard客户端 这是二手的配置 # /etc/wireguard/wg0-client.conf [Interface] Addre
我正在尝试在 mininet 上应用 MPLS,并且我能够安装 iproute2,但我遇到的问题是当我尝试使用格式中的任何命令时 ip -f mpls xxx 我总是出错。 我能够插入一条路线 min
我已经编写了一个内核模块,我想在其中向用户空间程序发送接口(interface)启动/关闭通知。我已将消息组分配为 RTMGRP_LINK 并且还包括 linux/rtnetlink.h 头文件。但是
我尝试了解 IFA_LOCAL 和 IFA_ADDRESS 之间的区别。 这是来自男人: IFA_ADDRESS raw protocol address interface address IF
接口(interface)文件 auto eth0 iface eth0 inet dhcp up route add 192.168.11.2 dev eth0 up
我正在尝试设置一个基于 Ubuntu 的 docker 镜像以拥有 Linux Test Project可以用了。当我尝试关闭 network > nfs > nfs_stress > nfs01我收
我正在尝试使用 libmnl 将 IPv6 地址添加到以太网接口(interface)。构建消息并发送给内核后,我看到它没有添加到接口(interface)中,即使内核回复的返回码不包含任何错误。请任
我正在尝试将 bash 脚本移植到 python。 bash 脚本运行一个 tc 命令来模拟慢速网络,主要部分是这样的: tc class add dev wlp1s0 parent 1:1 clas
我正在尝试在 mininet 上使用 MPLS 我能够安装 iproute2 并且当我尝试这样的事情时 ip route add 192.168.10.187/32 encap mpls 101 vi
我正在使用 Vagrant/VirtualBox 运行 CoreOS stable 494.5.0,并且正在运行 vanilla ruby:2.1.5 Docker 镜像。我正在尝试使用 Pipe
我是一名优秀的程序员,十分优秀!