模拟路由器
程序员文章站
2022-06-03 21:09:52
...
//路由器,功能为:存储,转发即抓包,改变包的内容
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/ether.h>
#include <arpa/inet.h>
#include <string.h>
#include <netpacket/packet.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <unistd.h>
#include <pthread.h>
#include "get_interface.h"
#include <stdlib.h>
typedef struct st_my_arp //arp应答内容:目的mac 与 目的主机ip
{
char ip_str[4];
char mac_str[6];
} ST_MY_ARP;
typedef struct st_my_ethname_and_arp
{
char ethname[10];
ST_MY_ARP my_eth_st[256]; //结构体嵌套
} ST_MY_ETHNAME_AND_ARP;
ST_MY_ARP my_arp[256]; //在my_rcv_arp中赋值
ST_MY_ETHNAME_AND_ARP my_ethname_arp[10]; //在获取ethname后赋值
unsigned char *my_find_from_arp(unsigned char *p, unsigned char *p_ethname) //一个参数为目的ip,另一个为ethname
{
//应该先进行arp请求,然后获取到arp应答的内容,写到结构体里,应传进来一个结构体数组(arp应答的mac与ip)
//应该传进来一个(eth与arp应答结构体数组的)结构体数组,传进来一个现在转发时发送用的哪个eth
printf("---------------------------------------进入从arp表里找目的mac\n");
unsigned char *my_arp_dst_mac = (unsigned char *)malloc(6);
int j = 0;
for (j = 0; j < get_interface_num(); j++) //找网卡
{
printf("2222222222222222222222222进入从arp表里找目的mac\n");
if (memcmp(my_ethname_arp[j].ethname, p_ethname, 10) == 0) //此处可能有问题:1参数name占20字节,2参数name10字节
{
printf("网卡比较成功\n");
printf("现在是第%d个my_ethname_arp\n", j);
break;
}
}
//上面得到了现在所用的带网卡的结构体即my_ethname_arp[j].ethname
int i = 0;
for (i = 0; i < 256; i++) //找ip对应的mac
{
printf("3333333333333333333333333333进入从arp表里找目的mac\n");
printf("现在验证my_ethname_arp[j].my_eth_st[i].ip_str------\n");
int uu=0;
for (uu = 0; uu < 4; uu++)
{
printf("-----------i=%d\n",i);
printf("%02x:", *(unsigned char*)(my_ethname_arp[j].my_eth_st[i].ip_str + uu));
}
printf("\n");
if (memcmp(my_ethname_arp[j].my_eth_st[i].ip_str, p, 4) == 0)
{
printf("ip匹配成功\n");
//将对应的mac赋值给p
memcpy(my_arp_dst_mac, my_ethname_arp[j].my_eth_st[i].mac_str, 6);
int tt=0;
for (tt = 0; tt < 6; tt++)
{
printf("%02x:", *( my_ethname_arp[j].my_eth_st[i].mac_str + tt));
}
return my_arp_dst_mac;
}
}
printf("4444444444444444444444444进入从arp表里找目的mac\n");
my_arp_dst_mac = NULL;
return my_arp_dst_mac;
}
//抓包,并改变包的dstmac
void *deal_fun(void *arg)
{
int sockfd = (int)arg;
printf("sockfd=%d\n", sockfd);
//这种函数下次记住,一看就是通过全局变量来完成工作的
getinterface();
//将getinterface()里的name直接写入自己的结构体
int mm=0;
for ( mm = 0; mm < get_interface_num() ; mm++)
{
memcpy(my_ethname_arp[mm].ethname,net_interface[mm].name,10);
}
while (1)
{
unsigned char buf[1500] = "";
//由于sockraw 无法分析iip 所以写null
int len = recvfrom(sockfd, buf, sizeof(buf), 0, NULL, NULL);
printf("len = %d\n", len);
unsigned short mac_type = ntohs(*(unsigned short *)(buf + 12));
if (mac_type == 0x0806)
{
if (buf[21] == 2) //确定类型是arp应答
{
//根据第几块网卡的ip,和现在收到包的源ip前三位是否相同,确定应改的arp表ii。
int ii = 0;
for (ii = 0; ii < get_interface_num(); ii++)
{
if (memcmp(buf + 28, net_interface[ii].ip, 3) == 0)//28代表arp中的源ip
break;
}
// memcpy(my_ethname_arp[ii].ethname, net_interface[ii].name, 10);
char ip_str[16] = "";
char mac_str[18] = "";
inet_ntop(AF_INET, buf + 28, ip_str, 16); //arp应答的源ip
unsigned char xxx = *(unsigned char *)(buf + 28 + 3);
sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x",
buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]);
printf("获得arp应答的源ip与源mac%s----%s\n", ip_str, mac_str);
//下面将ip与mac写到全局结构体
memcpy(my_ethname_arp[ii].my_eth_st[xxx].ip_str, buf + 28, 4);
memcpy(my_ethname_arp[ii].my_eth_st[xxx].mac_str, buf + 22, 6);
//验证写入是否有问题
int oo = 0;
printf("现在验证写入的mac------");
for (oo = 0; oo < 6; oo++)
{
printf("%02x:", *(unsigned char*)( my_ethname_arp[ii].my_eth_st[xxx].mac_str+ oo));
}
printf("\n");
printf("现在验证写入的ip------");
for (oo = 0; oo < 4; oo++)
{
printf("%02x:", *(unsigned char*)( my_ethname_arp[ii].my_eth_st[xxx].ip_str+ oo));
}
printf("\n");
// printf("现在是自己的arp表\n");
// sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x",
// my_ethname_arp[ii].my_eth_st[xxx].mac_str,my_ethname_arp[ii].my_eth_st[xxx].mac_str+1\
// ,my_ethname_arp[ii].my_eth_st[xxx].mac_str+2,my_ethname_arp[ii].my_eth_st[xxx].mac_str+3\
// ,my_ethname_arp[ii].my_eth_st[xxx].mac_str+4,my_ethname_arp[ii].my_eth_st[xxx].mac_str+5);
// printf("获得arp应答的源ip与源mac%s----%s\n",my_ethname_arp[ii].my_eth_st[xxx].ip_str , my_ethname_arp[ii].my_eth_st[xxx].mac_str);
}
}
//现在应该完成了arp表的写入工作
else if (mac_type == 0x0800)
{
printf("-----收到一只Ip报文\n");
unsigned char *dst_ip = buf + 14 + 16; //跳过以太网头部,以及ip头的前几位,来到目的ip的位置
int i = 0;
for (i = 0; i < get_interface_num(); i++)
{
//判断buf中的目的ip和路由器的哪块网卡同一网段
if (memcmp(dst_ip, net_interface[i].ip, 3) == 0 && memcmp(dst_ip, net_interface[i].ip, 4) != 0)
{
printf("dddddddddddddddddddddddd\n");
//修改buf中源mac,为路由器的和目的ip相同网段的mac
memcpy(buf + 6, net_interface[i].mac, 6);
unsigned char *dst_mac = my_find_from_arp(dst_ip, net_interface[i].name);
// int j = 0;
// for (j = 0; j < 6; j++)
// {
// printf("%02x:", *(dst_mac + j));
// }
printf("\n");
if (dst_mac == NULL)
{
//发送arp
unsigned char a[6] = "";
int jj = 0;
for (jj = 0; jj < 6; jj++)
{
sscanf(((unsigned char *)net_interface[i].mac) + jj, "%c", a + jj);
}
unsigned char b[4] = "";
for (jj = 0; jj < 4; jj++)
{
sscanf((unsigned char *)net_interface[i].ip + jj, "%c", b + jj);
}
unsigned char c[4] = "";
for (jj = 0; jj < 4; jj++)
{
sscanf((unsigned char *)dst_ip + jj, "%c", c + jj); //收到一个包,这个包中ip已知,但mac未知,故将ip考给arp协议
}
unsigned char msg[] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, //目的mac
a[0], a[1], a[2], a[3], a[4], a[5], //源mac
0x08, 0x06, //帧类型 arp
//arp 报文头
0x00, 0x01, //硬件类型
0x08, 0x00, //协议类型
6,
4,
0x00, 0x01, //arp请求命令
0x00, 0x0c, 0x29, 0xb3, 0x34, 0x0b, //源mac
b[0], b[1], b[2], b[3], //源ip
0, 0, 0, 0, 0, 0, //目的mac
c[0], c[1], c[2], c[3] //目的ip(209房兴业)240windows成功 181失败
//写255失败的原因 根本就没有255这个地址啊,arp本身就是广播,它一看没有255那算了
};
//发送arp
//获取本地网络接口
struct ifreq ethreq;
strncpy(ethreq.ifr_name, net_interface[i].name, IFNAMSIZ);
ioctl(sockfd, SIOGIFINDEX, ðreq);
//将本地接口赋值给sll
struct sockaddr_ll sll;
bzero(&sll, sizeof(sll));
sll.sll_ifindex = ethreq.ifr_ifindex;
sendto(sockfd, msg, 42, 0, (struct sockaddr *)&sll, sizeof(sll));
break;
}
else if (dst_mac != NULL)
{
printf("dddddddddddddddddddddddddddddddd\n");
memcpy(buf, dst_mac, 6);
printf("mac地址为");
int j = 0;
for (j = 0; j < 6; j++)
{
printf("%02x:", *(buf + j));
}
}
//获取本地网络接口
struct ifreq ethreq;
strncpy(ethreq.ifr_name, net_interface[i].name, IFNAMSIZ);
ioctl(sockfd, SIOGIFINDEX, ðreq);
//将本地接口赋值给sll
struct sockaddr_ll sll;
bzero(&sll, sizeof(sll));
sll.sll_ifindex = ethreq.ifr_ifindex;
sendto(sockfd, buf, len, 0, (struct sockaddr *)&sll, sizeof(sll));
}
}
}
}
}
int main(int argc, char const *argv[])
{
int sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sockfd == -1)
{
perror("sockfd");
}
pthread_t tid;
pthread_create(&tid, NULL, deal_fun, (void *)sockfd);
pthread_detach(tid);
sleep(100000);
close(sockfd);
return 0;
}
#ifndef GET_INTERFACE_H
#define GET_INTERFACE_H
#define MAXINTERFACES 16 /* 最大接口数 */
typedef struct interface{
char name[20]; //接口名字
unsigned char ip[4]; //IP地址
unsigned char mac[6]; //MAC地址
unsigned char netmask[4]; //子网掩码
unsigned char br_ip[4]; //广播地址
int flag; //状态
}INTERFACE;
extern INTERFACE net_interface[MAXINTERFACES];//接口数据
/******************************************************************
函 数: int getinterface()
功 能: 获取接口信息
参 数: 无
*******************************************************************/
extern void getinterface();
/******************************************************************
函 数: int get_interface_num()
功 能: 获取实际接口数量
参 数: 接口数量
*******************************************************************/
int get_interface_num();
#endif
#include <arpa/inet.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/ether.h>
#include "get_interface.h"
int interface_num=0;//接口数量
INTERFACE net_interface[MAXINTERFACES];//接口数据 结构体数组
/******************************************************************
函 数: int get_interface_num()
功 能: 获取接口数量
参 数: 无
*******************************************************************/
int get_interface_num(){
return interface_num;
}
/******************************************************************
函 数: int getinterface()
功 能: 获取接口信息
参 数: 无
*******************************************************************/
void getinterface(){
struct ifreq buf[MAXINTERFACES]; /* ifreq结构数组 */
struct ifconf ifc; /* ifconf结构 */
int sock_raw_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
/* 初始化ifconf结构 */
ifc.ifc_len = sizeof(buf);
ifc.ifc_buf = (caddr_t) buf;
/* 获得接口列表 */
if (ioctl(sock_raw_fd, SIOCGIFCONF, (char *) &ifc) == -1){
perror("SIOCGIFCONF ioctl");
return ;
}
interface_num = ifc.ifc_len / sizeof(struct ifreq); /* 接口数量 */
printf("interface_num=%d\n\n", interface_num);
char buff[20]="";
int ip;
int if_len = interface_num;
while (if_len-- > 0){ /* 遍历每个接口 */
printf("%s\n", buf[if_len].ifr_name); /* 接口名称 */
sprintf(net_interface[if_len].name, "%s", buf[if_len].ifr_name); /* 接口名称 */
printf("-%d-%s--\n",if_len,net_interface[if_len].name);
/* 获得接口标志 */
if (!(ioctl(sock_raw_fd, SIOCGIFFLAGS, (char *) &buf[if_len]))){
/* 接口状态 */
if (buf[if_len].ifr_flags & IFF_UP){
printf("UP\n");
net_interface[if_len].flag = 1;
}
else{
printf("DOWN\n");
net_interface[if_len].flag = 0;
}
}else{
char str[256];
sprintf(str, "SIOCGIFFLAGS ioctl %s", buf[if_len].ifr_name);
perror(str);
}
/* IP地址 */
if (!(ioctl(sock_raw_fd, SIOCGIFADDR, (char *) &buf[if_len]))){
printf("IP:%s\n",(char*)inet_ntoa(((struct sockaddr_in*) (&buf[if_len].ifr_addr))->sin_addr));
bzero(buff,sizeof(buff));
sprintf(buff, "%s", (char*)inet_ntoa(((struct sockaddr_in*) (&buf[if_len].ifr_addr))->sin_addr));
inet_pton(AF_INET, buff, &ip);
memcpy(net_interface[if_len].ip, &ip, 4);
}else{
char str[256];
sprintf(str, "SIOCGIFADDR ioctl %s", buf[if_len].ifr_name);
perror(str);
}
/* 子网掩码 */
if (!(ioctl(sock_raw_fd, SIOCGIFNETMASK, (char *) &buf[if_len]))){
printf("netmask:%s\n",(char*)inet_ntoa(((struct sockaddr_in*) (&buf[if_len].ifr_addr))->sin_addr));
bzero(buff,sizeof(buff));
sprintf(buff, "%s", (char*)inet_ntoa(((struct sockaddr_in*) (&buf[if_len].ifr_addr))->sin_addr));
inet_pton(AF_INET, buff, &ip);
memcpy(net_interface[if_len].netmask, &ip, 4);
}else{
char str[256];
sprintf(str, "SIOCGIFADDR ioctl %s", buf[if_len].ifr_name);
perror(str);
}
/* 广播地址 */
if (!(ioctl(sock_raw_fd, SIOCGIFBRDADDR, (char *) &buf[if_len]))){
printf("br_ip:%s\n",(char*)inet_ntoa(((struct sockaddr_in*) (&buf[if_len].ifr_addr))->sin_addr));
bzero(buff,sizeof(buff));
sprintf(buff, "%s", (char*)inet_ntoa(((struct sockaddr_in*) (&buf[if_len].ifr_addr))->sin_addr));
inet_pton(AF_INET, buff, &ip);
memcpy(net_interface[if_len].br_ip, &ip, 4);
}else{
char str[256];
sprintf(str, "SIOCGIFADDR ioctl %s", buf[if_len].ifr_name);
perror(str);
}
/*MAC地址 */
if (!(ioctl(sock_raw_fd, SIOCGIFHWADDR, (char *) &buf[if_len]))){
printf("MAC:%02x:%02x:%02x:%02x:%02x:%02x\n\n",
(unsigned char) buf[if_len].ifr_hwaddr.sa_data[0],
(unsigned char) buf[if_len].ifr_hwaddr.sa_data[1],
(unsigned char) buf[if_len].ifr_hwaddr.sa_data[2],
(unsigned char) buf[if_len].ifr_hwaddr.sa_data[3],
(unsigned char) buf[if_len].ifr_hwaddr.sa_data[4],
(unsigned char) buf[if_len].ifr_hwaddr.sa_data[5]);
memcpy(net_interface[if_len].mac, (unsigned char *)buf[if_len].ifr_hwaddr.sa_data, 6);
}else{
char str[256];
sprintf(str, "SIOCGIFHWADDR ioctl %s", buf[if_len].ifr_name);
perror(str);
}
}//–while end
close(sock_raw_fd); //关闭socket
}
上一篇: MySQL导入sql文件错误#1044
下一篇: 可更新物化视图复制站点