0

I want to get IP address from arp broadcast that net dev send.So I use tc egress to get this IP by ebpf.I can use this code parse struct xdp_buff but is not work on struct __sk_buff. I print eth->h_porto get error hex.So what should I do can soulve this probleme?

There is some stuct

#define ETH_P_IP 0x0800
#define ETH_P_ARP 0x0806
#define ETH_ALEN    6

struct ethhdr {
unsigned char   h_dest[ETH_ALEN];   /* destination eth addr */
unsigned char   h_source[ETH_ALEN]; /* source ether addr    */
__be16      h_proto;        /* packet type ID field */
}__attribute__((packed));

struct arphdr {
__be16      ar_hrd;     /* format of hardware address   */
__be16      ar_pro;     /* format of protocol address   */
unsigned char   ar_hln;     /* length of hardware address   */
unsigned char   ar_pln;     /* length of protocol address   */
__be16      ar_op;      /* ARP opcode (command)     */

#if 0
/*
*    Ethernet looks like this : This bit is variable sized however...
*/
unsigned char       ar_sha[ETH_ALEN];   /* sender hardware address  */
unsigned char       ar_sip[4];      /* sender IP address        */
unsigned char       ar_tha[ETH_ALEN];   /* target hardware address  */
unsigned char       ar_tip[4];      /* target IP address        */
#endif
};

struct arp_eth {
unsigned char       ar_sha[ETH_ALEN];
__be32                  ar_sip;
unsigned char       ar_tha[ETH_ALEN];
__be32                  ar_tip;
}__packed;

This is parse code

#define ETH_HLEN 14
static __always_inline int parse_ip_src_addr(struct __sk_buff *ctx, __u32 *ip_src_addr,struct pair *mac_info) {
    void *data_end = (void *) (long) ctx->data_end;
    void *data = (void *) (long) ctx->data;
    struct arphdr *arp = data + ETH_HLEN;
    struct ethhdr *eth = data;
    struct arp_eth *arp_eth;

    if (data + ETH_HLEN + sizeof(*arp) + sizeof(*arp_eth) > data_end){
        return 1;
    }
     char h_proto[] = "h_proto:%x";

     bpf_trace_printk(h_proto,sizeof(h_proto),bpf_ntohs(eth->h_proto));

    if (eth->h_proto == bpf_htons(ETH_P_ARP)){
    }
}

There is my attach golang code

    objs := bpfObjects{}
    if err := loadBpfObjects(&objs, nil); err != nil {
        log.Fatalf("loading objects: %v", err)
    }
    defer objs.Close()

    // Get the first-mounted cgroupv2 path.
    cgroupPath, err := detectCgroupPath()
    if err != nil {
        log.Fatal(err)
    }

    // Link the count_egress_packets program to the cgroup.
    l, err := link.AttachCgroup(link.CgroupOptions{
        Path:    cgroupPath,
        Attach:  ebpf.AttachCGroupInetEgress,
        Program: objs.ArpEgressPackets,
    })
    if err != nil {
        log.Fatal(err)
    }
    defer l.Close()

tcpdump hex info bpf_trace_printk info

niao ruo
  • 11
  • 3
  • 1
    Why is this tagged with the Go language tag, when all the shown code is C? Please take some time to read [the help pages](http://stackoverflow.com/help), take the SO [tour], read [ask], as well as [this question checklist](https://codeblog.jonskeet.uk/2012/11/24/stack-overflow-question-checklist/). Then [edit] your question to improve it. – Some programmer dude Dec 01 '22 at 09:45
  • I'm not sure I understand your first paragraph. Are you saying this parsing logic works for XDP but not for tc? – pchaigno Dec 01 '22 at 12:42
  • Yes, the function `parse_ip_src_addr` ,its first args need changed to `struct xdp_md` when it work for xdp hook,that can parse arp net package by `eth->h_proto == bpf_htons(ETH_P_ARP)` . But changed to `struct __sk_buff` to use tc hook, `eth->h_proto` get error hex code,but not 0x0806. – niao ruo Dec 01 '22 at 13:19

0 Answers0