Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/samples/bpf/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 5 kB image not shown  

Quelle  test_lwt_bpf.c   Sprache: C

 
/* Copyright (c) 2016 Thomas Graf <tgraf@tgraf.ch>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General Public
 * License as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 */


#include "vmlinux.h"
#include "net_shared.h"
#include <bpf/bpf_helpers.h>
#include <string.h>

define printk(fmt, ...)      \
  ({       \
   char ____fmt[] = fmt;    \
   bpf_trace_printk(____fmt, sizeof(____fmt), \
         ##__VA_ARGS__);   \
  })

#define CB_MAGIC 1234

/* Test: Pass all packets through */
SEC("nop")
int do_nop(struct __sk_buff *skb)
{
 return BPF_OK;
}

/* Test: Verify context information can be accessed */
SEC("test_ctx")
int do_test_ctx(struct __sk_buff *skb)
{
 skb->cb[0] = CB_MAGIC;
 printk("len %d hash %d protocol %d", skb->len, skb->hash,
        skb->protocol);
 printk("cb %d ingress_ifindex %d ifindex %d", skb->cb[0],
        skb->ingress_ifindex, skb->ifindex);

 return BPF_OK;
}

/* Test: Ensure skb->cb[] buffer is cleared */
SEC("test_cb")
int do_test_cb(struct __sk_buff *skb)
{
 printk("cb0: %x cb1: %x cb2: %x", skb->cb[0], skb->cb[1],
        skb->cb[2]);
 printk("cb3: %x cb4: %x", skb->cb[3], skb->cb[4]);

 return BPF_OK;
}

/* Test: Verify skb data can be read */
SEC("test_data")
int do_test_data(struct __sk_buff *skb)
{
 void *data = (void *)(long)skb->data;
 void *data_end = (void *)(long)skb->data_end;
 struct iphdr *iph = data;

 if (data + sizeof(*iph) > data_end) {
  printk("packet truncated");
  return BPF_DROP;
 }

 printk("src: %x dst: %x", iph->saddr, iph->daddr);

 return BPF_OK;
}

#define IP_CSUM_OFF offsetof(struct iphdr, check)
#define IP_DST_OFF offsetof(struct iphdr, daddr)
#define IP_SRC_OFF offsetof(struct iphdr, saddr)
#define IP_PROTO_OFF offsetof(struct iphdr, protocol)
#define TCP_CSUM_OFF offsetof(struct tcphdr, check)
#define UDP_CSUM_OFF offsetof(struct udphdr, check)
#define IS_PSEUDO 0x10

static inline int rewrite(struct __sk_buff *skb, uint32_t old_ip,
     uint32_t new_ip, int rw_daddr)
{
 int ret, off = 0, flags = IS_PSEUDO;
 uint8_t proto;

 ret = bpf_skb_load_bytes(skb, IP_PROTO_OFF, &proto, 1);
 if (ret < 0) {
  printk("bpf_l4_csum_replace failed: %d", ret);
  return BPF_DROP;
 }

 switch (proto) {
 case IPPROTO_TCP:
  off = TCP_CSUM_OFF;
  break;

 case IPPROTO_UDP:
  off = UDP_CSUM_OFF;
  flags |= BPF_F_MARK_MANGLED_0;
  break;

 case IPPROTO_ICMPV6:
  off = offsetof(struct icmp6hdr, icmp6_cksum);
  break;
 }

 if (off) {
  ret = bpf_l4_csum_replace(skb, off, old_ip, new_ip,
       flags | sizeof(new_ip));
  if (ret < 0) {
   printk("bpf_l4_csum_replace failed: %d");
   return BPF_DROP;
  }
 }

 ret = bpf_l3_csum_replace(skb, IP_CSUM_OFF, old_ip, new_ip, sizeof(new_ip));
 if (ret < 0) {
  printk("bpf_l3_csum_replace failed: %d", ret);
  return BPF_DROP;
 }

 if (rw_daddr)
  ret = bpf_skb_store_bytes(skb, IP_DST_OFF, &new_ip, sizeof(new_ip), 0);
 else
  ret = bpf_skb_store_bytes(skb, IP_SRC_OFF, &new_ip, sizeof(new_ip), 0);

 if (ret < 0) {
  printk("bpf_skb_store_bytes() failed: %d", ret);
  return BPF_DROP;
 }

 return BPF_OK;
}

/* Test: Verify skb data can be modified */
SEC("test_rewrite")
int do_test_rewrite(struct __sk_buff *skb)
{
 uint32_t old_ip, new_ip = 0x3fea8c0;
 int ret;

 ret = bpf_skb_load_bytes(skb, IP_DST_OFF, &old_ip, 4);
 if (ret < 0) {
  printk("bpf_skb_load_bytes failed: %d", ret);
  return BPF_DROP;
 }

 if (old_ip == 0x2fea8c0) {
  printk("out: rewriting from %x to %x", old_ip, new_ip);
  return rewrite(skb, old_ip, new_ip, 1);
 }

 return BPF_OK;
}

static inline int __do_push_ll_and_redirect(struct __sk_buff *skb)
{
 uint64_t smac = SRC_MAC, dmac = DST_MAC;
 int ret, ifindex = DST_IFINDEX;
 struct ethhdr ehdr;

 ret = bpf_skb_change_head(skb, 14, 0);
 if (ret < 0) {
  printk("skb_change_head() failed: %d", ret);
 }

 ehdr.h_proto = bpf_htons(ETH_P_IP);
 memcpy(&ehdr.h_source, &smac, 6);
 memcpy(&ehdr.h_dest, &dmac, 6);

 ret = bpf_skb_store_bytes(skb, 0, &ehdr, sizeof(ehdr), 0);
 if (ret < 0) {
  printk("skb_store_bytes() failed: %d", ret);
  return BPF_DROP;
 }

 return bpf_redirect(ifindex, 0);
}

SEC("push_ll_and_redirect_silent")
int do_push_ll_and_redirect_silent(struct __sk_buff *skb)
{
 return __do_push_ll_and_redirect(skb);
}

SEC("push_ll_and_redirect")
int do_push_ll_and_redirect(struct __sk_buff *skb)
{
 int ret, ifindex = DST_IFINDEX;

 ret = __do_push_ll_and_redirect(skb);
 if (ret >= 0)
  printk("redirected to %d", ifindex);

 return ret;
}

static inline void __fill_garbage(struct __sk_buff *skb)
{
 uint64_t f = 0xFFFFFFFFFFFFFFFF;

 bpf_skb_store_bytes(skb, 0, &f, sizeof(f), 0);
 bpf_skb_store_bytes(skb, 8, &f, sizeof(f), 0);
 bpf_skb_store_bytes(skb, 16, &f, sizeof(f), 0);
 bpf_skb_store_bytes(skb, 24, &f, sizeof(f), 0);
 bpf_skb_store_bytes(skb, 32, &f, sizeof(f), 0);
 bpf_skb_store_bytes(skb, 40, &f, sizeof(f), 0);
 bpf_skb_store_bytes(skb, 48, &f, sizeof(f), 0);
 bpf_skb_store_bytes(skb, 56, &f, sizeof(f), 0);
 bpf_skb_store_bytes(skb, 64, &f, sizeof(f), 0);
 bpf_skb_store_bytes(skb, 72, &f, sizeof(f), 0);
 bpf_skb_store_bytes(skb, 80, &f, sizeof(f), 0);
 bpf_skb_store_bytes(skb, 88, &f, sizeof(f), 0);
}

SEC("fill_garbage")
int do_fill_garbage(struct __sk_buff *skb)
{
 __fill_garbage(skb);
 printk("Set initial 96 bytes of header to FF");
 return BPF_OK;
}

SEC("fill_garbage_and_redirect")
int do_fill_garbage_and_redirect(struct __sk_buff *skb)
{
 int ifindex = DST_IFINDEX;
 __fill_garbage(skb);
 printk("redirected to %d", ifindex);
 return bpf_redirect(ifindex, 0);
}

/* Drop all packets */
SEC("drop_all")
int do_drop_all(struct __sk_buff *skb)
{
 printk("dropping with: %d", BPF_DROP);
 return BPF_DROP;
}

char _license[] SEC("license") = "GPL";

Messung V0.5
C=98 H=100 G=98

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.