【问题标题】:How to add route to a network interface programmatically如何以编程方式将路由添加到网络接口
【发布时间】:2019-10-20 18:37:58
【问题描述】:

如何添加路由到带有ioctl 的接口?

假设我有一个 TAP 设备 tap0 和一个 CIDR 块 10.0.0.0/24,我正在寻找一种以编程方式实现等效的方法

ip route add dev tap0 10.0.0.0/24

我尝试strace 来查找和复制基本行为,但我没有找到可以模仿的ioctl 用法:

root@ubuntu:~# strace ip route add dev tap0 10.0.0.0/24
execve("/sbin/ip", ["ip", "route", "add", "dev", "tap0", "10.0.0.0/24"], 0x7ffe3e1eec58 /* 23 vars */) = 0
brk(NULL)                               = 0x55ca9c9c6000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=94674, ...}) = 0
mmap(NULL, 94674, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f2367f46000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libelf.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0.\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=104952, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2367f44000
mmap(NULL, 2199936, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f2367b1d000
mprotect(0x7f2367b36000, 2093056, PROT_NONE) = 0
mmap(0x7f2367d35000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x18000) = 0x7f2367d35000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libmnl.so.0", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0@\31\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=22520, ...}) = 0
mmap(NULL, 2117648, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f2367917000
mprotect(0x7f236791c000, 2093056, PROT_NONE) = 0
mmap(0x7f2367b1b000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x4000) = 0x7f2367b1b000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P\16\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=14560, ...}) = 0
mmap(NULL, 2109712, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f2367713000
mprotect(0x7f2367716000, 2093056, PROT_NONE) = 0
mmap(0x7f2367915000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2000) = 0x7f2367915000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\260\34\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2030544, ...}) = 0
mmap(NULL, 4131552, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f2367322000
mprotect(0x7f2367509000, 2097152, PROT_NONE) = 0
mmap(0x7f2367709000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1e7000) = 0x7f2367709000
mmap(0x7f236770f000, 15072, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f236770f000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libz.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\220\37\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=116960, ...}) = 0
mmap(NULL, 2212016, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f2367105000
mprotect(0x7f2367121000, 2093056, PROT_NONE) = 0
mmap(0x7f2367320000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b000) = 0x7f2367320000
close(3)                                = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2367f42000
arch_prctl(ARCH_SET_FS, 0x7f2367f430c0) = 0
mprotect(0x7f2367709000, 16384, PROT_READ) = 0
mprotect(0x7f2367320000, 4096, PROT_READ) = 0
mprotect(0x7f2367915000, 4096, PROT_READ) = 0
mprotect(0x7f2367b1b000, 4096, PROT_READ) = 0
mprotect(0x7f2367d35000, 4096, PROT_READ) = 0
mprotect(0x55ca9c252000, 8192, PROT_READ) = 0
mprotect(0x7f2367f5e000, 4096, PROT_READ) = 0
munmap(0x7f2367f46000, 94674)           = 0
socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_ROUTE) = 3
setsockopt(3, SOL_SOCKET, SO_SNDBUF, [32768], 4) = 0
setsockopt(3, SOL_SOCKET, SO_RCVBUF, [1048576], 4) = 0
setsockopt(3, SOL_NETLINK, NETLINK_EXT_ACK, [1], 4) = 0
bind(3, {sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, 12) = 0
getsockname(3, {sa_family=AF_NETLINK, nl_pid=5172, nl_groups=00000000}, [12]) = 0
access("/proc/net", R_OK)               = 0
access("/proc/net/unix", R_OK)          = 0
socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0) = 4
ioctl(4, SIOCGIFINDEX, {ifr_name="tap0", }) = 0
close(4)                                = 0
sendmsg(3, {msg_name={sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, msg_namelen=12, msg_iov=[{iov_base={{len=44, type=RTM_NEWROUTE, flags=NLM_F_REQUEST|NLM_F_ACK|NLM_F_EXCL|NLM_F_CREATE, seq=1571595405, pid=0}, {rtm_family=AF_INET, rtm_dst_len=24, rtm_src_len=0, rtm_tos=0, rtm_table=RT_TABLE_MAIN, rtm_protocol=RTPROT_BOOT, rtm_scope=RT_SCOPE_LINK, rtm_type=RTN_UNICAST, rtm_flags=0}, [{{nla_len=8, nla_type=RTA_DST}, 10.0.0.0}, {{nla_len=8, nla_type=RTA_OIF}, if_nametoindex("tap0")}]}, iov_len=44}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 44
recvmsg(3, {msg_name={sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, msg_namelen=12, msg_iov=[{iov_base=NULL, iov_len=0}], msg_iovlen=1, msg_controllen=0, msg_flags=MSG_TRUNC}, MSG_PEEK|MSG_TRUNC) = 36
brk(NULL)                               = 0x55ca9c9c6000
brk(0x55ca9c9e7000)                     = 0x55ca9c9e7000
recvmsg(3, {msg_name={sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, msg_namelen=12, msg_iov=[{iov_base={{len=36, type=NLMSG_ERROR, flags=NLM_F_CAPPED, seq=1571595405, pid=5172}, {error=0, msg={len=44, type=RTM_NEWROUTE, flags=NLM_F_REQUEST|NLM_F_ACK|NLM_F_EXCL|NLM_F_CREATE, seq=1571595405, pid=0}}}, iov_len=36}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 36
exit_group(0)                           = ?
+++ exited with 0 +++

【问题讨论】:

    标签: c++ c linux network-programming


    【解决方案1】:

    我使用 rtnetlink 库来添加/读取内核路由,它们可以帮助你Rtnetlink manual

    编辑:如果您仔细查看执行跟踪,您可以看到带有 ip 命令的 iproute2 工具还如何使用 netlink 库在内核中配置路由。

    --> socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_ROUTE) = 3
    setsockopt(3, SOL_SOCKET, SO_SNDBUF, [32768], 4) = 0
    setsockopt(3, SOL_SOCKET, SO_RCVBUF, [1048576], 4) = 0
    setsockopt(3, SOL_NETLINK, NETLINK_EXT_ACK, [1], 4) = 0
    bind(3, {sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, 12) = 0
    getsockname(3, {sa_family=AF_NETLINK, nl_pid=5172, nl_groups=00000000}, [12]) = 0
    access("/proc/net", R_OK)               = 0
    access("/proc/net/unix", R_OK)          = 0
    socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0) = 4
    ioctl(4, SIOCGIFINDEX, {ifr_name="tap0", }) = 0
    close(4)                                = 0
    sendmsg(3, {msg_name={sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, msg_namelen=12, msg_iov=[{iov_base={{len=44, type=RTM_NEWROUTE, flags=NLM_F_REQUEST|NLM_F_ACK|NLM_F_EXCL|NLM_F_CREATE, seq=1571595405, pid=0}, {rtm_family=AF_INET, rtm_dst_len=24, rtm_src_len=0, rtm_tos=0, rtm_table=RT_TABLE_MAIN, rtm_protocol=RTPROT_BOOT, rtm_scope=RT_SCOPE_LINK, rtm_type=RTN_UNICAST, rtm_flags=0}, [{{nla_len=8, nla_type=RTA_DST}, 10.0.0.0}, {{nla_len=8, nla_type=RTA_OIF}, if_nametoindex("tap0")}]}, iov_len=44}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 44
    

    【讨论】:

      猜你喜欢
      • 2012-03-24
      • 1970-01-01
      • 2011-06-29
      • 1970-01-01
      • 1970-01-01
      • 2012-07-11
      • 2010-10-26
      • 2013-04-30
      • 1970-01-01
      相关资源
      最近更新 更多