C language router project under Linux (1K pure C code, suitable for practice, and can also be written on your resume)

1. Project flow chart

2. Environment construction

Host:

Ubuntu:

Set up the network:

开发板:
设置IP:ifconfig eth0 192.168.2.1 netmask 255.255.255.0
设置网关:route add  default gw 192.168.2.2

practice:

Host and virtual machine ping each other

success:

Development board and host ping each other

Failure: (because it is a different network segment)

OK, done

Finally, after running the router code we wrote, the host and development board can communicate under different network segments.

Development board and host ping each other

success:

3. The code is as follows:

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, &ethreq) == -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 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.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.c

#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;
}
//*************************过滤链表******************************

Guess you like

Origin blog.csdn.net/buhuidage/article/details/131586883