Commit 2505780c authored by Stephen Hemminger's avatar Stephen Hemminger

Merge branch 'net-next'

parents bc223ab8 f9dec657
#
# subpath mappings from mount point for pinning
#
#3 tracing
#4 foo/bar
#5 tc/cls1
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
#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");
#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__ */
#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");
#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");
#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;
};
......
#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];
......
#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__ */
#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;
enum ip6t_tryload {
DONT_LOAD,
TRY_LOAD,
LOAD_MUST_SUCCEED
};
struct xtc_handle **handle, bool restore);
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_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 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*/
#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 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 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 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;
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);
enum ipt_tryload {
DONT_LOAD,
TRY_LOAD,
LOAD_MUST_SUCCEED
};
extern struct xtables_globals iptables_globals;
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 struct xtables_globals xtables_globals;
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*/
#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);
/* Check whether a matching rule exists */
int ip6tc_check_entry(const xt_chainlabel chain,
const struct ip6t_entry *origfw,
unsigned char *matchmask,
struct xtc_handle *handle);
/* Delete the first rule in `chain' which matches `fw'. */
int ip6tc_delete_entry(const ip6t_chainlabel chain,
int ip6tc_delete_entry(const xt_chainlabel chain,
const struct ip6t_entry *origfw,
unsigned char *matchmask,
ip6tc_handle_t *handle);
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
......
#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 */
#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))
......
This diff is collapsed.
......@@ -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)
......
......@@ -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)
......
/*
* 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
......
.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;
......
......@@ -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,
};
......@@ -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();
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\"");
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;
}
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,
};
......@@ -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,
};
This diff is collapsed.
This diff is collapsed.
......@@ -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
......
This diff is collapsed.
/*
* 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
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment