红联Linux门户
Linux帮助

C/C++操作Linux路由表

发布时间:2016-06-15 15:49:04来源:topspeedsnail.com作者:linux人

本文介绍怎么使用C/C++从Linux路由表中添加移除无效的(Null Route)路由条目。


我们首先看一下怎么从命令行操作Linux路由表。

Linux路由表是在内核中的;查看:

$ sudo route -n

C/C++操作Linux路由表

你也可以查看 /proc/net/route 文件。


添加Null Routes

Null routes简单的忽略和它相匹配的包。使用它可以有效的屏蔽某个有问题的IP。

例如:

$ sudo route add 123.123.123.123 reject

C/C++操作Linux路由表

现在你不能和IP(123.123.123.123)  发送、接收数据包。


移除Null Routes

$ route del 123.123.123.123 reject

在操作路由表时要格外小心;如果你不小心移除了和SSH相关的远程主机路由,你只能通过访问物理主机解决。


使用C/C++更改路由表

要使用程序添加null route,你需要使用ioctl,控制参数SIOCADDRT:
#include <sys/types.h>
#include <sys/socket.h>
#include <net/route.h>
#include <sys/ioctl.h>

bool addNullRoute( long host )
{
// create the control socket.
int fd = socket( PF_INET, SOCK_DGRAM, IPPROTO_IP );

struct rtentry route;
memset( &route, 0, sizeof( route ) );

// set the gateway to 0.
struct sockaddr_in *addr = (struct sockaddr_in *)&route.rt_gateway;
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = 0;

// set the host we are rejecting.
addr = (struct sockaddr_in*) &route.rt_dst;
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = htonl(host);

// Set the mask. In this case we are using 255.255.255.255, to block a single
// IP. But you could use a less restrictive mask to block a range of IPs.
// To block and entire C block you would use 255.255.255.0, or 0x00FFFFFFF
addr = (struct sockaddr_in*) &route.rt_genmask;
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = 0xFFFFFFFF;

// These flags mean: this route is created "up", or active
// The blocked entity is a "host" as opposed to a "gateway"
// The packets should be rejected. On BSD there is a flag RTF_BLACKHOLE
// that causes packets to be dropped silently. We would use that if Linux
// had it. RTF_REJECT will cause the network interface to signal that the
// packets are being actively rejected.
route.rt_flags = RTF_UP | RTF_HOST | RTF_REJECT;
route.rt_metric = 0;

// this is where the magic happens..
if ( ioctl( fd, SIOCADDRT, &route ) )
{
close( fd );
return false;
}

// remember to close the socket lest you leak handles.
close( fd );
return true;
}

注意:重启系统更改失效。

上面代码的反操作,移除route:
bool delNullRoute( long host )
{
int fd = socket( PF_INET, SOCK_DGRAM, IPPROTO_IP );

struct rtentry route;
memset( &route, 0, sizeof( route ) );

struct sockaddr_in *addr = (struct sockaddr_in *)&route.rt_gateway;
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = 0;

addr = (struct sockaddr_in*) &route.rt_dst;
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = htonl(host);

addr = (struct sockaddr_in*) &route.rt_genmask;
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = 0xFFFFFFFF;

route.rt_flags = RTF_UP | RTF_HOST | RTF_REJECT;
route.rt_metric = 0;

// this time we are deleting the route:
if ( ioctl( fd, SIOCDELRT, &route ) )
{
close( fd );
return false;
}

close( fd );
return true;
}


本文永久更新地址:http://www.linuxdiyf.com/linux/21552.html