arp.c

#include <stdlib.h>
#include <stdio.h>
#include <dos.h>
#include <pcap.h>
void delay(void)          /*延时函数*/

  int m,n,s; 
  for(m=150;m>0;m--) 
  for(n=200;n>0;n--) 
  for(s=240;s>0;s--); 

void main(int argc, char **argv)
{
pcap_t *fp;
char errbuf[PCAP_ERRBUF_SIZE];
u_char packet[100];
int j;
pcap_if_t *alldevs;
pcap_if_t *d;
int inum;
int i=0;


if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
    {
        fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
        exit(1);
    }
    
    /* 打印列表 */
    for(d=alldevs; d; d=d->next)
    {
        printf("%d. %s", ++i, d->name);
        if (d->description)
            printf(" (%s)\n", d->description);
        else
            printf(" (No description available)\n");
    }
    
    if(i==0)
    {
        printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
        return -1;
    }
    
    printf("Enter the interface number (1-%d):",i);
    scanf("%d", &inum);
    
    if(inum < 1 || inum > i)
    {
        printf("\nInterface number out of range.\n");
        /* 释放设备列表 */
        pcap_freealldevs(alldevs);
        return -1;
    }




/* 跳转到选中的适配器 */
    for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);






    /* 打开输出设备 */
    if ( (fp= pcap_open(d=d->name,            // 设备名
                        100,                // 要捕获的部分 (只捕获前100个字节)
                        PCAP_OPENFLAG_PROMISCUOUS,  // 混杂模式
                        1000,               // 读超时时间
                        NULL,               // 远程机器验证
                        errbuf              // 错误缓冲
                        ) ) == NULL)
    {
        fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", argv[1]);
        return;
    }

    /* 目的地址的MAC地址*/
    packet[0]=0xff;
packet[1]=0xff;
packet[2]=0xff;
packet[3]=0xff;
packet[4]=0xff;
packet[5]=0xff;


/* 设置MAC源地址 */


packet[6]=0x00;
packet[7]=0x1e;
packet[8]=0xec;
packet[10]=0x9e;
packet[9]=0x65;
packet[11]=0x19;
/* 帧类型  */
packet[12]=0x08;
    packet[13]=0x06;


/* 硬件类型  */
packet[14]=0x00;
    packet[15]=0x01;


/* 协议类型 */
packet[16]=0x08;
    packet[17]=0x00;
/* op */
packet[18]=0x06;
    packet[19]=0x04;
    /*  ARP回复协议    */
packet[20]=0x00;

   packet[21]=0x02;
for(i=22;i<28;i++)
packet[i]=packet[i-16];
packet[28]=0xc0;
packet[29]=0xa8;
packet[30]=0x01;
packet[31]=0x67;

packet[32]=0x00;
packet[33]=0x19;
packet[34]=0xe0;
packet[35]=0xbf;
packet[36]=0xbd;
packet[37]=0x3e;


packet[38]=0xc0;
packet[39]=0xa8;
packet[40]=0x01;
packet[41]=0x01;
for(j=42;j<60;j++)
{
packet[j]=0x00;
}
   while(1)
{
pcap_sendpacket(fp, packet, 60 /* size */);
 delay();
   }


    /* 发送数据包 */
    if(pcap_sendpacket(fp, packet, 60 /* size */) != 0)
    {
        fprintf(stderr,"\nError sending the packet: \n", pcap_geterr(fp));
 
   // return;
   }



    return;
}
arp.c: In function ‘build_arp_packet’: arp.c:37:5: warning: implicit declaration of function ‘get_local_mac’ [-Wimplicit-function-declaration] get_local_mac(arp->arp_sha); ^ arp.c:41:5: warning: implicit declaration of function ‘get_local_ip’ [-Wimplicit-function-declaration] get_local_ip(&local_ip); ^ arp.c: In function ‘scan_thread’: arp.c:67:13: warning: implicit declaration of function ‘send_arp’ [-Wimplicit-function-declaration] send_arp(sock, &arp_req); ^ arp.c: In function ‘process_arp_response’: arp.c:88:24: warning: implicit declaration of function ‘find_or_create_entry’ [-Wimplicit-function-declaration] arp_entry *entry = find_or_create_entry(scanner, ip); ^ arp.c:88:24: warning: initialization makes pointer from integer without a cast [-Wint-conversion] arp.c: In function ‘main’: arp.c:173:13: warning: implicit declaration of function ‘recv_arp’ [-Wimplicit-function-declaration] if (recv_arp(arp_sock, &arp_resp) > 0) { ^ /tmp/ccBMGDff.o: In function `build_arp_packet': arp.c:(.text+0xc2): undefined reference to `get_local_mac' arp.c:(.text+0xd3): undefined reference to `get_local_ip' /tmp/ccBMGDff.o: In function `scan_thread': arp.c:(.text+0x1be): undefined reference to `send_arp' /tmp/ccBMGDff.o: In function `process_arp_response': arp.c:(.text+0x26a): undefined reference to `find_or_create_entry' /tmp/ccBMGDff.o: In function `main': arp.c:(.text+0x5b4): undefined reference to `recv_arp' collect2: error: ld returned 1 exit status这怎么报错了
最新发布
08-26
<think>我们正在解决ARP程序中出现的未声明函数警告和链接错误。这些错误通常包括: 1. 隐式声明函数警告(implicit declaration):当函数在使用前没有声明时,编译器会发出警告。 2. 链接错误(undefined reference):当函数被声明了但没有定义(即没有函数体)时,链接器会报错。 根据用户提供的上下文,我们注意到程序中使用了一些自定义函数,如: get_local_mac, get_local_ip, send_arp, find_or_create_entry, recv_arp 解决步骤: 步骤1:确保所有函数在使用前都有声明(即函数原型) - 在调用这些函数的源文件(如arp.c)中,应该在文件开头或者头文件中声明这些函数。 - 例如,在arp.c的开头添加: unsigned char *get_local_mac(const char *ifname); struct in_addr get_local_ip(const char *ifname); void send_arp(...); // 根据实际参数填写 // 其他函数声明 步骤2:确保这些函数在某个源文件中有定义(实现) - 检查这些函数是否在另一个源文件中实现(比如arp_utils.c),如果没有,则需要实现它们。 - 如果已经实现,确保该源文件被编译并链接到最终的可执行文件中。 步骤3:使用头文件来共享函数声明 - 最佳实践是创建一个头文件(如arp_utils.h),在其中声明这些函数。 - 然后在arp.c中包含这个头文件:`#include "arp_utils.h"` - 在实现这些函数的源文件(如arp_utils.c)中也包含同一个头文件。 步骤4:检查函数定义和声明的一致性 - 函数声明和定义必须一致(返回类型、参数类型和数量)。 步骤5:解决链接错误 - 如果函数在另一个源文件中定义,确保该源文件被编译成目标文件,并且一起链接。 - 例如,如果使用gcc编译: gcc -c arp.c -o arp.o gcc -c arp_utils.c -o arp_utils.o gcc arp.o arp_utils.o -o arp_program 步骤6:处理隐式声明警告 - 隐式声明通常是因为没有包含声明函数的头文件或者没有显式声明。 - 按照步骤1和3,添加声明即可。 具体到每个函数,我们可以参考用户提供的引用[3]来获取一些实现思路(如获取本地IP和MAC地址)。 例如,获取本地MAC地址的函数`get_local_mac`可以通过以下方式实现(参考引用[3]): - 使用socket和ioctl,通过SIOCGIFHWADDR请求获取。 获取本地IP地址的函数`get_local_ip`可以通过以下方式实现: - 使用socket和ioctl,通过SIOCGIFADDR请求获取。 下面我们分别给出这些函数的示例实现: 注意:以下代码仅为示例,可能需要根据实际需求调整。 创建头文件:arp_utils.h ```c #ifndef ARP_UTILS_H #define ARP_UTILS_H #include <net/if.h> #include <netinet/in.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <unistd.h> #include <string.h> #include <stdio.h> #include <arpa/inet.h> // 获取指定网络接口的MAC地址 unsigned char *get_local_mac(const char *ifname); // 获取指定网络接口的IP地址 struct in_addr get_local_ip(const char *ifname); // 发送ARP报文的函数 void send_arp(int sockfd, ...); // 参数根据实际需要设计 // 接收ARP报文的函数 void recv_arp(int sockfd, ...); // 在ARP缓存中查找或创建条目的函数 void *find_or_create_entry(...); // 参数根据实际需要设计 #endif ``` 实现文件:arp_utils.c ```c #include "arp_utils.h" unsigned char *get_local_mac(const char *ifname) { static unsigned char mac[6]; int fd; struct ifreq ifr; fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { perror("socket"); return NULL; } strncpy(ifr.ifr_name, ifname, IFNAMSIZ-1); if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) { perror("ioctl"); close(fd); return NULL; } memcpy(mac, ifr.ifr_hwaddr.sa_data, 6); close(fd); return mac; } struct in_addr get_local_ip(const char *ifname) { int fd; struct ifreq ifr; struct in_addr ip; fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { perror("socket"); ip.s_addr = 0; return ip; } strncpy(ifr.ifr_name, ifname, IFNAMSIZ-1); if (ioctl(fd, SIOCGIFADDR, &ifr) < 0) { perror("ioctl"); close(fd); ip.s_addr = 0; return ip; } close(fd); ip = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; return ip; } // 其他函数的实现(send_arp, recv_arp, find_or_create_entry)根据实际需求编写 ``` 在arp.c中,包含头文件: ```c #include "arp_utils.h" ``` 编译命令: ```bash gcc -c arp.c -o arp.o gcc -c arp_utils.c -o arp_utils.o gcc arp.o arp_utils.o -o arp_program ``` 这样,函数声明和定义就都有了,并且通过头文件共享声明,可以避免隐式声明警告和链接错误。 注意:实际实现中,send_arp, recv_arp, find_or_create_entry等函数需要根据ARP协议的具体要求来编写,这里只给出了获取MAC和IP的示例。 如果还有其他未定义的函数,同样需要检查是否在头文件中声明,在源文件中定义。 相关问题: 1. 如何获取网络接口的子网掩码? 2. 如何通过ARP协议解析目标MAC地址? 3. 如何设计ARP缓存表的数据结构? 4. 如何处理ARP请求和ARP应答? 5. 如何实现ARP缓存超时机制?</think>### 解决ARP程序中的未声明函数警告和链接错误 针对ARP程序中的隐式声明警告和链接错误,以下是系统化的解决方案: #### 1. 解决隐式声明警告 (implicit declaration) 在C语言中,函数使用前必须声明。在`arp.c`文件中添加函数原型声明: ```c /* arp.c 文件顶部添加 */ #include <netinet/if_ether.h> // 标准ARP结构体 #include <net/if.h> // 网络接口相关 // 函数原型声明 unsigned char *get_local_mac(const char *ifname); struct in_addr get_local_ip(const char *ifname); void send_arp(int sockfd, struct ether_arp *packet, struct sockaddr_ll *addr); arp_entry *find_or_create_entry(arp_table *table, uint32_t ip); void recv_arp(int sockfd, arp_table *table); ``` #### 2. 解决链接错误 (undefined reference) 链接错误通常由函数未实现引起。创建`arp_utils.c`文件实现核心功能: ```c /* arp_utils.c */ #include "arp_utils.h" #include <sys/ioctl.h> #include <net/if_arp.h> // 获取本地MAC地址[^3] unsigned char *get_local_mac(const char *ifname) { static unsigned char mac[6]; int fd = socket(AF_INET, SOCK_DGRAM, 0); struct ifreq ifr; strncpy(ifr.ifr_name, ifname, IFNAMSIZ); if (ioctl(fd, SIOCGIFHWADDR, &ifr) == 0) { memcpy(mac, ifr.ifr_hwaddr.sa_data, 6); } close(fd); return mac; } // 发送ARP报文[^1] void send_arp(int sockfd, struct ether_arp *packet, struct sockaddr_ll *addr) { sendto(sockfd, packet, sizeof(struct ether_arp), 0, (struct sockaddr*)addr, sizeof(struct sockaddr_ll)); } // ARP缓存管理 arp_entry *find_or_create_entry(arp_table *table, uint32_t ip) { // 实现哈希表查找/创建逻辑 // ... } ``` #### 3. 创建头文件 (arp_utils.h) ```c /* arp_utils.h */ #ifndef ARP_UTILS_H #define ARP_UTILS_H #include <netinet/in.h> typedef struct { uint32_t ip; unsigned char mac[6]; time_t last_update; } arp_entry; typedef struct { arp_entry *entries; int size; } arp_table; // 函数声明 unsigned char *get_local_mac(const char *ifname); struct in_addr get_local_ip(const char *ifname); void send_arp(int sockfd, struct ether_arp *packet, struct sockaddr_ll *addr); arp_entry *find_or_create_entry(arp_table *table, uint32_t ip); void recv_arp(int sockfd, arp_table *table); #endif ``` #### 4. 修改编译命令 确保所有源文件参与编译: ```bash gcc -o arp_program arp.c arp_utils.c -Wall -Wextra ``` #### 5. 关键实现说明 1. **MAC地址获取**:使用`ioctl`+`SIOCGIFHWADDR`从内核获取硬件地址[^3] 2. **ARP发送**:使用原始套接字发送`struct ether_arp`结构体 3. **缓存管理**: ```c // 示例缓存查找 for (int i = 0; i < table->size; i++) { if (table->entries[i].ip == ip) { return &table->entries[i]; } } ``` 4. **ARP接收**: ```c void recv_arp(int sockfd, arp_table *table) { struct ether_arp packet; recv(sockfd, &packet, sizeof(packet), 0); // 更新缓存 uint32_t src_ip = *((uint32_t*)packet.arp_spa); arp_entry *entry = find_or_create_entry(table, src_ip); memcpy(entry->mac, packet.arp_sha, 6); } ``` #### 6. 验证ARP缓存 使用系统命令验证ARP功能: ```bash # 查看ARP缓存[^2] arp -a # 测试输出应包含类似条目 ? (192.168.1.1) at 00:02:b3:38:08:62 [ether] on eth0 ``` ### 相关问题 1. 如何实现ARP缓存超时自动清理机制? 2. 怎样处理ARP欺骗攻击的检测和防御? 3. 如何优化ARP缓存查找的性能? 4. 在IPv6环境中如何实现类似的地址解析功能? 5. 如何通过原始套接字捕获所有ARP流量? [^1]: 参考ARP发送函数实现 [^2]: 验证ARP缓存的方法 [^3]: MAC地址获取的技术原理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值