[C][Mac OS X] gcc:链接器命令失败,退出代码为1

2w2cym1i  于 2022-11-12  发布在  Mac
关注(0)|答案(1)|浏览(228)

我正在编译这个sniffer_mid_16.c。一周前,我可以用gcc -o sniffer_mid_16 sniffer_mid_16.c编译这个程序。但是今天,我不能编译这个。
代码为:

#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <pcap.h>
#include <arpa/inet.h>
#include <stdlib.h>

struct ether_addr{
    unsigned char ether_addr_octet[6];
};

struct ether_header{
    struct ether_addr ether_dhost;
    struct ether_addr ether_shost;
    unsigned short ether_type;
};

struct pseudo_header{
    unsigned int source_address;
    unsigned int dest_address;
    unsigned char placeholder;
    unsigned char protocol;
    unsigned short tcp_length;
};

struct ip_hdr{
    unsigned char ip_header_len:4;
    unsigned char ip_version:4;
    unsigned char ip_tos;
    unsigned short ip_total_length;
    unsigned short ip_id;
    unsigned char ip_frag_offset:5;
    unsigned char ip_more_fragment:1;
    unsigned char ip_dont_fragment:1;
    unsigned char ip_reserved_zero:1;
    unsigned char ip_frag_offset1;
    unsigned char ip_ttl;
    unsigned char ip_protocol;
    unsigned short ip_checksum;
    unsigned int ip_srcaddr;
    unsigned int ip_destaddr;
};
struct tcp_hdr{
   unsigned short source_port;
   unsigned short dest_port;
   unsigned int sequence;
   unsigned int acknowledge;
   unsigned char ns:1;
   unsigned char reserved_part1:3;
   unsigned char data_offset:4;
   unsigned char fin:1;
   unsigned char syn:1;
   unsigned char rst:1;
   unsigned char psh:1;
   unsigned char ack:1;
   unsigned char urg:1;
   unsigned char ecn:1;
   unsigned char cwr:1;
   unsigned short window;
   unsigned short checksum;
   unsigned short urgent_pointer;
};

void print_raw_packet(const unsigned char* pkt_data, bpf_u_int32 caplen){
    printf("New packet of size : %d\n\t", caplen);
    for(int i=0;i<caplen;i++){
        printf("%.2x%s%s", pkt_data[i], (i%2==0 ? "" : " "), ((i+1)%16==0 ? "\n\t" : ""));
    }
    printf("\n");
    return;
}

void print_ether_header(const unsigned char *pkt_data){
    struct ether_header *value = (struct ether_header *) pkt_data;
    printf("Print Ethernet Header : \n");
    printf("\tDestination address: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
            value -> ether_dhost.ether_addr_octet[0],
            value -> ether_dhost.ether_addr_octet[1],
            value -> ether_dhost.ether_addr_octet[2],
            value -> ether_dhost.ether_addr_octet[3],
            value -> ether_dhost.ether_addr_octet[4],
            value -> ether_dhost.ether_addr_octet[5]
            );
    
    printf("\tSource address: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
            value -> ether_shost.ether_addr_octet[0],
            value -> ether_shost.ether_addr_octet[1],
            value -> ether_shost.ether_addr_octet[2],
            value -> ether_shost.ether_addr_octet[3],
            value -> ether_shost.ether_addr_octet[4],
            value -> ether_shost.ether_addr_octet[5]
            );

    printf("ether type : %.4x\n\n", ntohs(value->ether_type));
}

void print_ip_header(const unsigned char* pkt_data){
    struct ip_hdr *value = (struct ip_hdr *)(pkt_data+14);
    printf("Print IP Header : \n\t");
    printf("ip_header_len : %d bytes\n\t", value->ip_header_len * 4);
    printf("ip_version : %d\n\t", value->ip_version);
    printf("type of service : %d\n\t", value->ip_tos);
    printf("packet total length : %d\n\t", ntohs(value->ip_total_length));
    printf("identifier : %.4x\n\t", ntohs(value->ip_id));
    printf("fragment offset field : %d\n\t", (unsigned)value->ip_frag_offset);
    printf("more fragment : %d\n\t", (unsigned int)value->ip_more_fragment);
    printf("don't fragment : %d\n\t", (unsigned int)value->ip_dont_fragment);
    printf("reserved zero : %d\n\t", (unsigned int)value->ip_reserved_zero);
    printf("fragment offset : %d\n\t", (unsigned int)value->ip_frag_offset1);
    printf("time to live : %d\n\t", (unsigned int)value->ip_ttl);
    printf("protocol id : %d\n\t", (unsigned int)value->ip_protocol);
    printf("header checksum : %d\n\t", ntohs(value->ip_checksum));
    printf("source ip address : %s\n\t", inet_ntoa(*(struct in_addr *)&value->ip_srcaddr));
    printf("destination ip address : %s\n\n", inet_ntoa(*(struct in_addr *)&value->ip_destaddr));
}

unsigned int print_tcp_header(const unsigned char* pkt_data){
    struct tcp_hdr *value = (struct tcp_hdr *) (pkt_data+ 34);
    printf("Print TCP Header : \n\t");
    printf("Source port : %u\n\t", ntohs(value -> source_port));
    printf("Destination port : %u\n\t", ntohs(value->dest_port));
    printf("Sequence : %u\n\t", ntohl(value->sequence));
    printf("Acknowledge : %u\n\t", ntohl(value->acknowledge));
    printf("Nonce sum : %d\n\t", (unsigned int)value->ns);
    printf("Reserved part1 : %d\n\t", (unsigned int)value->reserved_part1);
    printf("Data offset :  %d bytes\n\t", (unsigned int)value->data_offset * 4); 
            //tcp_header size without data (includes options)
    printf("FIN flag : %d\n\t", (unsigned int) value->fin);
    printf("SYN flag : %d\n\t", (unsigned int) value->syn);
    printf("RST flag : %d\n\t", (unsigned int) value->rst);
    printf("PSH flag : %d\n\t", (unsigned int) value->psh);
    printf("ACK flag : %d\n\t", (unsigned int) value->ack);
    printf("URG flag : %d\n\t", (unsigned int) value->urg);
    printf("ECN flag : %d\n\t", (unsigned int) value->ecn);
    printf("CWR flag : %d\n\t", (unsigned int) value->cwr);
    printf("Window size : %d\n\t", ntohs(value->window));
    printf("Checksum : %d\n\t", ntohs(value->checksum));
    printf("Urgent pointer : %d\n", value->urgent_pointer);

    return ((unsigned int)value->data_offset*4);
}

void print_data(const unsigned char* pkt_data, unsigned int tcp_header_without_data, bpf_u_int32 caplen){
    int packet_size_without_data = tcp_header_without_data + 34;
    unsigned char* data = (unsigned char *)(pkt_data+packet_size_without_data);
    printf("Print Data  : \n\t");
    for(int i=0;i<caplen-packet_size_without_data;i++){
        printf("%.2x", (int)data[i]);
        if(i%2==1) printf(" ");
   } 
   printf("\n");
}

void detect_attack(const unsigned char* pkt_data, unsigned int tcp_header_without_data, bpf_u_int32 caplen){
    bool attacking = false;
    printf("Is there attack? : ");
    int packet_size_without_data = tcp_header_without_data + 34;
    unsigned char* data = (unsigned char *)(pkt_data+packet_size_without_data);
    if(caplen - packet_size_without_data < 6){
        printf("no\n\n");
        return;
    }
    for(int i=0;i<caplen-packet_size_without_data-5;i++){
        if(data[i]=='a' 
        && data[i+1]=='t'
        && data[i+2]=='t'
        && data[i+3]=='a'
        && data[i+4]=='c'
        && data[i+5]=='k'){
            attacking = true;
        }
    }
    if(attacking) printf("yes\n\n");
    else printf("no\n\n");
}

unsigned short in_checksum(unsigned short *ptr, int nbytes){
    register long sum;
    unsigned short oddbyte;
    register short answer;

    sum = 0;
    while(nbytes>1){
        sum+=*ptr++;
        nbytes-=2;
    }
    if(nbytes==1){
        oddbyte=0;
        *((u_char*)&oddbyte) = *(u_char*)ptr;
        sum+=oddbyte;
    }
    sum = (sum>>16) + (sum & 0xffff);
    sum = sum + (sum>>16);
    answer = (short)~sum;

    return answer;
}

int main(){
    pcap_if_t *alldevs=NULL;
    char errbuf[PCAP_ERRBUF_SIZE];

    // find all network adapters
    if (pcap_findalldevs(&alldevs, errbuf)==-1){
        printf("dev find failed\n");
        return -1;
    }
    if (alldevs==NULL){
        printf("no devs found\n");
        return -1;
    }
    // print them
    pcap_if_t *d; int i;
    for(d=alldevs,i=0; d!=NULL; d=d->next){
        printf("%d-th dev: %s ", ++i, d->name);
        if (d->description)
            printf(" (%s)\n", d->description);
        else
            printf(" (No description available)\n");
    }

    // opening an adapter

    int inum;
    printf("enter the interface number: ");
    scanf("%d", &inum);
    for(d=alldevs, i=0; i<inum-1; d=d->next, i++);

    //open
    pcap_t *fp;
    if((fp=pcap_open_live(d->name, //name of the device
            65536, //capture size
            1, // promiscuous mode
            20, //read timeout
            errbuf
            ))==NULL){
        printf("pcap open failed\n");
        pcap_freealldevs(alldevs);
        return -1;
            }
    printf("pcap open successful\n");

    // Set filtering rules for the traffic : pcap_compile(), pcap_setfilter()
    char filt[35] = "host ***.***.***.***"; //hide IP for ask
    struct bpf_program fcode;
    if(pcap_compile(fp, // pcap handle
            &fcode, // compiled rule
            // (char *)("host ***.***.***.*** and port 16700"), //filter rule, hide IP for ask
            filt,
            1, //optimize
            NULL) < 0){
        printf("pcap compile failed\n");
        pcap_freealldevs(alldevs);
        return -1;
    }

    if(pcap_setfilter(fp, &fcode) < 0){
        printf("pcap setfilter failed\n");
        pcap_freealldevs(alldevs);
        return -1;
    }
    pcap_freealldevs(alldevs);
    

    struct pcap_pkthdr *header;
    const unsigned char *pkt_data;

    int res;
    int cnt=0;
    unsigned int tcp_header_without_data;
    while((res=pcap_next_ex(fp, &header, &pkt_data))>=0){ // 1 if success
        if (res == 0) continue; // 0 if time-out
        printf("%dth packet : \n", cnt++);
        print_raw_packet(pkt_data, header->caplen);
        print_ether_header(pkt_data);
        print_ip_header(pkt_data);
        tcp_header_without_data = print_tcp_header(pkt_data);
        print_data(pkt_data, tcp_header_without_data, header->caplen);
        detect_attack(pkt_data, tcp_header_without_data, header->caplen);
        break;
    }
    printf("=================================\nLet's Send\n");
    const unsigned char* packet = pkt_data; //copy them into another buffer : pkt_data => packet
    struct ip_hdr *ip_value = (struct ip_hdr *)(packet+14);
    struct tcp_hdr *tcp_value = (struct tcp_hdr *)(packet+34);
    int k;
    for(;;){
        printf("which port to check?\n");
        scanf("%d", &k);
        if(k==-1) break;
        tcp_value -> dest_port = ntohs(k);

        ip_value->ip_checksum = 0; // set ip_check_sum to zero
        tcp_value->checksum = 0; // set tcp_check_sumto zero
        ip_value->ip_checksum = in_checksum((unsigned short*)ip_value,20); // recompute ip_check_sum
    
        struct pseudo_header psh;
        inet_pton(AF_INET, "***.***.***.***", &(psh.source_address));
        inet_pton(AF_INET, "***.***.***.***", &(psh.dest_address));
        psh.placeholder = 0;
        psh.protocol = 6;
        psh.tcp_length = htons(tcp_header_without_data);

        // Now build pseudo header + tcp header
        unsigned char *seudo = (unsigned char *)malloc(sizeof(struct pseudo_header) + tcp_header_without_data);
        memcpy(seudo, &psh, sizeof(struct pseudo_header));
        memcpy(seudo + sizeof(struct pseudo_header), tcp_value, tcp_header_without_data);

        //Compute the checksum
        tcp_value->checksum = in_checksum((unsigned short *)seudo,sizeof(struct pseudo_header)+tcp_header_without_data); // recompute tcp_check_sum
        
        // send packet to every port
        pcap_sendpacket(fp, packet, 34+tcp_header_without_data);

        //now receive port and analyze it.
        const unsigned char* receive_packet;
        pcap_next_ex(fp, &header, &receive_packet);
        struct ip_hdr *ip_h = (struct ip_hdr*)(receive_packet+14);
        struct tcp_hdr *tcp_h = (struct tcp_hdr*)(receive_packet+34);

        if(tcp_h->syn == 1 && tcp_h -> ack == 1){
            printf("it is a live port\n");
            continue;
            // printf("dest port : %d, src port : %d\n", ntohs(tcp_h -> dest_port), ntohs(tcp_h -> source_port));
        }
        printf("it is a closed port\n");

    }
    return 0;
}

而错误是:

sniffer_mid_16.c:254:13: warning: incompatible pointer to integer conversion passing 'void *' to parameter of type 'bpf_u_int32' (aka 'unsigned int') [-Wint-conversion]
            NULL) < 0){
            ^~~~
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_null.h:30:15: note: expanded from macro 'NULL'
#define NULL  __DARWIN_NULL
              ^~~~~~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types.h:52:23: note: expanded from macro '__DARWIN_NULL'
#define __DARWIN_NULL ((void *)0)
                      ^~~~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/14.0.0/include/pcap.h:466:17: note: passing argument to parameter here
            bpf_u_int32);
                       ^
1 warning generated.

Undefined symbols for architecture arm64:
  "_pcap_compile", referenced from:
      _main in sniffer_mid_16-f7c493.o
  "_pcap_findalldevs", referenced from:
      _main in sniffer_mid_16-f7c493.o
  "_pcap_freealldevs", referenced from:
      _main in sniffer_mid_16-f7c493.o
  "_pcap_next_ex", referenced from:
      _main in sniffer_mid_16-f7c493.o
  "_pcap_open_live", referenced from:
      _main in sniffer_mid_16-f7c493.o
  "_pcap_sendpacket", referenced from:
      _main in sniffer_mid_16-f7c493.o
  "_pcap_setfilter", referenced from:
      _main in sniffer_mid_16-f7c493.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

我尝试了所有我能做的事情。我该怎么办?
另外,当我在vs代码中单击“转到定义”时,我可以在“/库/开发人员/命令行工具/SDK/MacOSX12.3.sdk/usr/include/pcap. h”中找到pcap.h。

cs7cruho

cs7cruho1#

sniffer_mid_16.c:254:13: warning: incompatible pointer to integer conversion passing 'void *' to parameter of type 'bpf_u_int32' (aka 'unsigned int') [-Wint-conversion]
            NULL) < 0){

这是对pcap_compile()的调用; pcap_compile()的最后一个参数是一个32位的集成网络掩码值,而不是一个指针。只需传递PCAP_NETMASK_UNKNOWN(这在旧版本的libpcap中不起作用,但各种UN*Xes的最新版本都有它)。
一周前,我可以用gcc -o sniffer_mid_16 sniffer_mid_16.c编译这个程序,但是今天,我不能编译这个程序。
...

Undefined symbols for architecture arm64:
  "_pcap_compile", referenced from:

...
如果你能用gcc -o sniffer_mid_16 sniffer_mid_16.c编译你的程序,你一定还没有在里面放任何pcap调用;如果你调用libpcap中的例程,那么,要在任何UN*X(包括macOS)上编译程序,你需要使用-lpcap进行编译:

gcc -o sniffer_mid_16 sniffer_mid_16.c -lpcap

pcap例程在libpcap中,您 * 必须 * 告诉链接器与该库链接,否则,链接器将不会查看该库,也不会找到这些例程。

相关问题