Chinaunix首页 | 论坛 | 博客
  • 博客访问: 338651
  • 博文数量: 64
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 589
  • 用 户 组: 普通用户
  • 注册时间: 2012-11-08 15:50
文章分类

全部博文(64)

文章存档

2015年(52)

2014年(3)

2013年(9)

我的朋友

分类: LINUX

2015-05-27 11:20:28

在linux系统下可通过创建socket时指定protocol为NETLINK_ROUTE,通过netlink即可向系统发送消息获取路由表,获取路由表后即可通过route命令对路由表进行操作,可以实现删除不符合规则的路由项
/********
 * 此文件功能是通过netlink获取本机上的路由表信息,包括源地址,目的地址,经过的网关和目的地址的掩码长度
 * 如果存在不正常的路由表,则将路由从路由表中删除
 * 如果存在多个,则会显示多个
 * *********/
#include  //for in_addr   
#include    //for rtnetlink   
#include //for IF_NAMESIZ, route_info   
#include //for malloc(), free()   
#include //for strstr(), memset()   
#include
#include
#include
#include


//#include   


#define BUFSIZE 8192   


struct route_info{   
u_int dstAddr;   
u_int srcAddr;   
u_int gateWay;   
char ifName[IF_NAMESIZE];   
};   
int readNlSock(int sockFd, char *bufPtr, int seqNum, int pId)   
{   
struct nlmsghdr *nlHdr;   
int readLen = 0, msgLen = 0;   
do{   
//收到内核的应答   
if((readLen = recv(sockFd, bufPtr, BUFSIZE - msgLen, 0)) < 0)   
{   
perror("SOCK READ: ");   
return -1;   
}   


nlHdr = (struct nlmsghdr *)bufPtr;   
//检查header是否有效   
if((NLMSG_OK(nlHdr, readLen) == 0) || (nlHdr->nlmsg_type == NLMSG_ERROR))   
{   
perror("Error in recieved packet");   
return -1;   
}   




if(nlHdr->nlmsg_type == NLMSG_DONE)    
{   
break;   
}   
else   
{   


bufPtr += readLen;   
msgLen += readLen;   
}   




if((nlHdr->nlmsg_flags & NLM_F_MULTI) == 0)    
{   


break;   
}   
} while((nlHdr->nlmsg_seq != seqNum) || (nlHdr->nlmsg_pid != pId));   
return msgLen;   
}   
//分析返回的路由信息   
void parseRoutes(struct nlmsghdr *nlHdr, struct route_info *rtInfo,char *gateway)   
{   
struct rtmsg *rtMsg;   
struct rtattr *rtAttr;   
int rtLen,dstLen;   
char *tempBuf = NULL;   
struct in_addr dst;   
struct in_addr gate;   
char cmd[128];
char dstaddr[32],srcaddr[32];


tempBuf = (char *)malloc(100);   
rtMsg = (struct rtmsg *)NLMSG_DATA(nlHdr);   
// If the route is not for AF_INET or does not belong to main routing table   
//then return.    
if((rtMsg->rtm_family != AF_INET) || (rtMsg->rtm_table != RT_TABLE_MAIN))   
return;   
//printf("rtmsg srclen:%d,dstlen:%d\n",rtMsg->rtm_src_len,rtMsg->rtm_dst_len);
dstLen = rtMsg->rtm_dst_len; //路由表中目的地址的掩码长度


rtAttr = (struct rtattr *)RTM_RTA(rtMsg);   
rtLen = RTM_PAYLOAD(nlHdr);   
for(;RTA_OK(rtAttr,rtLen);rtAttr = RTA_NEXT(rtAttr,rtLen)){   
switch(rtAttr->rta_type) {   
case RTA_OIF:   
if_indextoname(*(int *)RTA_DATA(rtAttr), rtInfo->ifName);       //网卡名称
break;   
case RTA_GATEWAY:   
rtInfo->gateWay = *(u_int *)RTA_DATA(rtAttr);                       //此条路由项的网关
break;   
case RTA_PREFSRC:   
rtInfo->srcAddr = *(u_int *)RTA_DATA(rtAttr);                       //路由项的源地址        
break;   
case RTA_DST:   
rtInfo->dstAddr = *(u_int *)RTA_DATA(rtAttr);                       //路由项中的目的地址
break;   
}   
}   
dst.s_addr = rtInfo->dstAddr;   
//printf("oif:%s\t",rtInfo->ifName);   
//if (strstr((char *)inet_ntoa(dst), "0.0.0.0"))   
//{   
printf("oif:%s\t",rtInfo->ifName);   
gate.s_addr = rtInfo->gateWay;   
sprintf(gateway, (char *)inet_ntoa(gate));   
printf("%s\n",gateway);   
if(strcmp(gateway,"0.0.0.0") != 0 && strcmp(gateway,"192.168.1.1") != 0){            //如果网关不是0.0.0.0和192.168.1.1,则将路由项从路由表中删除
gate.s_addr = rtInfo->srcAddr;   
printf("src:%s\n",(char *)inet_ntoa(gate));   
snprintf(srcaddr,31,(char *)inet_ntoa(gate));
gate.s_addr = rtInfo->dstAddr;   
printf("dst:%s\n",(char *)inet_ntoa(gate));    
snprintf(dstaddr,31,(char *)inet_ntoa(gate));
snprintf(cmd,127,"route del -net %s/%d gw %s",dstaddr,dstLen,gateway);
printf("cmd:%s\n",cmd);
system(cmd);
}
//}   
free(tempBuf);   
return;   
}   


int get_gateway(char *gateway)   
{   
struct nlmsghdr *nlMsg;   
struct rtmsg *rtMsg;   
struct route_info *rtInfo;   
char msgBuf[BUFSIZE];   


int sock, len, msgSeq = 0;   


if((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0)   
{   
perror("Socket Creation: ");   
return -1;   
}   




memset(msgBuf, 0, BUFSIZE);   




nlMsg = (struct nlmsghdr *)msgBuf;   
rtMsg = (struct rtmsg *)NLMSG_DATA(nlMsg);   




nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); // Length of message.   
nlMsg->nlmsg_type = RTM_GETROUTE; // Get the routes from kernel routing table .   


nlMsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; // The message is a request for dump.   
nlMsg->nlmsg_seq = msgSeq++; // Sequence of the message packet.   
nlMsg->nlmsg_pid = getpid(); // PID of process sending the request.   




if(send(sock, nlMsg, nlMsg->nlmsg_len, 0) < 0){   
printf("Write To Socket Failed…\n");   
return -1;   
}   




if((len = readNlSock(sock, msgBuf, msgSeq, getpid())) < 0) {   
printf("Read From Socket Failed…\n");   
return -1;   
}   


rtInfo = (struct route_info *)malloc(sizeof(struct route_info));   
for(;NLMSG_OK(nlMsg,len);nlMsg = NLMSG_NEXT(nlMsg,len)){   
memset(rtInfo, 0, sizeof(struct route_info));   
parseRoutes(nlMsg, rtInfo,gateway);   
}   
free(rtInfo);   
close(sock);   
return 0;   
}   


int main()   
{   
char buff[256];   
get_gateway(buff);   
return 0;   
}  


阅读(6292) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~