您的位置:首页 > 运维架构 > Linux

linux netlink操作路由小例子

2014-05-14 12:42 190 查看
此文章为转载,可能有问题,主要是为了自己日后学习方便,

1,在网上查了关于netlink的实现路由查询和添加路由的文章,资料很少,提供的代码都没有运行结果或者编译不了。所以从网上拷贝的代码仔细研究,一步一步的调试,添加很多printf语句查看各结构的值。

2,我主要参考的代码网页链接有:
http://downloads.open-mesh.org/svn/batman/tags/batman-0.3/linux/route.c
(上面这个链接主要是用来实现添加/删除路由的程序的模块,没有这个源程序我也无从下手,大部分代码是从这个文件上面拷贝下来的)

3,需要注意的地方

rtmsg结构体中的rtm_dst_len代表的是目的网络或目的主机掩码的位数,我以前总是以为是ip地址长度所以就填4,这是不对的,同理rtm_src_len也是一样,不过本程序填0就可以了,添加路由不需要源地址。

nlmsghdr结构体中的nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE| NLM_F_EXCL;如果单填 NLM_F_CREATE好像是不行的添加不了路由。

我的linux是ubutun9.10,内核是2.6.31,其他linux系统编译是否有问题不清楚了。

4,长话不多说了,就看代码吧:

#include <stdio.h>

#include <sys/errno.h>

#include <sys/time.h>

#include <sys/socket.h>

#include <asm/types.h>

#include <sys/types.h>

#include <linux/rtnetlink.h>

#include <linux/netlink.h>

#include <unistd.h>

#include <string.h>

#include <sys/uio.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <stdlib.h>

typedef __u32 u32;

int addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data,int alen)

{

int len =RTA_LENGTH(alen);

structrtattr *rta;

if(NLMSG_ALIGN(n->nlmsg_len) + len >maxlen)

return -1;

rta =(struct rtattr*)(((char*)n) +NLMSG_ALIGN(n->nlmsg_len));

rta->rta_type = type;

rta->rta_len = len;

memcpy(RTA_DATA(rta), data, alen);

n->nlmsg_len =NLMSG_ALIGN(n->nlmsg_len) + len;

fprintf(stderr,"\nattrlen=%d\n",n->nlmsg_len);

return0;

}

void route_add(int fd, __u32* destination,__u32* gateway,unsignedint netmask)

{

structsockaddr_nl nladdr;

intstatus;

__u32index=2;

//__u32source=254;

// structureof the netlink packet.

struct

{

struct nlmsghdr n;

struct rtmsg r;

char buf[1024];

} req;

nladdr.nl_family=AF_NETLINK;

nladdr.nl_pad=0;

nladdr.nl_pid=0;

nladdr.nl_groups=0;

status=bind(fd,(struct sockaddr*)&nladdr,sizeof(nladdr));

if(status<0){

perror("bind");

exit(1);

}

// Forming the iovector with the netlink packet.

// structiovec iov = { (void*)&req.n, req.n.nlmsg_len};

// Forming the message to be sent.

// structmsghdr msg = { (void*)&nladdr, sizeof(nladdr),&iov, 1, NULL, 0, 0 };

memset(&req, 0,sizeof(req));

// Initialisation of a few parameters

memset(&nladdr,0,sizeof(nladdr));

nladdr.nl_family= AF_NETLINK;

nladdr.nl_pid=0;

nladdr.nl_groups=0;

req.n.nlmsg_len = NLMSG_LENGTH(sizeof(structrtmsg));

req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK |NLM_F_CREATE | NLM_F_EXCL;

req.n.nlmsg_type = RTM_NEWROUTE;

req.r.rtm_family = AF_INET;

req.r.rtm_table = RT_TABLE_MAIN;

req.r.rtm_protocol = RTPROT_STATIC;

req.r.rtm_scope = RT_SCOPE_UNIVERSE;

req.r.rtm_type = RTN_UNICAST;

req.r.rtm_dst_len=netmask; //目的网络子网掩码位数

req.r.rtm_src_len=0;

req.r.rtm_tos=0;

req.r.rtm_flags=RT_TABLE_MAIN;

req.n.nlmsg_len = NLMSG_LENGTH(sizeof(structrtmsg)) ;

// RTA_DST and RTA_GW are the two esential parameters for adding aroute,

// there are other parameters too which are not discussed here. Foripv4,

// the length of the address is 4 bytes.

addattr_l(&req.n, sizeof(req),RTA_DST, destination, 4);

addattr_l(&req.n, sizeof(req),RTA_GATEWAY, gateway, 4);

addattr_l(&req.n, sizeof(req),RTA_OIF,&index, 4);

// sending the packet to the kernel.

status=send(fd,&req,req.n.nlmsg_len,0);

fprintf(stderr,"\nstatus=%d,添加路由成功\n",status);

}

int main(int argc ,char ** argv)

{

intfd;

__u32dest,gate; //dest 代表目的网络或主机,gate代表网关;

if(argc!=4){

printf("usage:%s 10.168.0.0 2410.168.3.1\n",argv[0]);

exit(1);

}

if(atoi(argv[2])<0||atoi(argv[2])>32){

printf("unvalible netmask bits!!must be0-32\n");

exit(1);

}

if((fd=socket(AF_NETLINK,SOCK_RAW,NETLINK_ROUTE))<0){

printf("error creating a socket\n");

exit(1);

}

dest=inet_addr(argv[1]);

gate=inet_addr(argv[3]);

route_add(fd,&dest,&gate,(unsignedint)atoi(argv[2]));

return0;

}

编译后要用root权限运行。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: