一.项目流程图
二.环境搭建
主机:
Ubuntu:
设置网络:
开发板:
设置IP:ifconfig eth0 192.168.2.1 netmask 255.255.255.0
设置网关:route add default gw 192.168.2.2
实践:
主机与虚拟机相互ping
成功:
开发板与主机相互ping
失败:(因为是不同网段)
ok,完成
最后,运行我们写的路由器代码后,主机与开发板可以在不同网段下通信
开发板与主机相互ping
成功:
三.遇到的问题
1.默认网关有问题,导致开发板ping不通wind主机,后重启开发板后重新添加默认网关解决
异常(ping不通)
正常(可ping通)
2.wind的默认网关填错,导致ping不通开发板,这里的默认网关是根据虚拟机里面网卡来填的,需要灵活变动。
3.在虚拟机里面是需要2个网卡都能使用,在virtualbox只能有一个网卡可以down和up,所以环境一直有问题
成功互相ping通
四.代码如下:
Makefile
CC=gcc
target=main
$(target):main.o get_interface.o link.o -lpthread
$(CC) main.o get_interface.o link.o -o $(target) -lpthread
%*.o:%*.c
$(CC) -c $^ -o $@
clean:
rm -rf *.o $(target)
main.c
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <netinet/ether.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netpacket/packet.h>
#include <sys/ioctl.h>
#include "get_interface.h"
#include "link.h"
MY_ROU * roulink_head = NULL;
MY_ARP * arplink_head = NULL;
int sockfd = 0;
//*************************人机交互线程**********************************
void *callback1(void *arg)
{
while(1)
{
printf("输入相应的序号,实现对应功能\n");
int usercmd = -1;
scanf("%d", &usercmd);
switch (usercmd)
{
case 0:
getchar();
title();
break;
case 2:
getchar();//接收输入2的回车
roulink_head=rou_pTailInsert(roulink_head);
break;
case 3:
getchar();
roulink_head=rou_pDeleteLink(roulink_head);
break;
case 4:
getchar();
rou_print_link(roulink_head);/*将指针pHead传入输出函数遍历输出*/
printf("链表打印完毕!\n");
break;
case 5:
arp_print_link(arplink_head);
break;
case 10:
printf("10:退出路由器,释放IP、ARP链表\n");
getchar();
arp_freeLink(arplink_head);
rou_freeLink(roulink_head);//释放链表
exit(1);
break;
}
}
pthread_exit(NULL);
}
//*************************人机交互线程**********************************
//*************************ARP应答的IP和MAC存入缓存链表线程【开始】**************//
void * callback2_arp(void *arg)
{
arp_mac_ip *p = (arp_mac_ip*)arg;
//printf("将 ARP 应答的 IP 和 MAC 存入缓存链\n");
//printf("### %s\n", p->stc_ip);
if(arp_searcharpLink(arplink_head, p->stc_ip) == 0)
{
printf("插入链表中没有的ARP 应答 IP 和 MAC\n");
arplink_head = arp_pTailInsert( arplink_head, p->stc_mac ,p->stc_ip);
}
pthread_exit(NULL);
}
//*************************ARP应答的IP和MAC存入缓存链表线程【结束】***************//
//*************************IP包转发线程【开始】**********************************//
void *callback3_ip(void *arg)
{
//发送接口的结构体
struct sockaddr_ll sll;
ip_buf *pthread_ip_buf = (ip_buf *)arg;
unsigned char * ip_head= pthread_ip_buf->buf + 14;
char dst_ip[16] = "";
inet_ntop(AF_INET, ip_head + 16, dst_ip, 16);
printf("IP包转发线程中 目的 dst_ip = %s\n", dst_ip);
int i = 0;
for (i = 0; i < 16; i++)
{
unsigned char ip[16]="";
inet_ntop(AF_INET,net_interface[i].ip, ip, 16);//get_interface文件中得到的都是32位无符号整形数据(计算机数据),现转成成点分十进制(人能够书别的)
//---------------------[调试]----------------------------------------//
//printf("设置网卡循环进入次数 i = %d\n", i);
//printf("检索到的所有网卡名字net_interface[i].name = %s\n", net_interface[i].name);
//printf("net_interface[i].ip = %s\n",ip);
//---------------------[调试]----------------------------------------//
if(strncmp(ip, dst_ip, 9) == 0)//根据目标网段 查找活跃网卡
{
//网卡结构体
struct ifreq ethreq;
strncpy(ethreq.ifr_name, net_interface[i].name , IFNAMSIZ);//指定网卡名字
printf("网卡名字:%s\n", ethreq.ifr_name);
if(ioctl(sockfd, SIOCGIFINDEX, ðreq) == -1)//获取网卡接口地址
{
return 0;
}
bzero(&sll, sizeof(sll));
sll.sll_ifindex = ethreq.ifr_ifindex;//将网卡的接口类型赋值给发送接口
break;
}
else
{
//printf("找不到网段对应的网卡,继续查\n");
continue;
}
}
//--------------------------------------------拿到网卡,开始检索对应网卡所有数据,对比【开始】------------------------------------------------------//
if(strcmp(dst_ip + strlen(dst_ip) - 3, "255") == 0)//是 否为广 播地址
{
// printf("是广播地址, 退出线\n");
return;
}
else
{
//printf("不是广播地址,判断是否为回 环地址\n");
if(strcmp("127.0.0.1", dst_ip) == 0)
{
//printf("是回 环地址, 退出线\n");
return;
}
else
{
//printf("查找ARP缓存表 对应 MAC\n");
//指定目的MAC地址
//可以在链表中找到目的IP,组ICMP包的目的MAC就可以了
//之所以这样,是因为在网络中的ICMP包里,变化的只有目的MAC,源MAC、IP都不会发生变动
if(arp_searcharpLink(arplink_head, dst_ip) == 1)
{
//1网段中 指定目标IP是主机的IP、MAC
//2C-4D-54-57-04-7F
//printf("****icmp****\n");
if(strncmp("192.168.1.49", dst_ip, 9) == 0)
{
pthread_ip_buf->buf[0]=0x2C;
pthread_ip_buf->buf[1]=0x4D;
pthread_ip_buf->buf[2]=0x54;
pthread_ip_buf->buf[3]=0x57;
pthread_ip_buf->buf[4]=0x04;
pthread_ip_buf->buf[5]=0x7F;//目标
int send_len = sendto(sockfd, pthread_ip_buf->buf, pthread_ip_buf->my_buf_date_len, 0, (struct sockaddr *)&sll, sizeof(sll));
//-------------------[调试]------------------------//
//printf("****1 网段 icmp缓存表****\n");
// printf("send_len ICMP 1 = %d\n", send_len);
//-------------------[调试]------------------------//
}
//2网段中 指定目标IP是开发板的IP、MAC
// 00:53:50:00:01:33
else if(strncmp("192.168.2.100", dst_ip, 9) == 0)
{
pthread_ip_buf->buf[0]=0x00;
pthread_ip_buf->buf[1]=0x53;
pthread_ip_buf->buf[2]=0x50;
pthread_ip_buf->buf[3]=0x00;
pthread_ip_buf->buf[4]=0x59;
pthread_ip_buf->buf[5]=0x12;
//发送给套接字的数据长度,是实际传送过来的长度(main中的IP包有收到具体长度信息)
int send_len = sendto(sockfd, pthread_ip_buf->buf, pthread_ip_buf->my_buf_date_len, 0, (struct sockaddr *)&sll, sizeof(sll));
//-------------------[调试]------------------------//
//printf("****2 网段 icmp缓存表****\n");
// printf("send_len ICMP 2 = %d\n", send_len);
//-------------------[调试]------------------------//
}
}
else
{//没在链表中没有找到目的IP,需要重新组arp包才行
//printf("***************组ARP包\n");
int i = 0;
for(; i < 3; i++)
{
//printf("%s\n",dst_ip);
//比对到1网段的数据
if(strstr(dst_ip,"192.168.1") != 0)
{
printf("发送网段1arp包\n");
unsigned char arp_buf[42] = {
0xff,0xff,0xff,0xff,0xff,0xff,//目的mac,广播的形式发出去,等待目的IP恢复后覆盖
0x00,0x0c,0x29,0xfa,0x7c,0x9e,//源mac
0x08, 0x00,//协议类型
0, 1,//硬件类型
6,
4,
0, 1,//op
0x00,0x0c,0x29,0xfa,0x7c,0x9e,//源mac(网卡1 ech0的MAC)
192,168,1,88,//源IP是路由器1网段的网关,通过它发送到2网段
0x00,0x00,0x00,0x00,0x00,0x00,//目的mac,等待目的IP恢复后覆盖
0,0,0,0
//192,168,1,49,
};
int int_ip=0;
inet_pton(AF_INET, dst_ip, &int_ip);
unsigned char *intp=(char *)&int_ip;
arp_buf[38]=intp[0];
arp_buf[39]=intp[1];
arp_buf[40]=intp[2];
arp_buf[41]=intp[3];
int send_len = sendto(sockfd, arp_buf, sizeof(arp_buf), 0, (struct sockaddr *)&sll, sizeof(sll));
printf("send_len 11 = %d\n",send_len);
}
//网卡2,ech1的MAC:00:0c:29:fa:7c:a8
else if(strstr(dst_ip,"192.168.2") != 0)
{
printf("发送网段2arp包\n");
unsigned char arp_buf[42] = {
0xff,0xff,0xff,0xff,0xff,0xff,//目的mac
0x00,0x0c,0x29,0xfa,0x7c,0xa8,//源mac
0x08, 0x00,//协议类型
0, 1,//硬件类型
6,
4,
0, 1,//op
0x00,0x0c,0x29,0xfa,0x7c,0xa8,//源mac
192,168,2,89,//源IP是路由器2网段的网关,通过它发送到1网段
0x00,0x00,0x00,0x00,0x00,0x00,//目的mac
192,168,2,100,
};
int send_len = sendto(sockfd, arp_buf, sizeof(arp_buf), 0, (struct sockaddr *)&sll, sizeof(sll));
printf("send_len 22 = %d\n",send_len);
}
if(arp_searcharpLink(arplink_head, dst_ip) == 1)
{
//1
//2C-4D-54-57-04-7F
if(strncmp("192.168.0.11", dst_ip, 9) == 0)
{
pthread_ip_buf->buf[0] = 0xA8;
pthread_ip_buf->buf[1] = 0x5E;
pthread_ip_buf->buf[2] = 0x45;
pthread_ip_buf->buf[3] = 0xC1;
pthread_ip_buf->buf[4] = 0x8B;
pthread_ip_buf->buf[5] = 0x99;
int send_len = sendto(sockfd, pthread_ip_buf->buf, pthread_ip_buf->my_buf_date_len, 0, (struct sockaddr *)&sll, sizeof(sll));
//-------------------[调试]------------------------//
//printf("****3次发ARP过程中检索到ICMP包 1 网段****\n");
// printf("send_len ICMP 1 = %d\n", send_len);
//-------------------[调试]------------------------//
}
//2
// 开发板MAC(每次启动都会变化):1C:59:74:81:4A:43
1C:59:74:81:4A:43
else if(strncmp("192.168.1.1", dst_ip, 9) == 0)
{
pthread_ip_buf->buf[0] = 0x1c;
pthread_ip_buf->buf[1] = 0x59;
pthread_ip_buf->buf[2] = 0x74;
pthread_ip_buf->buf[3] = 0x81;
pthread_ip_buf->buf[4] = 0x4A;
pthread_ip_buf->buf[5] = 0x43;
int send_len = sendto(sockfd, pthread_ip_buf->buf, pthread_ip_buf->my_buf_date_len, 0, (struct sockaddr *)&sll, sizeof(sll));
//-------------------[调试]------------------------//
//printf("****3次发ARP过程中检索到ICMP包 2 网段****\n");
// printf("send_len ICMP 2 = %d\n", send_len);
//-------------------[调试]------------------------//
}
break;
}
}
}
return;
}
}
//--------------------------------------------拿到网卡,开始检索对应网卡所有数据,对比【结束】------------------------------------------------------//
pthread_exit(NULL);
}
//*************************建IP包转发线程【结束】**********************************//
int main()
{
//创建原始套接字,接收发送方的网卡信息
sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if(sockfd<0)
{
perror("sockfd:");
return 0;
}
getinterface();//拿取网卡信息(虚拟机的所有网卡,包括回环网卡)
pthread_t pth;
pthread_create(&pth, NULL, callback1, NULL);//人机交互线程,这里可以放在main里面
int len = 0;
char recv_buff[RECV_SIZE]="";//原始套接字数据包大约为1500个字节
ssize_t recv_len=0;
while(1)
{
//开始接收其他人的网卡信息
bzero(recv_buff,sizeof(recv_buff));
//[recv_len]设置成全局变量,让线程可以共用数据
recv_len = recvfrom(sockfd, recv_buff, sizeof(recv_buff), 0, NULL, NULL);
if(recv_len<=0||recv_len>RECV_SIZE)
{
perror("recvfrom");
continue;
}
//printf("链路层截取数据包长度 recv_len=%d\n",recv_len);
//MAC包类型
unsigned short mac_type = 0;
mac_type = ntohs( *((unsigned short *)(recv_buff + 12)));
if(mac_type == 0x0800)
{
//printf("-----------ip数据包------------\n");
unsigned char *ip_head = recv_buff + 14;
unsigned char dst_ip[16] ="";
inet_ntop(AF_INET, ip_head + 16, dst_ip, 16);
//IP包的类型
if(ip_head[9] == 1)
{
//printf("-----ICMP数据包\n");
//查找过滤IP链表中存在我们指定的目的IP吗
if(rou_searcharpLink(roulink_head, dst_ip) == 0)
{
static int i=0;
//-----------调试,打印原始套接字接收到的数据内容是否是空--------------------//
//printf("i=%d IP包中的目的IP = %d\n",++i, strlen(recv_buff + 30));
// printf("Rvfbuf=%p\n",recv_buff);
// int kk=0;
// while(kk<98)
// {
// printf("Rvfbuf[%d]=%d\n",kk,recv_buff[kk]);
// kk++;
// }
//----------------------------[调试]---------------------------------------//
usleep(1000);
ip_buf *recv = (ip_buf *)malloc(sizeof(ip_buf));
recv->my_buf_date_len = recv_len;
memcpy(recv->buf, recv_buff, recv_len);
//线程的创建放在满足它的条件中,while循环,满足就进来创建一个,切记不要放到条件外面创建线程,否则只会创建一个,导致所有情况共用一个线程
pthread_t pth2;
//最后数据包是ICMP的整包
pthread_create(&pth2, NULL, callback3_ip, (void*)recv);
pthread_detach(pth2);
}
}
}
else if(mac_type == 0x0806)
{
arp_mac_ip * head_mac_ip = NULL;//保存目的MAC\IP的结构体,安全措施,防止栈空间释放导致给线程传参为空,失败
head_mac_ip = (arp_mac_ip *)malloc(sizeof(arp_mac_ip ));
unsigned char *arp_head = recv_buff + 14;
unsigned char * arp_src_mac = arp_head + 8;//跳过[4.硬件类型、5.协议类型、6.硬件地址长度、7.协议地址长度、8.OP,拿到源MAC地址首地址信息]
unsigned char stc_mac[18] = "";
sprintf(stc_mac, "%02x:%02x:%02x:%02x:%02x:%02x", arp_src_mac[0],\
arp_src_mac[1],\
arp_src_mac[2], \
arp_src_mac[3],\
arp_src_mac[4], \
arp_src_mac[5]);
strcpy(head_mac_ip->stc_mac, stc_mac);
unsigned char src_ip[16] = "";
inet_ntop(AF_INET, arp_head + 14, src_ip, 16);//拿到源IP
strcpy(head_mac_ip->stc_ip, src_ip);
//-----------------------------------[调试]-----------------------------------//
//printf("-----------arp数据包------------\n");
//printf("arp 源mac:%s\n",head_mac_ip->stc_mac);
//printf("arp 源IP:src_ip = %s \n", src_ip);
//-----------------------------------[调试]-----------------------------------//
//线程中只保存源ARP的MAC、IP,目的主机的MAC、IP,在IP线程中指定(写死)
pthread_t pth1;
pthread_create(&pth1, NULL, callback2_arp, (void*)head_mac_ip);
pthread_detach(pth1);
}
}
return 0;
}
link.c
#include "link.h"
void title()
{
printf("[人机交互线程的全部功能]\n");
printf("2:设置过滤 IP \n");
printf("3:删除过滤 IP \n");
printf("4:查看过滤 IP \n");
printf("5:查看 arp 缓存 \n");
printf("10:退出路由器\n");
}
//*************************过滤链表******************************
//尾插
MY_ROU *rou_pTailInsert(MY_ROU *head)
{
//申请一个待插入的空间
MY_ROU *pi=(MY_ROU*)malloc(sizeof(MY_ROU));
pi->next=NULL;
printf("输入过滤ip:");
//向空间中插入数据
scanf("%s",pi->ip);
//判断是否有数据
if(head==NULL)
{
head=pi;
}
else
{
//寻找插入的节点
MY_ROU *p1=head;
while(p1->next!=NULL)
{
p1=p1->next;
}
//插入
p1->next=pi;
}
printf("设置完成\n");
return head;
}
//遍历
void rou_print_link(MY_ROU *head)
{
if(head==NULL)
{
printf("没有数据\n");
}
else
{
while(head!=NULL)
{
printf("ip:%s\n",head->ip);
head=head->next;
}
}
return;
}
//释放链表
MY_ROU* rou_freeLink(MY_ROU *head)
{
MY_ROU *pd;
pd=head;
while(head!=NULL)
{
head=pd->next;
free(pd);
pd=head;
}
printf("过滤链表释放完毕\n");
return head;
}
//查找ip
int rou_searcharpLink(MY_ROU *head,char *ip)
{
int i=0;
while(head!=NULL)
{
if(strcmp(ip,head->ip)==0)
{
i++;
//printf("存在相同ip\n");
return 1;
}
head=head->next;
}
if(0==i)
{
//printf("未找到ip\n");
return 0;
}
}
//删除
MY_ROU *rou_pDeleteLink(MY_ROU *head)
{
char num[16]="";
MY_ROU *pe=head;
MY_ROU *pf=head;
printf("请输入你要删除的ip:");
scanf("%s",num);
if(NULL==head)
{
printf("无可删除数据\n");
}
else
{
while(strcmp(pe->ip,num))
{
pf=pe;
pe=pe->next;
if(NULL==pf->next)
{
printf("未找到要删除数据\n");
return head;
}
}
if(pe==head)
{
head=pe->next;
free(pe);
}
else
{
pf->next=pe->next;
free(pe);
}
}
return head;
}
//*************************过滤链表******************************
//*************************arp缓存表*****************************
//arp缓存表尾插
MY_ARP *arp_pTailInsert(MY_ARP *head,char *mac,char *ip)
{
//申请一个待插入的空间
MY_ARP *pi=(MY_ARP*)malloc(sizeof(MY_ARP));
pi->next=NULL;
//向空间中插入数据
strcpy(pi->ip,ip);
strcpy(pi->mac,mac);
//判断是否有数据
if(head==NULL)
{
head=pi;
}
else
{
//寻找插入的节点
MY_ARP *p1=head;
while(p1->next!=NULL)
{
p1=p1->next;
}
//插入
p1->next=pi;
}
printf("插入一个ip:%s mac:%s 到arp缓存表\n",pi->ip,pi->mac);
return head;
}
//arp中查找ip和mac
int arp_searcharpLink(MY_ARP *head,char *ip)
{
int i=0;
while(head!=NULL)
{
if(strcmp(ip,head->ip)==0)
{
i++;
//printf("存在相同ip和mac\n");
return 1;
}
head=head->next;
}
if(0==i)
{
//printf("未找到ip和mac\n");
return 0;
}
}
//遍历arp缓存表
void arp_print_link(MY_ARP *head)
{
if(head==NULL)
{
printf("没有数据\n");
}
else
{
while(head!=NULL)
{
printf("ip:%s mac:%s\n",head->ip,head->mac);
head=head->next;
}
}
return;
}
//释放arp链表
MY_ARP* arp_freeLink(MY_ARP *head)
{
MY_ARP *pd;
pd=head;
while(head!=NULL)
{
head=pd->next;
free(pd);
pd=head;
}
printf("arp链表释放完毕\n");
return head;
}
//*************************arp缓存表*****************************
link.h
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define RECV_SIZE 2048
typedef struct My_buf
{
unsigned char buf[RECV_SIZE];
int my_buf_date_len;
}ip_buf;
typedef struct Arp_mac_ip
{
char stc_mac[18];
char stc_ip[16];
}arp_mac_ip;
extern void title();
//*************************arp缓存表*****************************
typedef struct myarp
{
unsigned char mac[32] ;
unsigned char ip[32] ;
struct myarp* next;
}MY_ARP;
//arp缓存表尾插
extern MY_ARP *arp_pTailInsert(MY_ARP *head,char *mac,char *ip);
//arp中查找ip
extern int arp_searcharpLink(MY_ARP *head,char *ip);
//遍历arp缓存表
extern void arp_print_link(MY_ARP *head);
//释放arp链表
extern MY_ARP* arp_freeLink(MY_ARP *head);
//*************************arp缓存表*****************************
//*************************过滤链表******************************
typedef struct myrouter
{
unsigned char ip[32] ;
struct myrouter* next;
}MY_ROU;
//释放链表
extern MY_ROU* rou_freeLink(MY_ROU *head);
//尾插
extern MY_ROU *rou_pTailInsert(MY_ROU *head);
//遍历
extern void rou_print_link(MY_ROU *head);
//查找ip
extern int rou_searcharpLink(MY_ROU *head,char *ip);
//删除
extern MY_ROU *rou_pDeleteLink(MY_ROU *head);
//*************************过滤链表******************************
get_interface.c
#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);
/* 获得接口标志、flags值 */
if (!(ioctl(sock_raw_fd, SIOCGIFFLAGS, (char *) &buf[if_len])))
{
/* 接口状态 */
/*IFF_UP :网络装置是否正常启用,不会因插拔网络线而有任何变化*/
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])))
{
/*inet_ntoa将一个网络字节序的IP地址(也就是结构体in_addr类型变量)
转化为点分十进制的IP地址(字符串)*/
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:
将点分十进制的ip地址转化为用于网络传输的数值格式*/
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, "SIOCGIF./ADDR 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
}
get_interface.h
#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
ip_file.h文章来源:https://www.toymoban.com/news/detail-723930.html
#ifndef IP_FILE_H
#define IP_FILE_H
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
//*************************过滤链表******************************
typedef struct myrouter
{
unsigned char ip[32] ;
struct myrouter* next;
}MY_ROU;
//释放链表
extern MY_ROU* rou_freeLink(MY_ROU *head);
//尾插
extern MY_ROU *rou_pTailInsert(MY_ROU *head);
//遍历
extern void rou_print_link(MY_ROU *head);
//查找ip
extern int rou_searcharpLink(MY_ROU *head,char *ip);
//删除
extern MY_ROU *rou_pDeleteLink(MY_ROU *head);
//*************************过滤链表******************************
/******************************************************************
函 数: void init_ip_link()
功 能: 读取配置文件数据到链表
参 数: 无
返回值: 无
*******************************************************************/
extern void init_ip_link();
/******************************************************************
函 数: IP_LINK *find_ip(IP_LINK *head, unsigned char *ip)
功 能: 插入ip过滤链表
参 数: IP_LINK *head ip过滤链表头 IP_LINK* p 待插入节点
返回值: IP_LINK *找到的节点
*******************************************************************/
extern MY_ROU *inner_ip_link(MY_ROU *head,MY_ROU* p);
/******************************************************************
函 数: void save_ip_link()
功 能: 保存链表数据到配置文件
参 数: 无
返回值: 无
*******************************************************************/
extern void save_ip_link();
#endif
ip_file.c文章来源地址https://www.toymoban.com/news/detail-723930.html
#include "ip_file.h"
#define ip_config_name "ip_config"
//与main.c共用一个结构体指针变量,保存过滤IP链表头节点
MY_ROU * roulink_head = NULL;
//--------------------操作文件中的过滤IP----------------------//
void init_ip_link()
{
FILE *ip_config = NULL;
ip_config = fopen(ip_config_name,"rb+");
if(ip_config == NULL){
perror("!!!configure file,in main.c");
_exit(1);
}
puts("filter IP:");
int i = 0;
while(1)
{
char buff[500]="";
bzero(buff, sizeof(buff));
int ip;
if(fgets(buff, sizeof(buff), ip_config) == NULL)
{
printf("ip_config 文件为空\n");
break;
}
if(strlen(buff) < 7)//1.1.1.1
{
break;
}
buff[strlen(buff)-1]=0;//注意文件中存在\r
//printf("IP[%d] = %s\n",i++,buff);
inet_pton(AF_INET, buff, &ip);
MY_ROU *pb = (MY_ROU *)malloc(sizeof(MY_ROU));
char ip_buf[16] = "";
inet_ntop(AF_INET, &ip, ip_buf, 16);
//printf("ip_buf[%d] = %s\n", ++i, ip_buf);
//strcpy(pb->ip, ip_buf);
memcpy(pb->ip, ip_buf, 16);
printf("pb->ip[%d] = %s\n", i, pb->ip);
//传入变化的头节点 + 带有IP信息的结构体指针变量
roulink_head = inner_ip_link(roulink_head, pb);
i++;
}
//rou_print_link(ip_head);
fclose(ip_config);
}
MY_ROU *inner_ip_link(MY_ROU *head, MY_ROU* p)
{
// head = (MY_ROU*)malloc(sizeof(MY_ROU)); //创建头结点
// head->next = NULL;
MY_ROU * pb = head;
int a = rou_searcharpLink(head, p->ip);//查找是否有该记录
if(a == 0)
{
if(pb==NULL)
{//未查找到,插入链表,直接插入表头方便
p->next = NULL;
head = p;
}
else
{
#if 1 //头插法--寻找插入的节点
MY_ROU * p2_new = (MY_ROU*)malloc(sizeof(MY_ROU));
strcpy(p2_new->ip, p->ip);
// printf("继续头插!!!!p2_new->ip = %s!!!!!!\n",p2_new->ip);
p2_new->next = pb->next;
pb->next = p2_new;
#endif
#if 0 //尾插法--正确
MY_ROU *p1=pb;
while(p1->next!=NULL)
{
p1=p1->next;
}
//插入
p1->next=p;
#endif
}
}
return head;
}
void save_ip_link()
{
FILE *ip_config = fopen(ip_config_name,"wb+");
if(ip_config == NULL){
perror("!!!configure file,in main.c");
_exit(1);
}
char buff[20]="";
MY_ROU *pb=roulink_head;
while(pb != NULL)
{
printf("!保存2命令输入IP\n");
memcpy(buff, pb->ip, 16);//一次拷贝16个字节
buff[strlen(buff)+1]='\n';//注意文件中存在\r
//一个IP新切换一行保存到文件
fprintf(ip_config, "%s\n", buff);
pb = pb->next;
}
fclose(ip_config);
}
//--------------------操作文件中的过滤IP----------------------//
//*************************过滤链表******************************//
//尾插
MY_ROU *rou_pTailInsert(MY_ROU *head)
{
//申请一个待插入的空间
MY_ROU *pi=(MY_ROU*)malloc(sizeof(MY_ROU));
pi->next=NULL;
printf("输入过滤ip:");
//向空间中插入数据
scanf("%s",pi->ip);
//判断是否有数据
if(head==NULL)
{
head=pi;
}
else
{
//寻找插入的节点
MY_ROU *p1=head;
while(p1->next!=NULL)
{
p1=p1->next;
}
//插入
p1->next=pi;
}
printf("设置完成\n");
return head;
}
//遍历
void rou_print_link(MY_ROU *head)
{
if(head==NULL)
{
printf("没有数据\n");
}
else
{
while(head!=NULL)
{
printf("ip:%s\n",head->ip);
head=head->next;
}
}
return;
}
//释放链表
MY_ROU* rou_freeLink(MY_ROU *head)
{
MY_ROU *pd;
pd=head;
while(head!=NULL)
{
head=pd->next;
free(pd);
pd=head;
}
printf("过滤链表释放完毕\n");
return head;
}
//查找ip
int rou_searcharpLink(MY_ROU *head,char *ip)
{
MY_ROU * pb = head;
int i=0;
while(pb!=NULL)
{
if(strcmp(ip, pb->ip)==0)
{
i++;
//printf("存在相同ip\n");
return 1;
}
pb = pb->next;
}
if(0==i)
{
//printf("未找到ip\n");
return 0;
}
}
//删除
MY_ROU *rou_pDeleteLink(MY_ROU *head)
{
char num[16]="";
MY_ROU *pe=head;
MY_ROU *pf=head;
printf("请输入你要删除的ip:");
scanf("%s",num);
if(NULL==head)
{
printf("无可删除数据\n");
}
else
{
while(strcmp(pe->ip,num))
{
pf=pe;
pe=pe->next;
if(NULL==pf->next)
{
printf("未找到要删除数据\n");
return head;
}
}
if(pe==head)
{
head=pe->next;
free(pe);
}
else
{
pf->next=pe->next;
free(pe);
}
}
return head;
}
//*************************过滤链表******************************
到了这里,关于Linux下 C语言路由器项目(纯C 1K代码,适合练手,也可写在简历上面 )的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!