#include <asm/types.h>
#include <netinet/ether.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <sys/types.h>
#include <ifaddrs.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "gateway.h"
#define BUFSIZE 8192
struct route_info{
in_addr_t dstAddr;
in_addr_t srcAddr;
in_addr_t gateWay;
char ifName[IF_NAMESIZE];
};
struct route_info route_table[
1024];
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;
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 printRoute(
struct route_info *rtInfo)
{
char tempBuf[
512];
if(!rtInfo)
return;
if(rtInfo->dstAddr !=
0)
strcpy(tempBuf, (
char *)inet_ntoa((
struct in_addr&)rtInfo->dstAddr));
else
sprintf(tempBuf,
"*.*.*.*\t");
fprintf(stdout,
"%s\t", tempBuf);
if(rtInfo->srcAddr !=
0)
strcpy(tempBuf, (
char *)inet_ntoa((
struct in_addr&)rtInfo->srcAddr));
else
sprintf(tempBuf,
"*.*.*.*\t");
fprintf(stdout,
"%s\t", tempBuf);
if(rtInfo->gateWay !=
0)
strcpy(tempBuf, (
char *)inet_ntoa((
struct in_addr&)rtInfo->gateWay));
else
sprintf(tempBuf,
"*.*.*.*\t");
fprintf(stdout,
"%s\t", tempBuf);
fprintf(stdout,
"%s\n", rtInfo->ifName);
}
void parseRoutes(
struct nlmsghdr *nlHdr,
struct route_info *rtInfo)
{
struct rtmsg *rtMsg;
struct rtattr *rtAttr;
int rtLen;
rtMsg = (
struct rtmsg *)NLMSG_DATA(nlHdr);
if((rtMsg->rtm_family != AF_INET) || (rtMsg->rtm_table != RT_TABLE_MAIN))
return;
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;
}
}
return;
}
int get_route(
struct route_info **table,
int *table_length)
{
struct nlmsghdr *nlMsg;
char msgBuf[BUFSIZE];
int i =
0;
int sock, len, msgSeq =
0;
if((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) <
0)
perror(
"Socket Creation: ");
memset(msgBuf,
0, BUFSIZE);
memset(route_table,
0,
sizeof(
struct route_info));
nlMsg = (
struct nlmsghdr *)msgBuf;
nlMsg->nlmsg_len = NLMSG_LENGTH(
sizeof(
struct rtmsg));
nlMsg->nlmsg_type = RTM_GETROUTE;
nlMsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
nlMsg->nlmsg_seq = msgSeq++;
nlMsg->nlmsg_pid = getpid();
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;
}
i =
0;
for(;NLMSG_OK(nlMsg,len);nlMsg = NLMSG_NEXT(nlMsg,len)){
parseRoutes(nlMsg, &route_table[i++]);
}
*table_length = i +
1;
close(sock);
*table = route_table;
return 0;
}
void test()
{
int i =
0, j =
0;
struct route_info *table;
get_route(&table, &i);
while(j < i)
{
printRoute(&table[j++]);
}
}