mirror of
https://git.proxmox.com/git/mirror_iproute2
synced 2026-01-24 10:14:26 +00:00
Merge branch 'net-next'
This commit is contained in:
commit
2505780c20
6
etc/iproute2/bpf_pinning
Normal file
6
etc/iproute2/bpf_pinning
Normal file
@ -0,0 +1,6 @@
|
||||
#
|
||||
# subpath mappings from mount point for pinning
|
||||
#
|
||||
#3 tracing
|
||||
#4 foo/bar
|
||||
#5 tc/cls1
|
||||
13
examples/bpf/README
Normal file
13
examples/bpf/README
Normal file
@ -0,0 +1,13 @@
|
||||
eBPF toy code examples (running in kernel) to familiarize yourself
|
||||
with syntax and features:
|
||||
|
||||
- bpf_prog.c -> Classifier examples with using maps
|
||||
- bpf_shared.c -> Ingress/egress map sharing example
|
||||
- bpf_tailcall.c -> Using tail call chains
|
||||
- bpf_cyclic.c -> Simple cycle as tail calls
|
||||
- bpf_graft.c -> Demo on altering runtime behaviour
|
||||
|
||||
User space code example:
|
||||
|
||||
- bpf_agent.c -> Counterpart to bpf_prog.c for user
|
||||
space to transfer/read out map data
|
||||
30
examples/bpf/bpf_cyclic.c
Normal file
30
examples/bpf/bpf_cyclic.c
Normal file
@ -0,0 +1,30 @@
|
||||
#include "../../include/bpf_api.h"
|
||||
|
||||
/* Cyclic dependency example to test the kernel's runtime upper
|
||||
* bound on loops. Also demonstrates on how to use direct-actions,
|
||||
* loaded as: tc filter add [...] bpf da obj [...]
|
||||
*/
|
||||
#define JMP_MAP_ID 0xabccba
|
||||
|
||||
BPF_PROG_ARRAY(jmp_tc, JMP_MAP_ID, PIN_OBJECT_NS, 1);
|
||||
|
||||
__section_tail(JMP_MAP_ID, 0)
|
||||
int cls_loop(struct __sk_buff *skb)
|
||||
{
|
||||
char fmt[] = "cb: %u\n";
|
||||
|
||||
trace_printk(fmt, sizeof(fmt), skb->cb[0]++);
|
||||
tail_call(skb, &jmp_tc, 0);
|
||||
|
||||
skb->tc_classid = TC_H_MAKE(1, 42);
|
||||
return TC_ACT_OK;
|
||||
}
|
||||
|
||||
__section_cls_entry
|
||||
int cls_entry(struct __sk_buff *skb)
|
||||
{
|
||||
tail_call(skb, &jmp_tc, 0);
|
||||
return TC_ACT_SHOT;
|
||||
}
|
||||
|
||||
BPF_LICENSE("GPL");
|
||||
@ -1,58 +0,0 @@
|
||||
#ifndef __BPF_FUNCS__
|
||||
#define __BPF_FUNCS__
|
||||
|
||||
/* Misc macros. */
|
||||
#ifndef __maybe_unused
|
||||
# define __maybe_unused __attribute__ ((__unused__))
|
||||
#endif
|
||||
|
||||
#ifndef __section
|
||||
# define __section(NAME) __attribute__((section(NAME), used))
|
||||
#endif
|
||||
|
||||
#ifndef offsetof
|
||||
# define offsetof __builtin_offsetof
|
||||
#endif
|
||||
|
||||
#ifndef htons
|
||||
# define htons(x) __constant_htons((x))
|
||||
#endif
|
||||
|
||||
#ifndef likely
|
||||
# define likely(x) __builtin_expect(!!(x), 1)
|
||||
#endif
|
||||
|
||||
#ifndef unlikely
|
||||
# define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#endif
|
||||
|
||||
/* The verifier will translate them to actual function calls. */
|
||||
static void *(*bpf_map_lookup_elem)(void *map, void *key) __maybe_unused =
|
||||
(void *) BPF_FUNC_map_lookup_elem;
|
||||
|
||||
static int (*bpf_map_update_elem)(void *map, void *key, void *value,
|
||||
unsigned long long flags) __maybe_unused =
|
||||
(void *) BPF_FUNC_map_update_elem;
|
||||
|
||||
static int (*bpf_map_delete_elem)(void *map, void *key) __maybe_unused =
|
||||
(void *) BPF_FUNC_map_delete_elem;
|
||||
|
||||
static unsigned int (*get_smp_processor_id)(void) __maybe_unused =
|
||||
(void *) BPF_FUNC_get_smp_processor_id;
|
||||
|
||||
static unsigned int (*get_prandom_u32)(void) __maybe_unused =
|
||||
(void *) BPF_FUNC_get_prandom_u32;
|
||||
|
||||
/* LLVM built-in functions that an eBPF C program may use to emit
|
||||
* BPF_LD_ABS and BPF_LD_IND instructions.
|
||||
*/
|
||||
unsigned long long load_byte(void *skb, unsigned long long off)
|
||||
asm ("llvm.bpf.load.byte");
|
||||
|
||||
unsigned long long load_half(void *skb, unsigned long long off)
|
||||
asm ("llvm.bpf.load.half");
|
||||
|
||||
unsigned long long load_word(void *skb, unsigned long long off)
|
||||
asm ("llvm.bpf.load.word");
|
||||
|
||||
#endif /* __BPF_FUNCS__ */
|
||||
67
examples/bpf/bpf_graft.c
Normal file
67
examples/bpf/bpf_graft.c
Normal file
@ -0,0 +1,67 @@
|
||||
#include "../../include/bpf_api.h"
|
||||
|
||||
/* This example demonstrates how classifier run-time behaviour
|
||||
* can be altered with tail calls. We start out with an empty
|
||||
* jmp_tc array, then add section aaa to the array slot 0, and
|
||||
* later on atomically replace it with section bbb. Note that
|
||||
* as shown in other examples, the tc loader can prepopulate
|
||||
* tail called sections, here we start out with an empty one
|
||||
* on purpose to show it can also be done this way.
|
||||
*
|
||||
* tc filter add dev foo parent ffff: bpf obj graft.o
|
||||
* tc exec bpf dbg
|
||||
* [...]
|
||||
* Socket Thread-20229 [001] ..s. 138993.003923: : fallthrough
|
||||
* <idle>-0 [001] ..s. 138993.202265: : fallthrough
|
||||
* Socket Thread-20229 [001] ..s. 138994.004149: : fallthrough
|
||||
* [...]
|
||||
*
|
||||
* tc exec bpf graft m:globals/jmp_tc key 0 obj graft.o sec aaa
|
||||
* tc exec bpf dbg
|
||||
* [...]
|
||||
* Socket Thread-19818 [002] ..s. 139012.053587: : aaa
|
||||
* <idle>-0 [002] ..s. 139012.172359: : aaa
|
||||
* Socket Thread-19818 [001] ..s. 139012.173556: : aaa
|
||||
* [...]
|
||||
*
|
||||
* tc exec bpf graft m:globals/jmp_tc key 0 obj graft.o sec bbb
|
||||
* tc exec bpf dbg
|
||||
* [...]
|
||||
* Socket Thread-19818 [002] ..s. 139022.102967: : bbb
|
||||
* <idle>-0 [002] ..s. 139022.155640: : bbb
|
||||
* Socket Thread-19818 [001] ..s. 139022.156730: : bbb
|
||||
* [...]
|
||||
*/
|
||||
|
||||
BPF_PROG_ARRAY(jmp_tc, 0, PIN_GLOBAL_NS, 1);
|
||||
|
||||
__section("aaa")
|
||||
int cls_aaa(struct __sk_buff *skb)
|
||||
{
|
||||
char fmt[] = "aaa\n";
|
||||
|
||||
trace_printk(fmt, sizeof(fmt));
|
||||
return TC_H_MAKE(1, 42);
|
||||
}
|
||||
|
||||
__section("bbb")
|
||||
int cls_bbb(struct __sk_buff *skb)
|
||||
{
|
||||
char fmt[] = "bbb\n";
|
||||
|
||||
trace_printk(fmt, sizeof(fmt));
|
||||
return TC_H_MAKE(1, 43);
|
||||
}
|
||||
|
||||
__section_cls_entry
|
||||
int cls_entry(struct __sk_buff *skb)
|
||||
{
|
||||
char fmt[] = "fallthrough\n";
|
||||
|
||||
tail_call(skb, &jmp_tc, 0);
|
||||
trace_printk(fmt, sizeof(fmt));
|
||||
|
||||
return BPF_H_DEFAULT;
|
||||
}
|
||||
|
||||
BPF_LICENSE("GPL");
|
||||
@ -168,8 +168,8 @@
|
||||
|
||||
/* Common, shared definitions with ebpf_agent.c. */
|
||||
#include "bpf_shared.h"
|
||||
/* Selection of BPF helper functions for our example. */
|
||||
#include "bpf_funcs.h"
|
||||
/* BPF helper functions for our example. */
|
||||
#include "../../include/bpf_api.h"
|
||||
|
||||
/* Could be defined here as well, or included from the header. */
|
||||
#define TC_ACT_UNSPEC (-1)
|
||||
@ -387,10 +387,10 @@ static inline void cls_update_proto_map(const struct __sk_buff *skb,
|
||||
uint8_t proto = flow->ip_proto;
|
||||
struct count_tuple *ct, _ct;
|
||||
|
||||
ct = bpf_map_lookup_elem(&map_proto, &proto);
|
||||
ct = map_lookup_elem(&map_proto, &proto);
|
||||
if (likely(ct)) {
|
||||
__sync_fetch_and_add(&ct->packets, 1);
|
||||
__sync_fetch_and_add(&ct->bytes, skb->len);
|
||||
lock_xadd(&ct->packets, 1);
|
||||
lock_xadd(&ct->bytes, skb->len);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -398,7 +398,7 @@ static inline void cls_update_proto_map(const struct __sk_buff *skb,
|
||||
_ct.packets = 1;
|
||||
_ct.bytes = skb->len;
|
||||
|
||||
bpf_map_update_elem(&map_proto, &proto, &_ct, BPF_ANY);
|
||||
map_update_elem(&map_proto, &proto, &_ct, BPF_ANY);
|
||||
}
|
||||
|
||||
static inline void cls_update_queue_map(const struct __sk_buff *skb)
|
||||
@ -409,11 +409,11 @@ static inline void cls_update_queue_map(const struct __sk_buff *skb)
|
||||
|
||||
mismatch = skb->queue_mapping != get_smp_processor_id();
|
||||
|
||||
cq = bpf_map_lookup_elem(&map_queue, &queue);
|
||||
cq = map_lookup_elem(&map_queue, &queue);
|
||||
if (likely(cq)) {
|
||||
__sync_fetch_and_add(&cq->total, 1);
|
||||
lock_xadd(&cq->total, 1);
|
||||
if (mismatch)
|
||||
__sync_fetch_and_add(&cq->mismatch, 1);
|
||||
lock_xadd(&cq->mismatch, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -421,7 +421,7 @@ static inline void cls_update_queue_map(const struct __sk_buff *skb)
|
||||
_cq.total = 1;
|
||||
_cq.mismatch = mismatch ? 1 : 0;
|
||||
|
||||
bpf_map_update_elem(&map_queue, &queue, &_cq, BPF_ANY);
|
||||
map_update_elem(&map_queue, &queue, &_cq, BPF_ANY);
|
||||
}
|
||||
|
||||
/* eBPF program definitions, placed in various sections, which can
|
||||
@ -439,7 +439,8 @@ static inline void cls_update_queue_map(const struct __sk_buff *skb)
|
||||
* It is however not required to have multiple programs sharing
|
||||
* a file.
|
||||
*/
|
||||
__section("classifier") int cls_main(struct __sk_buff *skb)
|
||||
__section("classifier")
|
||||
int cls_main(struct __sk_buff *skb)
|
||||
{
|
||||
struct flow_keys flow;
|
||||
|
||||
@ -456,13 +457,14 @@ static inline void act_update_drop_map(void)
|
||||
{
|
||||
uint32_t *count, cpu = get_smp_processor_id();
|
||||
|
||||
count = bpf_map_lookup_elem(&map_drops, &cpu);
|
||||
count = map_lookup_elem(&map_drops, &cpu);
|
||||
if (count)
|
||||
/* Only this cpu is accessing this element. */
|
||||
(*count)++;
|
||||
}
|
||||
|
||||
__section("action-mark") int act_mark_main(struct __sk_buff *skb)
|
||||
__section("action-mark")
|
||||
int act_mark_main(struct __sk_buff *skb)
|
||||
{
|
||||
/* You could also mangle skb data here with the helper function
|
||||
* BPF_FUNC_skb_store_bytes, etc. Or, alternatively you could
|
||||
@ -479,7 +481,8 @@ __section("action-mark") int act_mark_main(struct __sk_buff *skb)
|
||||
return TC_ACT_UNSPEC;
|
||||
}
|
||||
|
||||
__section("action-rand") int act_rand_main(struct __sk_buff *skb)
|
||||
__section("action-rand")
|
||||
int act_rand_main(struct __sk_buff *skb)
|
||||
{
|
||||
/* Sorry, we're near event horizon ... */
|
||||
if ((get_prandom_u32() & 3) == 0) {
|
||||
@ -493,4 +496,4 @@ __section("action-rand") int act_rand_main(struct __sk_buff *skb)
|
||||
/* Last but not least, the file contains a license. Some future helper
|
||||
* functions may only be available with a GPL license.
|
||||
*/
|
||||
char __license[] __section("license") = "GPL";
|
||||
BPF_LICENSE("GPL");
|
||||
|
||||
48
examples/bpf/bpf_shared.c
Normal file
48
examples/bpf/bpf_shared.c
Normal file
@ -0,0 +1,48 @@
|
||||
#include "../../include/bpf_api.h"
|
||||
|
||||
/* Minimal, stand-alone toy map pinning example:
|
||||
*
|
||||
* clang -target bpf -O2 [...] -o bpf_shared.o -c bpf_shared.c
|
||||
* tc filter add dev foo parent 1: bpf obj bpf_shared.o sec egress
|
||||
* tc filter add dev foo parent ffff: bpf obj bpf_shared.o sec ingress
|
||||
*
|
||||
* Both classifier will share the very same map instance in this example,
|
||||
* so map content can be accessed from ingress *and* egress side!
|
||||
*
|
||||
* This example has a pinning of PIN_OBJECT_NS, so it's private and
|
||||
* thus shared among various program sections within the object.
|
||||
*
|
||||
* A setting of PIN_GLOBAL_NS would place it into a global namespace,
|
||||
* so that it can be shared among different object files. A setting
|
||||
* of PIN_NONE (= 0) means no sharing, so each tc invocation a new map
|
||||
* instance is being created.
|
||||
*/
|
||||
|
||||
BPF_ARRAY4(map_sh, 0, PIN_OBJECT_NS, 1); /* or PIN_GLOBAL_NS, or PIN_NONE */
|
||||
|
||||
__section("egress")
|
||||
int emain(struct __sk_buff *skb)
|
||||
{
|
||||
int key = 0, *val;
|
||||
|
||||
val = map_lookup_elem(&map_sh, &key);
|
||||
if (val)
|
||||
lock_xadd(val, 1);
|
||||
|
||||
return BPF_H_DEFAULT;
|
||||
}
|
||||
|
||||
__section("ingress")
|
||||
int imain(struct __sk_buff *skb)
|
||||
{
|
||||
char fmt[] = "map val: %d\n";
|
||||
int key = 0, *val;
|
||||
|
||||
val = map_lookup_elem(&map_sh, &key);
|
||||
if (val)
|
||||
trace_printk(fmt, sizeof(fmt), *val);
|
||||
|
||||
return BPF_H_DEFAULT;
|
||||
}
|
||||
|
||||
BPF_LICENSE("GPL");
|
||||
@ -1,10 +1,6 @@
|
||||
#ifndef __BPF_SHARED__
|
||||
#define __BPF_SHARED__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "../../include/bpf_elf.h"
|
||||
|
||||
enum {
|
||||
BPF_MAP_ID_PROTO,
|
||||
BPF_MAP_ID_QUEUE,
|
||||
@ -14,7 +10,7 @@ enum {
|
||||
};
|
||||
|
||||
struct count_tuple {
|
||||
long packets; /* type long for __sync_fetch_and_add() */
|
||||
long packets; /* type long for lock_xadd() */
|
||||
long bytes;
|
||||
};
|
||||
|
||||
|
||||
99
examples/bpf/bpf_tailcall.c
Normal file
99
examples/bpf/bpf_tailcall.c
Normal file
@ -0,0 +1,99 @@
|
||||
#include "../../include/bpf_api.h"
|
||||
|
||||
#define ENTRY_INIT 3
|
||||
#define ENTRY_0 0
|
||||
#define ENTRY_1 1
|
||||
#define MAX_JMP_SIZE 2
|
||||
|
||||
#define FOO 42
|
||||
#define BAR 43
|
||||
|
||||
/* This example doesn't really do anything useful, but it's purpose is to
|
||||
* demonstrate eBPF tail calls on a very simple example.
|
||||
*
|
||||
* cls_entry() is our classifier entry point, from there we jump based on
|
||||
* skb->hash into cls_case1() or cls_case2(). They are both part of the
|
||||
* program array jmp_tc. Indicated via __section_tail(), the tc loader
|
||||
* populates the program arrays with the loaded file descriptors already.
|
||||
*
|
||||
* To demonstrate nested jumps, cls_case2() jumps within the same jmp_tc
|
||||
* array to cls_case1(). And whenever we arrive at cls_case1(), we jump
|
||||
* into cls_exit(), part of the jump array jmp_ex.
|
||||
*
|
||||
* Also, to show it's possible, all programs share map_sh and dump the value
|
||||
* that the entry point incremented. The sections that are loaded into a
|
||||
* program array can be atomically replaced during run-time, e.g. to change
|
||||
* classifier behaviour.
|
||||
*/
|
||||
|
||||
BPF_PROG_ARRAY(jmp_tc, FOO, PIN_OBJECT_NS, MAX_JMP_SIZE);
|
||||
BPF_PROG_ARRAY(jmp_ex, BAR, PIN_OBJECT_NS, 1);
|
||||
|
||||
BPF_ARRAY4(map_sh, 0, PIN_OBJECT_NS, 1);
|
||||
|
||||
__section_tail(FOO, ENTRY_0)
|
||||
int cls_case1(struct __sk_buff *skb)
|
||||
{
|
||||
char fmt[] = "case1: map-val: %d from:%u\n";
|
||||
int key = 0, *val;
|
||||
|
||||
val = map_lookup_elem(&map_sh, &key);
|
||||
if (val)
|
||||
trace_printk(fmt, sizeof(fmt), *val, skb->cb[0]);
|
||||
|
||||
skb->cb[0] = ENTRY_0;
|
||||
tail_call(skb, &jmp_ex, ENTRY_0);
|
||||
|
||||
return BPF_H_DEFAULT;
|
||||
}
|
||||
|
||||
__section_tail(FOO, ENTRY_1)
|
||||
int cls_case2(struct __sk_buff *skb)
|
||||
{
|
||||
char fmt[] = "case2: map-val: %d from:%u\n";
|
||||
int key = 0, *val;
|
||||
|
||||
val = map_lookup_elem(&map_sh, &key);
|
||||
if (val)
|
||||
trace_printk(fmt, sizeof(fmt), *val, skb->cb[0]);
|
||||
|
||||
skb->cb[0] = ENTRY_1;
|
||||
tail_call(skb, &jmp_tc, ENTRY_0);
|
||||
|
||||
return BPF_H_DEFAULT;
|
||||
}
|
||||
|
||||
__section_tail(BAR, ENTRY_0)
|
||||
int cls_exit(struct __sk_buff *skb)
|
||||
{
|
||||
char fmt[] = "exit: map-val: %d from:%u\n";
|
||||
int key = 0, *val;
|
||||
|
||||
val = map_lookup_elem(&map_sh, &key);
|
||||
if (val)
|
||||
trace_printk(fmt, sizeof(fmt), *val, skb->cb[0]);
|
||||
|
||||
/* Termination point. */
|
||||
return BPF_H_DEFAULT;
|
||||
}
|
||||
|
||||
__section_cls_entry
|
||||
int cls_entry(struct __sk_buff *skb)
|
||||
{
|
||||
char fmt[] = "fallthrough\n";
|
||||
int key = 0, *val;
|
||||
|
||||
/* For transferring state, we can use skb->cb[0] ... skb->cb[4]. */
|
||||
val = map_lookup_elem(&map_sh, &key);
|
||||
if (val) {
|
||||
lock_xadd(val, 1);
|
||||
|
||||
skb->cb[0] = ENTRY_INIT;
|
||||
tail_call(skb, &jmp_tc, skb->hash & (MAX_JMP_SIZE - 1));
|
||||
}
|
||||
|
||||
trace_printk(fmt, sizeof(fmt));
|
||||
return BPF_H_DEFAULT;
|
||||
}
|
||||
|
||||
BPF_LICENSE("GPL");
|
||||
@ -54,7 +54,7 @@ static int parse_nofopt(struct genl_util *f, int argc, char **argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct genl_util *get_genl_kind(char *str)
|
||||
static struct genl_util *get_genl_kind(const char *str)
|
||||
{
|
||||
void *dlh;
|
||||
char buf[256];
|
||||
|
||||
225
include/bpf_api.h
Normal file
225
include/bpf_api.h
Normal file
@ -0,0 +1,225 @@
|
||||
#ifndef __BPF_API__
|
||||
#define __BPF_API__
|
||||
|
||||
/* Note:
|
||||
*
|
||||
* This file can be included into eBPF kernel programs. It contains
|
||||
* a couple of useful helper functions, map/section ABI (bpf_elf.h),
|
||||
* misc macros and some eBPF specific LLVM built-ins.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <linux/pkt_cls.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/filter.h>
|
||||
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#include "bpf_elf.h"
|
||||
|
||||
/** Misc macros. */
|
||||
|
||||
#ifndef __stringify
|
||||
# define __stringify(X) #X
|
||||
#endif
|
||||
|
||||
#ifndef __maybe_unused
|
||||
# define __maybe_unused __attribute__((__unused__))
|
||||
#endif
|
||||
|
||||
#ifndef offsetof
|
||||
# define offsetof(TYPE, MEMBER) __builtin_offsetof(TYPE, MEMBER)
|
||||
#endif
|
||||
|
||||
#ifndef likely
|
||||
# define likely(X) __builtin_expect(!!(X), 1)
|
||||
#endif
|
||||
|
||||
#ifndef unlikely
|
||||
# define unlikely(X) __builtin_expect(!!(X), 0)
|
||||
#endif
|
||||
|
||||
#ifndef htons
|
||||
# define htons(X) __constant_htons((X))
|
||||
#endif
|
||||
|
||||
#ifndef ntohs
|
||||
# define ntohs(X) __constant_ntohs((X))
|
||||
#endif
|
||||
|
||||
#ifndef htonl
|
||||
# define htonl(X) __constant_htonl((X))
|
||||
#endif
|
||||
|
||||
#ifndef ntohl
|
||||
# define ntohl(X) __constant_ntohl((X))
|
||||
#endif
|
||||
|
||||
/** Section helper macros. */
|
||||
|
||||
#ifndef __section
|
||||
# define __section(NAME) \
|
||||
__attribute__((section(NAME), used))
|
||||
#endif
|
||||
|
||||
#ifndef __section_tail
|
||||
# define __section_tail(ID, KEY) \
|
||||
__section(__stringify(ID) "/" __stringify(KEY))
|
||||
#endif
|
||||
|
||||
#ifndef __section_cls_entry
|
||||
# define __section_cls_entry \
|
||||
__section(ELF_SECTION_CLASSIFIER)
|
||||
#endif
|
||||
|
||||
#ifndef __section_act_entry
|
||||
# define __section_act_entry \
|
||||
__section(ELF_SECTION_ACTION)
|
||||
#endif
|
||||
|
||||
#ifndef __section_license
|
||||
# define __section_license \
|
||||
__section(ELF_SECTION_LICENSE)
|
||||
#endif
|
||||
|
||||
#ifndef __section_maps
|
||||
# define __section_maps \
|
||||
__section(ELF_SECTION_MAPS)
|
||||
#endif
|
||||
|
||||
/** Declaration helper macros. */
|
||||
|
||||
#ifndef BPF_LICENSE
|
||||
# define BPF_LICENSE(NAME) \
|
||||
char ____license[] __section_license = NAME
|
||||
#endif
|
||||
|
||||
#ifndef __BPF_MAP
|
||||
# define __BPF_MAP(NAME, TYPE, ID, SIZE_KEY, SIZE_VALUE, PIN, MAX_ELEM) \
|
||||
struct bpf_elf_map __section_maps NAME = { \
|
||||
.type = (TYPE), \
|
||||
.id = (ID), \
|
||||
.size_key = (SIZE_KEY), \
|
||||
.size_value = (SIZE_VALUE), \
|
||||
.pinning = (PIN), \
|
||||
.max_elem = (MAX_ELEM), \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef BPF_HASH
|
||||
# define BPF_HASH(NAME, ID, SIZE_KEY, SIZE_VALUE, PIN, MAX_ELEM) \
|
||||
__BPF_MAP(NAME, BPF_MAP_TYPE_HASH, ID, SIZE_KEY, SIZE_VALUE, \
|
||||
PIN, MAX_ELEM)
|
||||
#endif
|
||||
|
||||
#ifndef BPF_ARRAY
|
||||
# define BPF_ARRAY(NAME, ID, SIZE_VALUE, PIN, MAX_ELEM) \
|
||||
__BPF_MAP(NAME, BPF_MAP_TYPE_ARRAY, ID, sizeof(uint32_t), \
|
||||
SIZE_VALUE, PIN, MAX_ELEM)
|
||||
#endif
|
||||
|
||||
#ifndef BPF_ARRAY2
|
||||
# define BPF_ARRAY2(NAME, ID, PIN, MAX_ELEM) \
|
||||
BPF_ARRAY(NAME, ID, sizeof(uint16_t), PIN, MAX_ELEM)
|
||||
#endif
|
||||
|
||||
#ifndef BPF_ARRAY4
|
||||
# define BPF_ARRAY4(NAME, ID, PIN, MAX_ELEM) \
|
||||
BPF_ARRAY(NAME, ID, sizeof(uint32_t), PIN, MAX_ELEM)
|
||||
#endif
|
||||
|
||||
#ifndef BPF_ARRAY8
|
||||
# define BPF_ARRAY8(NAME, ID, PIN, MAX_ELEM) \
|
||||
BPF_ARRAY(NAME, ID, sizeof(uint64_t), PIN, MAX_ELEM)
|
||||
#endif
|
||||
|
||||
#ifndef BPF_PROG_ARRAY
|
||||
# define BPF_PROG_ARRAY(NAME, ID, PIN, MAX_ELEM) \
|
||||
__BPF_MAP(NAME, BPF_MAP_TYPE_PROG_ARRAY, ID, sizeof(uint32_t), \
|
||||
sizeof(uint32_t), PIN, MAX_ELEM)
|
||||
#endif
|
||||
|
||||
/** Classifier helper */
|
||||
|
||||
#ifndef BPF_H_DEFAULT
|
||||
# define BPF_H_DEFAULT -1
|
||||
#endif
|
||||
|
||||
/** BPF helper functions for tc. */
|
||||
|
||||
#ifndef BPF_FUNC
|
||||
# define BPF_FUNC(NAME, ...) \
|
||||
(* NAME)(__VA_ARGS__) __maybe_unused = (void *) BPF_FUNC_##NAME
|
||||
#endif
|
||||
|
||||
/* Map access/manipulation */
|
||||
static void *BPF_FUNC(map_lookup_elem, void *map, const void *key);
|
||||
static int BPF_FUNC(map_update_elem, void *map, const void *key,
|
||||
const void *value, uint32_t flags);
|
||||
static int BPF_FUNC(map_delete_elem, void *map, const void *key);
|
||||
|
||||
/* Time access */
|
||||
static uint64_t BPF_FUNC(ktime_get_ns);
|
||||
|
||||
/* Debugging */
|
||||
static void BPF_FUNC(trace_printk, const char *fmt, int fmt_size, ...);
|
||||
|
||||
/* Random numbers */
|
||||
static uint32_t BPF_FUNC(get_prandom_u32);
|
||||
|
||||
/* Tail calls */
|
||||
static void BPF_FUNC(tail_call, struct __sk_buff *skb, void *map,
|
||||
uint32_t index);
|
||||
|
||||
/* System helpers */
|
||||
static uint32_t BPF_FUNC(get_smp_processor_id);
|
||||
|
||||
/* Packet misc meta data */
|
||||
static uint32_t BPF_FUNC(get_cgroup_classid, struct __sk_buff *skb);
|
||||
static uint32_t BPF_FUNC(get_route_realm, struct __sk_buff *skb);
|
||||
|
||||
/* Packet redirection */
|
||||
static int BPF_FUNC(redirect, int ifindex, uint32_t flags);
|
||||
static int BPF_FUNC(clone_redirect, struct __sk_buff *skb, int ifindex,
|
||||
uint32_t flags);
|
||||
|
||||
/* Packet manipulation */
|
||||
#define BPF_PSEUDO_HDR 0x10
|
||||
#define BPF_HAS_PSEUDO_HDR(flags) ((flags) & BPF_PSEUDO_HDR)
|
||||
#define BPF_HDR_FIELD_SIZE(flags) ((flags) & 0x0f)
|
||||
|
||||
static int BPF_FUNC(skb_store_bytes, struct __sk_buff *skb, uint32_t off,
|
||||
void *from, uint32_t len, uint32_t flags);
|
||||
static int BPF_FUNC(l3_csum_replace, struct __sk_buff *skb, uint32_t off,
|
||||
uint32_t from, uint32_t to, uint32_t flags);
|
||||
static int BPF_FUNC(l4_csum_replace, struct __sk_buff *skb, uint32_t off,
|
||||
uint32_t from, uint32_t to, uint32_t flags);
|
||||
|
||||
/* Packet vlan encap/decap */
|
||||
static int BPF_FUNC(skb_vlan_push, struct __sk_buff *skb, uint16_t proto,
|
||||
uint16_t vlan_tci);
|
||||
static int BPF_FUNC(skb_vlan_pop, struct __sk_buff *skb);
|
||||
|
||||
/* Packet tunnel encap/decap */
|
||||
static int BPF_FUNC(skb_get_tunnel_key, struct __sk_buff *skb,
|
||||
struct bpf_tunnel_key *to, uint32_t size, uint32_t flags);
|
||||
static int BPF_FUNC(skb_set_tunnel_key, struct __sk_buff *skb,
|
||||
struct bpf_tunnel_key *from, uint32_t size, uint32_t flags);
|
||||
|
||||
/** LLVM built-ins */
|
||||
|
||||
#ifndef lock_xadd
|
||||
# define lock_xadd(ptr, val) ((void) __sync_fetch_and_add(ptr, val))
|
||||
#endif
|
||||
|
||||
unsigned long long load_byte(void *skb, unsigned long long off)
|
||||
asm ("llvm.bpf.load.byte");
|
||||
|
||||
unsigned long long load_half(void *skb, unsigned long long off)
|
||||
asm ("llvm.bpf.load.half");
|
||||
|
||||
unsigned long long load_word(void *skb, unsigned long long off)
|
||||
asm ("llvm.bpf.load.word");
|
||||
|
||||
#endif /* __BPF_API__ */
|
||||
@ -21,6 +21,11 @@
|
||||
#define ELF_MAX_MAPS 64
|
||||
#define ELF_MAX_LICENSE_LEN 128
|
||||
|
||||
/* Object pinning settings */
|
||||
#define PIN_NONE 0
|
||||
#define PIN_OBJECT_NS 1
|
||||
#define PIN_GLOBAL_NS 2
|
||||
|
||||
/* ELF map definition */
|
||||
struct bpf_elf_map {
|
||||
__u32 type;
|
||||
@ -28,6 +33,7 @@ struct bpf_elf_map {
|
||||
__u32 size_value;
|
||||
__u32 max_elem;
|
||||
__u32 id;
|
||||
__u32 pinning;
|
||||
};
|
||||
|
||||
#endif /* __BPF_ELF__ */
|
||||
|
||||
@ -1,141 +1,20 @@
|
||||
#ifndef _IP6TABLES_USER_H
|
||||
#define _IP6TABLES_USER_H
|
||||
|
||||
#include "iptables_common.h"
|
||||
#include "libiptc/libip6tc.h"
|
||||
|
||||
struct ip6tables_rule_match
|
||||
{
|
||||
struct ip6tables_rule_match *next;
|
||||
|
||||
struct ip6tables_match *match;
|
||||
};
|
||||
|
||||
/* Include file for additions: new matches and targets. */
|
||||
struct ip6tables_match
|
||||
{
|
||||
struct ip6tables_match *next;
|
||||
|
||||
ip6t_chainlabel name;
|
||||
|
||||
const char *version;
|
||||
|
||||
/* Size of match data. */
|
||||
size_t size;
|
||||
|
||||
/* Size of match data relevent for userspace comparison purposes */
|
||||
size_t userspacesize;
|
||||
|
||||
/* Function which prints out usage message. */
|
||||
void (*help)(void);
|
||||
|
||||
/* Initialize the match. */
|
||||
void (*init)(struct ip6t_entry_match *m, unsigned int *nfcache);
|
||||
|
||||
/* Function which parses command options; returns true if it
|
||||
ate an option */
|
||||
int (*parse)(int c, char **argv, int invert, unsigned int *flags,
|
||||
const struct ip6t_entry *entry,
|
||||
unsigned int *nfcache,
|
||||
struct ip6t_entry_match **match);
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
void (*final_check)(unsigned int flags);
|
||||
|
||||
/* Prints out the match iff non-NULL: put space at end */
|
||||
void (*print)(const struct ip6t_ip6 *ip,
|
||||
const struct ip6t_entry_match *match, int numeric);
|
||||
|
||||
/* Saves the union ipt_matchinfo in parsable form to stdout. */
|
||||
void (*save)(const struct ip6t_ip6 *ip,
|
||||
const struct ip6t_entry_match *match);
|
||||
|
||||
/* Pointer to list of extra command-line options */
|
||||
const struct option *extra_opts;
|
||||
|
||||
/* Ignore these men behind the curtain: */
|
||||
unsigned int option_offset;
|
||||
struct ip6t_entry_match *m;
|
||||
unsigned int mflags;
|
||||
#ifdef NO_SHARED_LIBS
|
||||
unsigned int loaded; /* simulate loading so options are merged properly */
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ip6tables_target
|
||||
{
|
||||
struct ip6tables_target *next;
|
||||
|
||||
ip6t_chainlabel name;
|
||||
|
||||
const char *version;
|
||||
|
||||
/* Size of target data. */
|
||||
size_t size;
|
||||
|
||||
/* Size of target data relevent for userspace comparison purposes */
|
||||
size_t userspacesize;
|
||||
|
||||
/* Function which prints out usage message. */
|
||||
void (*help)(void);
|
||||
|
||||
/* Initialize the target. */
|
||||
void (*init)(struct ip6t_entry_target *t, unsigned int *nfcache);
|
||||
|
||||
/* Function which parses command options; returns true if it
|
||||
ate an option */
|
||||
int (*parse)(int c, char **argv, int invert, unsigned int *flags,
|
||||
const struct ip6t_entry *entry,
|
||||
struct ip6t_entry_target **target);
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
void (*final_check)(unsigned int flags);
|
||||
|
||||
/* Prints out the target iff non-NULL: put space at end */
|
||||
void (*print)(const struct ip6t_ip6 *ip,
|
||||
const struct ip6t_entry_target *target, int numeric);
|
||||
|
||||
/* Saves the targinfo in parsable form to stdout. */
|
||||
void (*save)(const struct ip6t_ip6 *ip,
|
||||
const struct ip6t_entry_target *target);
|
||||
|
||||
/* Pointer to list of extra command-line options */
|
||||
struct option *extra_opts;
|
||||
|
||||
/* Ignore these men behind the curtain: */
|
||||
unsigned int option_offset;
|
||||
struct ip6t_entry_target *t;
|
||||
unsigned int tflags;
|
||||
unsigned int used;
|
||||
#ifdef NO_SHARED_LIBS
|
||||
unsigned int loaded; /* simulate loading so options are merged properly */
|
||||
#endif
|
||||
};
|
||||
|
||||
extern int line;
|
||||
#include <netinet/ip.h>
|
||||
#include <xtables.h>
|
||||
#include <libiptc/libip6tc.h>
|
||||
#include <iptables/internal.h>
|
||||
|
||||
/* Your shared library should call one of these. */
|
||||
extern void register_match6(struct ip6tables_match *me);
|
||||
extern void register_target6(struct ip6tables_target *me);
|
||||
|
||||
extern int do_command6(int argc, char *argv[], char **table,
|
||||
ip6tc_handle_t *handle);
|
||||
/* Keeping track of external matches and targets: linked lists. */
|
||||
extern struct ip6tables_match *ip6tables_matches;
|
||||
extern struct ip6tables_target *ip6tables_targets;
|
||||
struct xtc_handle **handle, bool restore);
|
||||
|
||||
enum ip6t_tryload {
|
||||
DONT_LOAD,
|
||||
TRY_LOAD,
|
||||
LOAD_MUST_SUCCEED
|
||||
};
|
||||
extern int for_each_chain6(int (*fn)(const xt_chainlabel, int, struct xtc_handle *), int verbose, int builtinstoo, struct xtc_handle *handle);
|
||||
extern int flush_entries6(const xt_chainlabel chain, int verbose, struct xtc_handle *handle);
|
||||
extern int delete_chain6(const xt_chainlabel chain, int verbose, struct xtc_handle *handle);
|
||||
void print_rule6(const struct ip6t_entry *e, struct xtc_handle *h, const char *chain, int counters);
|
||||
|
||||
extern struct ip6tables_target *find_target(const char *name, enum ip6t_tryload);
|
||||
extern struct ip6tables_match *find_match(const char *name, enum ip6t_tryload, struct ip6tables_rule_match **match);
|
||||
|
||||
extern int for_each_chain(int (*fn)(const ip6t_chainlabel, int, ip6tc_handle_t *), int verbose, int builtinstoo, ip6tc_handle_t *handle);
|
||||
extern int flush_entries(const ip6t_chainlabel chain, int verbose, ip6tc_handle_t *handle);
|
||||
extern int delete_chain(const ip6t_chainlabel chain, int verbose, ip6tc_handle_t *handle);
|
||||
extern int ip6tables_insmod(const char *modname, const char *modprobe);
|
||||
extern struct xtables_globals ip6tables_globals;
|
||||
|
||||
#endif /*_IP6TABLES_USER_H*/
|
||||
|
||||
@ -1,179 +1,25 @@
|
||||
#ifndef _IPTABLES_USER_H
|
||||
#define _IPTABLES_USER_H
|
||||
|
||||
#include "iptables_common.h"
|
||||
#include "libiptc/libiptc.h"
|
||||
|
||||
#ifndef IPT_LIB_DIR
|
||||
#define IPT_LIB_DIR "/usr/local/lib/iptables"
|
||||
#endif
|
||||
|
||||
#ifndef IPPROTO_SCTP
|
||||
#define IPPROTO_SCTP 132
|
||||
#endif
|
||||
|
||||
#ifndef IPT_SO_GET_REVISION_MATCH /* Old kernel source. */
|
||||
#define IPT_SO_GET_REVISION_MATCH (IPT_BASE_CTL + 2)
|
||||
#define IPT_SO_GET_REVISION_TARGET (IPT_BASE_CTL + 3)
|
||||
|
||||
struct ipt_get_revision
|
||||
{
|
||||
char name[IPT_FUNCTION_MAXNAMELEN-1];
|
||||
|
||||
u_int8_t revision;
|
||||
};
|
||||
#endif /* IPT_SO_GET_REVISION_MATCH Old kernel source */
|
||||
|
||||
struct iptables_rule_match
|
||||
{
|
||||
struct iptables_rule_match *next;
|
||||
|
||||
struct iptables_match *match;
|
||||
};
|
||||
|
||||
/* Include file for additions: new matches and targets. */
|
||||
struct iptables_match
|
||||
{
|
||||
struct iptables_match *next;
|
||||
|
||||
ipt_chainlabel name;
|
||||
|
||||
/* Revision of match (0 by default). */
|
||||
u_int8_t revision;
|
||||
|
||||
const char *version;
|
||||
|
||||
/* Size of match data. */
|
||||
size_t size;
|
||||
|
||||
/* Size of match data relevent for userspace comparison purposes */
|
||||
size_t userspacesize;
|
||||
|
||||
/* Function which prints out usage message. */
|
||||
void (*help)(void);
|
||||
|
||||
/* Initialize the match. */
|
||||
void (*init)(struct ipt_entry_match *m, unsigned int *nfcache);
|
||||
|
||||
/* Function which parses command options; returns true if it
|
||||
ate an option */
|
||||
int (*parse)(int c, char **argv, int invert, unsigned int *flags,
|
||||
const struct ipt_entry *entry,
|
||||
unsigned int *nfcache,
|
||||
struct ipt_entry_match **match);
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
void (*final_check)(unsigned int flags);
|
||||
|
||||
/* Prints out the match iff non-NULL: put space at end */
|
||||
void (*print)(const struct ipt_ip *ip,
|
||||
const struct ipt_entry_match *match, int numeric);
|
||||
|
||||
/* Saves the match info in parsable form to stdout. */
|
||||
void (*save)(const struct ipt_ip *ip,
|
||||
const struct ipt_entry_match *match);
|
||||
|
||||
/* Pointer to list of extra command-line options */
|
||||
const struct option *extra_opts;
|
||||
|
||||
/* Ignore these men behind the curtain: */
|
||||
unsigned int option_offset;
|
||||
struct ipt_entry_match *m;
|
||||
unsigned int mflags;
|
||||
#ifdef NO_SHARED_LIBS
|
||||
unsigned int loaded; /* simulate loading so options are merged properly */
|
||||
#endif
|
||||
};
|
||||
|
||||
struct iptables_target
|
||||
{
|
||||
struct iptables_target *next;
|
||||
|
||||
ipt_chainlabel name;
|
||||
|
||||
/* Revision of target (0 by default). */
|
||||
u_int8_t revision;
|
||||
|
||||
const char *version;
|
||||
|
||||
/* Size of target data. */
|
||||
size_t size;
|
||||
|
||||
/* Size of target data relevent for userspace comparison purposes */
|
||||
size_t userspacesize;
|
||||
|
||||
/* Function which prints out usage message. */
|
||||
void (*help)(void);
|
||||
|
||||
/* Initialize the target. */
|
||||
void (*init)(struct ipt_entry_target *t, unsigned int *nfcache);
|
||||
|
||||
/* Function which parses command options; returns true if it
|
||||
ate an option */
|
||||
int (*parse)(int c, char **argv, int invert, unsigned int *flags,
|
||||
const struct ipt_entry *entry,
|
||||
struct ipt_entry_target **target);
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
void (*final_check)(unsigned int flags);
|
||||
|
||||
/* Prints out the target iff non-NULL: put space at end */
|
||||
void (*print)(const struct ipt_ip *ip,
|
||||
const struct ipt_entry_target *target, int numeric);
|
||||
|
||||
/* Saves the targinfo in parsable form to stdout. */
|
||||
void (*save)(const struct ipt_ip *ip,
|
||||
const struct ipt_entry_target *target);
|
||||
|
||||
/* Pointer to list of extra command-line options */
|
||||
struct option *extra_opts;
|
||||
|
||||
/* Ignore these men behind the curtain: */
|
||||
unsigned int option_offset;
|
||||
struct ipt_entry_target *t;
|
||||
unsigned int tflags;
|
||||
unsigned int used;
|
||||
#ifdef NO_SHARED_LIBS
|
||||
unsigned int loaded; /* simulate loading so options are merged properly */
|
||||
#endif
|
||||
};
|
||||
|
||||
extern int line;
|
||||
#include <netinet/ip.h>
|
||||
#include <xtables.h>
|
||||
#include <libiptc/libiptc.h>
|
||||
#include <iptables/internal.h>
|
||||
|
||||
/* Your shared library should call one of these. */
|
||||
extern void register_match(struct iptables_match *me);
|
||||
extern void register_target(struct iptables_target *me);
|
||||
extern void xtables_register_target(struct iptables_target *me);
|
||||
extern int build_st(struct iptables_target *target, struct ipt_entry_target *t);
|
||||
extern int do_command4(int argc, char *argv[], char **table,
|
||||
struct xtc_handle **handle, bool restore);
|
||||
extern int delete_chain4(const xt_chainlabel chain, int verbose,
|
||||
struct xtc_handle *handle);
|
||||
extern int flush_entries4(const xt_chainlabel chain, int verbose,
|
||||
struct xtc_handle *handle);
|
||||
extern int for_each_chain4(int (*fn)(const xt_chainlabel, int, struct xtc_handle *),
|
||||
int verbose, int builtinstoo, struct xtc_handle *handle);
|
||||
extern void print_rule4(const struct ipt_entry *e,
|
||||
struct xtc_handle *handle, const char *chain, int counters);
|
||||
|
||||
extern struct in_addr *dotted_to_addr(const char *dotted);
|
||||
extern char *addr_to_dotted(const struct in_addr *addrp);
|
||||
extern char *addr_to_anyname(const struct in_addr *addr);
|
||||
extern char *mask_to_dotted(const struct in_addr *mask);
|
||||
extern struct xtables_globals iptables_globals;
|
||||
|
||||
extern void parse_hostnetworkmask(const char *name, struct in_addr **addrpp,
|
||||
struct in_addr *maskp, unsigned int *naddrs);
|
||||
extern u_int16_t parse_protocol(const char *s);
|
||||
extern struct xtables_globals xtables_globals;
|
||||
|
||||
extern int do_command(int argc, char *argv[], char **table,
|
||||
iptc_handle_t *handle);
|
||||
/* Keeping track of external matches and targets: linked lists. */
|
||||
extern struct iptables_match *iptables_matches;
|
||||
extern struct iptables_target *iptables_targets;
|
||||
|
||||
enum ipt_tryload {
|
||||
DONT_LOAD,
|
||||
TRY_LOAD,
|
||||
LOAD_MUST_SUCCEED
|
||||
};
|
||||
|
||||
extern struct iptables_target *find_target(const char *name, enum ipt_tryload);
|
||||
extern struct iptables_match *find_match(const char *name, enum ipt_tryload, struct iptables_rule_match **match);
|
||||
|
||||
extern int delete_chain(const ipt_chainlabel chain, int verbose,
|
||||
iptc_handle_t *handle);
|
||||
extern int flush_entries(const ipt_chainlabel chain, int verbose,
|
||||
iptc_handle_t *handle);
|
||||
extern int for_each_chain(int (*fn)(const ipt_chainlabel, int, iptc_handle_t *),
|
||||
int verbose, int builtinstoo, iptc_handle_t *handle);
|
||||
#endif /*_IPTABLES_USER_H*/
|
||||
|
||||
13
include/iptables/internal.h
Normal file
13
include/iptables/internal.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef IPTABLES_INTERNAL_H
|
||||
#define IPTABLES_INTERNAL_H 1
|
||||
|
||||
#define IPTABLES_VERSION "1.6.0"
|
||||
|
||||
/**
|
||||
* Program's own name and version.
|
||||
*/
|
||||
extern const char *program_name, *program_version;
|
||||
|
||||
extern int line;
|
||||
|
||||
#endif /* IPTABLES_INTERNAL_H */
|
||||
@ -5,22 +5,11 @@
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#if defined(__GLIBC__) && __GLIBC__ == 2
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <net/if.h>
|
||||
#include <sys/types.h>
|
||||
#else /* libc5 */
|
||||
#include <sys/socket.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/icmp.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/in6.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -2,153 +2,160 @@
|
||||
#define _LIBIP6TC_H
|
||||
/* Library which manipulates firewall rules. Version 0.2. */
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <libiptc/ipt_kernel_headers.h>
|
||||
#include <linux/netfilter_ipv6/ip6_tables.h>
|
||||
|
||||
#ifndef IP6T_MIN_ALIGN
|
||||
#define IP6T_MIN_ALIGN (__alignof__(struct ip6t_entry))
|
||||
#ifdef __cplusplus
|
||||
# include <climits>
|
||||
#else
|
||||
# include <limits.h> /* INT_MAX in ip6_tables.h */
|
||||
#endif
|
||||
#define IP6T_ALIGN(s) (((s) + (IP6T_MIN_ALIGN-1)) & ~(IP6T_MIN_ALIGN-1))
|
||||
#include <linux/netfilter_ipv6/ip6_tables.h>
|
||||
#include <libiptc/xtcshared.h>
|
||||
|
||||
typedef char ip6t_chainlabel[32];
|
||||
#define ip6tc_handle xtc_handle
|
||||
#define ip6t_chainlabel xt_chainlabel
|
||||
|
||||
#define IP6TC_LABEL_ACCEPT "ACCEPT"
|
||||
#define IP6TC_LABEL_DROP "DROP"
|
||||
#define IP6TC_LABEL_QUEUE "QUEUE"
|
||||
#define IP6TC_LABEL_RETURN "RETURN"
|
||||
|
||||
/* Transparent handle type. */
|
||||
typedef struct ip6tc_handle *ip6tc_handle_t;
|
||||
|
||||
/* Does this chain exist? */
|
||||
int ip6tc_is_chain(const char *chain, const ip6tc_handle_t handle);
|
||||
int ip6tc_is_chain(const char *chain, struct xtc_handle *const handle);
|
||||
|
||||
/* Take a snapshot of the rules. Returns NULL on error. */
|
||||
ip6tc_handle_t ip6tc_init(const char *tablename);
|
||||
struct xtc_handle *ip6tc_init(const char *tablename);
|
||||
|
||||
/* Cleanup after ip6tc_init(). */
|
||||
void ip6tc_free(ip6tc_handle_t *h);
|
||||
void ip6tc_free(struct xtc_handle *h);
|
||||
|
||||
/* Iterator functions to run through the chains. Returns NULL at end. */
|
||||
const char *ip6tc_first_chain(ip6tc_handle_t *handle);
|
||||
const char *ip6tc_next_chain(ip6tc_handle_t *handle);
|
||||
const char *ip6tc_first_chain(struct xtc_handle *handle);
|
||||
const char *ip6tc_next_chain(struct xtc_handle *handle);
|
||||
|
||||
/* Get first rule in the given chain: NULL for empty chain. */
|
||||
const struct ip6t_entry *ip6tc_first_rule(const char *chain,
|
||||
ip6tc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Returns NULL when rules run out. */
|
||||
const struct ip6t_entry *ip6tc_next_rule(const struct ip6t_entry *prev,
|
||||
ip6tc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Returns a pointer to the target name of this position. */
|
||||
const char *ip6tc_get_target(const struct ip6t_entry *e,
|
||||
ip6tc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Is this a built-in chain? */
|
||||
int ip6tc_builtin(const char *chain, const ip6tc_handle_t handle);
|
||||
int ip6tc_builtin(const char *chain, struct xtc_handle *const handle);
|
||||
|
||||
/* Get the policy of a given built-in chain */
|
||||
const char *ip6tc_get_policy(const char *chain,
|
||||
struct ip6t_counters *counters,
|
||||
ip6tc_handle_t *handle);
|
||||
struct xt_counters *counters,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* These functions return TRUE for OK or 0 and set errno. If errno ==
|
||||
0, it means there was a version error (ie. upgrade libiptc). */
|
||||
/* Rule numbers start at 1 for the first rule. */
|
||||
|
||||
/* Insert the entry `fw' in chain `chain' into position `rulenum'. */
|
||||
int ip6tc_insert_entry(const ip6t_chainlabel chain,
|
||||
int ip6tc_insert_entry(const xt_chainlabel chain,
|
||||
const struct ip6t_entry *e,
|
||||
unsigned int rulenum,
|
||||
ip6tc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Atomically replace rule `rulenum' in `chain' with `fw'. */
|
||||
int ip6tc_replace_entry(const ip6t_chainlabel chain,
|
||||
int ip6tc_replace_entry(const xt_chainlabel chain,
|
||||
const struct ip6t_entry *e,
|
||||
unsigned int rulenum,
|
||||
ip6tc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Append entry `fw' to chain `chain'. Equivalent to insert with
|
||||
rulenum = length of chain. */
|
||||
int ip6tc_append_entry(const ip6t_chainlabel chain,
|
||||
int ip6tc_append_entry(const xt_chainlabel chain,
|
||||
const struct ip6t_entry *e,
|
||||
ip6tc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Delete the first rule in `chain' which matches `fw'. */
|
||||
int ip6tc_delete_entry(const ip6t_chainlabel chain,
|
||||
/* Check whether a matching rule exists */
|
||||
int ip6tc_check_entry(const xt_chainlabel chain,
|
||||
const struct ip6t_entry *origfw,
|
||||
unsigned char *matchmask,
|
||||
ip6tc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Delete the first rule in `chain' which matches `fw'. */
|
||||
int ip6tc_delete_entry(const xt_chainlabel chain,
|
||||
const struct ip6t_entry *origfw,
|
||||
unsigned char *matchmask,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Delete the rule in position `rulenum' in `chain'. */
|
||||
int ip6tc_delete_num_entry(const ip6t_chainlabel chain,
|
||||
int ip6tc_delete_num_entry(const xt_chainlabel chain,
|
||||
unsigned int rulenum,
|
||||
ip6tc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Check the packet `fw' on chain `chain'. Returns the verdict, or
|
||||
NULL and sets errno. */
|
||||
const char *ip6tc_check_packet(const ip6t_chainlabel chain,
|
||||
const char *ip6tc_check_packet(const xt_chainlabel chain,
|
||||
struct ip6t_entry *,
|
||||
ip6tc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Flushes the entries in the given chain (ie. empties chain). */
|
||||
int ip6tc_flush_entries(const ip6t_chainlabel chain,
|
||||
ip6tc_handle_t *handle);
|
||||
int ip6tc_flush_entries(const xt_chainlabel chain,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Zeroes the counters in a chain. */
|
||||
int ip6tc_zero_entries(const ip6t_chainlabel chain,
|
||||
ip6tc_handle_t *handle);
|
||||
int ip6tc_zero_entries(const xt_chainlabel chain,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Creates a new chain. */
|
||||
int ip6tc_create_chain(const ip6t_chainlabel chain,
|
||||
ip6tc_handle_t *handle);
|
||||
int ip6tc_create_chain(const xt_chainlabel chain,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Deletes a chain. */
|
||||
int ip6tc_delete_chain(const ip6t_chainlabel chain,
|
||||
ip6tc_handle_t *handle);
|
||||
int ip6tc_delete_chain(const xt_chainlabel chain,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Renames a chain. */
|
||||
int ip6tc_rename_chain(const ip6t_chainlabel oldname,
|
||||
const ip6t_chainlabel newname,
|
||||
ip6tc_handle_t *handle);
|
||||
int ip6tc_rename_chain(const xt_chainlabel oldname,
|
||||
const xt_chainlabel newname,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Sets the policy on a built-in chain. */
|
||||
int ip6tc_set_policy(const ip6t_chainlabel chain,
|
||||
const ip6t_chainlabel policy,
|
||||
struct ip6t_counters *counters,
|
||||
ip6tc_handle_t *handle);
|
||||
int ip6tc_set_policy(const xt_chainlabel chain,
|
||||
const xt_chainlabel policy,
|
||||
struct xt_counters *counters,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Get the number of references to this chain */
|
||||
int ip6tc_get_references(unsigned int *ref, const ip6t_chainlabel chain,
|
||||
ip6tc_handle_t *handle);
|
||||
int ip6tc_get_references(unsigned int *ref, const xt_chainlabel chain,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* read packet and byte counters for a specific rule */
|
||||
struct ip6t_counters *ip6tc_read_counter(const ip6t_chainlabel chain,
|
||||
struct xt_counters *ip6tc_read_counter(const xt_chainlabel chain,
|
||||
unsigned int rulenum,
|
||||
ip6tc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* zero packet and byte counters for a specific rule */
|
||||
int ip6tc_zero_counter(const ip6t_chainlabel chain,
|
||||
int ip6tc_zero_counter(const xt_chainlabel chain,
|
||||
unsigned int rulenum,
|
||||
ip6tc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* set packet and byte counters for a specific rule */
|
||||
int ip6tc_set_counter(const ip6t_chainlabel chain,
|
||||
int ip6tc_set_counter(const xt_chainlabel chain,
|
||||
unsigned int rulenum,
|
||||
struct ip6t_counters *counters,
|
||||
ip6tc_handle_t *handle);
|
||||
struct xt_counters *counters,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Makes the actual changes. */
|
||||
int ip6tc_commit(ip6tc_handle_t *handle);
|
||||
int ip6tc_commit(struct xtc_handle *handle);
|
||||
|
||||
/* Get raw socket. */
|
||||
int ip6tc_get_raw_socket();
|
||||
int ip6tc_get_raw_socket(void);
|
||||
|
||||
/* Translates errno numbers into more human-readable form than strerror. */
|
||||
const char *ip6tc_strerror(int err);
|
||||
|
||||
/* Return prefix length, or -1 if not contiguous */
|
||||
int ipv6_prefix_length(const struct in6_addr *a);
|
||||
extern void dump_entries6(struct xtc_handle *const);
|
||||
|
||||
extern const struct xtc_ops ip6tc_ops;
|
||||
|
||||
#endif /* _LIBIP6TC_H */
|
||||
|
||||
@ -2,155 +2,157 @@
|
||||
#define _LIBIPTC_H
|
||||
/* Library which manipulates filtering rules. */
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <libiptc/ipt_kernel_headers.h>
|
||||
#ifdef __cplusplus
|
||||
# include <climits>
|
||||
#else
|
||||
# include <limits.h> /* INT_MAX in ip_tables.h */
|
||||
#endif
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#include <libiptc/xtcshared.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef IPT_MIN_ALIGN
|
||||
/* ipt_entry has pointers and u_int64_t's in it, so if you align to
|
||||
it, you'll also align to any crazy matches and targets someone
|
||||
might write */
|
||||
#define IPT_MIN_ALIGN (__alignof__(struct ipt_entry))
|
||||
#endif
|
||||
|
||||
#define IPT_ALIGN(s) (((s) + ((IPT_MIN_ALIGN)-1)) & ~((IPT_MIN_ALIGN)-1))
|
||||
|
||||
typedef char ipt_chainlabel[32];
|
||||
#define iptc_handle xtc_handle
|
||||
#define ipt_chainlabel xt_chainlabel
|
||||
|
||||
#define IPTC_LABEL_ACCEPT "ACCEPT"
|
||||
#define IPTC_LABEL_DROP "DROP"
|
||||
#define IPTC_LABEL_QUEUE "QUEUE"
|
||||
#define IPTC_LABEL_RETURN "RETURN"
|
||||
|
||||
/* Transparent handle type. */
|
||||
typedef struct iptc_handle *iptc_handle_t;
|
||||
|
||||
/* Does this chain exist? */
|
||||
int iptc_is_chain(const char *chain, const iptc_handle_t handle);
|
||||
int iptc_is_chain(const char *chain, struct xtc_handle *const handle);
|
||||
|
||||
/* Take a snapshot of the rules. Returns NULL on error. */
|
||||
iptc_handle_t iptc_init(const char *tablename);
|
||||
struct xtc_handle *iptc_init(const char *tablename);
|
||||
|
||||
/* Cleanup after iptc_init(). */
|
||||
void iptc_free(iptc_handle_t *h);
|
||||
void iptc_free(struct xtc_handle *h);
|
||||
|
||||
/* Iterator functions to run through the chains. Returns NULL at end. */
|
||||
const char *iptc_first_chain(iptc_handle_t *handle);
|
||||
const char *iptc_next_chain(iptc_handle_t *handle);
|
||||
const char *iptc_first_chain(struct xtc_handle *handle);
|
||||
const char *iptc_next_chain(struct xtc_handle *handle);
|
||||
|
||||
/* Get first rule in the given chain: NULL for empty chain. */
|
||||
const struct ipt_entry *iptc_first_rule(const char *chain,
|
||||
iptc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Returns NULL when rules run out. */
|
||||
const struct ipt_entry *iptc_next_rule(const struct ipt_entry *prev,
|
||||
iptc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Returns a pointer to the target name of this entry. */
|
||||
const char *iptc_get_target(const struct ipt_entry *e,
|
||||
iptc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Is this a built-in chain? */
|
||||
int iptc_builtin(const char *chain, const iptc_handle_t handle);
|
||||
int iptc_builtin(const char *chain, struct xtc_handle *const handle);
|
||||
|
||||
/* Get the policy of a given built-in chain */
|
||||
const char *iptc_get_policy(const char *chain,
|
||||
struct ipt_counters *counter,
|
||||
iptc_handle_t *handle);
|
||||
struct xt_counters *counter,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* These functions return TRUE for OK or 0 and set errno. If errno ==
|
||||
0, it means there was a version error (ie. upgrade libiptc). */
|
||||
/* Rule numbers start at 1 for the first rule. */
|
||||
|
||||
/* Insert the entry `e' in chain `chain' into position `rulenum'. */
|
||||
int iptc_insert_entry(const ipt_chainlabel chain,
|
||||
int iptc_insert_entry(const xt_chainlabel chain,
|
||||
const struct ipt_entry *e,
|
||||
unsigned int rulenum,
|
||||
iptc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Atomically replace rule `rulenum' in `chain' with `e'. */
|
||||
int iptc_replace_entry(const ipt_chainlabel chain,
|
||||
int iptc_replace_entry(const xt_chainlabel chain,
|
||||
const struct ipt_entry *e,
|
||||
unsigned int rulenum,
|
||||
iptc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Append entry `e' to chain `chain'. Equivalent to insert with
|
||||
rulenum = length of chain. */
|
||||
int iptc_append_entry(const ipt_chainlabel chain,
|
||||
int iptc_append_entry(const xt_chainlabel chain,
|
||||
const struct ipt_entry *e,
|
||||
iptc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Check whether a mathching rule exists */
|
||||
int iptc_check_entry(const xt_chainlabel chain,
|
||||
const struct ipt_entry *origfw,
|
||||
unsigned char *matchmask,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Delete the first rule in `chain' which matches `e', subject to
|
||||
matchmask (array of length == origfw) */
|
||||
int iptc_delete_entry(const ipt_chainlabel chain,
|
||||
int iptc_delete_entry(const xt_chainlabel chain,
|
||||
const struct ipt_entry *origfw,
|
||||
unsigned char *matchmask,
|
||||
iptc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Delete the rule in position `rulenum' in `chain'. */
|
||||
int iptc_delete_num_entry(const ipt_chainlabel chain,
|
||||
int iptc_delete_num_entry(const xt_chainlabel chain,
|
||||
unsigned int rulenum,
|
||||
iptc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Check the packet `e' on chain `chain'. Returns the verdict, or
|
||||
NULL and sets errno. */
|
||||
const char *iptc_check_packet(const ipt_chainlabel chain,
|
||||
const char *iptc_check_packet(const xt_chainlabel chain,
|
||||
struct ipt_entry *entry,
|
||||
iptc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Flushes the entries in the given chain (ie. empties chain). */
|
||||
int iptc_flush_entries(const ipt_chainlabel chain,
|
||||
iptc_handle_t *handle);
|
||||
int iptc_flush_entries(const xt_chainlabel chain,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Zeroes the counters in a chain. */
|
||||
int iptc_zero_entries(const ipt_chainlabel chain,
|
||||
iptc_handle_t *handle);
|
||||
int iptc_zero_entries(const xt_chainlabel chain,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Creates a new chain. */
|
||||
int iptc_create_chain(const ipt_chainlabel chain,
|
||||
iptc_handle_t *handle);
|
||||
int iptc_create_chain(const xt_chainlabel chain,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Deletes a chain. */
|
||||
int iptc_delete_chain(const ipt_chainlabel chain,
|
||||
iptc_handle_t *handle);
|
||||
int iptc_delete_chain(const xt_chainlabel chain,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Renames a chain. */
|
||||
int iptc_rename_chain(const ipt_chainlabel oldname,
|
||||
const ipt_chainlabel newname,
|
||||
iptc_handle_t *handle);
|
||||
int iptc_rename_chain(const xt_chainlabel oldname,
|
||||
const xt_chainlabel newname,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Sets the policy on a built-in chain. */
|
||||
int iptc_set_policy(const ipt_chainlabel chain,
|
||||
const ipt_chainlabel policy,
|
||||
struct ipt_counters *counters,
|
||||
iptc_handle_t *handle);
|
||||
int iptc_set_policy(const xt_chainlabel chain,
|
||||
const xt_chainlabel policy,
|
||||
struct xt_counters *counters,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Get the number of references to this chain */
|
||||
int iptc_get_references(unsigned int *ref,
|
||||
const ipt_chainlabel chain,
|
||||
iptc_handle_t *handle);
|
||||
const xt_chainlabel chain,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* read packet and byte counters for a specific rule */
|
||||
struct ipt_counters *iptc_read_counter(const ipt_chainlabel chain,
|
||||
struct xt_counters *iptc_read_counter(const xt_chainlabel chain,
|
||||
unsigned int rulenum,
|
||||
iptc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* zero packet and byte counters for a specific rule */
|
||||
int iptc_zero_counter(const ipt_chainlabel chain,
|
||||
int iptc_zero_counter(const xt_chainlabel chain,
|
||||
unsigned int rulenum,
|
||||
iptc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* set packet and byte counters for a specific rule */
|
||||
int iptc_set_counter(const ipt_chainlabel chain,
|
||||
int iptc_set_counter(const xt_chainlabel chain,
|
||||
unsigned int rulenum,
|
||||
struct ipt_counters *counters,
|
||||
iptc_handle_t *handle);
|
||||
struct xt_counters *counters,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Makes the actual changes. */
|
||||
int iptc_commit(iptc_handle_t *handle);
|
||||
int iptc_commit(struct xtc_handle *handle);
|
||||
|
||||
/* Get raw socket. */
|
||||
int iptc_get_raw_socket(void);
|
||||
@ -158,6 +160,10 @@ int iptc_get_raw_socket(void);
|
||||
/* Translates errno numbers into more human-readable form than strerror. */
|
||||
const char *iptc_strerror(int err);
|
||||
|
||||
extern void dump_entries(struct xtc_handle *const);
|
||||
|
||||
extern const struct xtc_ops iptc_ops;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
33
include/libiptc/libxtc.h
Normal file
33
include/libiptc/libxtc.h
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef _LIBXTC_H
|
||||
#define _LIBXTC_H
|
||||
/* Library which manipulates filtering rules. */
|
||||
|
||||
#include <libiptc/ipt_kernel_headers.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef XT_MIN_ALIGN
|
||||
/* xt_entry has pointers and u_int64_t's in it, so if you align to
|
||||
it, you'll also align to any crazy matches and targets someone
|
||||
might write */
|
||||
#define XT_MIN_ALIGN (__alignof__(struct xt_entry))
|
||||
#endif
|
||||
|
||||
#ifndef XT_ALIGN
|
||||
#define XT_ALIGN(s) (((s) + ((XT_MIN_ALIGN)-1)) & ~((XT_MIN_ALIGN)-1))
|
||||
#endif
|
||||
|
||||
#define XTC_LABEL_ACCEPT "ACCEPT"
|
||||
#define XTC_LABEL_DROP "DROP"
|
||||
#define XTC_LABEL_QUEUE "QUEUE"
|
||||
#define XTC_LABEL_RETURN "RETURN"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LIBXTC_H */
|
||||
20
include/libiptc/xtcshared.h
Normal file
20
include/libiptc/xtcshared.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef _LIBXTC_SHARED_H
|
||||
#define _LIBXTC_SHARED_H 1
|
||||
|
||||
typedef char xt_chainlabel[32];
|
||||
struct xtc_handle;
|
||||
struct xt_counters;
|
||||
|
||||
struct xtc_ops {
|
||||
int (*commit)(struct xtc_handle *);
|
||||
void (*free)(struct xtc_handle *);
|
||||
int (*builtin)(const char *, struct xtc_handle *const);
|
||||
int (*is_chain)(const char *, struct xtc_handle *const);
|
||||
int (*flush_entries)(const xt_chainlabel, struct xtc_handle *);
|
||||
int (*create_chain)(const xt_chainlabel, struct xtc_handle *);
|
||||
int (*set_policy)(const xt_chainlabel, const xt_chainlabel,
|
||||
struct xt_counters *, struct xtc_handle *);
|
||||
const char *(*strerror)(int);
|
||||
};
|
||||
|
||||
#endif /* _LIBXTC_SHARED_H */
|
||||
@ -269,6 +269,7 @@ enum bpf_func_id {
|
||||
* Return: 0 on success
|
||||
*/
|
||||
BPF_FUNC_perf_event_output,
|
||||
BPF_FUNC_skb_load_bytes,
|
||||
__BPF_FUNC_MAX_ID,
|
||||
};
|
||||
|
||||
|
||||
@ -216,6 +216,7 @@ enum in6_addr_gen_mode {
|
||||
IN6_ADDR_GEN_MODE_EUI64,
|
||||
IN6_ADDR_GEN_MODE_NONE,
|
||||
IN6_ADDR_GEN_MODE_STABLE_PRIVACY,
|
||||
IN6_ADDR_GEN_MODE_RANDOM,
|
||||
};
|
||||
|
||||
/* Bridge section */
|
||||
@ -460,6 +461,9 @@ enum {
|
||||
IFLA_GENEVE_PORT, /* destination port */
|
||||
IFLA_GENEVE_COLLECT_METADATA,
|
||||
IFLA_GENEVE_REMOTE6,
|
||||
IFLA_GENEVE_UDP_CSUM,
|
||||
IFLA_GENEVE_UDP_ZERO_CSUM6_TX,
|
||||
IFLA_GENEVE_UDP_ZERO_CSUM6_RX,
|
||||
__IFLA_GENEVE_MAX
|
||||
};
|
||||
#define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1)
|
||||
|
||||
@ -3,13 +3,35 @@
|
||||
#ifndef _LINUX_ILA_H
|
||||
#define _LINUX_ILA_H
|
||||
|
||||
/* NETLINK_GENERIC related info */
|
||||
#define ILA_GENL_NAME "ila"
|
||||
#define ILA_GENL_VERSION 0x1
|
||||
|
||||
enum {
|
||||
ILA_ATTR_UNSPEC,
|
||||
ILA_ATTR_LOCATOR, /* u64 */
|
||||
ILA_ATTR_IDENTIFIER, /* u64 */
|
||||
ILA_ATTR_LOCATOR_MATCH, /* u64 */
|
||||
ILA_ATTR_IFINDEX, /* s32 */
|
||||
ILA_ATTR_DIR, /* u32 */
|
||||
|
||||
__ILA_ATTR_MAX,
|
||||
};
|
||||
|
||||
#define ILA_ATTR_MAX (__ILA_ATTR_MAX - 1)
|
||||
|
||||
enum {
|
||||
ILA_CMD_UNSPEC,
|
||||
ILA_CMD_ADD,
|
||||
ILA_CMD_DEL,
|
||||
ILA_CMD_GET,
|
||||
|
||||
__ILA_CMD_MAX,
|
||||
};
|
||||
|
||||
#define ILA_CMD_MAX (__ILA_CMD_MAX - 1)
|
||||
|
||||
#define ILA_DIR_IN (1 << 0)
|
||||
#define ILA_DIR_OUT (1 << 1)
|
||||
|
||||
#endif /* _LINUX_ILA_H */
|
||||
|
||||
@ -196,6 +196,7 @@ struct in6_flowlabel_req {
|
||||
|
||||
#define IPV6_IPSEC_POLICY 34
|
||||
#define IPV6_XFRM_POLICY 35
|
||||
#define IPV6_HDRINCL 36
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
@ -311,6 +311,7 @@ enum rtattr_type_t {
|
||||
RTA_PREF,
|
||||
RTA_ENCAP_TYPE,
|
||||
RTA_ENCAP,
|
||||
RTA_EXPIRES,
|
||||
__RTA_MAX
|
||||
};
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
#include <linux/types.h>
|
||||
|
||||
#define SOCK_DIAG_BY_FAMILY 20
|
||||
#define SOCK_DESTROY 21
|
||||
|
||||
struct sock_diag_req {
|
||||
__u8 sdiag_family;
|
||||
|
||||
@ -56,6 +56,7 @@ enum {
|
||||
TIPC_NL_NET_GET,
|
||||
TIPC_NL_NET_SET,
|
||||
TIPC_NL_NAME_TABLE_GET,
|
||||
TIPC_NL_PEER_REMOVE,
|
||||
|
||||
__TIPC_NL_CMD_MAX,
|
||||
TIPC_NL_CMD_MAX = __TIPC_NL_CMD_MAX - 1
|
||||
|
||||
@ -40,6 +40,10 @@ extern bool do_all;
|
||||
#define IPSEC_PROTO_ANY 255
|
||||
#endif
|
||||
|
||||
#ifndef CONFDIR
|
||||
#define CONFDIR "/etc/iproute2"
|
||||
#endif
|
||||
|
||||
#define SPRINT_BSIZE 64
|
||||
#define SPRINT_BUF(x) char x[SPRINT_BSIZE]
|
||||
|
||||
@ -196,6 +200,9 @@ void print_nlmsg_timestamp(FILE *fp, const struct nlmsghdr *n);
|
||||
__attribute__ ((format (printf, (pos_str), (pos_args))))
|
||||
#endif
|
||||
|
||||
#define _textify(x) #x
|
||||
#define textify(x) _textify(x)
|
||||
|
||||
#define htonll(x) ((1==htonl(1)) ? (x) : ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
|
||||
#define ntohll(x) ((1==ntohl(1)) ? (x) : ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))
|
||||
|
||||
|
||||
567
include/xtables.h
Normal file
567
include/xtables.h
Normal file
@ -0,0 +1,567 @@
|
||||
#ifndef _XTABLES_H
|
||||
#define _XTABLES_H
|
||||
|
||||
/*
|
||||
* Changing any structs/functions may incur a needed change
|
||||
* in libxtables_vcurrent/vage too.
|
||||
*/
|
||||
|
||||
#include <sys/socket.h> /* PF_* */
|
||||
#include <sys/types.h>
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <netinet/in.h>
|
||||
#include <net/if.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
|
||||
#ifndef IPPROTO_SCTP
|
||||
#define IPPROTO_SCTP 132
|
||||
#endif
|
||||
#ifndef IPPROTO_DCCP
|
||||
#define IPPROTO_DCCP 33
|
||||
#endif
|
||||
#ifndef IPPROTO_MH
|
||||
# define IPPROTO_MH 135
|
||||
#endif
|
||||
#ifndef IPPROTO_UDPLITE
|
||||
#define IPPROTO_UDPLITE 136
|
||||
#endif
|
||||
|
||||
#include <xtables-version.h>
|
||||
|
||||
struct in_addr;
|
||||
|
||||
/*
|
||||
* .size is here so that there is a somewhat reasonable check
|
||||
* against the chosen .type.
|
||||
*/
|
||||
#define XTOPT_POINTER(stype, member) \
|
||||
.ptroff = offsetof(stype, member), \
|
||||
.size = sizeof(((stype *)NULL)->member)
|
||||
#define XTOPT_TABLEEND {.name = NULL}
|
||||
|
||||
/**
|
||||
* Select the format the input has to conform to, as well as the target type
|
||||
* (area pointed to with XTOPT_POINTER). Note that the storing is not always
|
||||
* uniform. @cb->val will be populated with as much as there is space, i.e.
|
||||
* exactly 2 items for ranges, but the target area can receive more values
|
||||
* (e.g. in case of ranges), or less values (e.g. %XTTYPE_HOSTMASK).
|
||||
*
|
||||
* %XTTYPE_NONE: option takes no argument
|
||||
* %XTTYPE_UINT*: standard integer
|
||||
* %XTTYPE_UINT*RC: colon-separated range of standard integers
|
||||
* %XTTYPE_DOUBLE: double-precision floating point number
|
||||
* %XTTYPE_STRING: arbitrary string
|
||||
* %XTTYPE_TOSMASK: 8-bit TOS value with optional mask
|
||||
* %XTTYPE_MARKMASK32: 32-bit mark with optional mask
|
||||
* %XTTYPE_SYSLOGLEVEL: syslog level by name or number
|
||||
* %XTTYPE_HOST: one host or address (ptr: union nf_inet_addr)
|
||||
* %XTTYPE_HOSTMASK: one host or address, with an optional prefix length
|
||||
* (ptr: union nf_inet_addr; only host portion is stored)
|
||||
* %XTTYPE_PROTOCOL: protocol number/name from /etc/protocols (ptr: uint8_t)
|
||||
* %XTTYPE_PORT: 16-bit port name or number (supports %XTOPT_NBO)
|
||||
* %XTTYPE_PORTRC: colon-separated port range (names acceptable),
|
||||
* (supports %XTOPT_NBO)
|
||||
* %XTTYPE_PLEN: prefix length
|
||||
* %XTTYPE_PLENMASK: prefix length (ptr: union nf_inet_addr)
|
||||
* %XTTYPE_ETHERMAC: Ethernet MAC address in hex form
|
||||
*/
|
||||
enum xt_option_type {
|
||||
XTTYPE_NONE,
|
||||
XTTYPE_UINT8,
|
||||
XTTYPE_UINT16,
|
||||
XTTYPE_UINT32,
|
||||
XTTYPE_UINT64,
|
||||
XTTYPE_UINT8RC,
|
||||
XTTYPE_UINT16RC,
|
||||
XTTYPE_UINT32RC,
|
||||
XTTYPE_UINT64RC,
|
||||
XTTYPE_DOUBLE,
|
||||
XTTYPE_STRING,
|
||||
XTTYPE_TOSMASK,
|
||||
XTTYPE_MARKMASK32,
|
||||
XTTYPE_SYSLOGLEVEL,
|
||||
XTTYPE_HOST,
|
||||
XTTYPE_HOSTMASK,
|
||||
XTTYPE_PROTOCOL,
|
||||
XTTYPE_PORT,
|
||||
XTTYPE_PORTRC,
|
||||
XTTYPE_PLEN,
|
||||
XTTYPE_PLENMASK,
|
||||
XTTYPE_ETHERMAC,
|
||||
};
|
||||
|
||||
/**
|
||||
* %XTOPT_INVERT: option is invertible (usable with !)
|
||||
* %XTOPT_MAND: option is mandatory
|
||||
* %XTOPT_MULTI: option may be specified multiple times
|
||||
* %XTOPT_PUT: store value into memory at @ptroff
|
||||
* %XTOPT_NBO: store value in network-byte order
|
||||
* (only certain XTTYPEs recognize this)
|
||||
*/
|
||||
enum xt_option_flags {
|
||||
XTOPT_INVERT = 1 << 0,
|
||||
XTOPT_MAND = 1 << 1,
|
||||
XTOPT_MULTI = 1 << 2,
|
||||
XTOPT_PUT = 1 << 3,
|
||||
XTOPT_NBO = 1 << 4,
|
||||
};
|
||||
|
||||
/**
|
||||
* @name: name of option
|
||||
* @type: type of input and validation method, see %XTTYPE_*
|
||||
* @id: unique number (within extension) for option, 0-31
|
||||
* @excl: bitmask of flags that cannot be used with this option
|
||||
* @also: bitmask of flags that must be used with this option
|
||||
* @flags: bitmask of option flags, see %XTOPT_*
|
||||
* @ptroff: offset into private structure for member
|
||||
* @size: size of the item pointed to by @ptroff; this is a safeguard
|
||||
* @min: lowest allowed value (for singular integral types)
|
||||
* @max: highest allowed value (for singular integral types)
|
||||
*/
|
||||
struct xt_option_entry {
|
||||
const char *name;
|
||||
enum xt_option_type type;
|
||||
unsigned int id, excl, also, flags;
|
||||
unsigned int ptroff;
|
||||
size_t size;
|
||||
unsigned int min, max;
|
||||
};
|
||||
|
||||
/**
|
||||
* @arg: input from command line
|
||||
* @ext_name: name of extension currently being processed
|
||||
* @entry: current option being processed
|
||||
* @data: per-extension kernel data block
|
||||
* @xflags: options of the extension that have been used
|
||||
* @invert: whether option was used with !
|
||||
* @nvals: number of results in uXX_multi
|
||||
* @val: parsed result
|
||||
* @udata: per-extension private scratch area
|
||||
* (cf. xtables_{match,target}->udata_size)
|
||||
*/
|
||||
struct xt_option_call {
|
||||
const char *arg, *ext_name;
|
||||
const struct xt_option_entry *entry;
|
||||
void *data;
|
||||
unsigned int xflags;
|
||||
bool invert;
|
||||
uint8_t nvals;
|
||||
union {
|
||||
uint8_t u8, u8_range[2], syslog_level, protocol;
|
||||
uint16_t u16, u16_range[2], port, port_range[2];
|
||||
uint32_t u32, u32_range[2];
|
||||
uint64_t u64, u64_range[2];
|
||||
double dbl;
|
||||
struct {
|
||||
union nf_inet_addr haddr, hmask;
|
||||
uint8_t hlen;
|
||||
};
|
||||
struct {
|
||||
uint8_t tos_value, tos_mask;
|
||||
};
|
||||
struct {
|
||||
uint32_t mark, mask;
|
||||
};
|
||||
uint8_t ethermac[6];
|
||||
} val;
|
||||
/* Wished for a world where the ones below were gone: */
|
||||
union {
|
||||
struct xt_entry_match **match;
|
||||
struct xt_entry_target **target;
|
||||
};
|
||||
void *xt_entry;
|
||||
void *udata;
|
||||
};
|
||||
|
||||
/**
|
||||
* @ext_name: name of extension currently being processed
|
||||
* @data: per-extension (kernel) data block
|
||||
* @udata: per-extension private scratch area
|
||||
* (cf. xtables_{match,target}->udata_size)
|
||||
* @xflags: options of the extension that have been used
|
||||
*/
|
||||
struct xt_fcheck_call {
|
||||
const char *ext_name;
|
||||
void *data, *udata;
|
||||
unsigned int xflags;
|
||||
};
|
||||
|
||||
/**
|
||||
* A "linear"/linked-list based name<->id map, for files similar to
|
||||
* /etc/iproute2/.
|
||||
*/
|
||||
struct xtables_lmap {
|
||||
char *name;
|
||||
int id;
|
||||
struct xtables_lmap *next;
|
||||
};
|
||||
|
||||
enum xtables_ext_flags {
|
||||
XTABLES_EXT_ALIAS = 1 << 0,
|
||||
};
|
||||
|
||||
/* Include file for additions: new matches and targets. */
|
||||
struct xtables_match
|
||||
{
|
||||
/*
|
||||
* ABI/API version this module requires. Must be first member,
|
||||
* as the rest of this struct may be subject to ABI changes.
|
||||
*/
|
||||
const char *version;
|
||||
|
||||
struct xtables_match *next;
|
||||
|
||||
const char *name;
|
||||
const char *real_name;
|
||||
|
||||
/* Revision of match (0 by default). */
|
||||
uint8_t revision;
|
||||
|
||||
/* Extension flags */
|
||||
uint8_t ext_flags;
|
||||
|
||||
uint16_t family;
|
||||
|
||||
/* Size of match data. */
|
||||
size_t size;
|
||||
|
||||
/* Size of match data relevant for userspace comparison purposes */
|
||||
size_t userspacesize;
|
||||
|
||||
/* Function which prints out usage message. */
|
||||
void (*help)(void);
|
||||
|
||||
/* Initialize the match. */
|
||||
void (*init)(struct xt_entry_match *m);
|
||||
|
||||
/* Function which parses command options; returns true if it
|
||||
ate an option */
|
||||
/* entry is struct ipt_entry for example */
|
||||
int (*parse)(int c, char **argv, int invert, unsigned int *flags,
|
||||
const void *entry,
|
||||
struct xt_entry_match **match);
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
void (*final_check)(unsigned int flags);
|
||||
|
||||
/* Prints out the match iff non-NULL: put space at end */
|
||||
/* ip is struct ipt_ip * for example */
|
||||
void (*print)(const void *ip,
|
||||
const struct xt_entry_match *match, int numeric);
|
||||
|
||||
/* Saves the match info in parsable form to stdout. */
|
||||
/* ip is struct ipt_ip * for example */
|
||||
void (*save)(const void *ip, const struct xt_entry_match *match);
|
||||
|
||||
/* Print match name or alias */
|
||||
const char *(*alias)(const struct xt_entry_match *match);
|
||||
|
||||
/* Pointer to list of extra command-line options */
|
||||
const struct option *extra_opts;
|
||||
|
||||
/* New parser */
|
||||
void (*x6_parse)(struct xt_option_call *);
|
||||
void (*x6_fcheck)(struct xt_fcheck_call *);
|
||||
const struct xt_option_entry *x6_options;
|
||||
|
||||
/* Size of per-extension instance extra "global" scratch space */
|
||||
size_t udata_size;
|
||||
|
||||
/* Ignore these men behind the curtain: */
|
||||
void *udata;
|
||||
unsigned int option_offset;
|
||||
struct xt_entry_match *m;
|
||||
unsigned int mflags;
|
||||
unsigned int loaded; /* simulate loading so options are merged properly */
|
||||
};
|
||||
|
||||
struct xtables_target
|
||||
{
|
||||
/*
|
||||
* ABI/API version this module requires. Must be first member,
|
||||
* as the rest of this struct may be subject to ABI changes.
|
||||
*/
|
||||
const char *version;
|
||||
|
||||
struct xtables_target *next;
|
||||
|
||||
|
||||
const char *name;
|
||||
|
||||
/* Real target behind this, if any. */
|
||||
const char *real_name;
|
||||
|
||||
/* Revision of target (0 by default). */
|
||||
uint8_t revision;
|
||||
|
||||
/* Extension flags */
|
||||
uint8_t ext_flags;
|
||||
|
||||
uint16_t family;
|
||||
|
||||
|
||||
/* Size of target data. */
|
||||
size_t size;
|
||||
|
||||
/* Size of target data relevant for userspace comparison purposes */
|
||||
size_t userspacesize;
|
||||
|
||||
/* Function which prints out usage message. */
|
||||
void (*help)(void);
|
||||
|
||||
/* Initialize the target. */
|
||||
void (*init)(struct xt_entry_target *t);
|
||||
|
||||
/* Function which parses command options; returns true if it
|
||||
ate an option */
|
||||
/* entry is struct ipt_entry for example */
|
||||
int (*parse)(int c, char **argv, int invert, unsigned int *flags,
|
||||
const void *entry,
|
||||
struct xt_entry_target **targetinfo);
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
void (*final_check)(unsigned int flags);
|
||||
|
||||
/* Prints out the target iff non-NULL: put space at end */
|
||||
void (*print)(const void *ip,
|
||||
const struct xt_entry_target *target, int numeric);
|
||||
|
||||
/* Saves the targinfo in parsable form to stdout. */
|
||||
void (*save)(const void *ip,
|
||||
const struct xt_entry_target *target);
|
||||
|
||||
/* Print target name or alias */
|
||||
const char *(*alias)(const struct xt_entry_target *target);
|
||||
|
||||
/* Pointer to list of extra command-line options */
|
||||
const struct option *extra_opts;
|
||||
|
||||
/* New parser */
|
||||
void (*x6_parse)(struct xt_option_call *);
|
||||
void (*x6_fcheck)(struct xt_fcheck_call *);
|
||||
const struct xt_option_entry *x6_options;
|
||||
|
||||
size_t udata_size;
|
||||
|
||||
/* Ignore these men behind the curtain: */
|
||||
void *udata;
|
||||
unsigned int option_offset;
|
||||
struct xt_entry_target *t;
|
||||
unsigned int tflags;
|
||||
unsigned int used;
|
||||
unsigned int loaded; /* simulate loading so options are merged properly */
|
||||
};
|
||||
|
||||
struct xtables_rule_match {
|
||||
struct xtables_rule_match *next;
|
||||
struct xtables_match *match;
|
||||
/* Multiple matches of the same type: the ones before
|
||||
the current one are completed from parsing point of view */
|
||||
bool completed;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct xtables_pprot -
|
||||
*
|
||||
* A few hardcoded protocols for 'all' and in case the user has no
|
||||
* /etc/protocols.
|
||||
*/
|
||||
struct xtables_pprot {
|
||||
const char *name;
|
||||
uint8_t num;
|
||||
};
|
||||
|
||||
enum xtables_tryload {
|
||||
XTF_DONT_LOAD,
|
||||
XTF_DURING_LOAD,
|
||||
XTF_TRY_LOAD,
|
||||
XTF_LOAD_MUST_SUCCEED,
|
||||
};
|
||||
|
||||
enum xtables_exittype {
|
||||
OTHER_PROBLEM = 1,
|
||||
PARAMETER_PROBLEM,
|
||||
VERSION_PROBLEM,
|
||||
RESOURCE_PROBLEM,
|
||||
XTF_ONLY_ONCE,
|
||||
XTF_NO_INVERT,
|
||||
XTF_BAD_VALUE,
|
||||
XTF_ONE_ACTION,
|
||||
};
|
||||
|
||||
struct xtables_globals
|
||||
{
|
||||
unsigned int option_offset;
|
||||
const char *program_name, *program_version;
|
||||
struct option *orig_opts;
|
||||
struct option *opts;
|
||||
void (*exit_err)(enum xtables_exittype status, const char *msg, ...) __attribute__((noreturn, format(printf,2,3)));
|
||||
int (*compat_rev)(const char *name, uint8_t rev, int opt);
|
||||
};
|
||||
|
||||
#define XT_GETOPT_TABLEEND {.name = NULL, .has_arg = false}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern const char *xtables_modprobe_program;
|
||||
extern struct xtables_match *xtables_matches;
|
||||
extern struct xtables_target *xtables_targets;
|
||||
|
||||
extern void xtables_init(void);
|
||||
extern void xtables_set_nfproto(uint8_t);
|
||||
extern void *xtables_calloc(size_t, size_t);
|
||||
extern void *xtables_malloc(size_t);
|
||||
extern void *xtables_realloc(void *, size_t);
|
||||
|
||||
extern int xtables_insmod(const char *, const char *, bool);
|
||||
extern int xtables_load_ko(const char *, bool);
|
||||
extern int xtables_set_params(struct xtables_globals *xtp);
|
||||
extern void xtables_free_opts(int reset_offset);
|
||||
extern struct option *xtables_merge_options(struct option *origopts,
|
||||
struct option *oldopts, const struct option *newopts,
|
||||
unsigned int *option_offset);
|
||||
|
||||
extern int xtables_init_all(struct xtables_globals *xtp, uint8_t nfproto);
|
||||
extern struct xtables_match *xtables_find_match(const char *name,
|
||||
enum xtables_tryload, struct xtables_rule_match **match);
|
||||
extern struct xtables_target *xtables_find_target(const char *name,
|
||||
enum xtables_tryload);
|
||||
extern int xtables_compatible_revision(const char *name, uint8_t revision,
|
||||
int opt);
|
||||
|
||||
extern void xtables_rule_matches_free(struct xtables_rule_match **matches);
|
||||
|
||||
/* Your shared library should call one of these. */
|
||||
extern void xtables_register_match(struct xtables_match *me);
|
||||
extern void xtables_register_matches(struct xtables_match *, unsigned int);
|
||||
extern void xtables_register_target(struct xtables_target *me);
|
||||
extern void xtables_register_targets(struct xtables_target *, unsigned int);
|
||||
|
||||
extern bool xtables_strtoul(const char *, char **, uintmax_t *,
|
||||
uintmax_t, uintmax_t);
|
||||
extern bool xtables_strtoui(const char *, char **, unsigned int *,
|
||||
unsigned int, unsigned int);
|
||||
extern int xtables_service_to_port(const char *name, const char *proto);
|
||||
extern uint16_t xtables_parse_port(const char *port, const char *proto);
|
||||
extern void
|
||||
xtables_parse_interface(const char *arg, char *vianame, unsigned char *mask);
|
||||
|
||||
/* this is a special 64bit data type that is 8-byte aligned */
|
||||
#define aligned_u64 uint64_t __attribute__((aligned(8)))
|
||||
|
||||
extern struct xtables_globals *xt_params;
|
||||
#define xtables_error (xt_params->exit_err)
|
||||
|
||||
extern void xtables_param_act(unsigned int, const char *, ...);
|
||||
|
||||
extern const char *xtables_ipaddr_to_numeric(const struct in_addr *);
|
||||
extern const char *xtables_ipaddr_to_anyname(const struct in_addr *);
|
||||
extern const char *xtables_ipmask_to_numeric(const struct in_addr *);
|
||||
extern struct in_addr *xtables_numeric_to_ipaddr(const char *);
|
||||
extern struct in_addr *xtables_numeric_to_ipmask(const char *);
|
||||
extern int xtables_ipmask_to_cidr(const struct in_addr *);
|
||||
extern void xtables_ipparse_any(const char *, struct in_addr **,
|
||||
struct in_addr *, unsigned int *);
|
||||
extern void xtables_ipparse_multiple(const char *, struct in_addr **,
|
||||
struct in_addr **, unsigned int *);
|
||||
|
||||
extern struct in6_addr *xtables_numeric_to_ip6addr(const char *);
|
||||
extern const char *xtables_ip6addr_to_numeric(const struct in6_addr *);
|
||||
extern const char *xtables_ip6addr_to_anyname(const struct in6_addr *);
|
||||
extern const char *xtables_ip6mask_to_numeric(const struct in6_addr *);
|
||||
extern int xtables_ip6mask_to_cidr(const struct in6_addr *);
|
||||
extern void xtables_ip6parse_any(const char *, struct in6_addr **,
|
||||
struct in6_addr *, unsigned int *);
|
||||
extern void xtables_ip6parse_multiple(const char *, struct in6_addr **,
|
||||
struct in6_addr **, unsigned int *);
|
||||
|
||||
/**
|
||||
* Print the specified value to standard output, quoting dangerous
|
||||
* characters if required.
|
||||
*/
|
||||
extern void xtables_save_string(const char *value);
|
||||
|
||||
#define FMT_NUMERIC 0x0001
|
||||
#define FMT_NOCOUNTS 0x0002
|
||||
#define FMT_KILOMEGAGIGA 0x0004
|
||||
#define FMT_OPTIONS 0x0008
|
||||
#define FMT_NOTABLE 0x0010
|
||||
#define FMT_NOTARGET 0x0020
|
||||
#define FMT_VIA 0x0040
|
||||
#define FMT_NONEWLINE 0x0080
|
||||
#define FMT_LINENUMBERS 0x0100
|
||||
|
||||
#define FMT_PRINT_RULE (FMT_NOCOUNTS | FMT_OPTIONS | FMT_VIA \
|
||||
| FMT_NUMERIC | FMT_NOTABLE)
|
||||
#define FMT(tab,notab) ((format) & FMT_NOTABLE ? (notab) : (tab))
|
||||
|
||||
extern void xtables_print_num(uint64_t number, unsigned int format);
|
||||
|
||||
#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
|
||||
# ifdef _INIT
|
||||
# undef _init
|
||||
# define _init _INIT
|
||||
# endif
|
||||
extern void init_extensions(void);
|
||||
extern void init_extensions4(void);
|
||||
extern void init_extensions6(void);
|
||||
#else
|
||||
# define _init __attribute__((constructor)) _INIT
|
||||
#endif
|
||||
|
||||
extern const struct xtables_pprot xtables_chain_protos[];
|
||||
extern uint16_t xtables_parse_protocol(const char *s);
|
||||
|
||||
/* kernel revision handling */
|
||||
extern int kernel_version;
|
||||
extern void get_kernel_version(void);
|
||||
#define LINUX_VERSION(x,y,z) (0x10000*(x) + 0x100*(y) + z)
|
||||
#define LINUX_VERSION_MAJOR(x) (((x)>>16) & 0xFF)
|
||||
#define LINUX_VERSION_MINOR(x) (((x)>> 8) & 0xFF)
|
||||
#define LINUX_VERSION_PATCH(x) ( (x) & 0xFF)
|
||||
|
||||
/* xtoptions.c */
|
||||
extern void xtables_option_metavalidate(const char *,
|
||||
const struct xt_option_entry *);
|
||||
extern struct option *xtables_options_xfrm(struct option *, struct option *,
|
||||
const struct xt_option_entry *,
|
||||
unsigned int *);
|
||||
extern void xtables_option_parse(struct xt_option_call *);
|
||||
extern void xtables_option_tpcall(unsigned int, char **, bool,
|
||||
struct xtables_target *, void *);
|
||||
extern void xtables_option_mpcall(unsigned int, char **, bool,
|
||||
struct xtables_match *, void *);
|
||||
extern void xtables_option_tfcall(struct xtables_target *);
|
||||
extern void xtables_option_mfcall(struct xtables_match *);
|
||||
extern void xtables_options_fcheck(const char *, unsigned int,
|
||||
const struct xt_option_entry *);
|
||||
|
||||
extern struct xtables_lmap *xtables_lmap_init(const char *);
|
||||
extern void xtables_lmap_free(struct xtables_lmap *);
|
||||
extern int xtables_lmap_name2id(const struct xtables_lmap *, const char *);
|
||||
extern const char *xtables_lmap_id2name(const struct xtables_lmap *, int);
|
||||
|
||||
#ifdef XTABLES_INTERNAL
|
||||
|
||||
/* Shipped modules rely on this... */
|
||||
|
||||
# ifndef ARRAY_SIZE
|
||||
# define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
|
||||
# endif
|
||||
|
||||
extern void _init(void);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* _XTABLES_H */
|
||||
@ -296,6 +296,9 @@ static void print_af_spec(FILE *fp, struct rtattr *af_spec_attr)
|
||||
case IN6_ADDR_GEN_MODE_STABLE_PRIVACY:
|
||||
fprintf(fp, "addrgenmode stable_secret ");
|
||||
break;
|
||||
case IN6_ADDR_GEN_MODE_RANDOM:
|
||||
fprintf(fp, "addrgenmode random ");
|
||||
break;
|
||||
default:
|
||||
fprintf(fp, "addrgenmode %#.2hhx ", mode);
|
||||
break;
|
||||
|
||||
@ -84,7 +84,7 @@ void iplink_usage(void)
|
||||
fprintf(stderr, " [ state { auto | enable | disable} ] ]\n");
|
||||
fprintf(stderr, " [ master DEVICE ]\n");
|
||||
fprintf(stderr, " [ nomaster ]\n");
|
||||
fprintf(stderr, " [ addrgenmode { eui64 | none } ]\n");
|
||||
fprintf(stderr, " [ addrgenmode { eui64 | none | stable_secret | random } ]\n");
|
||||
fprintf(stderr, " [ protodown { on | off } ]\n");
|
||||
fprintf(stderr, " ip link show [ DEVICE | group GROUP ] [up] [master DEV] [type TYPE]\n");
|
||||
|
||||
@ -176,6 +176,10 @@ static int get_addr_gen_mode(const char *mode)
|
||||
return IN6_ADDR_GEN_MODE_EUI64;
|
||||
if (strcasecmp(mode, "none") == 0)
|
||||
return IN6_ADDR_GEN_MODE_NONE;
|
||||
if (strcasecmp(mode, "stable_secret") == 0)
|
||||
return IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
|
||||
if (strcasecmp(mode, "random") == 0)
|
||||
return IN6_ADDR_GEN_MODE_RANDOM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -284,12 +284,16 @@ int do_ipmonitor(int argc, char **argv)
|
||||
}
|
||||
if (file) {
|
||||
FILE *fp;
|
||||
int err;
|
||||
|
||||
fp = fopen(file, "r");
|
||||
if (fp == NULL) {
|
||||
perror("Cannot fopen");
|
||||
exit(-1);
|
||||
}
|
||||
return rtnl_from_file(fp, accept_msg, stdout);
|
||||
err = rtnl_from_file(fp, accept_msg, stdout);
|
||||
fclose(fp);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (rtnl_open(&rth, groups) < 0)
|
||||
|
||||
11
ip/iproute.c
11
ip/iproute.c
@ -86,7 +86,7 @@ static void usage(void)
|
||||
fprintf(stderr, " [ ssthresh NUMBER ] [ realms REALM ] [ src ADDRESS ]\n");
|
||||
fprintf(stderr, " [ rto_min TIME ] [ hoplimit NUMBER ] [ initrwnd NUMBER ]\n");
|
||||
fprintf(stderr, " [ features FEATURES ] [ quickack BOOL ] [ congctl NAME ]\n");
|
||||
fprintf(stderr, " [ pref PREF ]\n");
|
||||
fprintf(stderr, " [ pref PREF ] [ expires TIME ]\n");
|
||||
fprintf(stderr, "TYPE := [ unicast | local | broadcast | multicast | throw |\n");
|
||||
fprintf(stderr, " unreachable | prohibit | blackhole | nat ]\n");
|
||||
fprintf(stderr, "TABLE_ID := [ local | main | default | all | NUMBER ]\n");
|
||||
@ -829,6 +829,7 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv)
|
||||
int table_ok = 0;
|
||||
int raw = 0;
|
||||
int type_ok = 0;
|
||||
static int hz;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
|
||||
@ -899,6 +900,14 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv)
|
||||
if (rtnl_dsfield_a2n(&tos, *argv))
|
||||
invarg("\"tos\" value is invalid\n", *argv);
|
||||
req.r.rtm_tos = tos;
|
||||
} else if (strcmp(*argv, "expires") == 0 ) {
|
||||
__u32 expires;
|
||||
NEXT_ARG();
|
||||
if (get_u32(&expires, *argv, 0))
|
||||
invarg("\"expires\" value is invalid\n", *argv);
|
||||
if (!hz)
|
||||
hz = get_user_hz();
|
||||
addattr32(&req.n, sizeof(req), RTA_EXPIRES, expires*hz);
|
||||
} else if (matches(*argv, "metric") == 0 ||
|
||||
matches(*argv, "priority") == 0 ||
|
||||
strcmp(*argv, "preference") == 0) {
|
||||
|
||||
@ -411,12 +411,16 @@ int do_xfrm_monitor(int argc, char **argv)
|
||||
|
||||
if (file) {
|
||||
FILE *fp;
|
||||
int err;
|
||||
|
||||
fp = fopen(file, "r");
|
||||
if (fp == NULL) {
|
||||
perror("Cannot fopen");
|
||||
exit(-1);
|
||||
}
|
||||
return rtnl_from_file(fp, xfrm_accept_msg, (void*)stdout);
|
||||
err = rtnl_from_file(fp, xfrm_accept_msg, stdout);
|
||||
fclose(fp);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (rtnl_open_byproto(&rth, groups, NETLINK_XFRM) < 0)
|
||||
|
||||
19
lib/coverity_model.c
Normal file
19
lib/coverity_model.c
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Coverity Scan model
|
||||
*
|
||||
* This is a modeling file for Coverity Scan. Modeling helps to avoid false
|
||||
* positives.
|
||||
*
|
||||
* - A model file can't import any header files.
|
||||
* - Therefore only some built-in primitives like int, char and void are
|
||||
* available but not wchar_t, NULL etc.
|
||||
* - Modeling doesn't need full structs and typedefs. Rudimentary structs
|
||||
* and similar types are sufficient.
|
||||
* - An uninitialized local pointer is not an error. It signifies that the
|
||||
* variable could be either NULL or have some data.
|
||||
*
|
||||
* Coverity Scan doesn't pick up modifications automatically. The model file
|
||||
* must be uploaded by an admin.
|
||||
*/
|
||||
|
||||
|
||||
@ -23,10 +23,7 @@
|
||||
#include <linux/rtnetlink.h>
|
||||
|
||||
#include "rt_names.h"
|
||||
|
||||
#ifndef CONFDIR
|
||||
#define CONFDIR "/etc/iproute2"
|
||||
#endif
|
||||
#include "utils.h"
|
||||
|
||||
#define NAME_MAX_LEN 512
|
||||
|
||||
|
||||
@ -150,7 +150,7 @@ ip-link \- network device configuration
|
||||
.br
|
||||
.B nomaster " |"
|
||||
.br
|
||||
.B addrgenmode { eui64 | none }
|
||||
.B addrgenmode { eui64 | none | stable_secret | random }
|
||||
.br
|
||||
.B link-netnsid ID
|
||||
.BR " }"
|
||||
@ -1029,8 +1029,20 @@ set master device of the device (enslave device).
|
||||
unset master device of the device (release device).
|
||||
|
||||
.TP
|
||||
.BR "addrgenmode eui64 " or " addrgenmode none"
|
||||
set IPv6 address generation mode
|
||||
.BI addrgenmode " eui64|none|stable_secret|random"
|
||||
set the IPv6 address generation mode
|
||||
|
||||
.I eui64
|
||||
- use a Modified EUI-64 format interface identifier
|
||||
|
||||
.I none
|
||||
- disable automatic address generation
|
||||
|
||||
.I stable_secret
|
||||
- generate the interface identifier based on a preset /proc/sys/net/ipv6/conf/{default,DEVICE}/stable_secret
|
||||
|
||||
.I random
|
||||
- like stable_secret, but auto-generate a new random secret if none is set
|
||||
|
||||
.TP
|
||||
.BR "link-netnsid "
|
||||
|
||||
@ -130,9 +130,11 @@ replace " } "
|
||||
.B quickack
|
||||
.IR BOOL " ] [ "
|
||||
.B congctl
|
||||
.IR NAME " ]"
|
||||
.IR NAME " ] [ "
|
||||
.B pref
|
||||
.IR PREF " ]"
|
||||
.IR PREF " ] [ "
|
||||
.B expires
|
||||
.IR TIME " ]"
|
||||
|
||||
.ti -8
|
||||
.IR TYPE " := [ "
|
||||
@ -656,6 +658,12 @@ is a set of encapsulation attributes specific to the
|
||||
.in -8
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.BI expires " TIME " "(4.4+ only)"
|
||||
the route will be deleted after the expires time.
|
||||
.B Only
|
||||
support IPv6 at present.
|
||||
|
||||
.TP
|
||||
ip route delete
|
||||
delete route
|
||||
|
||||
@ -218,6 +218,7 @@ Exit status is 0 if command was successful or a positive integer upon failure.
|
||||
.BR tipc-media (8),
|
||||
.BR tipc-nametable (8),
|
||||
.BR tipc-node (8),
|
||||
.BR tipc-peer (8),
|
||||
.BR tipc-socket (8)
|
||||
.br
|
||||
.SH REPORTING BUGS
|
||||
|
||||
@ -213,6 +213,7 @@ Exit status is 0 if command was successful or a positive integer upon failure.
|
||||
.BR tipc-bearer (8),
|
||||
.BR tipc-nametable (8),
|
||||
.BR tipc-node (8),
|
||||
.BR tipc-peer (8),
|
||||
.BR tipc-socket (8)
|
||||
.br
|
||||
.SH REPORTING BUGS
|
||||
|
||||
@ -74,6 +74,7 @@ Exit status is 0 if command was successful or a positive integer upon failure.
|
||||
.BR tipc-link (8),
|
||||
.BR tipc-nametable (8),
|
||||
.BR tipc-node (8),
|
||||
.BR tipc-peer (8),
|
||||
.BR tipc-socket (8)
|
||||
.br
|
||||
.SH REPORTING BUGS
|
||||
|
||||
@ -87,6 +87,7 @@ Exit status is 0 if command was successful or a positive integer upon failure.
|
||||
.BR tipc-link (8),
|
||||
.BR tipc-media (8),
|
||||
.BR tipc-node (8),
|
||||
.BR tipc-peer (8),
|
||||
.BR tipc-socket (8)
|
||||
.br
|
||||
.SH REPORTING BUGS
|
||||
|
||||
@ -59,6 +59,7 @@ Exit status is 0 if command was successful or a positive integer upon failure.
|
||||
.BR tipc-link (8),
|
||||
.BR tipc-media (8),
|
||||
.BR tipc-nametable (8),
|
||||
.BR tipc-peer (8),
|
||||
.BR tipc-socket (8)
|
||||
.br
|
||||
.SH REPORTING BUGS
|
||||
|
||||
52
man/man8/tipc-peer.8
Normal file
52
man/man8/tipc-peer.8
Normal file
@ -0,0 +1,52 @@
|
||||
.TH TIPC-PEER 8 "04 Dec 2015" "iproute2" "Linux"
|
||||
|
||||
.\" For consistency, please keep padding right aligned.
|
||||
.\" For example '.B "foo " bar' and not '.B foo " bar"'
|
||||
|
||||
.SH NAME
|
||||
tipc-peer \- modify peer information
|
||||
|
||||
.SH SYNOPSIS
|
||||
.ad l
|
||||
.in +8
|
||||
|
||||
.ti -8
|
||||
.B tipc peer remove address
|
||||
.IR ADDRESS
|
||||
|
||||
.SH OPTIONS
|
||||
Options (flags) that can be passed anywhere in the command chain.
|
||||
.TP
|
||||
.BR "\-h" , " --help"
|
||||
Show help about last valid command. For example
|
||||
.B tipc peer --help
|
||||
will show peer help and
|
||||
.B tipc --help
|
||||
will show general help. The position of the option in the string is irrelevant.
|
||||
.SH DESCRIPTION
|
||||
|
||||
.SS Peer remove
|
||||
Remove an offline peer node from the local data structures. The peer is
|
||||
identified by its
|
||||
.B address
|
||||
|
||||
.SH EXIT STATUS
|
||||
Exit status is 0 if command was successful or a positive integer upon failure.
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR tipc (8),
|
||||
.BR tipc-bearer (8),
|
||||
.BR tipc-link (8),
|
||||
.BR tipc-media (8),
|
||||
.BR tipc-nametable (8),
|
||||
.BR tipc-node (8),
|
||||
.BR tipc-socket (8)
|
||||
.br
|
||||
.SH REPORTING BUGS
|
||||
Report any bugs to the Network Developers mailing list
|
||||
.B <netdev@vger.kernel.org>
|
||||
where the development and maintenance is primarily done.
|
||||
You do not have to be subscribed to the list to send a message there.
|
||||
|
||||
.SH AUTHOR
|
||||
Richard Alpe <richard.alpe@ericsson.com>
|
||||
@ -87,6 +87,7 @@ Exit status is 0 if command was successful or a positive integer upon failure.
|
||||
.BR tipc-media (8),
|
||||
.BR tipc-nametable (8),
|
||||
.BR tipc-node (8),
|
||||
.BR tipc-peer (8),
|
||||
.BR tipc-socket (8)
|
||||
.br
|
||||
.SH REPORTING BUGS
|
||||
|
||||
@ -172,8 +172,10 @@ static struct lnstat_file *alloc_and_open(const char *path, const char *file)
|
||||
|
||||
/* allocate */
|
||||
lf = malloc(sizeof(*lf));
|
||||
if (!lf)
|
||||
if (!lf) {
|
||||
fprintf(stderr, "out of memory\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* initialize */
|
||||
memset(lf, 0, sizeof(*lf));
|
||||
@ -190,6 +192,7 @@ static struct lnstat_file *alloc_and_open(const char *path, const char *file)
|
||||
/* open */
|
||||
lf->fp = fopen(lf->path, "r");
|
||||
if (!lf->fp) {
|
||||
perror(lf->path);
|
||||
free(lf);
|
||||
return NULL;
|
||||
}
|
||||
@ -256,12 +259,16 @@ struct lnstat_file *lnstat_scan_dir(const char *path, const int num_req_files,
|
||||
continue;
|
||||
|
||||
lf = alloc_and_open(path, de->d_name);
|
||||
if (!lf)
|
||||
if (!lf) {
|
||||
closedir(dir);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* fill in field structure */
|
||||
if (lnstat_scan_fields(lf) < 0)
|
||||
if (lnstat_scan_fields(lf) < 0) {
|
||||
closedir(dir);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* prepend to global list */
|
||||
lf->next = lnstat_files;
|
||||
|
||||
46
tc/e_bpf.c
46
tc/e_bpf.c
@ -26,10 +26,19 @@ static char *argv_default[] = { BPF_DEFAULT_CMD, NULL };
|
||||
|
||||
static void explain(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: ... bpf [ import UDS_FILE ] [ run CMD ]\n\n");
|
||||
fprintf(stderr, "Usage: ... bpf [ import UDS_FILE ] [ run CMD ]\n");
|
||||
fprintf(stderr, " ... bpf [ debug ]\n");
|
||||
fprintf(stderr, " ... bpf [ graft MAP_FILE ] [ key KEY ]\n");
|
||||
fprintf(stderr, " `... [ object-file OBJ_FILE ] [ type TYPE ] [ section NAME ] [ verbose ]\n");
|
||||
fprintf(stderr, " `... [ object-pinned PROG_FILE ]\n");
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "Where UDS_FILE provides the name of a unix domain socket file\n");
|
||||
fprintf(stderr, "to import eBPF maps and the optional CMD denotes the command\n");
|
||||
fprintf(stderr, "to be executed (default: \'%s\').\n", BPF_DEFAULT_CMD);
|
||||
fprintf(stderr, "Where MAP_FILE points to a pinned map, OBJ_FILE to an object file\n");
|
||||
fprintf(stderr, "and PROG_FILE to a pinned program. TYPE can be {cls, act}, where\n");
|
||||
fprintf(stderr, "\'cls\' is default. KEY is optional and can be inferred from the\n");
|
||||
fprintf(stderr, "section name, otherwise it needs to be provided.\n");
|
||||
}
|
||||
|
||||
static int bpf_num_env_entries(void)
|
||||
@ -58,17 +67,40 @@ static int parse_bpf(struct exec_util *eu, int argc, char **argv)
|
||||
NEXT_ARG();
|
||||
argv_run = argv;
|
||||
break;
|
||||
} else if (matches(*argv, "import") == 0 ||
|
||||
matches(*argv, "imp") == 0) {
|
||||
} else if (matches(*argv, "import") == 0) {
|
||||
NEXT_ARG();
|
||||
bpf_uds_name = *argv;
|
||||
} else if (matches(*argv, "debug") == 0 ||
|
||||
matches(*argv, "dbg") == 0) {
|
||||
if (bpf_trace_pipe())
|
||||
fprintf(stderr,
|
||||
"No trace pipe, tracefs not mounted?\n");
|
||||
return -1;
|
||||
} else if (matches(*argv, "graft") == 0) {
|
||||
const char *bpf_map_path;
|
||||
bool has_key = false;
|
||||
uint32_t key;
|
||||
|
||||
NEXT_ARG();
|
||||
bpf_map_path = *argv;
|
||||
NEXT_ARG();
|
||||
if (matches(*argv, "key") == 0) {
|
||||
NEXT_ARG();
|
||||
if (get_unsigned(&key, *argv, 0)) {
|
||||
fprintf(stderr, "Illegal \"key\"\n");
|
||||
return -1;
|
||||
}
|
||||
has_key = true;
|
||||
NEXT_ARG();
|
||||
}
|
||||
return bpf_graft_map(bpf_map_path, has_key ?
|
||||
&key : NULL, argc, argv);
|
||||
} else {
|
||||
explain();
|
||||
return -1;
|
||||
}
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
NEXT_ARG_FWD();
|
||||
}
|
||||
|
||||
if (!bpf_uds_name) {
|
||||
@ -142,6 +174,6 @@ err:
|
||||
}
|
||||
|
||||
struct exec_util bpf_exec_util = {
|
||||
.id = "bpf",
|
||||
.parse_eopt = parse_bpf,
|
||||
.id = "bpf",
|
||||
.parse_eopt = parse_bpf,
|
||||
};
|
||||
|
||||
131
tc/f_bpf.c
131
tc/f_bpf.c
@ -11,19 +11,8 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <syslog.h>
|
||||
#include <fcntl.h>
|
||||
#include <libgen.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <linux/filter.h>
|
||||
#include <linux/if.h>
|
||||
|
||||
#include <linux/bpf.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "tc_util.h"
|
||||
@ -31,6 +20,13 @@
|
||||
|
||||
static const enum bpf_prog_type bpf_type = BPF_PROG_TYPE_SCHED_CLS;
|
||||
|
||||
static const int nla_tbl[BPF_NLA_MAX] = {
|
||||
[BPF_NLA_OPS_LEN] = TCA_BPF_OPS_LEN,
|
||||
[BPF_NLA_OPS] = TCA_BPF_OPS,
|
||||
[BPF_NLA_FD] = TCA_BPF_FD,
|
||||
[BPF_NLA_NAME] = TCA_BPF_NAME,
|
||||
};
|
||||
|
||||
static void explain(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: ... bpf ...\n");
|
||||
@ -42,6 +38,7 @@ static void explain(void)
|
||||
fprintf(stderr, "eBPF use case:\n");
|
||||
fprintf(stderr, " object-file FILE [ section CLS_NAME ] [ export UDS_FILE ]");
|
||||
fprintf(stderr, " [ verbose ] [ direct-action ]\n");
|
||||
fprintf(stderr, " object-pinned FILE [ direct-action ]\n");
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "Common remaining options:\n");
|
||||
fprintf(stderr, " [ action ACTION_SPEC ]\n");
|
||||
@ -51,7 +48,8 @@ static void explain(void)
|
||||
fprintf(stderr, "c,t,f,k and s are decimals; s denotes number of 4-tuples\n");
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "Where FILE points to a file containing the BPF_BYTECODE string,\n");
|
||||
fprintf(stderr, "an ELF file containing eBPF map definitions and bytecode.\n");
|
||||
fprintf(stderr, "an ELF file containing eBPF map definitions and bytecode, or a\n");
|
||||
fprintf(stderr, "pinned eBPF program.\n");
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "Where CLS_NAME refers to the section name containing the\n");
|
||||
fprintf(stderr, "classifier (default \'%s\').\n", bpf_default_section(bpf_type));
|
||||
@ -66,119 +64,38 @@ static void explain(void)
|
||||
static int bpf_parse_opt(struct filter_util *qu, char *handle,
|
||||
int argc, char **argv, struct nlmsghdr *n)
|
||||
{
|
||||
const char *bpf_obj = NULL, *bpf_uds_name = NULL;
|
||||
struct tcmsg *t = NLMSG_DATA(n);
|
||||
const char *bpf_uds_name = NULL;
|
||||
const char *bpf_sec_name = NULL;
|
||||
unsigned int bpf_flags = 0;
|
||||
char *bpf_obj = NULL;
|
||||
struct rtattr *tail;
|
||||
bool seen_run = false;
|
||||
long h = 0;
|
||||
struct rtattr *tail;
|
||||
int ret = 0;
|
||||
|
||||
if (argc == 0)
|
||||
return 0;
|
||||
|
||||
if (handle) {
|
||||
h = strtol(handle, NULL, 0);
|
||||
if (h == LONG_MIN || h == LONG_MAX) {
|
||||
fprintf(stderr, "Illegal handle \"%s\", must be "
|
||||
"numeric.\n", handle);
|
||||
if (get_u32(&t->tcm_handle, handle, 0)) {
|
||||
fprintf(stderr, "Illegal \"handle\"\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
t->tcm_handle = h;
|
||||
|
||||
tail = (struct rtattr *)(((void *)n) + NLMSG_ALIGN(n->nlmsg_len));
|
||||
addattr_l(n, MAX_MSG, TCA_OPTIONS, NULL, 0);
|
||||
|
||||
while (argc > 0) {
|
||||
if (matches(*argv, "run") == 0) {
|
||||
struct sock_filter bpf_ops[BPF_MAXINSNS];
|
||||
bool from_file, ebpf, bpf_verbose;
|
||||
int ret;
|
||||
|
||||
NEXT_ARG();
|
||||
opt_bpf:
|
||||
bpf_sec_name = bpf_default_section(bpf_type);
|
||||
bpf_verbose = false;
|
||||
ebpf = false;
|
||||
seen_run = true;
|
||||
|
||||
if (strcmp(*argv, "bytecode-file") == 0 ||
|
||||
strcmp(*argv, "bcf") == 0) {
|
||||
from_file = true;
|
||||
} else if (strcmp(*argv, "bytecode") == 0 ||
|
||||
strcmp(*argv, "bc") == 0) {
|
||||
from_file = false;
|
||||
} else if (strcmp(*argv, "object-file") == 0 ||
|
||||
strcmp(*argv, "obj") == 0) {
|
||||
ebpf = true;
|
||||
} else {
|
||||
fprintf(stderr, "What is \"%s\"?\n", *argv);
|
||||
explain();
|
||||
if (bpf_parse_common(&argc, &argv, nla_tbl, bpf_type,
|
||||
&bpf_obj, &bpf_uds_name, n)) {
|
||||
fprintf(stderr, "Failed to retrieve (e)BPF data!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
NEXT_ARG();
|
||||
if (ebpf) {
|
||||
bpf_uds_name = getenv(BPF_ENV_UDS);
|
||||
bpf_obj = *argv;
|
||||
|
||||
NEXT_ARG_FWD();
|
||||
|
||||
if (argc > 0 &&
|
||||
(strcmp(*argv, "section") == 0 ||
|
||||
strcmp(*argv, "sec") == 0)) {
|
||||
NEXT_ARG();
|
||||
bpf_sec_name = *argv;
|
||||
NEXT_ARG_FWD();
|
||||
}
|
||||
if (argc > 0 && !bpf_uds_name &&
|
||||
(strcmp(*argv, "export") == 0 ||
|
||||
strcmp(*argv, "exp") == 0)) {
|
||||
NEXT_ARG();
|
||||
bpf_uds_name = *argv;
|
||||
NEXT_ARG_FWD();
|
||||
}
|
||||
if (argc > 0 &&
|
||||
(strcmp(*argv, "verbose") == 0 ||
|
||||
strcmp(*argv, "verb") == 0)) {
|
||||
bpf_verbose = true;
|
||||
NEXT_ARG_FWD();
|
||||
}
|
||||
|
||||
PREV_ARG();
|
||||
}
|
||||
|
||||
ret = ebpf ? bpf_open_object(bpf_obj, bpf_type, bpf_sec_name,
|
||||
bpf_verbose) :
|
||||
bpf_parse_ops(argc, argv, bpf_ops, from_file);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "%s\n", ebpf ?
|
||||
"Could not load object" :
|
||||
"Illegal \"bytecode\"");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ebpf) {
|
||||
char bpf_name[256];
|
||||
|
||||
bpf_obj = basename(bpf_obj);
|
||||
|
||||
snprintf(bpf_name, sizeof(bpf_name), "%s:[%s]",
|
||||
bpf_obj, bpf_sec_name);
|
||||
|
||||
addattr32(n, MAX_MSG, TCA_BPF_FD, ret);
|
||||
addattrstrz(n, MAX_MSG, TCA_BPF_NAME, bpf_name);
|
||||
} else {
|
||||
addattr16(n, MAX_MSG, TCA_BPF_OPS_LEN, ret);
|
||||
addattr_l(n, MAX_MSG, TCA_BPF_OPS, &bpf_ops,
|
||||
ret * sizeof(struct sock_filter));
|
||||
}
|
||||
} else if (matches(*argv, "classid") == 0 ||
|
||||
strcmp(*argv, "flowid") == 0) {
|
||||
matches(*argv, "flowid") == 0) {
|
||||
unsigned int handle;
|
||||
|
||||
NEXT_ARG();
|
||||
@ -204,7 +121,7 @@ opt_bpf:
|
||||
return -1;
|
||||
}
|
||||
continue;
|
||||
} else if (strcmp(*argv, "help") == 0) {
|
||||
} else if (matches(*argv, "help") == 0) {
|
||||
explain();
|
||||
return -1;
|
||||
} else {
|
||||
@ -280,7 +197,7 @@ static int bpf_print_opt(struct filter_util *qu, FILE *f,
|
||||
}
|
||||
|
||||
struct filter_util bpf_filter_util = {
|
||||
.id = "bpf",
|
||||
.parse_fopt = bpf_parse_opt,
|
||||
.print_fopt = bpf_print_opt,
|
||||
.id = "bpf",
|
||||
.parse_fopt = bpf_parse_opt,
|
||||
.print_fopt = bpf_print_opt,
|
||||
};
|
||||
|
||||
158
tc/m_bpf.c
158
tc/m_bpf.c
@ -12,20 +12,23 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/tc_act/tc_bpf.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "rt_names.h"
|
||||
#include "tc_util.h"
|
||||
#include "tc_bpf.h"
|
||||
|
||||
static const enum bpf_prog_type bpf_type = BPF_PROG_TYPE_SCHED_ACT;
|
||||
|
||||
static const int nla_tbl[BPF_NLA_MAX] = {
|
||||
[BPF_NLA_OPS_LEN] = TCA_ACT_BPF_OPS_LEN,
|
||||
[BPF_NLA_OPS] = TCA_ACT_BPF_OPS,
|
||||
[BPF_NLA_FD] = TCA_ACT_BPF_FD,
|
||||
[BPF_NLA_NAME] = TCA_ACT_BPF_NAME,
|
||||
};
|
||||
|
||||
static void explain(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: ... bpf ... [ index INDEX ]\n");
|
||||
@ -37,12 +40,14 @@ static void explain(void)
|
||||
fprintf(stderr, "eBPF use case:\n");
|
||||
fprintf(stderr, " object-file FILE [ section ACT_NAME ] [ export UDS_FILE ]");
|
||||
fprintf(stderr, " [ verbose ]\n");
|
||||
fprintf(stderr, " object-pinned FILE\n");
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "Where BPF_BYTECODE := \'s,c t f k,c t f k,c t f k,...\'\n");
|
||||
fprintf(stderr, "c,t,f,k and s are decimals; s denotes number of 4-tuples\n");
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "Where FILE points to a file containing the BPF_BYTECODE string,\n");
|
||||
fprintf(stderr, "an ELF file containing eBPF map definitions and bytecode.\n");
|
||||
fprintf(stderr, "an ELF file containing eBPF map definitions and bytecode, or a\n");
|
||||
fprintf(stderr, "pinned eBPF program.\n");
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "Where ACT_NAME refers to the section name containing the\n");
|
||||
fprintf(stderr, "action (default \'%s\').\n", bpf_default_section(bpf_type));
|
||||
@ -54,114 +59,40 @@ static void explain(void)
|
||||
fprintf(stderr, "explicitly specifies an action index upon creation.\n");
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
static int bpf_parse_opt(struct action_util *a, int *ptr_argc, char ***ptr_argv,
|
||||
int tca_id, struct nlmsghdr *n)
|
||||
{
|
||||
explain();
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
static int parse_bpf(struct action_util *a, int *argc_p, char ***argv_p,
|
||||
int tca_id, struct nlmsghdr *n)
|
||||
{
|
||||
char **argv = *argv_p, bpf_name[256];
|
||||
const char *bpf_obj = NULL, *bpf_uds_name = NULL;
|
||||
struct tc_act_bpf parm;
|
||||
bool seen_run = false;
|
||||
struct rtattr *tail;
|
||||
struct tc_act_bpf parm = { 0 };
|
||||
struct sock_filter bpf_ops[BPF_MAXINSNS];
|
||||
bool ebpf_fill = false, bpf_fill = false;
|
||||
bool ebpf = false, seen_run = false;
|
||||
const char *bpf_uds_name = NULL;
|
||||
const char *bpf_sec_name = NULL;
|
||||
char *bpf_obj = NULL;
|
||||
int argc = *argc_p, ret = 0;
|
||||
__u16 bpf_len = 0;
|
||||
__u32 bpf_fd = 0;
|
||||
int argc, ret = 0;
|
||||
char **argv;
|
||||
|
||||
argv = *ptr_argv;
|
||||
argc = *ptr_argc;
|
||||
|
||||
if (matches(*argv, "bpf") != 0)
|
||||
return -1;
|
||||
|
||||
NEXT_ARG();
|
||||
|
||||
tail = NLMSG_TAIL(n);
|
||||
addattr_l(n, MAX_MSG, tca_id, NULL, 0);
|
||||
|
||||
while (argc > 0) {
|
||||
if (matches(*argv, "run") == 0) {
|
||||
bool from_file, bpf_verbose;
|
||||
int ret;
|
||||
|
||||
NEXT_ARG();
|
||||
opt_bpf:
|
||||
bpf_sec_name = bpf_default_section(bpf_type);
|
||||
bpf_verbose = false;
|
||||
seen_run = true;
|
||||
|
||||
if (strcmp(*argv, "bytecode-file") == 0 ||
|
||||
strcmp(*argv, "bcf") == 0) {
|
||||
from_file = true;
|
||||
} else if (strcmp(*argv, "bytecode") == 0 ||
|
||||
strcmp(*argv, "bc") == 0) {
|
||||
from_file = false;
|
||||
} else if (strcmp(*argv, "object-file") == 0 ||
|
||||
strcmp(*argv, "obj") == 0) {
|
||||
ebpf = true;
|
||||
} else {
|
||||
fprintf(stderr, "unexpected \"%s\"\n", *argv);
|
||||
explain();
|
||||
if (bpf_parse_common(&argc, &argv, nla_tbl, bpf_type,
|
||||
&bpf_obj, &bpf_uds_name, n)) {
|
||||
fprintf(stderr, "Failed to retrieve (e)BPF data!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
NEXT_ARG();
|
||||
if (ebpf) {
|
||||
bpf_uds_name = getenv(BPF_ENV_UDS);
|
||||
bpf_obj = *argv;
|
||||
|
||||
NEXT_ARG_FWD();
|
||||
|
||||
if (argc > 0 &&
|
||||
(strcmp(*argv, "section") == 0 ||
|
||||
strcmp(*argv, "sec") == 0)) {
|
||||
NEXT_ARG();
|
||||
bpf_sec_name = *argv;
|
||||
NEXT_ARG_FWD();
|
||||
}
|
||||
if (argc > 0 && !bpf_uds_name &&
|
||||
(strcmp(*argv, "export") == 0 ||
|
||||
strcmp(*argv, "exp") == 0)) {
|
||||
NEXT_ARG();
|
||||
bpf_uds_name = *argv;
|
||||
NEXT_ARG_FWD();
|
||||
}
|
||||
if (argc > 0 &&
|
||||
(strcmp(*argv, "verbose") == 0 ||
|
||||
strcmp(*argv, "verb") == 0)) {
|
||||
bpf_verbose = true;
|
||||
NEXT_ARG_FWD();
|
||||
}
|
||||
|
||||
PREV_ARG();
|
||||
}
|
||||
|
||||
ret = ebpf ? bpf_open_object(bpf_obj, bpf_type, bpf_sec_name,
|
||||
bpf_verbose) :
|
||||
bpf_parse_ops(argc, argv, bpf_ops, from_file);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "%s\n", ebpf ?
|
||||
"Could not load object" :
|
||||
"Illegal \"bytecode\"");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ebpf) {
|
||||
bpf_obj = basename(bpf_obj);
|
||||
|
||||
snprintf(bpf_name, sizeof(bpf_name), "%s:[%s]",
|
||||
bpf_obj, bpf_sec_name);
|
||||
|
||||
bpf_fd = ret;
|
||||
ebpf_fill = true;
|
||||
} else {
|
||||
bpf_len = ret;
|
||||
bpf_fill = true;
|
||||
}
|
||||
} else if (matches(*argv, "help") == 0) {
|
||||
usage();
|
||||
explain();
|
||||
return -1;
|
||||
} else if (matches(*argv, "index") == 0) {
|
||||
break;
|
||||
} else {
|
||||
@ -173,7 +104,9 @@ opt_bpf:
|
||||
NEXT_ARG_FWD();
|
||||
}
|
||||
|
||||
memset(&parm, 0, sizeof(parm));
|
||||
parm.action = TC_ACT_PIPE;
|
||||
|
||||
if (argc) {
|
||||
if (matches(*argv, "reclassify") == 0) {
|
||||
parm.action = TC_ACT_RECLASSIFY;
|
||||
@ -207,32 +140,19 @@ opt_bpf:
|
||||
}
|
||||
}
|
||||
|
||||
tail = NLMSG_TAIL(n);
|
||||
|
||||
addattr_l(n, MAX_MSG, tca_id, NULL, 0);
|
||||
addattr_l(n, MAX_MSG, TCA_ACT_BPF_PARMS, &parm, sizeof(parm));
|
||||
|
||||
if (ebpf_fill) {
|
||||
addattr32(n, MAX_MSG, TCA_ACT_BPF_FD, bpf_fd);
|
||||
addattrstrz(n, MAX_MSG, TCA_ACT_BPF_NAME, bpf_name);
|
||||
} else if (bpf_fill) {
|
||||
addattr16(n, MAX_MSG, TCA_ACT_BPF_OPS_LEN, bpf_len);
|
||||
addattr_l(n, MAX_MSG, TCA_ACT_BPF_OPS, &bpf_ops,
|
||||
bpf_len * sizeof(struct sock_filter));
|
||||
}
|
||||
|
||||
tail->rta_len = (char *)NLMSG_TAIL(n) - (char *)tail;
|
||||
|
||||
*argc_p = argc;
|
||||
*argv_p = argv;
|
||||
|
||||
if (bpf_uds_name)
|
||||
ret = bpf_send_map_fds(bpf_uds_name, bpf_obj);
|
||||
|
||||
*ptr_argc = argc;
|
||||
*ptr_argv = argv;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int print_bpf(struct action_util *au, FILE *f, struct rtattr *arg)
|
||||
static int bpf_print_opt(struct action_util *au, FILE *f, struct rtattr *arg)
|
||||
{
|
||||
struct rtattr *tb[TCA_ACT_BPF_MAX + 1];
|
||||
struct tc_act_bpf *parm;
|
||||
@ -249,7 +169,6 @@ static int print_bpf(struct action_util *au, FILE *f, struct rtattr *arg)
|
||||
}
|
||||
|
||||
parm = RTA_DATA(tb[TCA_ACT_BPF_PARMS]);
|
||||
|
||||
fprintf(f, "bpf ");
|
||||
|
||||
if (tb[TCA_ACT_BPF_NAME])
|
||||
@ -276,12 +195,11 @@ static int print_bpf(struct action_util *au, FILE *f, struct rtattr *arg)
|
||||
}
|
||||
|
||||
fprintf(f, "\n ");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct action_util bpf_action_util = {
|
||||
.id = "bpf",
|
||||
.parse_aopt = parse_bpf,
|
||||
.print_aopt = print_bpf,
|
||||
.id = "bpf",
|
||||
.parse_aopt = bpf_parse_opt,
|
||||
.print_aopt = bpf_print_opt,
|
||||
};
|
||||
|
||||
1709
tc/tc_bpf.c
1709
tc/tc_bpf.c
File diff suppressed because it is too large
Load Diff
74
tc/tc_bpf.h
74
tc/tc_bpf.h
@ -13,61 +13,57 @@
|
||||
#ifndef _TC_BPF_H_
|
||||
#define _TC_BPF_H_ 1
|
||||
|
||||
#include <linux/filter.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <linux/magic.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "bpf_scm.h"
|
||||
|
||||
enum {
|
||||
BPF_NLA_OPS_LEN = 0,
|
||||
BPF_NLA_OPS,
|
||||
BPF_NLA_FD,
|
||||
BPF_NLA_NAME,
|
||||
__BPF_NLA_MAX,
|
||||
};
|
||||
|
||||
#define BPF_NLA_MAX __BPF_NLA_MAX
|
||||
|
||||
#define BPF_ENV_UDS "TC_BPF_UDS"
|
||||
#define BPF_ENV_MNT "TC_BPF_MNT"
|
||||
#define BPF_ENV_NOLOG "TC_BPF_NOLOG"
|
||||
|
||||
int bpf_parse_string(char *arg, bool from_file, __u16 *bpf_len,
|
||||
char **bpf_string, bool *need_release,
|
||||
const char separator);
|
||||
int bpf_parse_ops(int argc, char **argv, struct sock_filter *bpf_ops,
|
||||
bool from_file);
|
||||
void bpf_print_ops(FILE *f, struct rtattr *bpf_ops, __u16 len);
|
||||
#ifndef BPF_FS_MAGIC
|
||||
# define BPF_FS_MAGIC 0xcafe4a11
|
||||
#endif
|
||||
|
||||
#define BPF_DIR_MNT "/sys/fs/bpf"
|
||||
|
||||
#define BPF_DIR_TC "tc"
|
||||
#define BPF_DIR_GLOBALS "globals"
|
||||
|
||||
#ifndef TRACEFS_MAGIC
|
||||
# define TRACEFS_MAGIC 0x74726163
|
||||
#endif
|
||||
|
||||
#define TRACE_DIR_MNT "/sys/kernel/tracing"
|
||||
|
||||
int bpf_trace_pipe(void);
|
||||
const char *bpf_default_section(const enum bpf_prog_type type);
|
||||
|
||||
#ifdef HAVE_ELF
|
||||
int bpf_open_object(const char *path, enum bpf_prog_type type,
|
||||
const char *sec, bool verbose);
|
||||
int bpf_parse_common(int *ptr_argc, char ***ptr_argv, const int *nla_tbl,
|
||||
enum bpf_prog_type type, const char **ptr_object,
|
||||
const char **ptr_uds_name, struct nlmsghdr *n);
|
||||
int bpf_graft_map(const char *map_path, uint32_t *key, int argc, char **argv);
|
||||
|
||||
void bpf_print_ops(FILE *f, struct rtattr *bpf_ops, __u16 len);
|
||||
|
||||
#ifdef HAVE_ELF
|
||||
int bpf_send_map_fds(const char *path, const char *obj);
|
||||
int bpf_recv_map_fds(const char *path, int *fds, struct bpf_map_aux *aux,
|
||||
unsigned int entries);
|
||||
|
||||
static inline __u64 bpf_ptr_to_u64(const void *ptr)
|
||||
{
|
||||
return (__u64) (unsigned long) ptr;
|
||||
}
|
||||
|
||||
static inline int bpf(int cmd, union bpf_attr *attr, unsigned int size)
|
||||
{
|
||||
#ifdef __NR_bpf
|
||||
return syscall(__NR_bpf, cmd, attr, size);
|
||||
#else
|
||||
fprintf(stderr, "No bpf syscall, kernel headers too old?\n");
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
static inline int bpf_open_object(const char *path, enum bpf_prog_type type,
|
||||
const char *sec, bool verbose)
|
||||
{
|
||||
fprintf(stderr, "No ELF library support compiled in.\n");
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int bpf_send_map_fds(const char *path, const char *obj)
|
||||
{
|
||||
return 0;
|
||||
|
||||
@ -91,13 +91,17 @@ int do_tcmonitor(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (file) {
|
||||
FILE *fp;
|
||||
fp = fopen(file, "r");
|
||||
FILE *fp = fopen(file, "r");
|
||||
int ret;
|
||||
|
||||
if (fp == NULL) {
|
||||
perror("Cannot fopen");
|
||||
exit(-1);
|
||||
}
|
||||
return rtnl_from_file(fp, accept_tcmsg, (void*)stdout);
|
||||
|
||||
ret = rtnl_from_file(fp, accept_tcmsg, stdout);
|
||||
fclose(fp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (rtnl_open(&rth, groups) < 0)
|
||||
|
||||
@ -6,7 +6,7 @@ TIPCOBJ=bearer.o \
|
||||
media.o misc.o \
|
||||
msg.o nametable.o \
|
||||
node.o socket.o \
|
||||
tipc.o
|
||||
peer.o tipc.o
|
||||
|
||||
include ../Config
|
||||
|
||||
|
||||
93
tipc/peer.c
Normal file
93
tipc/peer.c
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* peer.c TIPC peer functionality.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* Authors: Richard Alpe <richard.alpe@ericsson.com>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <linux/tipc_netlink.h>
|
||||
#include <linux/tipc.h>
|
||||
#include <linux/genetlink.h>
|
||||
#include <libmnl/libmnl.h>
|
||||
|
||||
#include "cmdl.h"
|
||||
#include "msg.h"
|
||||
#include "misc.h"
|
||||
#include "peer.h"
|
||||
|
||||
static int cmd_peer_rm_addr(struct nlmsghdr *nlh, const struct cmd *cmd,
|
||||
struct cmdl *cmdl, void *data)
|
||||
{
|
||||
char *str;
|
||||
uint32_t addr;
|
||||
struct nlattr *nest;
|
||||
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||
|
||||
if ((cmdl->argc != cmdl->optind + 1) || help_flag) {
|
||||
fprintf(stderr, "Usage: %s peer remove address ADDRESS\n",
|
||||
cmdl->argv[0]);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
str = shift_cmdl(cmdl);
|
||||
addr = str2addr(str);
|
||||
if (!addr)
|
||||
return -1;
|
||||
|
||||
if (!(nlh = msg_init(buf, TIPC_NL_PEER_REMOVE))) {
|
||||
fprintf(stderr, "error, message initialisation failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
nest = mnl_attr_nest_start(nlh, TIPC_NLA_NET);
|
||||
mnl_attr_put_u32(nlh, TIPC_NLA_NET_ADDR, addr);
|
||||
mnl_attr_nest_end(nlh, nest);
|
||||
|
||||
return msg_doit(nlh, NULL, NULL);
|
||||
}
|
||||
|
||||
static void cmd_peer_rm_help(struct cmdl *cmdl)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s peer remove address ADDRESS\n",
|
||||
cmdl->argv[0]);
|
||||
}
|
||||
|
||||
static int cmd_peer_rm(struct nlmsghdr *nlh, const struct cmd *cmd,
|
||||
struct cmdl *cmdl, void *data)
|
||||
{
|
||||
const struct cmd cmds[] = {
|
||||
{ "address", cmd_peer_rm_addr, cmd_peer_rm_help },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
return run_cmd(nlh, cmd, cmds, cmdl, NULL);
|
||||
}
|
||||
|
||||
void cmd_peer_help(struct cmdl *cmdl)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: %s peer COMMAND [ARGS] ...\n\n"
|
||||
"COMMANDS\n"
|
||||
" remove - Remove an offline peer node\n",
|
||||
cmdl->argv[0]);
|
||||
}
|
||||
|
||||
int cmd_peer(struct nlmsghdr *nlh, const struct cmd *cmd, struct cmdl *cmdl,
|
||||
void *data)
|
||||
{
|
||||
const struct cmd cmds[] = {
|
||||
{ "remove", cmd_peer_rm, cmd_peer_rm_help },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
return run_cmd(nlh, cmd, cmds, cmdl, NULL);
|
||||
}
|
||||
21
tipc/peer.h
Normal file
21
tipc/peer.h
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* peer.h TIPC peer functionality.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* Authors: Richard Alpe <richard.alpe@ericsson.com>
|
||||
*/
|
||||
|
||||
#ifndef _TIPC_PEER_H
|
||||
#define _TIPC_PEER_H
|
||||
|
||||
extern int help_flag;
|
||||
|
||||
int cmd_peer(struct nlmsghdr *nlh, const struct cmd *cmd, struct cmdl *cmdl,
|
||||
void *data);
|
||||
void cmd_peer_help(struct cmdl *cmdl);
|
||||
|
||||
#endif
|
||||
@ -20,6 +20,7 @@
|
||||
#include "socket.h"
|
||||
#include "media.h"
|
||||
#include "node.h"
|
||||
#include "peer.h"
|
||||
#include "cmdl.h"
|
||||
|
||||
int help_flag;
|
||||
@ -39,6 +40,7 @@ static void about(struct cmdl *cmdl)
|
||||
" media - Show or modify media\n"
|
||||
" nametable - Show nametable\n"
|
||||
" node - Show or modify node related parameters\n"
|
||||
" peer - Peer related operations\n"
|
||||
" socket - Show sockets\n",
|
||||
cmdl->argv[0]);
|
||||
}
|
||||
@ -59,6 +61,7 @@ int main(int argc, char *argv[])
|
||||
{ "media", cmd_media, cmd_media_help},
|
||||
{ "nametable", cmd_nametable, cmd_nametable_help},
|
||||
{ "node", cmd_node, cmd_node_help},
|
||||
{ "peer", cmd_peer, cmd_peer_help},
|
||||
{ "socket", cmd_socket, cmd_socket_help},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user