linux/tools/testing/selftests/bpf/progs/connect6_prog.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2// Copyright (c) 2018 Facebook
   3
   4#include <string.h>
   5
   6#include <linux/stddef.h>
   7#include <linux/bpf.h>
   8#include <linux/in.h>
   9#include <linux/in6.h>
  10#include <sys/socket.h>
  11
  12#include <bpf/bpf_helpers.h>
  13#include <bpf/bpf_endian.h>
  14
  15#define SRC_REWRITE_IP6_0       0
  16#define SRC_REWRITE_IP6_1       0
  17#define SRC_REWRITE_IP6_2       0
  18#define SRC_REWRITE_IP6_3       6
  19
  20#define DST_REWRITE_IP6_0       0
  21#define DST_REWRITE_IP6_1       0
  22#define DST_REWRITE_IP6_2       0
  23#define DST_REWRITE_IP6_3       1
  24
  25#define DST_REWRITE_PORT6       6666
  26
  27int _version SEC("version") = 1;
  28
  29SEC("cgroup/connect6")
  30int connect_v6_prog(struct bpf_sock_addr *ctx)
  31{
  32        struct bpf_sock_tuple tuple = {};
  33        struct sockaddr_in6 sa;
  34        struct bpf_sock *sk;
  35
  36        /* Verify that new destination is available. */
  37        memset(&tuple.ipv6.saddr, 0, sizeof(tuple.ipv6.saddr));
  38        memset(&tuple.ipv6.sport, 0, sizeof(tuple.ipv6.sport));
  39
  40        tuple.ipv6.daddr[0] = bpf_htonl(DST_REWRITE_IP6_0);
  41        tuple.ipv6.daddr[1] = bpf_htonl(DST_REWRITE_IP6_1);
  42        tuple.ipv6.daddr[2] = bpf_htonl(DST_REWRITE_IP6_2);
  43        tuple.ipv6.daddr[3] = bpf_htonl(DST_REWRITE_IP6_3);
  44
  45        tuple.ipv6.dport = bpf_htons(DST_REWRITE_PORT6);
  46
  47        if (ctx->type != SOCK_STREAM && ctx->type != SOCK_DGRAM)
  48                return 0;
  49        else if (ctx->type == SOCK_STREAM)
  50                sk = bpf_sk_lookup_tcp(ctx, &tuple, sizeof(tuple.ipv6),
  51                                       BPF_F_CURRENT_NETNS, 0);
  52        else
  53                sk = bpf_sk_lookup_udp(ctx, &tuple, sizeof(tuple.ipv6),
  54                                       BPF_F_CURRENT_NETNS, 0);
  55
  56        if (!sk)
  57                return 0;
  58
  59        if (sk->src_ip6[0] != tuple.ipv6.daddr[0] ||
  60            sk->src_ip6[1] != tuple.ipv6.daddr[1] ||
  61            sk->src_ip6[2] != tuple.ipv6.daddr[2] ||
  62            sk->src_ip6[3] != tuple.ipv6.daddr[3] ||
  63            sk->src_port != DST_REWRITE_PORT6) {
  64                bpf_sk_release(sk);
  65                return 0;
  66        }
  67
  68        bpf_sk_release(sk);
  69
  70        /* Rewrite destination. */
  71        ctx->user_ip6[0] = bpf_htonl(DST_REWRITE_IP6_0);
  72        ctx->user_ip6[1] = bpf_htonl(DST_REWRITE_IP6_1);
  73        ctx->user_ip6[2] = bpf_htonl(DST_REWRITE_IP6_2);
  74        ctx->user_ip6[3] = bpf_htonl(DST_REWRITE_IP6_3);
  75
  76        ctx->user_port = bpf_htons(DST_REWRITE_PORT6);
  77
  78        /* Rewrite source. */
  79        memset(&sa, 0, sizeof(sa));
  80
  81        sa.sin6_family = AF_INET6;
  82        sa.sin6_port = bpf_htons(0);
  83
  84        sa.sin6_addr.s6_addr32[0] = bpf_htonl(SRC_REWRITE_IP6_0);
  85        sa.sin6_addr.s6_addr32[1] = bpf_htonl(SRC_REWRITE_IP6_1);
  86        sa.sin6_addr.s6_addr32[2] = bpf_htonl(SRC_REWRITE_IP6_2);
  87        sa.sin6_addr.s6_addr32[3] = bpf_htonl(SRC_REWRITE_IP6_3);
  88
  89        if (bpf_bind(ctx, (struct sockaddr *)&sa, sizeof(sa)) != 0)
  90                return 0;
  91
  92        return 1;
  93}
  94
  95char _license[] SEC("license") = "GPL";
  96