Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2

This commit is contained in:
Stephen Hemminger 2016-02-02 15:57:23 +11:00
commit 62392ecbbb
171 changed files with 8125 additions and 2538 deletions

View File

@ -9,6 +9,7 @@
#include <unistd.h>
#include <sys/socket.h>
#include <string.h>
#include <errno.h>
#include "SNAPSHOT.h"
#include "utils.h"
@ -23,6 +24,8 @@ int show_stats;
int show_details;
int compress_vlans;
int timestamp;
char *batch_file;
int force;
const char *_SL_;
static void usage(void) __attribute__((noreturn));
@ -31,6 +34,7 @@ static void usage(void)
{
fprintf(stderr,
"Usage: bridge [ OPTIONS ] OBJECT { COMMAND | help }\n"
" bridge [ -force ] -batch filename\n"
"where OBJECT := { link | fdb | mdb | vlan | monitor }\n"
" OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] |\n"
" -o[neline] | -t[imestamp] | -n[etns] name |\n"
@ -71,6 +75,50 @@ static int do_cmd(const char *argv0, int argc, char **argv)
return -1;
}
static int batch(const char *name)
{
char *line = NULL;
size_t len = 0;
int ret = EXIT_SUCCESS;
if (name && strcmp(name, "-") != 0) {
if (freopen(name, "r", stdin) == NULL) {
fprintf(stderr,
"Cannot open file \"%s\" for reading: %s\n",
name, strerror(errno));
return EXIT_FAILURE;
}
}
if (rtnl_open(&rth, 0) < 0) {
fprintf(stderr, "Cannot open rtnetlink\n");
return EXIT_FAILURE;
}
cmdlineno = 0;
while (getcmdline(&line, &len, stdin) != -1) {
char *largv[100];
int largc;
largc = makeargs(line, largv, 100);
if (largc == 0)
continue; /* blank line */
if (do_cmd(largv[0], largc, largv)) {
fprintf(stderr, "Command failed %s:%d\n",
name, cmdlineno);
ret = EXIT_FAILURE;
if (!force)
break;
}
}
if (line)
free(line);
rtnl_close(&rth);
return ret;
}
int
main(int argc, char **argv)
{
@ -123,6 +171,14 @@ main(int argc, char **argv)
exit(-1);
} else if (matches(opt, "-compressvlans") == 0) {
++compress_vlans;
} else if (matches(opt, "-force") == 0) {
++force;
} else if (matches(opt, "-batch") == 0) {
argc--;
argv++;
if (argc <= 1)
usage();
batch_file = argv[1];
} else {
fprintf(stderr,
"Option \"%s\" is unknown, try \"bridge help\".\n",
@ -134,6 +190,9 @@ main(int argc, char **argv)
_SL_ = oneline ? "\\" : "\n";
if (batch_file)
return batch(batch_file);
if (rtnl_open(&rth, 0) < 0)
exit(1);

View File

@ -31,11 +31,11 @@ static unsigned int filter_index;
static void usage(void)
{
fprintf(stderr, "Usage: bridge fdb { add | append | del | replace ADDR dev DEV\n"
fprintf(stderr, "Usage: bridge fdb { add | append | del | replace } ADDR dev DEV\n"
" [ self ] [ master ] [ use ] [ router ]\n"
" [ local | temp ] [ dst IPADDR ] [ vlan VID ]\n"
" [ port PORT] [ vni VNI ] [via DEV]\n");
fprintf(stderr, " bridge fdb {show} [ br BRDEV ] [ brport DEV ]\n");
" [ port PORT] [ vni VNI ] [ via DEV ]\n");
fprintf(stderr, " bridge fdb [ show [ br BRDEV ] [ brport DEV ] ]\n");
exit(-1);
}
@ -163,6 +163,8 @@ int print_fdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
fprintf(fp, "offload ");
fprintf(fp, "%s\n", state_n2a(r->ndm_state));
fflush(fp);
return 0;
}

View File

@ -135,6 +135,8 @@ int print_mdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
}
}
fflush(fp);
return 0;
}

View File

@ -2246,6 +2246,42 @@ Besides that, the host 193.233.7.83 is translated into
another prefix to look like 192.203.80.144 when talking
to the outer world.
\subsection{{\tt ip rule save} -- save rules tables}
\label{IP-RULE-SAVE}
\paragraph{Description:} this command saves the contents of the rules
tables or the rule(s) selected by some criteria to standard output.
\paragraph{Arguments:} \verb|ip rule save| has the same arguments as
\verb|ip rule show|.
\paragraph{Example:} This saves all the rules to the {\tt saved\_rules}
file:
\begin{verbatim}
dan@caffeine:~ # ip rule save > saved_rules
\end{verbatim}
\paragraph{Output format:} The format of the data stream provided by
\verb|ip rule save| is that of \verb|rtnetlink|. See
\verb|rtnetlink(7)| for more information.
\subsection{{\tt ip rule restore} -- restore rules tables}
\label{IP-RULE-RESTORE}
\paragraph{Description:} this command restores the contents of the rules
tables according to a data stream as provided by \verb|ip rule save| via
standard input. Note that any rules already in the table are left unchanged,
and duplicates are not ignored.
\paragraph{Arguments:} This command takes no arguments.
\paragraph{Example:} This restores all rules that were saved to the
{\tt saved\_rules} file:
\begin{verbatim}
dan@caffeine:~ # ip rule restore < saved_rules
\end{verbatim}
\section{{\tt ip maddress} --- multicast addresses management}

6
etc/iproute2/bpf_pinning Normal file
View File

@ -0,0 +1,6 @@
#
# subpath mappings from mount point for pinning
#
#3 tracing
#4 foo/bar
#5 tc/cls1

View File

@ -0,0 +1,3 @@
Each file in this directory is an rt_tables configuration file. iproute2
commands scan this directory processing all files that end in '.conf'.

13
examples/bpf/README Normal file
View 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
View 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");

View File

@ -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
View 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");

View File

@ -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
View 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");

View File

@ -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;
};

View 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");

View File

@ -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];

View File

@ -1 +1 @@
static const char SNAPSHOT[] = "150831";
static const char SNAPSHOT[] = "160111";

225
include/bpf_api.h Normal file
View 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__ */

View File

@ -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__ */

View File

@ -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*/

View File

@ -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*/

View 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 */

View File

@ -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

View File

@ -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 */

View File

@ -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
View 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 */

View 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 */

View File

@ -42,6 +42,8 @@ int rtnl_wilddump_req_filter(struct rtnl_handle *rth, int fam, int type,
int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req,
int len)
__attribute__((warn_unused_result));
int rtnl_dump_request_n(struct rtnl_handle *rth, struct nlmsghdr *n)
__attribute__((warn_unused_result));
struct rtnl_ctrl_data {
int nsid;
@ -58,11 +60,16 @@ struct rtnl_dump_filter_arg
{
rtnl_filter_t filter;
void *arg1;
__u16 nc_flags;
};
int rtnl_dump_filter_l(struct rtnl_handle *rth,
const struct rtnl_dump_filter_arg *arg);
int rtnl_dump_filter(struct rtnl_handle *rth, rtnl_filter_t filter, void *arg);
int rtnl_dump_filter_nc(struct rtnl_handle *rth,
rtnl_filter_t filter,
void *arg, __u16 nc_flags);
#define rtnl_dump_filter(rth, filter, arg) \
rtnl_dump_filter_nc(rth, filter, arg, 0)
int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
struct nlmsghdr *answer, size_t len)
__attribute__((warn_unused_result));
@ -86,7 +93,10 @@ int addattr_nest_end(struct nlmsghdr *n, struct rtattr *nest);
struct rtattr *addattr_nest_compat(struct nlmsghdr *n, int maxlen, int type,
const void *data, int len);
int addattr_nest_compat_end(struct nlmsghdr *n, struct rtattr *nest);
int rta_addattr8(struct rtattr *rta, int maxlen, int type, __u8 data);
int rta_addattr16(struct rtattr *rta, int maxlen, int type, __u16 data);
int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data);
int rta_addattr64(struct rtattr *rta, int maxlen, int type, __u64 data);
int rta_addattr_l(struct rtattr *rta, int maxlen, int type,
const void *data, int alen);
@ -98,6 +108,13 @@ int parse_rtattr_byindex(struct rtattr *tb[], int max,
struct rtattr *parse_rtattr_one(int type, struct rtattr *rta, int len);
int __parse_rtattr_nested_compat(struct rtattr *tb[], int max, struct rtattr *rta, int len);
struct rtattr *rta_nest(struct rtattr *rta, int maxlen, int type);
int rta_nest_end(struct rtattr *rta, struct rtattr *nest);
#define RTA_TAIL(rta) \
((struct rtattr *) (((void *) (rta)) + \
RTA_ALIGN((rta)->rta_len)))
#define parse_rtattr_nested(tb, max, rta) \
(parse_rtattr((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta)))

View File

@ -63,50 +63,16 @@ struct bpf_insn {
__s32 imm; /* signed immediate constant */
};
/* BPF syscall commands */
/* BPF syscall commands, see bpf(2) man-page for details. */
enum bpf_cmd {
/* create a map with given type and attributes
* fd = bpf(BPF_MAP_CREATE, union bpf_attr *, u32 size)
* returns fd or negative error
* map is deleted when fd is closed
*/
BPF_MAP_CREATE,
/* lookup key in a given map
* err = bpf(BPF_MAP_LOOKUP_ELEM, union bpf_attr *attr, u32 size)
* Using attr->map_fd, attr->key, attr->value
* returns zero and stores found elem into value
* or negative error
*/
BPF_MAP_LOOKUP_ELEM,
/* create or update key/value pair in a given map
* err = bpf(BPF_MAP_UPDATE_ELEM, union bpf_attr *attr, u32 size)
* Using attr->map_fd, attr->key, attr->value, attr->flags
* returns zero or negative error
*/
BPF_MAP_UPDATE_ELEM,
/* find and delete elem by key in a given map
* err = bpf(BPF_MAP_DELETE_ELEM, union bpf_attr *attr, u32 size)
* Using attr->map_fd, attr->key
* returns zero or negative error
*/
BPF_MAP_DELETE_ELEM,
/* lookup key in a given map and return next key
* err = bpf(BPF_MAP_GET_NEXT_KEY, union bpf_attr *attr, u32 size)
* Using attr->map_fd, attr->key, attr->next_key
* returns zero and stores next key or negative error
*/
BPF_MAP_GET_NEXT_KEY,
/* verify and load eBPF program
* prog_fd = bpf(BPF_PROG_LOAD, union bpf_attr *attr, u32 size)
* Using attr->prog_type, attr->insns, attr->license
* returns fd or negative error
*/
BPF_PROG_LOAD,
BPF_OBJ_PIN,
BPF_OBJ_GET,
};
enum bpf_map_type {
@ -160,6 +126,11 @@ union bpf_attr {
__aligned_u64 log_buf; /* user supplied buffer */
__u32 kern_version; /* checked when prog_type=kprobe */
};
struct { /* anonymous struct used by BPF_OBJ_* commands */
__aligned_u64 pathname;
__u32 bpf_fd;
};
} __attribute__((aligned(8)));
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
@ -272,9 +243,55 @@ enum bpf_func_id {
BPF_FUNC_skb_get_tunnel_key,
BPF_FUNC_skb_set_tunnel_key,
BPF_FUNC_perf_event_read, /* u64 bpf_perf_event_read(&map, index) */
/**
* bpf_redirect(ifindex, flags) - redirect to another netdev
* @ifindex: ifindex of the net device
* @flags: bit 0 - if set, redirect to ingress instead of egress
* other bits - reserved
* Return: TC_ACT_REDIRECT
*/
BPF_FUNC_redirect,
/**
* bpf_get_route_realm(skb) - retrieve a dst's tclassid
* @skb: pointer to skb
* Return: realm if != 0
*/
BPF_FUNC_get_route_realm,
/**
* bpf_perf_event_output(ctx, map, index, data, size) - output perf raw sample
* @ctx: struct pt_regs*
* @map: pointer to perf_event_array map
* @index: index of event in the map
* @data: data on stack to be output as raw data
* @size: size of data
* Return: 0 on success
*/
BPF_FUNC_perf_event_output,
BPF_FUNC_skb_load_bytes,
__BPF_FUNC_MAX_ID,
};
/* All flags used by eBPF helper functions, placed here. */
/* BPF_FUNC_skb_store_bytes flags. */
#define BPF_F_RECOMPUTE_CSUM (1ULL << 0)
/* BPF_FUNC_l3_csum_replace and BPF_FUNC_l4_csum_replace flags.
* First 4 bits are for passing the header field size.
*/
#define BPF_F_HDR_FIELD_MASK 0xfULL
/* BPF_FUNC_l4_csum_replace flags. */
#define BPF_F_PSEUDO_HDR (1ULL << 4)
/* BPF_FUNC_clone_redirect and BPF_FUNC_redirect flags. */
#define BPF_F_INGRESS (1ULL << 0)
/* BPF_FUNC_skb_set_tunnel_key and BPF_FUNC_skb_get_tunnel_key flags. */
#define BPF_F_TUNINFO_IPV6 (1ULL << 0)
/* user accessible mirror of in-kernel sk_buff.
* new fields can only be added to the end of this structure
*/
@ -293,11 +310,17 @@ struct __sk_buff {
__u32 tc_index;
__u32 cb[5];
__u32 hash;
__u32 tc_classid;
};
struct bpf_tunnel_key {
__u32 tunnel_id;
__u32 remote_ipv4;
union {
__u32 remote_ipv4;
__u32 remote_ipv6[4];
};
__u8 tunnel_tos;
__u8 tunnel_ttl;
};
#endif /* __LINUX_BPF_H__ */

View File

@ -127,6 +127,7 @@ enum {
#define BRIDGE_VLAN_INFO_UNTAGGED (1<<2) /* VLAN egresses untagged */
#define BRIDGE_VLAN_INFO_RANGE_BEGIN (1<<3) /* VLAN is start of vlan range */
#define BRIDGE_VLAN_INFO_RANGE_END (1<<4) /* VLAN is end of vlan range */
#define BRIDGE_VLAN_INFO_BRENTRY (1<<5) /* Global bridge VLAN entry */
struct bridge_vlan_info {
__u16 flags;

View File

@ -42,6 +42,7 @@
#define ETH_P_LOOP 0x0060 /* Ethernet Loopback packet */
#define ETH_P_PUP 0x0200 /* Xerox PUP packet */
#define ETH_P_PUPAT 0x0201 /* Xerox PUP Addr Trans packet */
#define ETH_P_TSN 0x22F0 /* TSN (IEEE 1722) packet */
#define ETH_P_IP 0x0800 /* Internet Protocol packet */
#define ETH_P_X25 0x0805 /* CCITT X.25 */
#define ETH_P_ARP 0x0806 /* Address Resolution packet */

View File

@ -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 */
@ -230,11 +231,47 @@ enum {
IFLA_BR_PRIORITY,
IFLA_BR_VLAN_FILTERING,
IFLA_BR_VLAN_PROTOCOL,
IFLA_BR_GROUP_FWD_MASK,
IFLA_BR_ROOT_ID,
IFLA_BR_BRIDGE_ID,
IFLA_BR_ROOT_PORT,
IFLA_BR_ROOT_PATH_COST,
IFLA_BR_TOPOLOGY_CHANGE,
IFLA_BR_TOPOLOGY_CHANGE_DETECTED,
IFLA_BR_HELLO_TIMER,
IFLA_BR_TCN_TIMER,
IFLA_BR_TOPOLOGY_CHANGE_TIMER,
IFLA_BR_GC_TIMER,
IFLA_BR_GROUP_ADDR,
IFLA_BR_FDB_FLUSH,
IFLA_BR_MCAST_ROUTER,
IFLA_BR_MCAST_SNOOPING,
IFLA_BR_MCAST_QUERY_USE_IFADDR,
IFLA_BR_MCAST_QUERIER,
IFLA_BR_MCAST_HASH_ELASTICITY,
IFLA_BR_MCAST_HASH_MAX,
IFLA_BR_MCAST_LAST_MEMBER_CNT,
IFLA_BR_MCAST_STARTUP_QUERY_CNT,
IFLA_BR_MCAST_LAST_MEMBER_INTVL,
IFLA_BR_MCAST_MEMBERSHIP_INTVL,
IFLA_BR_MCAST_QUERIER_INTVL,
IFLA_BR_MCAST_QUERY_INTVL,
IFLA_BR_MCAST_QUERY_RESPONSE_INTVL,
IFLA_BR_MCAST_STARTUP_QUERY_INTVL,
IFLA_BR_NF_CALL_IPTABLES,
IFLA_BR_NF_CALL_IP6TABLES,
IFLA_BR_NF_CALL_ARPTABLES,
IFLA_BR_VLAN_DEFAULT_PVID,
__IFLA_BR_MAX,
};
#define IFLA_BR_MAX (__IFLA_BR_MAX - 1)
struct ifla_bridge_id {
__u8 prio[2];
__u8 addr[6]; /* ETH_ALEN */
};
enum {
BRIDGE_MODE_UNSPEC,
BRIDGE_MODE_HAIRPIN,
@ -254,6 +291,19 @@ enum {
IFLA_BRPORT_PROXYARP, /* proxy ARP */
IFLA_BRPORT_LEARNING_SYNC, /* mac learning sync from device */
IFLA_BRPORT_PROXYARP_WIFI, /* proxy ARP for Wi-Fi */
IFLA_BRPORT_ROOT_ID, /* designated root */
IFLA_BRPORT_BRIDGE_ID, /* designated bridge */
IFLA_BRPORT_DESIGNATED_PORT,
IFLA_BRPORT_DESIGNATED_COST,
IFLA_BRPORT_ID,
IFLA_BRPORT_NO,
IFLA_BRPORT_TOPOLOGY_CHANGE_ACK,
IFLA_BRPORT_CONFIG_PENDING,
IFLA_BRPORT_MESSAGE_AGE_TIMER,
IFLA_BRPORT_FORWARD_DELAY_TIMER,
IFLA_BRPORT_HOLD_TIMER,
IFLA_BRPORT_FLUSH,
IFLA_BRPORT_MULTICAST_ROUTER,
__IFLA_BRPORT_MAX
};
#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
@ -410,6 +460,10 @@ enum {
IFLA_GENEVE_TOS,
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)
@ -499,6 +553,7 @@ enum {
* on/off switch
*/
IFLA_VF_STATS, /* network device statistics */
IFLA_VF_TRUST, /* Trust VF */
__IFLA_VF_MAX,
};
@ -560,6 +615,11 @@ enum {
#define IFLA_VF_STATS_MAX (__IFLA_VF_STATS_MAX - 1)
struct ifla_vf_trust {
__u32 vf;
__u32 setting;
};
/* VF ports management section
*
* Nested layout of set/get msg is:

37
include/linux/ila.h Normal file
View File

@ -0,0 +1,37 @@
/* ila.h - ILA Interface */
#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 */

View File

@ -196,6 +196,7 @@ struct in6_flowlabel_req {
#define IPV6_IPSEC_POLICY 34
#define IPV6_XFRM_POLICY 35
#define IPV6_HDRINCL 36
#endif
/*

43
include/linux/lwtunnel.h Normal file
View File

@ -0,0 +1,43 @@
#ifndef _LWTUNNEL_H_
#define _LWTUNNEL_H_
#include <linux/types.h>
enum lwtunnel_encap_types {
LWTUNNEL_ENCAP_NONE,
LWTUNNEL_ENCAP_MPLS,
LWTUNNEL_ENCAP_IP,
LWTUNNEL_ENCAP_ILA,
LWTUNNEL_ENCAP_IP6,
__LWTUNNEL_ENCAP_MAX,
};
#define LWTUNNEL_ENCAP_MAX (__LWTUNNEL_ENCAP_MAX - 1)
enum lwtunnel_ip_t {
LWTUNNEL_IP_UNSPEC,
LWTUNNEL_IP_ID,
LWTUNNEL_IP_DST,
LWTUNNEL_IP_SRC,
LWTUNNEL_IP_TTL,
LWTUNNEL_IP_TOS,
LWTUNNEL_IP_FLAGS,
__LWTUNNEL_IP_MAX,
};
#define LWTUNNEL_IP_MAX (__LWTUNNEL_IP_MAX - 1)
enum lwtunnel_ip6_t {
LWTUNNEL_IP6_UNSPEC,
LWTUNNEL_IP6_ID,
LWTUNNEL_IP6_DST,
LWTUNNEL_IP6_SRC,
LWTUNNEL_IP6_HOPLIMIT,
LWTUNNEL_IP6_TC,
LWTUNNEL_IP6_FLAGS,
__LWTUNNEL_IP6_MAX,
};
#define LWTUNNEL_IP6_MAX (__LWTUNNEL_IP6_MAX - 1)
#endif /* _LWTUNNEL_H_ */

View File

@ -0,0 +1,28 @@
/*
* mpls tunnel api
*
* Authors:
* Roopa Prabhu <roopa@cumulusnetworks.com>
*
* 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.
*/
#ifndef _LINUX_MPLS_IPTUNNEL_H
#define _LINUX_MPLS_IPTUNNEL_H
/* MPLS tunnel attributes
* [RTA_ENCAP] = {
* [MPLS_IPTUNNEL_DST]
* }
*/
enum {
MPLS_IPTUNNEL_UNSPEC,
MPLS_IPTUNNEL_DST,
__MPLS_IPTUNNEL_MAX,
};
#define MPLS_IPTUNNEL_MAX (__MPLS_IPTUNNEL_MAX - 1)
#endif /* _LINUX_MPLS_IPTUNNEL_H */

View File

@ -54,6 +54,7 @@ struct nlmsghdr {
#define NLM_F_ACK 4 /* Reply with ack, with zero or error code */
#define NLM_F_ECHO 8 /* Echo this request */
#define NLM_F_DUMP_INTR 16 /* Dump was inconsistent due to sequence change */
#define NLM_F_DUMP_FILTERED 32 /* Dump was filtered as requested */
/* Modifiers to GET request */
#define NLM_F_ROOT 0x100 /* specify tree root */

View File

@ -33,6 +33,7 @@ enum {
#define TC_ACT_STOLEN 4
#define TC_ACT_QUEUED 5
#define TC_ACT_REPEAT 6
#define TC_ACT_REDIRECT 7
#define TC_ACT_JUMP 0x10000000
/* Action type identifiers*/
@ -319,6 +320,8 @@ enum {
/* BPF classifier */
#define TCA_BPF_FLAG_ACT_DIRECT (1 << 0)
enum {
TCA_BPF_UNSPEC,
TCA_BPF_ACT,
@ -328,6 +331,7 @@ enum {
TCA_BPF_OPS,
TCA_BPF_FD,
TCA_BPF_NAME,
TCA_BPF_FLAGS,
__TCA_BPF_MAX,
};

View File

@ -72,6 +72,10 @@ struct tc_estimator {
#define TC_H_UNSPEC (0U)
#define TC_H_ROOT (0xFFFFFFFFU)
#define TC_H_INGRESS (0xFFFFFFF1U)
#define TC_H_CLSACT TC_H_INGRESS
#define TC_H_MIN_INGRESS 0xFFF2U
#define TC_H_MIN_EGRESS 0xFFF3U
/* Need to corrospond to iproute2 tc/tc_core.h "enum link_layer" */
enum tc_link_layer {

View File

@ -160,7 +160,7 @@ struct rtattr {
/* Macros to handle rtattributes */
#define RTA_ALIGNTO 4
#define RTA_ALIGNTO 4U
#define RTA_ALIGN(len) ( ((len)+RTA_ALIGNTO-1) & ~(RTA_ALIGNTO-1) )
#define RTA_OK(rta,len) ((len) >= (int)sizeof(struct rtattr) && \
(rta)->rta_len >= sizeof(struct rtattr) && \
@ -270,6 +270,7 @@ enum rt_scope_t {
#define RTM_F_CLONED 0x200 /* This route is cloned */
#define RTM_F_EQUALIZE 0x400 /* Multipath equalizer: NI */
#define RTM_F_PREFIX 0x800 /* Prefix addresses */
#define RTM_F_LOOKUP_TABLE 0x1000 /* set rtm_table to FIB lookup result */
/* Reserved table identifiers */
@ -310,6 +311,7 @@ enum rtattr_type_t {
RTA_PREF,
RTA_ENCAP_TYPE,
RTA_ENCAP,
RTA_EXPIRES,
__RTA_MAX
};
@ -664,6 +666,7 @@ struct tcamsg {
#define RTEXT_FILTER_VF (1 << 0)
#define RTEXT_FILTER_BRVLAN (1 << 1)
#define RTEXT_FILTER_BRVLAN_COMPRESSED (1 << 2)
#define RTEXT_FILTER_SKIP_STATS (1 << 3)
/* End of information exported to user level */

View File

@ -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;

View File

@ -11,7 +11,8 @@
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, see <http://www.gnu.org/licenses>.
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307 USA.
*
* Author: Alexander Duyck <alexander.h.duyck@intel.com>
*/

View File

@ -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

View File

@ -4,7 +4,6 @@
char *rtnl_rtntype_n2a(int id, char *buf, int len);
int rtnl_rtntype_a2n(int *id, char *arg);
int get_rt_realms(__u32 *realms, char *arg);
int get_rt_realms_or_raw(__u32 *realms, char *arg);
#endif /* __RTM_MAP_H__ */

View File

@ -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]
@ -47,6 +51,7 @@ void incomplete_command(void) __attribute__((noreturn));
#define NEXT_ARG() do { argv++; if (--argc <= 0) incomplete_command(); } while(0)
#define NEXT_ARG_OK() (argc - 1 > 0)
#define NEXT_ARG_FWD() do { argv++; argc--; } while(0)
#define PREV_ARG() do { argv--; argc++; } while(0)
typedef struct
@ -92,6 +97,7 @@ int get_prefix_1(inet_prefix *dst, char *arg, int family);
int get_addr(inet_prefix *dst, const char *arg, int family);
int get_prefix(inet_prefix *dst, char *arg, int family);
int mask2bits(__u32 netmask);
int get_addr_ila(__u64 *val, const char *arg);
int get_integer(int *val, const char *arg, int base);
int get_unsigned(unsigned *val, const char *arg, int base);
@ -106,9 +112,12 @@ int get_u16(__u16 *val, const char *arg, int base);
int get_s16(__s16 *val, const char *arg, int base);
int get_u8(__u8 *val, const char *arg, int base);
int get_s8(__s8 *val, const char *arg, int base);
int get_addr64(__u64 *ap, const char *cp);
char* hexstring_n2a(const __u8 *str, int len, char *buf, int blen);
__u8* hexstring_a2n(const char *str, __u8 *buf, int blen);
#define ADDR64_BUF_SIZE sizeof("xxxx:xxxx:xxxx:xxxx")
int addr64_n2a(__u64 addr, char *buff, size_t len);
int af_bit_len(int af);
int af_byte_len(int af);
@ -191,6 +200,12 @@ 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))
extern int cmdlineno;
ssize_t getcmdline(char **line, size_t *len, FILE *in);
int makeargs(char *line, char *argv[], int maxargs);

567
include/xtables.h Normal file
View 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 */

View File

@ -3,11 +3,11 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \
ipmaddr.o ipmonitor.o ipmroute.o ipprefix.o iptuntap.o iptoken.o \
ipxfrm.o xfrm_state.o xfrm_policy.o xfrm_monitor.o \
iplink_vlan.o link_veth.o link_gre.o iplink_can.o \
iplink_macvlan.o iplink_macvtap.o ipl2tp.o link_vti.o link_vti6.o \
iplink_macvlan.o ipl2tp.o link_vti.o link_vti6.o \
iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o \
link_iptnl.o link_gre6.o iplink_bond.o iplink_bond_slave.o iplink_hsr.o \
iplink_bridge.o iplink_bridge_slave.o ipfou.o iplink_ipvlan.o \
iplink_geneve.o iplink_vrf.o
iplink_geneve.o iplink_vrf.o iproute_lwtunnel.o
RTMONOBJ=rtmon.o

View File

@ -68,14 +68,17 @@ static void usage(void)
static void print_tunnel(struct ip6_tnl_parm2 *p)
{
char remote[64];
char local[64];
inet_ntop(AF_INET6, &p->raddr, remote, sizeof(remote));
inet_ntop(AF_INET6, &p->laddr, local, sizeof(local));
char s1[1024];
char s2[1024];
/* Do not use format_host() for local addr,
* symbolic name will not be useful.
*/
printf("%s: %s/ipv6 remote %s local %s",
p->name, tnl_strproto(p->proto), remote, local);
p->name,
tnl_strproto(p->proto),
format_host(AF_INET6, 16, &p->raddr, s1, sizeof(s1)),
rt_addr_n2a(AF_INET6, 16, &p->laddr, s2, sizeof(s2)));
if (p->link) {
const char *n = ll_index_to_name(p->link);
if (n)
@ -107,22 +110,22 @@ static void print_tunnel(struct ip6_tnl_parm2 *p)
printf(" dscp inherit");
if (p->proto == IPPROTO_GRE) {
if ((p->i_flags&GRE_KEY) && (p->o_flags&GRE_KEY) && p->o_key == p->i_key)
if ((p->i_flags & GRE_KEY) && (p->o_flags & GRE_KEY) && p->o_key == p->i_key)
printf(" key %u", ntohl(p->i_key));
else if ((p->i_flags|p->o_flags)&GRE_KEY) {
if (p->i_flags&GRE_KEY)
printf(" ikey %u ", ntohl(p->i_key));
if (p->o_flags&GRE_KEY)
printf(" okey %u ", ntohl(p->o_key));
else if ((p->i_flags | p->o_flags) & GRE_KEY) {
if (p->i_flags & GRE_KEY)
printf(" ikey %u", ntohl(p->i_key));
if (p->o_flags & GRE_KEY)
printf(" okey %u", ntohl(p->o_key));
}
if (p->i_flags&GRE_SEQ)
if (p->i_flags & GRE_SEQ)
printf("%s Drop packets out of sequence.", _SL_);
if (p->i_flags&GRE_CSUM)
if (p->i_flags & GRE_CSUM)
printf("%s Checksum in received packet is required.", _SL_);
if (p->o_flags&GRE_SEQ)
if (p->o_flags & GRE_SEQ)
printf("%s Sequence packets on output.", _SL_);
if (p->o_flags&GRE_CSUM)
if (p->o_flags & GRE_CSUM)
printf("%s Checksum output packets.", _SL_);
}
}
@ -230,45 +233,18 @@ static int parse_args(int argc, char **argv, int cmd, struct ip6_tnl_parm2 *p)
invarg("not inherit", *argv);
p->flags |= IP6_TNL_F_RCV_DSCP_COPY;
} else if (strcmp(*argv, "key") == 0) {
unsigned uval;
NEXT_ARG();
p->i_flags |= GRE_KEY;
p->o_flags |= GRE_KEY;
if (strchr(*argv, '.'))
p->i_key = p->o_key = get_addr32(*argv);
else {
if (get_unsigned(&uval, *argv, 0) < 0) {
fprintf(stderr, "invalid value of \"key\"\n");
exit(-1);
}
p->i_key = p->o_key = htonl(uval);
}
p->i_key = p->o_key = tnl_parse_key("key", *argv);
} else if (strcmp(*argv, "ikey") == 0) {
unsigned uval;
NEXT_ARG();
p->i_flags |= GRE_KEY;
if (strchr(*argv, '.'))
p->i_key = get_addr32(*argv);
else {
if (get_unsigned(&uval, *argv, 0)<0) {
fprintf(stderr, "invalid value of \"ikey\"\n");
exit(-1);
}
p->i_key = htonl(uval);
}
p->i_key = tnl_parse_key("ikey", *argv);
} else if (strcmp(*argv, "okey") == 0) {
unsigned uval;
NEXT_ARG();
p->o_flags |= GRE_KEY;
if (strchr(*argv, '.'))
p->o_key = get_addr32(*argv);
else {
if (get_unsigned(&uval, *argv, 0)<0) {
fprintf(stderr, "invalid value of \"okey\"\n");
exit(-1);
}
p->o_key = htonl(uval);
}
p->o_key = tnl_parse_key("okey", *argv);
} else if (strcmp(*argv, "seq") == 0) {
p->i_flags |= GRE_SEQ;
p->o_flags |= GRE_SEQ;
@ -286,8 +262,7 @@ static int parse_args(int argc, char **argv, int cmd, struct ip6_tnl_parm2 *p)
} else {
if (strcmp(*argv, "name") == 0) {
NEXT_ARG();
}
if (matches(*argv, "help") == 0)
} else if (matches(*argv, "help") == 0)
usage();
if (p->name[0])
duparg2("name", *argv);
@ -305,8 +280,10 @@ static int parse_args(int argc, char **argv, int cmd, struct ip6_tnl_parm2 *p)
}
if (medium[0]) {
p->link = ll_name_to_index(medium);
if (p->link == 0)
if (p->link == 0) {
fprintf(stderr, "Cannot find device \"%s\"\n", medium);
return -1;
}
}
return 0;
}
@ -351,23 +328,19 @@ static int do_tunnels_list(struct ip6_tnl_parm2 *p)
FILE *fp = fopen("/proc/net/dev", "r");
if (fp == NULL) {
perror("fopen");
goto end;
return -1;
}
/* skip two lines at the begenning of the file */
if (!fgets(buf, sizeof(buf), fp) ||
!fgets(buf, sizeof(buf), fp)) {
fprintf(stderr, "/proc/net/dev read error\n");
return -1;
goto end;
}
while (fgets(buf, sizeof(buf), fp) != NULL) {
char name[IFNAMSIZ];
int index, type;
unsigned long rx_bytes, rx_packets, rx_errs, rx_drops,
rx_fifo, rx_frame,
tx_bytes, tx_packets, tx_errs, tx_drops,
tx_fifo, tx_colls, tx_carrier, rx_multi;
struct ip6_tnl_parm2 p1;
char *ptr;
@ -377,12 +350,6 @@ static int do_tunnels_list(struct ip6_tnl_parm2 *p)
fprintf(stderr, "Wrong format for /proc/net/dev. Giving up.\n");
goto end;
}
if (sscanf(ptr, "%ld%ld%ld%ld%ld%ld%ld%*d%ld%ld%ld%ld%ld%ld%ld",
&rx_bytes, &rx_packets, &rx_errs, &rx_drops,
&rx_fifo, &rx_frame, &rx_multi,
&tx_bytes, &tx_packets, &tx_errs, &tx_drops,
&tx_fifo, &tx_colls, &tx_carrier) != 14)
continue;
if (p->name[0] && strcmp(p->name, name))
continue;
index = ll_name_to_index(name);
@ -408,22 +375,13 @@ static int do_tunnels_list(struct ip6_tnl_parm2 *p)
if (!ip6_tnl_parm_match(p, &p1))
continue;
print_tunnel(&p1);
if (show_stats) {
printf("%s", _SL_);
printf("RX: Packets Bytes Errors CsumErrs OutOfSeq Mcasts%s", _SL_);
printf(" %-10ld %-12ld %-6ld %-8ld %-8ld %-8ld%s",
rx_packets, rx_bytes, rx_errs, rx_frame, rx_fifo, rx_multi, _SL_);
printf("TX: Packets Bytes Errors DeadLoop NoRoute NoBufs%s", _SL_);
printf(" %-10ld %-12ld %-6ld %-8ld %-8ld %-6ld",
tx_packets, tx_bytes, tx_errs, tx_colls, tx_carrier, tx_drops);
}
if (show_stats)
tnl_print_stats(ptr);
printf("\n");
}
err = 0;
end:
if (fp)
fclose(fp);
fclose(fp);
return err;
}

View File

@ -1,68 +1,60 @@
extern int get_operstate(const char *name);
extern int print_linkinfo(const struct sockaddr_nl *who,
struct nlmsghdr *n,
void *arg);
extern int print_linkinfo_brief(const struct sockaddr_nl *who,
struct nlmsghdr *n,
void *arg);
extern int print_addrinfo(const struct sockaddr_nl *who,
struct nlmsghdr *n,
void *arg);
extern int print_addrlabel(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg);
extern int print_neigh(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg);
extern int print_ntable(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg);
extern int ipaddr_list(int argc, char **argv);
extern int ipaddr_list_link(int argc, char **argv);
void ipaddr_get_vf_rate(int, int *, int *, int);
extern int iproute_monitor(int argc, char **argv);
extern void iplink_usage(void) __attribute__((noreturn));
extern void iproute_reset_filter(int ifindex);
extern void ipmroute_reset_filter(int ifindex);
extern void ipaddr_reset_filter(int oneline, int ifindex);
extern void ipneigh_reset_filter(int ifindex);
extern void ipntable_reset_filter(void);
extern void ipnetconf_reset_filter(int ifindex);
extern int print_route(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg);
extern int print_mroute(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg);
extern int print_prefix(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg);
extern int print_rule(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg);
extern int print_netconf(const struct sockaddr_nl *who,
struct rtnl_ctrl_data *ctrl,
int get_operstate(const char *name);
int print_linkinfo(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg);
int print_linkinfo_brief(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg);
extern void netns_map_init(void);
extern int print_nsid(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg);
extern int do_ipaddr(int argc, char **argv);
extern int do_ipaddrlabel(int argc, char **argv);
extern int do_iproute(int argc, char **argv);
extern int do_iprule(int argc, char **argv);
extern int do_ipneigh(int argc, char **argv);
extern int do_ipntable(int argc, char **argv);
extern int do_iptunnel(int argc, char **argv);
extern int do_ip6tunnel(int argc, char **argv);
extern int do_iptuntap(int argc, char **argv);
extern int do_iplink(int argc, char **argv);
extern int do_ipmonitor(int argc, char **argv);
extern int do_multiaddr(int argc, char **argv);
extern int do_multiroute(int argc, char **argv);
extern int do_multirule(int argc, char **argv);
extern int do_netns(int argc, char **argv);
extern int do_xfrm(int argc, char **argv);
extern int do_ipl2tp(int argc, char **argv);
extern int do_ipfou(int argc, char **argv);
extern int do_tcp_metrics(int argc, char **argv);
extern int do_ipnetconf(int argc, char **argv);
extern int do_iptoken(int argc, char **argv);
extern int iplink_get(unsigned int flags, char *name, __u32 filt_mask);
int print_addrinfo(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg);
int print_addrlabel(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg);
int print_neigh(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg);
int ipaddr_list_link(int argc, char **argv);
void ipaddr_get_vf_rate(int, int *, int *, int);
void iplink_usage(void) __attribute__((noreturn));
void iproute_reset_filter(int ifindex);
void ipmroute_reset_filter(int ifindex);
void ipaddr_reset_filter(int oneline, int ifindex);
void ipneigh_reset_filter(int ifindex);
void ipnetconf_reset_filter(int ifindex);
int print_route(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg);
int print_mroute(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg);
int print_prefix(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg);
int print_rule(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg);
int print_netconf(const struct sockaddr_nl *who,
struct rtnl_ctrl_data *ctrl,
struct nlmsghdr *n, void *arg);
void netns_map_init(void);
int print_nsid(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg);
int do_ipaddr(int argc, char **argv);
int do_ipaddrlabel(int argc, char **argv);
int do_iproute(int argc, char **argv);
int do_iprule(int argc, char **argv);
int do_ipneigh(int argc, char **argv);
int do_ipntable(int argc, char **argv);
int do_iptunnel(int argc, char **argv);
int do_ip6tunnel(int argc, char **argv);
int do_iptuntap(int argc, char **argv);
int do_iplink(int argc, char **argv);
int do_ipmonitor(int argc, char **argv);
int do_multiaddr(int argc, char **argv);
int do_multiroute(int argc, char **argv);
int do_multirule(int argc, char **argv);
int do_netns(int argc, char **argv);
int do_xfrm(int argc, char **argv);
int do_ipl2tp(int argc, char **argv);
int do_ipfou(int argc, char **argv);
int do_tcp_metrics(int argc, char **argv);
int do_ipnetconf(int argc, char **argv);
int do_iptoken(int argc, char **argv);
int iplink_get(unsigned int flags, char *name, __u32 filt_mask);
static inline int rtm_get_table(struct rtmsg *r, struct rtattr **tb)
{

View File

@ -285,13 +285,23 @@ static void print_af_spec(FILE *fp, struct rtattr *af_spec_attr)
parse_rtattr_nested(tb, IFLA_INET6_MAX, inet6_attr);
if (tb[IFLA_INET6_ADDR_GEN_MODE]) {
switch (rta_getattr_u8(tb[IFLA_INET6_ADDR_GEN_MODE])) {
__u8 mode = rta_getattr_u8(tb[IFLA_INET6_ADDR_GEN_MODE]);
switch (mode) {
case IN6_ADDR_GEN_MODE_EUI64:
fprintf(fp, "addrgenmode eui64 ");
break;
case IN6_ADDR_GEN_MODE_NONE:
fprintf(fp, "addrgenmode none ");
break;
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;
}
}
}
@ -345,7 +355,7 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo)
} else
vf_linkstate = NULL;
fprintf(fp, "\n vf %d MAC %s", vf_mac->vf,
fprintf(fp, "%s vf %d MAC %s", _SL_, vf_mac->vf,
ll_addr_n2a((unsigned char *)&vf_mac->mac,
ETH_ALEN, 0, b1, sizeof(b1)));
if (vf_vlan->vlan)
@ -893,7 +903,17 @@ int print_linkinfo(const struct sockaddr_nl *who,
static int flush_update(void)
{
if (rtnl_send_check(&rth, filter.flushb, filter.flushp) < 0) {
/*
* Note that the kernel may delete multiple addresses for one
* delete request (e.g. if ipv4 address promotion is disabled).
* Since a flush operation is really a series of delete requests
* its possible that we may request an address delete that has
* already been done by the kernel. Therefore, ignore EADDRNOTAVAIL
* errors returned from a flush request
*/
if ((rtnl_send_check(&rth, filter.flushb, filter.flushp) < 0) &&
(errno != EADDRNOTAVAIL)) {
perror("Failed to send flush request");
return -1;
}
@ -1138,28 +1158,6 @@ brief_exit:
return 0;
}
static int print_addrinfo_primary(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg)
{
struct ifaddrmsg *ifa = NLMSG_DATA(n);
if (ifa->ifa_flags & IFA_F_SECONDARY)
return 0;
return print_addrinfo(who, n, arg);
}
static int print_addrinfo_secondary(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg)
{
struct ifaddrmsg *ifa = NLMSG_DATA(n);
if (!(ifa->ifa_flags & IFA_F_SECONDARY))
return 0;
return print_addrinfo(who, n, arg);
}
struct nlmsg_list
{
struct nlmsg_list *next;
@ -1410,26 +1408,13 @@ static int ipaddr_flush(void)
filter.flushe = sizeof(flushb);
while ((max_flush_loops == 0) || (round < max_flush_loops)) {
const struct rtnl_dump_filter_arg a[3] = {
{
.filter = print_addrinfo_secondary,
.arg1 = stdout,
},
{
.filter = print_addrinfo_primary,
.arg1 = stdout,
},
{
.filter = NULL,
.arg1 = NULL,
},
};
if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) {
perror("Cannot send dump request");
exit(1);
}
filter.flushed = 0;
if (rtnl_dump_filter_l(&rth, a) < 0) {
if (rtnl_dump_filter_nc(&rth, print_addrinfo,
stdout, NLM_F_DUMP_INTR) < 0) {
fprintf(stderr, "Flush terminated\n");
exit(1);
}
@ -1476,10 +1461,7 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
ipaddr_reset_filter(oneline, 0);
filter.showqueue = 1;
if (filter.family == AF_UNSPEC)
filter.family = preferred_family;
filter.family = preferred_family;
filter.group = -1;
if (action == IPADD_FLUSH) {
@ -1580,7 +1562,7 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
if (strcmp(*argv, "dev") == 0) {
NEXT_ARG();
}
if (matches(*argv, "help") == 0)
else if (matches(*argv, "help") == 0)
usage();
if (filter_dev)
duparg2("dev", *argv);

View File

@ -263,4 +263,3 @@ int do_ipaddrlabel(int argc, char **argv)
fprintf(stderr, "Command \"%s\" is unknown, try \"ip addrlabel help\".\n", *argv);
exit(-1);
}

View File

@ -156,4 +156,3 @@ int do_ipfou(int argc, char **argv)
fprintf(stderr, "Command \"%s\" is unknown, try \"ip fou help\".\n", *argv);
exit(-1);
}

View File

@ -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;
}
@ -710,7 +714,7 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
req.i.ifi_index = 0;
addattr32(&req.n, sizeof(req), IFLA_GROUP, group);
if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
exit(2);
return -2;
return 0;
}
}
@ -809,7 +813,7 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
}
if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
exit(2);
return -2;
return 0;
}
@ -1148,8 +1152,7 @@ static int do_set(int argc, char **argv)
} else {
if (strcmp(*argv, "dev") == 0)
NEXT_ARG();
if (matches(*argv, "help") == 0)
else if (matches(*argv, "help") == 0)
usage();
if (dev)

View File

@ -113,4 +113,3 @@ struct link_util bond_slave_link_util = {
.parse_opt = bond_slave_parse_opt,
.slave = true,
};

View File

@ -55,7 +55,7 @@ static int geneve_parse_opt(struct link_util *lu, int argc, char **argv,
fprintf(stderr, "Invalid address \"%s\"\n", *argv);
return -1;
}
if (IN_MULTICAST(ntohl(daddr)))
if (IN6_IS_ADDR_MULTICAST(&daddr6) || IN_MULTICAST(ntohl(daddr)))
invarg("invalid remote address", *argv);
} else if (!matches(*argv, "ttl") ||
!matches(*argv, "hoplimit")) {
@ -96,18 +96,16 @@ static int geneve_parse_opt(struct link_util *lu, int argc, char **argv,
return -1;
}
if (!daddr) {
fprintf(stderr, "geneve: remove link partner not specified\n");
return -1;
}
if (memcmp(&daddr6, &in6addr_any, sizeof(daddr6)) != 0) {
fprintf(stderr, "geneve: remove link over IPv6 not supported\n");
if (!daddr && memcmp(&daddr6, &in6addr_any, sizeof(daddr6)) == 0) {
fprintf(stderr, "geneve: remote link partner not specified\n");
return -1;
}
addattr32(n, 1024, IFLA_GENEVE_ID, vni);
if (daddr)
addattr_l(n, 1024, IFLA_GENEVE_REMOTE, &daddr, 4);
if (memcmp(&daddr6, &in6addr_any, sizeof(daddr6)) != 0)
addattr_l(n, 1024, IFLA_GENEVE_REMOTE6, &daddr6, sizeof(struct in6_addr));
addattr8(n, 1024, IFLA_GENEVE_TTL, ttl);
addattr8(n, 1024, IFLA_GENEVE_TOS, tos);
@ -135,6 +133,14 @@ static void geneve_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
if (addr)
fprintf(f, "remote %s ",
format_host(AF_INET, 4, &addr, s1, sizeof(s1)));
} else if (tb[IFLA_GENEVE_REMOTE6]) {
struct in6_addr addr;
memcpy(&addr, RTA_DATA(tb[IFLA_GENEVE_REMOTE6]), sizeof(struct in6_addr));
if (memcmp(&addr, &in6addr_any, sizeof(addr)) != 0) {
if (IN6_IS_ADDR_MULTICAST(&addr))
fprintf(f, "remote %s ",
format_host(AF_INET6, sizeof(struct in6_addr), &addr, s1, sizeof(s1)));
}
}
if (tb[IFLA_GENEVE_TTL]) {

View File

@ -1,5 +1,5 @@
/*
* iplink_vlan.c VLAN device support
* iplink_macvlan.c macvlan/macvtap device support
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -20,31 +20,40 @@
#include "utils.h"
#include "ip_common.h"
static void print_explain(FILE *f)
#define pfx_err(lu, ...) { \
fprintf(stderr, "%s: ", lu->id); \
fprintf(stderr, __VA_ARGS__); \
fprintf(stderr, "\n"); \
}
static void print_explain(struct link_util *lu, FILE *f)
{
fprintf(f,
"Usage: ... macvlan mode { private | vepa | bridge | passthru }\n"
"Usage: ... %s mode { private | vepa | bridge | passthru [nopromisc] }\n",
lu->id
);
}
static void explain(void)
static void explain(struct link_util *lu)
{
print_explain(stderr);
print_explain(lu, stderr);
}
static int mode_arg(void)
static int mode_arg(const char *arg)
{
fprintf(stderr, "Error: argument of \"mode\" must be \"private\", "
"\"vepa\", \"bridge\" or \"passthru\" \n");
"\"vepa\", \"bridge\" or \"passthru\", not \"%s\"\n", arg);
return -1;
}
static int macvlan_parse_opt(struct link_util *lu, int argc, char **argv,
struct nlmsghdr *n)
{
__u32 mode = 0;
__u16 flags = 0;
while (argc > 0) {
if (matches(*argv, "mode") == 0) {
__u32 mode = 0;
NEXT_ARG();
if (strcmp(*argv, "private") == 0)
@ -56,26 +65,39 @@ static int macvlan_parse_opt(struct link_util *lu, int argc, char **argv,
else if (strcmp(*argv, "passthru") == 0)
mode = MACVLAN_MODE_PASSTHRU;
else
return mode_arg();
addattr32(n, 1024, IFLA_MACVLAN_MODE, mode);
return mode_arg(*argv);
} else if (matches(*argv, "nopromisc") == 0) {
flags |= MACVLAN_FLAG_NOPROMISC;
} else if (matches(*argv, "help") == 0) {
explain();
explain(lu);
return -1;
} else {
fprintf(stderr, "macvlan: unknown option \"%s\"?\n", *argv);
explain();
pfx_err(lu, "unknown option \"%s\"?", *argv);
explain(lu);
return -1;
}
argc--, argv++;
}
if (mode)
addattr32(n, 1024, IFLA_MACVLAN_MODE, mode);
if (flags) {
if (flags & MACVLAN_FLAG_NOPROMISC &&
mode != MACVLAN_MODE_PASSTHRU) {
pfx_err(lu, "nopromisc flag only valid in passthru mode");
explain(lu);
return -1;
}
addattr16(n, 1024, IFLA_MACVLAN_FLAGS, flags);
}
return 0;
}
static void macvlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
{
__u32 mode;
__u16 flags;
if (!tb)
return;
@ -91,12 +113,20 @@ static void macvlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]
: mode == MACVLAN_MODE_BRIDGE ? "bridge"
: mode == MACVLAN_MODE_PASSTHRU ? "passthru"
: "unknown");
if (!tb[IFLA_MACVLAN_FLAGS] ||
RTA_PAYLOAD(tb[IFLA_MACVLAN_FLAGS]) < sizeof(__u16))
return;
flags = rta_getattr_u16(tb[IFLA_MACVLAN_FLAGS]);
if (flags & MACVLAN_FLAG_NOPROMISC)
fprintf(f, "nopromisc ");
}
static void macvlan_print_help(struct link_util *lu, int argc, char **argv,
FILE *f)
{
print_explain(f);
print_explain(lu, f);
}
struct link_util macvlan_link_util = {
@ -106,3 +136,11 @@ struct link_util macvlan_link_util = {
.print_opt = macvlan_print_opt,
.print_help = macvlan_print_help,
};
struct link_util macvtap_link_util = {
.id = "macvtap",
.maxattr = IFLA_MACVLAN_MAX,
.parse_opt = macvlan_parse_opt,
.print_opt = macvlan_print_opt,
.print_help = macvlan_print_help,
};

View File

@ -1,105 +0,0 @@
/*
* iplink_macvtap.c macvtap device support
*
* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <linux/if_link.h>
#include "rt_names.h"
#include "utils.h"
#include "ip_common.h"
static void print_explain(FILE *f)
{
fprintf(stderr,
"Usage: ... macvtap mode { private | vepa | bridge | passthru }\n"
);
}
static void explain(void)
{
print_explain(stderr);
}
static int mode_arg(const char *arg)
{
fprintf(stderr, "Error: argument of \"mode\" must be \"private\", "
"\"vepa\", \"bridge\" or \"passthru\", not \"%s\"\n", arg);
return -1;
}
static int macvtap_parse_opt(struct link_util *lu, int argc, char **argv,
struct nlmsghdr *n)
{
while (argc > 0) {
if (matches(*argv, "mode") == 0) {
__u32 mode = 0;
NEXT_ARG();
if (strcmp(*argv, "private") == 0)
mode = MACVLAN_MODE_PRIVATE;
else if (strcmp(*argv, "vepa") == 0)
mode = MACVLAN_MODE_VEPA;
else if (strcmp(*argv, "bridge") == 0)
mode = MACVLAN_MODE_BRIDGE;
else if (strcmp(*argv, "passthru") == 0)
mode = MACVLAN_MODE_PASSTHRU;
else
return mode_arg(*argv);
addattr32(n, 1024, IFLA_MACVLAN_MODE, mode);
} else if (matches(*argv, "help") == 0) {
explain();
return -1;
} else {
fprintf(stderr, "macvtap: unknown command \"%s\"?\n", *argv);
explain();
return -1;
}
argc--, argv++;
}
return 0;
}
static void macvtap_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
{
__u32 mode;
if (!tb)
return;
if (!tb[IFLA_MACVLAN_MODE] ||
RTA_PAYLOAD(tb[IFLA_MACVLAN_MODE]) < sizeof(__u32))
return;
mode = rta_getattr_u32(tb[IFLA_VLAN_ID]);
fprintf(f, " mode %s ",
mode == MACVLAN_MODE_PRIVATE ? "private"
: mode == MACVLAN_MODE_VEPA ? "vepa"
: mode == MACVLAN_MODE_BRIDGE ? "bridge"
: mode == MACVLAN_MODE_PASSTHRU ? "passthru"
: "unknown");
}
static void macvtap_print_help(struct link_util *lu, int argc, char **argv,
FILE *f)
{
print_explain(f);
}
struct link_util macvtap_link_util = {
.id = "macvtap",
.maxattr = IFLA_MACVLAN_MAX,
.parse_opt = macvtap_parse_opt,
.print_opt = macvtap_print_opt,
.print_help = macvtap_print_help,
};

View File

@ -28,12 +28,6 @@ static void explain(void)
vrf_explain(stderr);
}
static int table_arg(void)
{
fprintf(stderr,"Error: argument of \"table\" must be 0-32767 and currently unused\n");
return -1;
}
static int vrf_parse_opt(struct link_util *lu, int argc, char **argv,
struct nlmsghdr *n)
{
@ -43,9 +37,8 @@ static int vrf_parse_opt(struct link_util *lu, int argc, char **argv,
NEXT_ARG();
table = atoi(*argv);
if (table > 32767)
return table_arg();
if (rtnl_rttable_a2n(&table, *argv))
invarg("invalid table ID\n", *argv);
addattr32(n, 1024, IFLA_VRF_TABLE, table);
} else if (matches(*argv, "help") == 0) {
explain();

View File

@ -23,14 +23,15 @@
static void print_explain(FILE *f)
{
fprintf(f, "Usage: ... vxlan id VNI [ { group | remote } ADDR ] [ local ADDR ]\n");
fprintf(f, "Usage: ... vxlan id VNI [ { group | remote } IP_ADDRESS ] [ local ADDR ]\n");
fprintf(f, " [ ttl TTL ] [ tos TOS ] [ dev PHYS_DEV ]\n");
fprintf(f, " [ dstport PORT ] [ srcport MIN MAX ]\n");
fprintf(f, " [ [no]learning ] [ [no]proxy ] [ [no]rsc ]\n");
fprintf(f, " [ [no]l2miss ] [ [no]l3miss ]\n");
fprintf(f, " [ ageing SECONDS ] [ maxaddress NUMBER ]\n");
fprintf(f, " [ [no]udpcsum ] [ [no]udp6zerocsumtx ] [ [no]udp6zerocsumrx ]\n");
fprintf(f, " [ gbp ]\n");
fprintf(f, " [ [no]remcsumtx ] [ [no]remcsumrx ]\n");
fprintf(f, " [ [no]external ] [ gbp ]\n");
fprintf(f, "\n");
fprintf(f, "Where: VNI := 0-16777215\n");
fprintf(f, " ADDR := { IP_ADDRESS | any }\n");
@ -69,6 +70,9 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
__u8 udpcsum = 0;
__u8 udp6zerocsumtx = 0;
__u8 udp6zerocsumrx = 0;
__u8 remcsumtx = 0;
__u8 remcsumrx = 0;
__u8 metadata = 0;
__u8 gbp = 0;
int dst_port_set = 0;
struct ifla_vxlan_port_range range = { 0, 0 };
@ -199,6 +203,18 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
udp6zerocsumrx = 1;
} else if (!matches(*argv, "noudp6zerocsumrx")) {
udp6zerocsumrx = 0;
} else if (!matches(*argv, "remcsumtx")) {
remcsumtx = 1;
} else if (!matches(*argv, "noremcsumtx")) {
remcsumtx = 0;
} else if (!matches(*argv, "remcsumrx")) {
remcsumrx = 1;
} else if (!matches(*argv, "noremcsumrx")) {
remcsumrx = 0;
} else if (!matches(*argv, "external")) {
metadata = 1;
} else if (!matches(*argv, "noexternal")) {
metadata = 0;
} else if (!matches(*argv, "gbp")) {
gbp = 1;
} else if (matches(*argv, "help") == 0) {
@ -212,7 +228,12 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
argc--, argv++;
}
if (!vni_set) {
if (metadata && vni_set) {
fprintf(stderr, "vxlan: both 'external' and vni cannot be specified\n");
return -1;
}
if (!metadata && !vni_set) {
fprintf(stderr, "vxlan: missing virtual network identifier\n");
return -1;
}
@ -259,6 +280,9 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
addattr8(n, 1024, IFLA_VXLAN_UDP_CSUM, udpcsum);
addattr8(n, 1024, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, udp6zerocsumtx);
addattr8(n, 1024, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, udp6zerocsumrx);
addattr8(n, 1024, IFLA_VXLAN_REMCSUM_TX, remcsumtx);
addattr8(n, 1024, IFLA_VXLAN_REMCSUM_RX, remcsumrx);
addattr8(n, 1024, IFLA_VXLAN_COLLECT_METADATA, metadata);
if (noage)
addattr32(n, 1024, IFLA_VXLAN_AGEING, 0);
@ -407,6 +431,18 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
rta_getattr_u8(tb[IFLA_VXLAN_UDP_ZERO_CSUM6_RX]))
fputs("udp6zerocsumrx ", f);
if (tb[IFLA_VXLAN_REMCSUM_TX] &&
rta_getattr_u8(tb[IFLA_VXLAN_REMCSUM_TX]))
fputs("remcsumtx ", f);
if (tb[IFLA_VXLAN_REMCSUM_RX] &&
rta_getattr_u8(tb[IFLA_VXLAN_REMCSUM_RX]))
fputs("remcsumrx ", f);
if (tb[IFLA_VXLAN_COLLECT_METADATA] &&
rta_getattr_u8(tb[IFLA_VXLAN_COLLECT_METADATA]))
fputs("external ", f);
if (tb[IFLA_VXLAN_GBP])
fputs("gbp ", f);
}

View File

@ -257,7 +257,7 @@ static int multiaddr_list(int argc, char **argv)
if (strcmp(*argv, "dev") == 0) {
NEXT_ARG();
}
if (matches(*argv, "help") == 0)
else if (matches(*argv, "help") == 0)
usage();
if (filter.dev)
duparg2("dev", *argv);

View File

@ -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)

View File

@ -39,6 +39,7 @@ static struct
char *flushb;
int flushp;
int flushe;
int master;
} filter;
static void usage(void) __attribute__((noreturn));
@ -99,8 +100,9 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv)
struct ndmsg ndm;
char buf[256];
} req;
char *d = NULL;
char *dev = NULL;
int dst_ok = 0;
int dev_ok = 0;
int lladdr_ok = 0;
char * lla = NULL;
inet_prefix dst;
@ -134,10 +136,12 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv)
duparg("address", *argv);
get_addr(&dst, *argv, preferred_family);
dst_ok = 1;
dev_ok = 1;
req.ndm.ndm_flags |= NTF_PROXY;
} else if (strcmp(*argv, "dev") == 0) {
NEXT_ARG();
d = *argv;
dev = *argv;
dev_ok = 1;
} else {
if (strcmp(*argv, "to") == 0) {
NEXT_ARG();
@ -152,7 +156,7 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv)
}
argc--; argv++;
}
if (d == NULL || !dst_ok || dst.family == AF_UNSPEC) {
if (!dev_ok || !dst_ok || dst.family == AF_UNSPEC) {
fprintf(stderr, "Device and destination are required arguments.\n");
exit(-1);
}
@ -174,8 +178,8 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv)
ll_init_map(&rth);
if ((req.ndm.ndm_ifindex = ll_name_to_index(d)) == 0) {
fprintf(stderr, "Cannot find device \"%s\"\n", d);
if (dev && (req.ndm.ndm_ifindex = ll_name_to_index(dev)) == 0) {
fprintf(stderr, "Cannot find device \"%s\"\n", dev);
return -1;
}
@ -193,6 +197,7 @@ int print_neigh(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
int len = n->nlmsg_len;
struct rtattr * tb[NDA_MAX+1];
char abuf[256];
static int logit = 1;
if (n->nlmsg_type != RTM_NEWNEIGH && n->nlmsg_type != RTM_DELNEIGH &&
n->nlmsg_type != RTM_GETNEIGH) {
@ -220,6 +225,14 @@ int print_neigh(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
(r->ndm_family != AF_DECnet))
return 0;
if (filter.master && !(n->nlmsg_flags & NLM_F_DUMP_FILTERED)) {
if (logit) {
logit = 0;
fprintf(fp,
"\nWARNING: Kernel does not support filtering by master device\n\n");
}
}
parse_rtattr(tb, NDA_MAX, NDA_RTA(r), n->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));
if (tb[NDA_DST]) {
@ -256,7 +269,7 @@ int print_neigh(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
}
if (n->nlmsg_type == RTM_DELNEIGH)
fprintf(fp, "delete ");
fprintf(fp, "Deleted ");
else if (n->nlmsg_type == RTM_GETNEIGH)
fprintf(fp, "miss ");
if (tb[NDA_DST]) {
@ -327,9 +340,18 @@ void ipneigh_reset_filter(int ifindex)
static int do_show_or_flush(int argc, char **argv, int flush)
{
struct {
struct nlmsghdr n;
struct ndmsg ndm;
char buf[256];
} req;
char *filter_dev = NULL;
int state_given = 0;
struct ndmsg ndm = { 0 };
memset(&req, 0, sizeof(req));
req.n.nlmsg_type = RTM_GETNEIGH;
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
ipneigh_reset_filter(0);
@ -351,6 +373,14 @@ static int do_show_or_flush(int argc, char **argv, int flush)
if (filter_dev)
duparg("dev", *argv);
filter_dev = *argv;
} else if (strcmp(*argv, "master") == 0) {
int ifindex;
NEXT_ARG();
ifindex = ll_name_to_index(*argv);
if (!ifindex)
invarg("Device does not exist\n", *argv);
addattr32(&req.n, sizeof(req), NDA_MASTER, ifindex);
filter.master = ifindex;
} else if (strcmp(*argv, "unused") == 0) {
filter.unused_only = 1;
} else if (strcmp(*argv, "nud") == 0) {
@ -371,7 +401,7 @@ static int do_show_or_flush(int argc, char **argv, int flush)
state = 0x100;
filter.state |= state;
} else if (strcmp(*argv, "proxy") == 0)
ndm.ndm_flags = NTF_PROXY;
req.ndm.ndm_flags = NTF_PROXY;
else {
if (strcmp(*argv, "to") == 0) {
NEXT_ARG();
@ -392,6 +422,7 @@ static int do_show_or_flush(int argc, char **argv, int flush)
fprintf(stderr, "Cannot find device \"%s\"\n", filter_dev);
return -1;
}
addattr32(&req.n, sizeof(req), NDA_IFINDEX, filter.index);
}
if (flush) {
@ -436,9 +467,9 @@ static int do_show_or_flush(int argc, char **argv, int flush)
return 1;
}
ndm.ndm_family = filter.family;
req.ndm.ndm_family = filter.family;
if (rtnl_dump_request(&rth, RTM_GETNEIGH, &ndm, sizeof(struct ndmsg)) < 0) {
if (rtnl_dump_request_n(&rth, &req.n) < 0) {
perror("Cannot send dump request");
exit(1);
}

View File

@ -349,7 +349,7 @@ static const char *ntable_strtime_delta(__u32 msec)
return str;
}
int print_ntable(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
static int print_ntable(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
{
FILE *fp = (FILE*)arg;
struct ndtmsg *ndtm = NLMSG_DATA(n);
@ -601,7 +601,7 @@ int print_ntable(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
return 0;
}
void ipntable_reset_filter(void)
static void ipntable_reset_filter(void)
{
memset(&filter, 0, sizeof(filter));
}

View File

@ -107,4 +107,3 @@ int print_prefix(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
return 0;
}

View File

@ -29,6 +29,7 @@
#include "rt_names.h"
#include "utils.h"
#include "ip_common.h"
#include "iproute_lwtunnel.h"
#ifndef RTAX_RTTVAR
#define RTAX_RTTVAR RTAX_HOPS
@ -76,7 +77,8 @@ static void usage(void)
fprintf(stderr, " [ table TABLE_ID ] [ proto RTPROTO ]\n");
fprintf(stderr, " [ scope SCOPE ] [ metric METRIC ]\n");
fprintf(stderr, "INFO_SPEC := NH OPTIONS FLAGS [ nexthop NH ]...\n");
fprintf(stderr, "NH := [ via [ FAMILY ] ADDRESS ] [ dev STRING ] [ weight NUMBER ] NHFLAGS\n");
fprintf(stderr, "NH := [ encap ENCAPTYPE ENCAPHDR ] [ via [ FAMILY ] ADDRESS ]\n");
fprintf(stderr, " [ dev STRING ] [ weight NUMBER ] NHFLAGS\n");
fprintf(stderr, "FAMILY := [ inet | inet6 | ipx | dnet | mpls | bridge | link ]\n");
fprintf(stderr, "OPTIONS := FLAGS [ mtu NUMBER ] [ advmss NUMBER ] [ as [ to ] ADDRESS ]\n");
fprintf(stderr, " [ rtt TIME ] [ rttvar TIME ] [ reordering NUMBER ]\n");
@ -84,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");
@ -95,6 +97,8 @@ static void usage(void)
fprintf(stderr, "TIME := NUMBER[s|ms]\n");
fprintf(stderr, "BOOL := [1|0]\n");
fprintf(stderr, "FEATURES := ecn\n");
fprintf(stderr, "ENCAPTYPE := [ mpls | ip | ip6 ]\n");
fprintf(stderr, "ENCAPHDR := [ MPLSLABEL ]\n");
exit(-1);
}
@ -401,6 +405,10 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
abuf, sizeof(abuf))
);
}
if (tb[RTA_ENCAP])
lwt_print_encap(fp, tb[RTA_ENCAP_TYPE], tb[RTA_ENCAP]);
if (r->rtm_tos && filter.tosmask != -1) {
SPRINT_BUF(b1);
fprintf(fp, "tos %s ", rtnl_dsfield_n2a(r->rtm_tos, b1, sizeof(b1)));
@ -424,9 +432,9 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
if (tb[RTA_OIF] && filter.oifmask != -1)
fprintf(fp, "dev %s ", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_OIF])));
if (table && (table != RT_TABLE_MAIN || show_details > 0) && !filter.tb)
fprintf(fp, " table %s ", rtnl_rttable_n2a(table, b1, sizeof(b1)));
if (!(r->rtm_flags&RTM_F_CLONED)) {
if ((table != RT_TABLE_MAIN || show_details > 0) && !filter.tb)
fprintf(fp, " table %s ", rtnl_rttable_n2a(table, b1, sizeof(b1)));
if ((r->rtm_protocol != RTPROT_BOOT || show_details > 0) && filter.protocolmask != -1)
fprintf(fp, " proto %s ", rtnl_rtprot_n2a(r->rtm_protocol, b1, sizeof(b1)));
if ((r->rtm_scope != RT_SCOPE_UNIVERSE || show_details > 0) && filter.scopemask != -1)
@ -569,6 +577,12 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
if (mxrta[i] == NULL)
continue;
if (i != RTAX_CC_ALGO)
val = rta_getattr_u32(mxrta[i]);
if (i == RTAX_HOPLIMIT && (int)val == -1)
continue;
if (i < sizeof(mx_names)/sizeof(char*) && mx_names[i])
fprintf(fp, " %s", mx_names[i]);
else
@ -576,17 +590,11 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
if (mxlock & (1<<i))
fprintf(fp, " lock");
if (i != RTAX_CC_ALGO)
val = rta_getattr_u32(mxrta[i]);
switch (i) {
case RTAX_FEATURES:
print_rtax_features(fp, val);
break;
case RTAX_HOPLIMIT:
if ((int)val == -1)
val = 0;
/* fall through */
default:
fprintf(fp, " %u", val);
break;
@ -633,6 +641,12 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
fprintf(fp, "%s\tnexthop", _SL_);
if (nh->rtnh_len > sizeof(*nh)) {
parse_rtattr(tb, RTA_MAX, RTNH_DATA(nh), nh->rtnh_len - sizeof(*nh));
if (tb[RTA_ENCAP])
lwt_print_encap(fp,
tb[RTA_ENCAP_TYPE],
tb[RTA_ENCAP]);
if (tb[RTA_GATEWAY]) {
fprintf(fp, " via %s ",
format_host(r->rtm_family,
@ -704,9 +718,8 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
return 0;
}
static int parse_one_nh(struct rtmsg *r, struct rtattr *rta,
struct rtnexthop *rtnh,
static int parse_one_nh(struct nlmsghdr *n, struct rtmsg *r,
struct rtattr *rta, struct rtnexthop *rtnh,
int *argcp, char ***argvp)
{
int argc = *argcp;
@ -749,10 +762,15 @@ static int parse_one_nh(struct rtmsg *r, struct rtattr *rta,
} else if (matches(*argv, "realms") == 0) {
__u32 realm;
NEXT_ARG();
if (get_rt_realms(&realm, *argv))
if (get_rt_realms_or_raw(&realm, *argv))
invarg("\"realm\" value is invalid\n", *argv);
rta_addattr32(rta, 4096, RTA_FLOW, realm);
rtnh->rtnh_len += sizeof(struct rtattr) + 4;
} else if (strcmp(*argv, "encap") == 0) {
int len = rta->rta_len;
lwt_parse_encap(rta, 4096, &argc, &argv);
rtnh->rtnh_len += rta->rta_len - len;
} else
break;
}
@ -784,7 +802,7 @@ static int parse_nexthops(struct nlmsghdr *n, struct rtmsg *r,
memset(rtnh, 0, sizeof(*rtnh));
rtnh->rtnh_len = sizeof(*rtnh);
rta->rta_len += rtnh->rtnh_len;
parse_one_nh(r, rta, rtnh, &argc, &argv);
parse_one_nh(n, r, rta, rtnh, &argc, &argv);
rtnh = RTNH_NEXT(rtnh);
}
@ -811,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));
@ -881,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) {
@ -913,7 +940,7 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv)
mxlock |= (1<<RTAX_HOPLIMIT);
NEXT_ARG();
}
if (get_unsigned(&hoplimit, *argv, 0))
if (get_unsigned(&hoplimit, *argv, 0) || hoplimit > 255)
invarg("\"hoplimit\" value is invalid\n", *argv);
rta_addattr32(mxrta, sizeof(mxbuf), RTAX_HOPLIMIT, hoplimit);
} else if (strcmp(*argv, "advmss") == 0) {
@ -1050,7 +1077,7 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv)
} else if (matches(*argv, "realms") == 0) {
__u32 realm;
NEXT_ARG();
if (get_rt_realms(&realm, *argv))
if (get_rt_realms_or_raw(&realm, *argv))
invarg("\"realm\" value is invalid\n", *argv);
addattr32(&req.n, sizeof(req), RTA_FLOW, realm);
} else if (strcmp(*argv, "onlink") == 0) {
@ -1092,6 +1119,17 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv)
else if (get_u8(&pref, *argv, 0))
invarg("\"pref\" value is invalid\n", *argv);
addattr8(&req.n, sizeof(req), RTA_PREF, pref);
} else if (strcmp(*argv, "encap") == 0) {
char buf[1024];
struct rtattr *rta = (void*)buf;
rta->rta_type = RTA_ENCAP;
rta->rta_len = RTA_LENGTH(0);
lwt_parse_encap(rta, sizeof(buf), &argc, &argv);
if (rta->rta_len > RTA_LENGTH(0))
addraw_l(&req.n, 1024, RTA_DATA(rta), RTA_PAYLOAD(rta));
} else {
int type;
inet_prefix dst;
@ -1383,7 +1421,7 @@ static int iproute_list_flush_or_save(int argc, char **argv, int action)
} else if (matches(*argv, "realms") == 0) {
__u32 realm;
NEXT_ARG();
if (get_rt_realms(&realm, *argv))
if (get_rt_realms_or_raw(&realm, *argv))
invarg("invalid realms\n", *argv);
filter.realm = realm;
filter.realmmask = ~0U;
@ -1642,8 +1680,10 @@ static int iproute_get(int argc, char **argv)
if (req.r.rtm_family == AF_UNSPEC)
req.r.rtm_family = AF_INET;
req.r.rtm_flags |= RTM_F_LOOKUP_TABLE;
if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0)
exit(2);
return -2;
if (connected && !from_ok) {
struct rtmsg *r = NLMSG_DATA(&req.n);
@ -1811,4 +1851,3 @@ int do_iproute(int argc, char **argv)
fprintf(stderr, "Command \"%s\" is unknown, try \"ip route help\".\n", *argv);
exit(-1);
}

367
ip/iproute_lwtunnel.c Normal file
View File

@ -0,0 +1,367 @@
/*
* iproute_lwtunnel.c
*
* 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: Roopa Prabhu, <roopa@cumulusnetworks.com>
* Thomas Graf <tgraf@suug.ch>
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <linux/ila.h>
#include <linux/lwtunnel.h>
#include <linux/mpls_iptunnel.h>
#include <errno.h>
#include "rt_names.h"
#include "utils.h"
#include "iproute_lwtunnel.h"
static int read_encap_type(const char *name)
{
if (strcmp(name, "mpls") == 0)
return LWTUNNEL_ENCAP_MPLS;
else if (strcmp(name, "ip") == 0)
return LWTUNNEL_ENCAP_IP;
else if (strcmp(name, "ip6") == 0)
return LWTUNNEL_ENCAP_IP6;
else if (strcmp(name, "ila") == 0)
return LWTUNNEL_ENCAP_ILA;
else
return LWTUNNEL_ENCAP_NONE;
}
static const char *format_encap_type(int type)
{
switch (type) {
case LWTUNNEL_ENCAP_MPLS:
return "mpls";
case LWTUNNEL_ENCAP_IP:
return "ip";
case LWTUNNEL_ENCAP_IP6:
return "ip6";
case LWTUNNEL_ENCAP_ILA:
return "ila";
default:
return "unknown";
}
}
static void print_encap_mpls(FILE *fp, struct rtattr *encap)
{
struct rtattr *tb[MPLS_IPTUNNEL_MAX+1];
char abuf[256];
parse_rtattr_nested(tb, MPLS_IPTUNNEL_MAX, encap);
if (tb[MPLS_IPTUNNEL_DST])
fprintf(fp, " %s ", format_host(AF_MPLS,
RTA_PAYLOAD(tb[MPLS_IPTUNNEL_DST]),
RTA_DATA(tb[MPLS_IPTUNNEL_DST]),
abuf, sizeof(abuf)));
}
static void print_encap_ip(FILE *fp, struct rtattr *encap)
{
struct rtattr *tb[LWTUNNEL_IP_MAX+1];
char abuf[256];
parse_rtattr_nested(tb, LWTUNNEL_IP_MAX, encap);
if (tb[LWTUNNEL_IP_ID])
fprintf(fp, "id %llu ", ntohll(rta_getattr_u64(tb[LWTUNNEL_IP_ID])));
if (tb[LWTUNNEL_IP_SRC])
fprintf(fp, "src %s ",
rt_addr_n2a(AF_INET,
RTA_PAYLOAD(tb[LWTUNNEL_IP_SRC]),
RTA_DATA(tb[LWTUNNEL_IP_SRC]),
abuf, sizeof(abuf)));
if (tb[LWTUNNEL_IP_DST])
fprintf(fp, "dst %s ",
rt_addr_n2a(AF_INET,
RTA_PAYLOAD(tb[LWTUNNEL_IP_DST]),
RTA_DATA(tb[LWTUNNEL_IP_DST]),
abuf, sizeof(abuf)));
if (tb[LWTUNNEL_IP_TTL])
fprintf(fp, "ttl %d ", rta_getattr_u8(tb[LWTUNNEL_IP_TTL]));
if (tb[LWTUNNEL_IP_TOS])
fprintf(fp, "tos %d ", rta_getattr_u8(tb[LWTUNNEL_IP_TOS]));
}
static void print_encap_ila(FILE *fp, struct rtattr *encap)
{
struct rtattr *tb[ILA_ATTR_MAX+1];
parse_rtattr_nested(tb, ILA_ATTR_MAX, encap);
if (tb[ILA_ATTR_LOCATOR]) {
char abuf[ADDR64_BUF_SIZE];
addr64_n2a(*(__u64 *)RTA_DATA(tb[ILA_ATTR_LOCATOR]),
abuf, sizeof(abuf));
fprintf(fp, " %s ", abuf);
}
}
static void print_encap_ip6(FILE *fp, struct rtattr *encap)
{
struct rtattr *tb[LWTUNNEL_IP6_MAX+1];
char abuf[256];
parse_rtattr_nested(tb, LWTUNNEL_IP6_MAX, encap);
if (tb[LWTUNNEL_IP6_ID])
fprintf(fp, "id %llu ", ntohll(rta_getattr_u64(tb[LWTUNNEL_IP6_ID])));
if (tb[LWTUNNEL_IP6_SRC])
fprintf(fp, "src %s ",
rt_addr_n2a(AF_INET6,
RTA_PAYLOAD(tb[LWTUNNEL_IP6_SRC]),
RTA_DATA(tb[LWTUNNEL_IP6_SRC]),
abuf, sizeof(abuf)));
if (tb[LWTUNNEL_IP6_DST])
fprintf(fp, "dst %s ",
rt_addr_n2a(AF_INET6,
RTA_PAYLOAD(tb[LWTUNNEL_IP6_DST]),
RTA_DATA(tb[LWTUNNEL_IP6_DST]),
abuf, sizeof(abuf)));
if (tb[LWTUNNEL_IP6_HOPLIMIT])
fprintf(fp, "hoplimit %d ", rta_getattr_u8(tb[LWTUNNEL_IP6_HOPLIMIT]));
if (tb[LWTUNNEL_IP6_TC])
fprintf(fp, "tc %d ", rta_getattr_u8(tb[LWTUNNEL_IP6_TC]));
}
void lwt_print_encap(FILE *fp, struct rtattr *encap_type,
struct rtattr *encap)
{
int et;
if (!encap_type)
return;
et = rta_getattr_u16(encap_type);
fprintf(fp, " encap %s ", format_encap_type(et));
switch (et) {
case LWTUNNEL_ENCAP_MPLS:
print_encap_mpls(fp, encap);
break;
case LWTUNNEL_ENCAP_IP:
print_encap_ip(fp, encap);
break;
case LWTUNNEL_ENCAP_ILA:
print_encap_ila(fp, encap);
break;
case LWTUNNEL_ENCAP_IP6:
print_encap_ip6(fp, encap);
break;
}
}
static int parse_encap_mpls(struct rtattr *rta, size_t len, int *argcp, char ***argvp)
{
inet_prefix addr;
int argc = *argcp;
char **argv = *argvp;
if (get_addr(&addr, *argv, AF_MPLS)) {
fprintf(stderr, "Error: an inet address is expected rather than \"%s\".\n", *argv);
exit(1);
}
rta_addattr_l(rta, len, MPLS_IPTUNNEL_DST, &addr.data,
addr.bytelen);
*argcp = argc;
*argvp = argv;
return 0;
}
static int parse_encap_ip(struct rtattr *rta, size_t len, int *argcp, char ***argvp)
{
int id_ok = 0, dst_ok = 0, tos_ok = 0, ttl_ok = 0;
char **argv = *argvp;
int argc = *argcp;
while (argc > 0) {
if (strcmp(*argv, "id") == 0) {
__u64 id;
NEXT_ARG();
if (id_ok++)
duparg2("id", *argv);
if (get_u64(&id, *argv, 0))
invarg("\"id\" value is invalid\n", *argv);
rta_addattr64(rta, len, LWTUNNEL_IP_ID, htonll(id));
} else if (strcmp(*argv, "dst") == 0) {
inet_prefix addr;
NEXT_ARG();
if (dst_ok++)
duparg2("dst", *argv);
get_addr(&addr, *argv, AF_INET);
rta_addattr_l(rta, len, LWTUNNEL_IP_DST, &addr.data, addr.bytelen);
} else if (strcmp(*argv, "tos") == 0) {
__u32 tos;
NEXT_ARG();
if (tos_ok++)
duparg2("tos", *argv);
if (rtnl_dsfield_a2n(&tos, *argv))
invarg("\"tos\" value is invalid\n", *argv);
rta_addattr8(rta, len, LWTUNNEL_IP_TOS, tos);
} else if (strcmp(*argv, "ttl") == 0) {
__u8 ttl;
NEXT_ARG();
if (ttl_ok++)
duparg2("ttl", *argv);
if (get_u8(&ttl, *argv, 0))
invarg("\"ttl\" value is invalid\n", *argv);
rta_addattr8(rta, len, LWTUNNEL_IP_TTL, ttl);
} else {
break;
}
argc--; argv++;
}
/* argv is currently the first unparsed argument,
* but the lwt_parse_encap() caller will move to the next,
* so step back */
*argcp = argc + 1;
*argvp = argv - 1;
return 0;
}
static int parse_encap_ila(struct rtattr *rta, size_t len,
int *argcp, char ***argvp)
{
__u64 locator;
int argc = *argcp;
char **argv = *argvp;
if (get_addr64(&locator, *argv) < 0) {
fprintf(stderr, "Bad locator: %s\n", *argv);
exit(1);
}
rta_addattr64(rta, 1024, ILA_ATTR_LOCATOR, locator);
*argcp = argc;
*argvp = argv;
return 0;
}
static int parse_encap_ip6(struct rtattr *rta, size_t len, int *argcp, char ***argvp)
{
int id_ok = 0, dst_ok = 0, tos_ok = 0, ttl_ok = 0;
char **argv = *argvp;
int argc = *argcp;
while (argc > 0) {
if (strcmp(*argv, "id") == 0) {
__u64 id;
NEXT_ARG();
if (id_ok++)
duparg2("id", *argv);
if (get_u64(&id, *argv, 0))
invarg("\"id\" value is invalid\n", *argv);
rta_addattr64(rta, len, LWTUNNEL_IP6_ID, htonll(id));
} else if (strcmp(*argv, "dst") == 0) {
inet_prefix addr;
NEXT_ARG();
if (dst_ok++)
duparg2("dst", *argv);
get_addr(&addr, *argv, AF_INET6);
rta_addattr_l(rta, len, LWTUNNEL_IP6_DST, &addr.data, addr.bytelen);
} else if (strcmp(*argv, "tc") == 0) {
__u32 tc;
NEXT_ARG();
if (tos_ok++)
duparg2("tc", *argv);
if (rtnl_dsfield_a2n(&tc, *argv))
invarg("\"tc\" value is invalid\n", *argv);
rta_addattr8(rta, len, LWTUNNEL_IP6_TC, tc);
} else if (strcmp(*argv, "hoplimit") == 0) {
__u8 hoplimit;
NEXT_ARG();
if (ttl_ok++)
duparg2("hoplimit", *argv);
if (get_u8(&hoplimit, *argv, 0))
invarg("\"hoplimit\" value is invalid\n", *argv);
rta_addattr8(rta, len, LWTUNNEL_IP6_HOPLIMIT, hoplimit);
} else {
break;
}
argc--; argv++;
}
/* argv is currently the first unparsed argument,
* but the lwt_parse_encap() caller will move to the next,
* so step back */
*argcp = argc + 1;
*argvp = argv - 1;
return 0;
}
int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp)
{
struct rtattr *nest;
int argc = *argcp;
char **argv = *argvp;
__u16 type;
NEXT_ARG();
type = read_encap_type(*argv);
if (!type)
invarg("\"encap type\" value is invalid\n", *argv);
NEXT_ARG();
if (argc <= 1) {
fprintf(stderr, "Error: unexpected end of line after \"encap\"\n");
exit(-1);
}
nest = rta_nest(rta, 1024, RTA_ENCAP);
switch (type) {
case LWTUNNEL_ENCAP_MPLS:
parse_encap_mpls(rta, len, &argc, &argv);
break;
case LWTUNNEL_ENCAP_IP:
parse_encap_ip(rta, len, &argc, &argv);
break;
case LWTUNNEL_ENCAP_ILA:
parse_encap_ila(rta, len, &argc, &argv);
break;
case LWTUNNEL_ENCAP_IP6:
parse_encap_ip6(rta, len, &argc, &argv);
break;
default:
fprintf(stderr, "Error: unsupported encap type\n");
break;
}
rta_nest_end(rta, nest);
rta_addattr16(rta, 1024, RTA_ENCAP_TYPE, type);
*argcp = argc;
*argvp = argv;
return 0;
}

8
ip/iproute_lwtunnel.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef __LWTUNNEL_H__
#define __LETUNNEL_H__ 1
int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp);
void lwt_print_encap(FILE *fp, struct rtattr *encap_type,
struct rtattr *encap);
#endif

View File

@ -21,6 +21,7 @@
#include <arpa/inet.h>
#include <string.h>
#include <linux/fib_rules.h>
#include <errno.h>
#include "rt_names.h"
#include "utils.h"
@ -32,11 +33,11 @@ static void usage(void) __attribute__((noreturn));
static void usage(void)
{
fprintf(stderr, "Usage: ip rule [ list | add | del | flush ] SELECTOR ACTION\n");
fprintf(stderr, "Usage: ip rule [ list | add | del | flush | save ] SELECTOR ACTION\n");
fprintf(stderr, " ip rule restore\n");
fprintf(stderr, "SELECTOR := [ not ] [ from PREFIX ] [ to PREFIX ] [ tos TOS ] [ fwmark FWMARK[/MASK] ]\n");
fprintf(stderr, " [ iif STRING ] [ oif STRING ] [ pref NUMBER ]\n");
fprintf(stderr, "ACTION := [ table TABLE_ID ]\n");
fprintf(stderr, " [ prohibit | reject | unreachable ]\n");
fprintf(stderr, " [ realms [SRCREALM/]DSTREALM ]\n");
fprintf(stderr, " [ goto NUMBER ]\n");
fprintf(stderr, " SUPPRESSOR\n");
@ -206,24 +207,65 @@ int print_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
return 0;
}
static int iprule_list(int argc, char **argv)
static __u32 rule_dump_magic = 0x71706986;
static int save_rule_prep(void)
{
int ret;
if (isatty(STDOUT_FILENO)) {
fprintf(stderr, "Not sending a binary stream to stdout\n");
return -1;
}
ret = write(STDOUT_FILENO, &rule_dump_magic, sizeof(rule_dump_magic));
if (ret != sizeof(rule_dump_magic)) {
fprintf(stderr, "Can't write magic to dump file\n");
return -1;
}
return 0;
}
static int save_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
{
int ret;
ret = write(STDOUT_FILENO, n, n->nlmsg_len);
if ((ret > 0) && (ret != n->nlmsg_len)) {
fprintf(stderr, "Short write while saving nlmsg\n");
ret = -EIO;
}
return ret == n->nlmsg_len ? 0 : ret;
}
static int iprule_list_or_save(int argc, char **argv, int save)
{
rtnl_filter_t filter = print_rule;
int af = preferred_family;
if (af == AF_UNSPEC)
af = AF_INET;
if (argc > 0) {
fprintf(stderr, "\"ip rule show\" does not take any arguments.\n");
fprintf(stderr, "\"ip rule %s\" does not take any arguments.\n",
save ? "save" : "show");
return -1;
}
if (save) {
if (save_rule_prep())
return -1;
filter = save_rule;
}
if (rtnl_wilddump_request(&rth, af, RTM_GETRULE) < 0) {
perror("Cannot send dump request");
return 1;
}
if (rtnl_dump_filter(&rth, print_rule, stdout) < 0) {
if (rtnl_dump_filter(&rth, filter, stdout) < 0) {
fprintf(stderr, "Dump terminated\n");
return 1;
}
@ -231,6 +273,50 @@ static int iprule_list(int argc, char **argv)
return 0;
}
static int rule_dump_check_magic(void)
{
int ret;
__u32 magic = 0;
if (isatty(STDIN_FILENO)) {
fprintf(stderr, "Can't restore rule dump from a terminal\n");
return -1;
}
ret = fread(&magic, sizeof(magic), 1, stdin);
if (magic != rule_dump_magic) {
fprintf(stderr, "Magic mismatch (%d elems, %x magic)\n", ret, magic);
return -1;
}
return 0;
}
static int restore_handler(const struct sockaddr_nl *nl,
struct rtnl_ctrl_data *ctrl,
struct nlmsghdr *n, void *arg)
{
int ret;
n->nlmsg_flags |= NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK;
ll_init_map(&rth);
ret = rtnl_talk(&rth, n, n, sizeof(*n));
if ((ret < 0) && (errno == EEXIST))
ret = 0;
return ret;
}
static int iprule_restore(void)
{
if (rule_dump_check_magic())
exit(-1);
exit(rtnl_from_file(stdin, &restore_handler, NULL));
}
static int iprule_modify(int cmd, int argc, char **argv)
{
@ -305,7 +391,7 @@ static int iprule_modify(int cmd, int argc, char **argv)
} else if (matches(*argv, "realms") == 0) {
__u32 realm;
NEXT_ARG();
if (get_rt_realms(&realm, *argv))
if (get_rt_realms_or_raw(&realm, *argv))
invarg("invalid realms\n", *argv);
addattr32(&req.n, sizeof(req), FRA_FLOW, realm);
} else if (matches(*argv, "table") == 0 ||
@ -444,11 +530,15 @@ static int iprule_flush(int argc, char **argv)
int do_iprule(int argc, char **argv)
{
if (argc < 1) {
return iprule_list(0, NULL);
return iprule_list_or_save(0, NULL, 0);
} else if (matches(argv[0], "list") == 0 ||
matches(argv[0], "lst") == 0 ||
matches(argv[0], "show") == 0) {
return iprule_list(argc-1, argv+1);
return iprule_list_or_save(argc-1, argv+1, 0);
} else if (matches(argv[0], "save") == 0) {
return iprule_list_or_save(argc-1, argv+1, 1);
} else if (matches(argv[0], "restore") == 0) {
return iprule_restore();
} else if (matches(argv[0], "add") == 0) {
return iprule_modify(RTM_NEWRULE, argc-1, argv+1);
} else if (matches(argv[0], "delete") == 0) {

View File

@ -95,10 +95,6 @@ static int iptoken_list(int argc, char **argv)
{
int af = AF_INET6;
struct rtnl_dump_args da;
const struct rtnl_dump_filter_arg a[2] = {
{ .filter = print_token, .arg1 = &da, },
{ .filter = NULL, .arg1 = NULL, },
};
memset(&da, 0, sizeof(da));
da.fp = stdout;
@ -118,7 +114,7 @@ static int iptoken_list(int argc, char **argv)
return -1;
}
if (rtnl_dump_filter_l(&rth, a) < 0) {
if (rtnl_dump_filter(&rth, print_token, &da) < 0) {
fprintf(stderr, "Dump terminated\n");
return -1;
}

View File

@ -47,6 +47,16 @@ static void usage(void)
exit(-1);
}
static void set_tunnel_proto(struct ip_tunnel_parm *p, int proto)
{
if (p->iph.protocol && p->iph.protocol != proto) {
fprintf(stderr,
"You managed to ask for more than one tunnel mode.\n");
exit(-1);
}
p->iph.protocol = proto;
}
static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p)
{
int count = 0;
@ -68,83 +78,37 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p)
NEXT_ARG();
if (strcmp(*argv, "ipip") == 0 ||
strcmp(*argv, "ip/ip") == 0) {
if (p->iph.protocol && p->iph.protocol != IPPROTO_IPIP) {
fprintf(stderr,"You managed to ask for more than one tunnel mode.\n");
exit(-1);
}
p->iph.protocol = IPPROTO_IPIP;
set_tunnel_proto(p, IPPROTO_IPIP);
} else if (strcmp(*argv, "gre") == 0 ||
strcmp(*argv, "gre/ip") == 0) {
if (p->iph.protocol && p->iph.protocol != IPPROTO_GRE) {
fprintf(stderr,"You managed to ask for more than one tunnel mode.\n");
exit(-1);
}
p->iph.protocol = IPPROTO_GRE;
set_tunnel_proto(p, IPPROTO_GRE);
} else if (strcmp(*argv, "sit") == 0 ||
strcmp(*argv, "ipv6/ip") == 0) {
if (p->iph.protocol && p->iph.protocol != IPPROTO_IPV6) {
fprintf(stderr,"You managed to ask for more than one tunnel mode.\n");
exit(-1);
}
p->iph.protocol = IPPROTO_IPV6;
set_tunnel_proto(p, IPPROTO_IPV6);
} else if (strcmp(*argv, "isatap") == 0) {
if (p->iph.protocol && p->iph.protocol != IPPROTO_IPV6) {
fprintf(stderr, "You managed to ask for more than one tunnel mode.\n");
exit(-1);
}
p->iph.protocol = IPPROTO_IPV6;
set_tunnel_proto(p, IPPROTO_IPV6);
isatap++;
} else if (strcmp(*argv, "vti") == 0) {
if (p->iph.protocol && p->iph.protocol != IPPROTO_IPIP) {
fprintf(stderr, "You managed to ask for more than one tunnel mode.\n");
exit(-1);
}
p->iph.protocol = IPPROTO_IPIP;
set_tunnel_proto(p, IPPROTO_IPIP);
p->i_flags |= VTI_ISVTI;
} else {
fprintf(stderr,"Unknown tunnel mode \"%s\"\n", *argv);
fprintf(stderr,
"Unknown tunnel mode \"%s\"\n", *argv);
exit(-1);
}
} else if (strcmp(*argv, "key") == 0) {
unsigned uval;
NEXT_ARG();
p->i_flags |= GRE_KEY;
p->o_flags |= GRE_KEY;
if (strchr(*argv, '.'))
p->i_key = p->o_key = get_addr32(*argv);
else {
if (get_unsigned(&uval, *argv, 0)<0) {
fprintf(stderr, "invalid value for \"key\": \"%s\"; it should be an unsigned integer\n", *argv);
exit(-1);
}
p->i_key = p->o_key = htonl(uval);
}
p->i_key = p->o_key = tnl_parse_key("key", *argv);
} else if (strcmp(*argv, "ikey") == 0) {
unsigned uval;
NEXT_ARG();
p->i_flags |= GRE_KEY;
if (strchr(*argv, '.'))
p->i_key = get_addr32(*argv);
else {
if (get_unsigned(&uval, *argv, 0)<0) {
fprintf(stderr, "invalid value for \"ikey\": \"%s\"; it should be an unsigned integer\n", *argv);
exit(-1);
}
p->i_key = htonl(uval);
}
p->i_key = tnl_parse_key("ikey", *argv);
} else if (strcmp(*argv, "okey") == 0) {
unsigned uval;
NEXT_ARG();
p->o_flags |= GRE_KEY;
if (strchr(*argv, '.'))
p->o_key = get_addr32(*argv);
else {
if (get_unsigned(&uval, *argv, 0)<0) {
fprintf(stderr, "invalid value for \"okey\": \"%s\"; it should be an unsigned integer\n", *argv);
exit(-1);
}
p->o_key = htonl(uval);
}
p->o_key = tnl_parse_key("okey", *argv);
} else if (strcmp(*argv, "seq") == 0) {
p->i_flags |= GRE_SEQ;
p->o_flags |= GRE_SEQ;
@ -177,16 +141,16 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p)
p->iph.saddr = htonl(INADDR_ANY);
} else if (strcmp(*argv, "dev") == 0) {
NEXT_ARG();
strncpy(medium, *argv, IFNAMSIZ-1);
strncpy(medium, *argv, IFNAMSIZ - 1);
} else if (strcmp(*argv, "ttl") == 0 ||
strcmp(*argv, "hoplimit") == 0) {
unsigned uval;
strcmp(*argv, "hoplimit") == 0 ||
strcmp(*argv, "hlim") == 0) {
__u8 uval;
NEXT_ARG();
if (strcmp(*argv, "inherit") != 0) {
if (get_unsigned(&uval, *argv, 0))
if (get_u8(&uval, *argv, 0))
invarg("invalid TTL\n", *argv);
if (uval > 255)
invarg("TTL must be <=255\n", *argv);
p->iph.ttl = uval;
}
} else if (strcmp(*argv, "tos") == 0 ||
@ -194,6 +158,7 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p)
matches(*argv, "dsfield") == 0) {
char *dsfield;
__u32 uval;
NEXT_ARG();
dsfield = *argv;
strsep(&dsfield, "/");
@ -208,15 +173,17 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p)
p->iph.tos |= uval;
}
} else {
if (strcmp(*argv, "name") == 0) {
if (strcmp(*argv, "name") == 0)
NEXT_ARG();
} else if (matches(*argv, "help") == 0)
else if (matches(*argv, "help") == 0)
usage();
if (p->name[0])
duparg2("name", *argv);
strncpy(p->name, *argv, IFNAMSIZ);
strncpy(p->name, *argv, IFNAMSIZ - 1);
if (cmd == SIOCCHGTUNNEL && count == 0) {
struct ip_tunnel_parm old_p;
memset(&old_p, 0, sizeof(old_p));
if (tnl_get_ioctl(*argv, &old_p))
return -1;
@ -253,10 +220,9 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p)
}
if (medium[0]) {
p->link = if_nametoindex(medium);
p->link = ll_name_to_index(medium);
if (p->link == 0) {
fprintf(stderr, "Cannot find device \"%s\"\n",
medium);
fprintf(stderr, "Cannot find device \"%s\"\n", medium);
return -1;
}
}
@ -279,10 +245,26 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p)
return 0;
}
static const char *tnl_defname(const struct ip_tunnel_parm *p)
{
switch (p->iph.protocol) {
case IPPROTO_IPIP:
if (p->i_flags & VTI_ISVTI)
return "ip_vti0";
else
return "tunl0";
case IPPROTO_GRE:
return "gre0";
case IPPROTO_IPV6:
return "sit0";
}
return NULL;
}
static int do_add(int cmd, int argc, char **argv)
{
struct ip_tunnel_parm p;
const char *basedev;
if (parse_args(argc, argv, cmd, &p) < 0)
return -1;
@ -292,21 +274,14 @@ static int do_add(int cmd, int argc, char **argv)
return -1;
}
switch (p.iph.protocol) {
case IPPROTO_IPIP:
if (p.i_flags & VTI_ISVTI)
return tnl_add_ioctl(cmd, "ip_vti0", p.name, &p);
else
return tnl_add_ioctl(cmd, "tunl0", p.name, &p);
case IPPROTO_GRE:
return tnl_add_ioctl(cmd, "gre0", p.name, &p);
case IPPROTO_IPV6:
return tnl_add_ioctl(cmd, "sit0", p.name, &p);
default:
fprintf(stderr, "cannot determine tunnel mode (ipip, gre, vti or sit)\n");
basedev = tnl_defname(&p);
if (!basedev) {
fprintf(stderr,
"cannot determine tunnel mode (ipip, gre, vti or sit)\n");
return -1;
}
return -1;
return tnl_add_ioctl(cmd, basedev, p.name, &p);
}
static int do_del(int argc, char **argv)
@ -316,20 +291,7 @@ static int do_del(int argc, char **argv)
if (parse_args(argc, argv, SIOCDELTUNNEL, &p) < 0)
return -1;
switch (p.iph.protocol) {
case IPPROTO_IPIP:
if (p.i_flags & VTI_ISVTI)
return tnl_del_ioctl("ip_vti0", p.name, &p);
else
return tnl_del_ioctl("tunl0", p.name, &p);
case IPPROTO_GRE:
return tnl_del_ioctl("gre0", p.name, &p);
case IPPROTO_IPV6:
return tnl_del_ioctl("sit0", p.name, &p);
default:
return tnl_del_ioctl(p.name, p.name, &p);
}
return -1;
return tnl_del_ioctl(tnl_defname(&p) ? : p.name, p.name, &p);
}
static void print_tunnel(struct ip_tunnel_parm *p)
@ -343,7 +305,7 @@ static void print_tunnel(struct ip_tunnel_parm *p)
/* Do not use format_host() for local addr,
* symbolic name will not be useful.
*/
printf("%s: %s/ip remote %s local %s ",
printf("%s: %s/ip remote %s local %s",
p->name,
tnl_strproto(p->iph.protocol),
p->iph.daddr ? format_host(AF_INET, 4, &p->iph.daddr, s1, sizeof(s1)) : "any",
@ -358,81 +320,76 @@ static void print_tunnel(struct ip_tunnel_parm *p)
prl[0].addr = htonl(INADDR_ANY);
if (!tnl_prl_ioctl(SIOCGETPRL, p->name, prl))
for (i = 1; i < sizeof(prl) / sizeof(prl[0]); i++)
{
if (prl[i].addr != htonl(INADDR_ANY)) {
printf(" %s %s ",
(prl[i].flags & PRL_DEFAULT) ? "pdr" : "pr",
format_host(AF_INET, 4, &prl[i].addr, s1, sizeof(s1)));
for (i = 1; i < ARRAY_SIZE(prl); i++) {
if (prl[i].addr != htonl(INADDR_ANY)) {
printf(" %s %s ",
(prl[i].flags & PRL_DEFAULT) ? "pdr" : "pr",
format_host(AF_INET, 4, &prl[i].addr, s1, sizeof(s1)));
}
}
}
}
if (p->link) {
const char *n = ll_index_to_name(p->link);
if (n)
printf(" dev %s ", n);
printf(" dev %s", n);
}
if (p->iph.ttl)
printf(" ttl %d ", p->iph.ttl);
printf(" ttl %d", p->iph.ttl);
else
printf(" ttl inherit ");
printf(" ttl inherit");
if (p->iph.tos) {
SPRINT_BUF(b1);
printf(" tos");
if (p->iph.tos&1)
if (p->iph.tos & 1)
printf(" inherit");
if (p->iph.tos&~1)
printf("%c%s ", p->iph.tos&1 ? '/' : ' ',
rtnl_dsfield_n2a(p->iph.tos&~1, b1, sizeof(b1)));
if (p->iph.tos & ~1)
printf("%c%s ", p->iph.tos & 1 ? '/' : ' ',
rtnl_dsfield_n2a(p->iph.tos & ~1, b1, sizeof(b1)));
}
if (!(p->iph.frag_off&htons(IP_DF)))
if (!(p->iph.frag_off & htons(IP_DF)))
printf(" nopmtudisc");
if (p->iph.protocol == IPPROTO_IPV6 && !tnl_ioctl_get_6rd(p->name, &ip6rd) && ip6rd.prefixlen) {
printf(" 6rd-prefix %s/%u ",
printf(" 6rd-prefix %s/%u",
inet_ntop(AF_INET6, &ip6rd.prefix, s1, sizeof(s1)),
ip6rd.prefixlen);
if (ip6rd.relay_prefix) {
printf("6rd-relay_prefix %s/%u ",
printf(" 6rd-relay_prefix %s/%u",
format_host(AF_INET, 4, &ip6rd.relay_prefix, s1, sizeof(s1)),
ip6rd.relay_prefixlen);
}
}
if ((p->i_flags&GRE_KEY) && (p->o_flags&GRE_KEY) && p->o_key == p->i_key)
if ((p->i_flags & GRE_KEY) && (p->o_flags & GRE_KEY) && p->o_key == p->i_key)
printf(" key %u", ntohl(p->i_key));
else if ((p->i_flags|p->o_flags)&GRE_KEY) {
if (p->i_flags&GRE_KEY)
printf(" ikey %u ", ntohl(p->i_key));
if (p->o_flags&GRE_KEY)
printf(" okey %u ", ntohl(p->o_key));
else if ((p->i_flags | p->o_flags) & GRE_KEY) {
if (p->i_flags & GRE_KEY)
printf(" ikey %u", ntohl(p->i_key));
if (p->o_flags & GRE_KEY)
printf(" okey %u", ntohl(p->o_key));
}
if (p->i_flags&GRE_SEQ)
if (p->i_flags & GRE_SEQ)
printf("%s Drop packets out of sequence.", _SL_);
if (p->i_flags&GRE_CSUM)
if (p->i_flags & GRE_CSUM)
printf("%s Checksum in received packet is required.", _SL_);
if (p->o_flags&GRE_SEQ)
if (p->o_flags & GRE_SEQ)
printf("%s Sequence packets on output.", _SL_);
if (p->o_flags&GRE_CSUM)
if (p->o_flags & GRE_CSUM)
printf("%s Checksum output packets.", _SL_);
}
static int do_tunnels_list(struct ip_tunnel_parm *p)
{
char name[IFNAMSIZ];
unsigned long rx_bytes, rx_packets, rx_errs, rx_drops,
rx_fifo, rx_frame,
tx_bytes, tx_packets, tx_errs, tx_drops,
tx_fifo, tx_colls, tx_carrier, rx_multi;
struct ip_tunnel_parm p1;
char buf[512];
int err = -1;
FILE *fp = fopen("/proc/net/dev", "r");
if (fp == NULL) {
perror("fopen");
return -1;
@ -442,26 +399,22 @@ static int do_tunnels_list(struct ip_tunnel_parm *p)
if (!fgets(buf, sizeof(buf), fp) ||
!fgets(buf, sizeof(buf), fp)) {
fprintf(stderr, "/proc/net/dev read error\n");
fclose(fp);
return -1;
goto end;
}
while (fgets(buf, sizeof(buf), fp) != NULL) {
char name[IFNAMSIZ];
int index, type;
struct ip_tunnel_parm p1;
char *ptr;
buf[sizeof(buf) - 1] = 0;
if ((ptr = strchr(buf, ':')) == NULL ||
ptr = strchr(buf, ':');
if (ptr == NULL ||
(*ptr++ = 0, sscanf(buf, "%s", name) != 1)) {
fprintf(stderr, "Wrong format for /proc/net/dev. Giving up.\n");
fclose(fp);
return -1;
goto end;
}
if (sscanf(ptr, "%ld%ld%ld%ld%ld%ld%ld%*d%ld%ld%ld%ld%ld%ld%ld",
&rx_bytes, &rx_packets, &rx_errs, &rx_drops,
&rx_fifo, &rx_frame, &rx_multi,
&tx_bytes, &tx_packets, &tx_errs, &tx_drops,
&tx_fifo, &tx_colls, &tx_carrier) != 14)
continue;
if (p->name[0] && strcmp(p->name, name))
continue;
index = ll_name_to_index(name);
@ -484,48 +437,30 @@ static int do_tunnels_list(struct ip_tunnel_parm *p)
(p->i_key && p1.i_key != p->i_key))
continue;
print_tunnel(&p1);
if (show_stats) {
printf("%s", _SL_);
printf("RX: Packets Bytes Errors CsumErrs OutOfSeq Mcasts%s", _SL_);
printf(" %-10ld %-12ld %-6ld %-8ld %-8ld %-8ld%s",
rx_packets, rx_bytes, rx_errs, rx_frame, rx_fifo, rx_multi, _SL_);
printf("TX: Packets Bytes Errors DeadLoop NoRoute NoBufs%s", _SL_);
printf(" %-10ld %-12ld %-6ld %-8ld %-8ld %-6ld",
tx_packets, tx_bytes, tx_errs, tx_colls, tx_carrier, tx_drops);
}
if (show_stats)
tnl_print_stats(ptr);
printf("\n");
}
err = 0;
end:
fclose(fp);
return 0;
return err;
}
static int do_show(int argc, char **argv)
{
int err;
struct ip_tunnel_parm p;
const char *basedev;
ll_init_map(&rth);
if (parse_args(argc, argv, SIOCGETTUNNEL, &p) < 0)
return -1;
switch (p.iph.protocol) {
case IPPROTO_IPIP:
if (p.i_flags & VTI_ISVTI)
err = tnl_get_ioctl(p.name[0] ? p.name : "ip_vti0", &p);
else
err = tnl_get_ioctl(p.name[0] ? p.name : "tunl0", &p);
break;
case IPPROTO_GRE:
err = tnl_get_ioctl(p.name[0] ? p.name : "gre0", &p);
break;
case IPPROTO_IPV6:
err = tnl_get_ioctl(p.name[0] ? p.name : "sit0", &p);
break;
default:
do_tunnels_list(&p);
return 0;
}
if (err)
basedev = tnl_defname(&p);
if (!basedev)
return do_tunnels_list(&p);
if (tnl_get_ioctl(p.name[0] ? p.name : basedev, &p))
return -1;
print_tunnel(&p);
@ -566,11 +501,13 @@ static int do_prl(int argc, char **argv)
strncpy(medium, *argv, IFNAMSIZ-1);
devname++;
} else {
fprintf(stderr,"Invalid PRL parameter \"%s\"\n", *argv);
fprintf(stderr,
"Invalid PRL parameter \"%s\"\n", *argv);
exit(-1);
}
if (count > 1) {
fprintf(stderr,"One PRL entry at a time\n");
fprintf(stderr,
"One PRL entry at a time\n");
exit(-1);
}
argc--; argv++;
@ -616,7 +553,8 @@ static int do_6rd(int argc, char **argv)
strncpy(medium, *argv, IFNAMSIZ-1);
devname++;
} else {
fprintf(stderr,"Invalid 6RD parameter \"%s\"\n", *argv);
fprintf(stderr,
"Invalid 6RD parameter \"%s\"\n", *argv);
exit(-1);
}
argc--; argv++;
@ -629,8 +567,35 @@ static int do_6rd(int argc, char **argv)
return tnl_6rd_ioctl(cmd, medium, &ip6rd);
}
static int tunnel_mode_is_ipv6(char *tunnel_mode)
{
static const char * const ipv6_modes[] = {
"ipv6/ipv6", "ip6ip6",
"vti6",
"ip/ipv6", "ipv4/ipv6", "ipip6", "ip4ip6",
"ip6gre", "gre/ipv6",
"any/ipv6", "any"
};
int i;
for (i = 0; i < ARRAY_SIZE(ipv6_modes); i++) {
if (strcmp(ipv6_modes[i], tunnel_mode) == 0)
return 1;
}
return 0;
}
int do_iptunnel(int argc, char **argv)
{
int i;
for (i = 0; i < argc - 1; i++) {
if (strcmp(argv[i], "mode") == 0) {
if (tunnel_mode_is_ipv6(argv[i + 1]))
preferred_family = AF_INET6;
break;
}
}
switch (preferred_family) {
case AF_UNSPEC:
preferred_family = AF_INET;
@ -651,19 +616,19 @@ int do_iptunnel(int argc, char **argv)
if (argc > 0) {
if (matches(*argv, "add") == 0)
return do_add(SIOCADDTUNNEL, argc-1, argv+1);
return do_add(SIOCADDTUNNEL, argc - 1, argv + 1);
if (matches(*argv, "change") == 0)
return do_add(SIOCCHGTUNNEL, argc-1, argv+1);
return do_add(SIOCCHGTUNNEL, argc - 1, argv + 1);
if (matches(*argv, "delete") == 0)
return do_del(argc-1, argv+1);
return do_del(argc - 1, argv + 1);
if (matches(*argv, "show") == 0 ||
matches(*argv, "lst") == 0 ||
matches(*argv, "list") == 0)
return do_show(argc-1, argv+1);
return do_show(argc - 1, argv + 1);
if (matches(*argv, "prl") == 0)
return do_prl(argc-1, argv+1);
return do_prl(argc - 1, argv + 1);
if (matches(*argv, "6rd") == 0)
return do_6rd(argc-1, argv+1);
return do_6rd(argc - 1, argv + 1);
if (matches(*argv, "help") == 0)
usage();
} else

View File

@ -74,6 +74,7 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
__u16 encapflags = 0;
__u16 encapsport = 0;
__u16 encapdport = 0;
__u8 metadata = 0;
if (!(n->nlmsg_flags & NLM_F_CREATE)) {
memset(&req, 0, sizeof(req));
@ -148,6 +149,9 @@ get_failed:
encapsport = rta_getattr_u16(greinfo[IFLA_GRE_ENCAP_SPORT]);
if (greinfo[IFLA_GRE_ENCAP_DPORT])
encapdport = rta_getattr_u16(greinfo[IFLA_GRE_ENCAP_DPORT]);
if (greinfo[IFLA_GRE_COLLECT_METADATA])
metadata = 1;
}
while (argc > 0) {
@ -291,6 +295,8 @@ get_failed:
encapflags |= TUNNEL_ENCAP_FLAG_REMCSUM;
} else if (strcmp(*argv, "noencap-remcsum") == 0) {
encapflags |= ~TUNNEL_ENCAP_FLAG_REMCSUM;
} else if (strcmp(*argv, "external") == 0) {
metadata = 1;
} else
usage();
argc--; argv++;
@ -325,6 +331,8 @@ get_failed:
addattr16(n, 1024, IFLA_GRE_ENCAP_FLAGS, encapflags);
addattr16(n, 1024, IFLA_GRE_ENCAP_SPORT, htons(encapsport));
addattr16(n, 1024, IFLA_GRE_ENCAP_DPORT, htons(encapdport));
if (metadata)
addattr_l(n, 1024, IFLA_GRE_COLLECT_METADATA, NULL, 0);
return 0;
}
@ -413,6 +421,9 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
if (oflags & GRE_CSUM)
fputs("ocsum ", f);
if (tb[IFLA_GRE_COLLECT_METADATA])
fputs("external ", f);
if (tb[IFLA_GRE_ENCAP_TYPE] &&
*(__u16 *)RTA_DATA(tb[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE) {
__u16 type = rta_getattr_u16(tb[IFLA_GRE_ENCAP_TYPE]);

View File

@ -93,7 +93,7 @@ int rtnl_rtntype_a2n(int *id, char *arg)
return 0;
}
int get_rt_realms(__u32 *realms, char *arg)
static int get_rt_realms(__u32 *realms, char *arg)
{
__u32 realm = 0;
char *p = strchr(arg, '/');
@ -114,3 +114,11 @@ int get_rt_realms(__u32 *realms, char *arg)
*realms |= realm;
return 0;
}
int get_rt_realms_or_raw(__u32 *realms, char *arg)
{
if (!get_rt_realms(realms, arg))
return 0;
return get_unsigned(realms, arg, 0);
}

View File

@ -508,4 +508,3 @@ int do_tcp_metrics(int argc, char **argv)
"try \"ip tcp_metrics help\".\n", *argv);
exit(-1);
}

View File

@ -180,3 +180,46 @@ int tnl_ioctl_get_6rd(const char *name, void *p)
{
return tnl_gen_ioctl(SIOCGET6RD, name, p, EINVAL);
}
__be32 tnl_parse_key(const char *name, const char *key)
{
unsigned uval;
if (strchr(key, '.'))
return get_addr32(key);
if (get_unsigned(&uval, key, 0) < 0) {
fprintf(stderr, "invalid value for \"%s\": \"%s\";", name, key);
fprintf(stderr, " it should be an unsigned integer\n");
exit(-1);
}
return htonl(uval);
}
/* tnl_print_stats - print tunnel statistics
*
* @buf - tunnel interface's line in /proc/net/dev,
* starting past the interface name and following colon
*/
void tnl_print_stats(const char *buf)
{
unsigned long rx_bytes, rx_packets, rx_errs, rx_drops,
rx_fifo, rx_frame,
tx_bytes, tx_packets, tx_errs, tx_drops,
tx_fifo, tx_colls, tx_carrier, rx_multi;
if (sscanf(buf, "%lu%lu%lu%lu%lu%lu%lu%*d%lu%lu%lu%lu%lu%lu%lu",
&rx_bytes, &rx_packets, &rx_errs, &rx_drops,
&rx_fifo, &rx_frame, &rx_multi,
&tx_bytes, &tx_packets, &tx_errs, &tx_drops,
&tx_fifo, &tx_colls, &tx_carrier) != 14)
return;
printf("%s", _SL_);
printf("RX: Packets Bytes Errors CsumErrs OutOfSeq Mcasts%s", _SL_);
printf(" %-10ld %-12ld %-6ld %-8ld %-8ld %-8ld%s",
rx_packets, rx_bytes, rx_errs, rx_frame, rx_fifo, rx_multi, _SL_);
printf("TX: Packets Bytes Errors DeadLoop NoRoute NoBufs%s", _SL_);
printf(" %-10ld %-12ld %-6ld %-8ld %-8ld %-6ld",
tx_packets, tx_bytes, tx_errs, tx_colls, tx_carrier, tx_drops);
}

View File

@ -31,5 +31,7 @@ int tnl_del_ioctl(const char *basedev, const char *name, void *p);
int tnl_prl_ioctl(int cmd, const char *name, void *p);
int tnl_6rd_ioctl(int cmd, const char *name, void *p);
int tnl_ioctl_get_6rd(const char *name, void *p);
__be32 tnl_parse_key(const char *name, const char *key);
void tnl_print_stats(const char *buf);
#endif

View File

@ -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
View 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.
*/

View File

@ -191,6 +191,27 @@ int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len)
return sendmsg(rth->fd, &msg, 0);
}
int rtnl_dump_request_n(struct rtnl_handle *rth, struct nlmsghdr *n)
{
struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };
struct iovec iov = {
.iov_base = (void*) n,
.iov_len = n->nlmsg_len
};
struct msghdr msg = {
.msg_name = &nladdr,
.msg_namelen = sizeof(nladdr),
.msg_iov = &iov,
.msg_iovlen = 1,
};
n->nlmsg_flags = NLM_F_DUMP|NLM_F_REQUEST;
n->nlmsg_pid = 0;
n->nlmsg_seq = rth->dump = ++rth->seq;
return sendmsg(rth->fd, &msg, 0);
}
int rtnl_dump_filter_l(struct rtnl_handle *rth,
const struct rtnl_dump_filter_arg *arg)
{
@ -238,6 +259,8 @@ int rtnl_dump_filter_l(struct rtnl_handle *rth,
while (NLMSG_OK(h, msglen)) {
int err = 0;
h->nlmsg_flags &= ~a->nc_flags;
if (nladdr.nl_pid != 0 ||
h->nlmsg_pid != rth->local.nl_pid ||
h->nlmsg_seq != rth->dump)
@ -296,20 +319,20 @@ skip_it:
}
}
int rtnl_dump_filter(struct rtnl_handle *rth,
int rtnl_dump_filter_nc(struct rtnl_handle *rth,
rtnl_filter_t filter,
void *arg1)
void *arg1, __u16 nc_flags)
{
const struct rtnl_dump_filter_arg a[2] = {
{ .filter = filter, .arg1 = arg1, },
{ .filter = NULL, .arg1 = NULL, },
{ .filter = filter, .arg1 = arg1, .nc_flags = nc_flags, },
{ .filter = NULL, .arg1 = NULL, .nc_flags = 0, },
};
return rtnl_dump_filter_l(rth, a);
}
int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
struct nlmsghdr *answer, size_t len)
struct nlmsghdr *answer, size_t maxlen)
{
int status;
unsigned seq;
@ -392,19 +415,21 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
} else if (!err->error) {
if (answer)
memcpy(answer, h,
MIN(len, h->nlmsg_len));
MIN(maxlen, h->nlmsg_len));
return 0;
}
fprintf(stderr, "RTNETLINK answers: %s\n",
strerror(-err->error));
if (rtnl->proto != NETLINK_SOCK_DIAG)
fprintf(stderr,
"RTNETLINK answers: %s\n",
strerror(-err->error));
errno = -err->error;
return -1;
}
if (answer) {
memcpy(answer, h,
MIN(len, h->nlmsg_len));
MIN(maxlen, h->nlmsg_len));
return 0;
}
@ -721,6 +746,37 @@ int rta_addattr_l(struct rtattr *rta, int maxlen, int type,
return 0;
}
int rta_addattr8(struct rtattr *rta, int maxlen, int type, __u8 data)
{
return rta_addattr_l(rta, maxlen, type, &data, sizeof(__u8));
}
int rta_addattr16(struct rtattr *rta, int maxlen, int type, __u16 data)
{
return rta_addattr_l(rta, maxlen, type, &data, sizeof(__u16));
}
int rta_addattr64(struct rtattr *rta, int maxlen, int type, __u64 data)
{
return rta_addattr_l(rta, maxlen, type, &data, sizeof(__u64));
}
struct rtattr *rta_nest(struct rtattr *rta, int maxlen, int type)
{
struct rtattr *nest = RTA_TAIL(rta);
rta_addattr_l(rta, maxlen, type, NULL, 0);
return nest;
}
int rta_nest_end(struct rtattr *rta, struct rtattr *nest)
{
nest->rta_len = (void *)RTA_TAIL(rta) - (void *)nest;
return rta->rta_len;
}
int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
{
return parse_rtattr_flags(tb, max, rta, len, 0);

View File

@ -17,21 +17,19 @@
#include <string.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <dirent.h>
#include <asm/types.h>
#include <linux/rtnetlink.h>
#include "rt_names.h"
#ifndef CONFDIR
#define CONFDIR "/etc/iproute2"
#endif
#include "utils.h"
#define NAME_MAX_LEN 512
struct rtnl_hash_entry {
struct rtnl_hash_entry *next;
const char * name;
struct rtnl_hash_entry *next;
const char *name;
unsigned int id;
};
@ -81,7 +79,7 @@ rtnl_hash_initialize(const char *file, struct rtnl_hash_entry **hash, int size)
return;
}
if (id<0)
if (id < 0)
continue;
entry = malloc(sizeof(*entry));
@ -111,7 +109,7 @@ static void rtnl_tab_initialize(const char *file, char **tab, int size)
fclose(fp);
return;
}
if (id<0 || id>size)
if (id < 0 || id > size)
continue;
tab[id] = strdup(namebuf);
@ -119,23 +117,23 @@ static void rtnl_tab_initialize(const char *file, char **tab, int size)
fclose(fp);
}
static char * rtnl_rtprot_tab[256] = {
[RTPROT_UNSPEC] = "none",
[RTPROT_REDIRECT] ="redirect",
[RTPROT_KERNEL] = "kernel",
[RTPROT_BOOT] = "boot",
[RTPROT_STATIC] = "static",
static char *rtnl_rtprot_tab[256] = {
[RTPROT_UNSPEC] = "none",
[RTPROT_REDIRECT] = "redirect",
[RTPROT_KERNEL] = "kernel",
[RTPROT_BOOT] = "boot",
[RTPROT_STATIC] = "static",
[RTPROT_GATED] = "gated",
[RTPROT_RA] = "ra",
[RTPROT_MRT] = "mrt",
[RTPROT_ZEBRA] ="zebra",
[RTPROT_BIRD] = "bird",
[RTPROT_BABEL] = "babel",
[RTPROT_GATED] = "gated",
[RTPROT_RA] = "ra",
[RTPROT_MRT] = "mrt",
[RTPROT_ZEBRA] = "zebra",
[RTPROT_BIRD] = "bird",
[RTPROT_BABEL] = "babel",
[RTPROT_DNROUTED] = "dnrouted",
[RTPROT_XORP] = "xorp",
[RTPROT_NTK] = "ntk",
[RTPROT_DHCP] = "dhcp",
[RTPROT_XORP] = "xorp",
[RTPROT_NTK] = "ntk",
[RTPROT_DHCP] = "dhcp",
};
@ -148,9 +146,9 @@ static void rtnl_rtprot_initialize(void)
rtnl_rtprot_tab, 256);
}
const char * rtnl_rtprot_n2a(int id, char *buf, int len)
const char *rtnl_rtprot_n2a(int id, char *buf, int len)
{
if (id<0 || id>=256) {
if (id < 0 || id >= 256) {
snprintf(buf, len, "%u", id);
return buf;
}
@ -166,7 +164,7 @@ const char * rtnl_rtprot_n2a(int id, char *buf, int len)
int rtnl_rtprot_a2n(__u32 *id, const char *arg)
{
static char *cache = NULL;
static char *cache;
static unsigned long res;
char *end;
int i;
@ -179,7 +177,7 @@ int rtnl_rtprot_a2n(__u32 *id, const char *arg)
if (!rtnl_rtprot_init)
rtnl_rtprot_initialize();
for (i=0; i<256; i++) {
for (i = 0; i < 256; i++) {
if (rtnl_rtprot_tab[i] &&
strcmp(rtnl_rtprot_tab[i], arg) == 0) {
cache = rtnl_rtprot_tab[i];
@ -196,8 +194,13 @@ int rtnl_rtprot_a2n(__u32 *id, const char *arg)
return 0;
}
static char * rtnl_rtscope_tab[256] = {
"global",
static char *rtnl_rtscope_tab[256] = {
[RT_SCOPE_UNIVERSE] = "global",
[RT_SCOPE_NOWHERE] = "nowhere",
[RT_SCOPE_HOST] = "host",
[RT_SCOPE_LINK] = "link",
[RT_SCOPE_SITE] = "site",
};
static int rtnl_rtscope_init;
@ -205,33 +208,32 @@ static int rtnl_rtscope_init;
static void rtnl_rtscope_initialize(void)
{
rtnl_rtscope_init = 1;
rtnl_rtscope_tab[RT_SCOPE_NOWHERE] = "nowhere";
rtnl_rtscope_tab[RT_SCOPE_HOST] = "host";
rtnl_rtscope_tab[RT_SCOPE_LINK] = "link";
rtnl_rtscope_tab[RT_SCOPE_SITE] = "site";
rtnl_tab_initialize(CONFDIR "/rt_scopes",
rtnl_rtscope_tab, 256);
}
const char *rtnl_rtscope_n2a(int id, char *buf, int len)
{
if (id<0 || id>=256) {
if (id < 0 || id >= 256) {
snprintf(buf, len, "%d", id);
return buf;
}
if (!rtnl_rtscope_tab[id]) {
if (!rtnl_rtscope_init)
rtnl_rtscope_initialize();
}
if (rtnl_rtscope_tab[id])
return rtnl_rtscope_tab[id];
snprintf(buf, len, "%d", id);
return buf;
}
int rtnl_rtscope_a2n(__u32 *id, const char *arg)
{
static const char *cache = NULL;
static const char *cache;
static unsigned long res;
char *end;
int i;
@ -244,7 +246,7 @@ int rtnl_rtscope_a2n(__u32 *id, const char *arg)
if (!rtnl_rtscope_init)
rtnl_rtscope_initialize();
for (i=0; i<256; i++) {
for (i = 0; i < 256; i++) {
if (rtnl_rtscope_tab[i] &&
strcmp(rtnl_rtscope_tab[i], arg) == 0) {
cache = rtnl_rtscope_tab[i];
@ -262,7 +264,7 @@ int rtnl_rtscope_a2n(__u32 *id, const char *arg)
}
static char * rtnl_rtrealm_tab[256] = {
static char *rtnl_rtrealm_tab[256] = {
"unknown",
};
@ -277,7 +279,7 @@ static void rtnl_rtrealm_initialize(void)
const char *rtnl_rtrealm_n2a(int id, char *buf, int len)
{
if (id<0 || id>=256) {
if (id < 0 || id >= 256) {
snprintf(buf, len, "%d", id);
return buf;
}
@ -294,7 +296,7 @@ const char *rtnl_rtrealm_n2a(int id, char *buf, int len)
int rtnl_rtrealm_a2n(__u32 *id, const char *arg)
{
static char *cache = NULL;
static char *cache;
static unsigned long res;
char *end;
int i;
@ -307,7 +309,7 @@ int rtnl_rtrealm_a2n(__u32 *id, const char *arg)
if (!rtnl_rtrealm_init)
rtnl_rtrealm_initialize();
for (i=0; i<256; i++) {
for (i = 0; i < 256; i++) {
if (rtnl_rtrealm_tab[i] &&
strcmp(rtnl_rtrealm_tab[i], arg) == 0) {
cache = rtnl_rtrealm_tab[i];
@ -329,7 +331,7 @@ static struct rtnl_hash_entry dflt_table_entry = { .name = "default" };
static struct rtnl_hash_entry main_table_entry = { .name = "main" };
static struct rtnl_hash_entry local_table_entry = { .name = "local" };
static struct rtnl_hash_entry * rtnl_rttable_hash[256] = {
static struct rtnl_hash_entry *rtnl_rttable_hash[256] = {
[RT_TABLE_DEFAULT] = &dflt_table_entry,
[RT_TABLE_MAIN] = &main_table_entry,
[RT_TABLE_LOCAL] = &local_table_entry,
@ -339,6 +341,8 @@ static int rtnl_rttable_init;
static void rtnl_rttable_initialize(void)
{
struct dirent *de;
DIR *d;
int i;
rtnl_rttable_init = 1;
@ -348,9 +352,33 @@ static void rtnl_rttable_initialize(void)
}
rtnl_hash_initialize(CONFDIR "/rt_tables",
rtnl_rttable_hash, 256);
d = opendir(CONFDIR "/rt_tables.d");
if (!d)
return;
while ((de = readdir(d)) != NULL) {
char path[PATH_MAX];
size_t len;
if (*de->d_name == '.')
continue;
/* only consider filenames ending in '.conf' */
len = strlen(de->d_name);
if (len <= 5)
continue;
if (strcmp(de->d_name + len - 5, ".conf"))
continue;
snprintf(path, sizeof(path),
CONFDIR "/rt_tables.d/%s", de->d_name);
rtnl_hash_initialize(path, rtnl_rttable_hash, 256);
}
closedir(d);
}
const char * rtnl_rttable_n2a(__u32 id, char *buf, int len)
const char *rtnl_rttable_n2a(__u32 id, char *buf, int len)
{
struct rtnl_hash_entry *entry;
@ -371,7 +399,7 @@ const char * rtnl_rttable_n2a(__u32 id, char *buf, int len)
int rtnl_rttable_a2n(__u32 *id, const char *arg)
{
static const char *cache = NULL;
static const char *cache;
static unsigned long res;
struct rtnl_hash_entry *entry;
char *end;
@ -385,7 +413,7 @@ int rtnl_rttable_a2n(__u32 *id, const char *arg)
if (!rtnl_rttable_init)
rtnl_rttable_initialize();
for (i=0; i<256; i++) {
for (i = 0; i < 256; i++) {
entry = rtnl_rttable_hash[i];
while (entry && strcmp(entry->name, arg))
entry = entry->next;
@ -405,7 +433,7 @@ int rtnl_rttable_a2n(__u32 *id, const char *arg)
}
static char * rtnl_rtdsfield_tab[256] = {
static char *rtnl_rtdsfield_tab[256] = {
"0",
};
@ -420,7 +448,7 @@ static void rtnl_rtdsfield_initialize(void)
const char *rtnl_dsfield_n2a(int id, char *buf, int len)
{
if (id<0 || id>=256) {
if (id < 0 || id >= 256) {
snprintf(buf, len, "%d", id);
return buf;
}
@ -437,7 +465,7 @@ const char *rtnl_dsfield_n2a(int id, char *buf, int len)
int rtnl_dsfield_a2n(__u32 *id, const char *arg)
{
static char *cache = NULL;
static char *cache;
static unsigned long res;
char *end;
int i;
@ -450,7 +478,7 @@ int rtnl_dsfield_a2n(__u32 *id, const char *arg)
if (!rtnl_rtdsfield_init)
rtnl_rtdsfield_initialize();
for (i=0; i<256; i++) {
for (i = 0; i < 256; i++) {
if (rtnl_rtdsfield_tab[i] &&
strcmp(rtnl_rtdsfield_tab[i], arg) == 0) {
cache = rtnl_rtdsfield_tab[i];
@ -468,9 +496,11 @@ int rtnl_dsfield_a2n(__u32 *id, const char *arg)
}
static struct rtnl_hash_entry dflt_group_entry = { .id = 0, .name = "default" };
static struct rtnl_hash_entry dflt_group_entry = {
.id = 0, .name = "default"
};
static struct rtnl_hash_entry * rtnl_group_hash[256] = {
static struct rtnl_hash_entry *rtnl_group_hash[256] = {
[0] = &dflt_group_entry,
};
@ -485,7 +515,7 @@ static void rtnl_group_initialize(void)
int rtnl_group_a2n(int *id, const char *arg)
{
static const char *cache = NULL;
static const char *cache;
static unsigned long res;
struct rtnl_hash_entry *entry;
char *end;
@ -499,7 +529,7 @@ int rtnl_group_a2n(int *id, const char *arg)
if (!rtnl_group_init)
rtnl_group_initialize();
for (i=0; i<256; i++) {
for (i = 0; i < 256; i++) {
entry = rtnl_group_hash[i];
while (entry && strcmp(entry->name, arg))
entry = entry->next;
@ -526,11 +556,10 @@ const char *rtnl_group_n2a(int id, char *buf, int len)
if (!rtnl_group_init)
rtnl_group_initialize();
for (i=0; i<256; i++) {
for (i = 0; i < 256; i++) {
entry = rtnl_group_hash[i];
if (entry && entry->id == id) {
if (entry && entry->id == id)
return entry->name;
}
}
snprintf(buf, len, "%d", id);
@ -589,7 +618,7 @@ const char *nl_proto_n2a(int id, char *buf, int len)
int nl_proto_a2n(__u32 *id, const char *arg)
{
static char *cache = NULL;
static char *cache;
static unsigned long res;
char *end;
int i;

View File

@ -384,6 +384,41 @@ static int get_addr_ipv4(__u8 *ap, const char *cp)
return 1;
}
int get_addr64(__u64 *ap, const char *cp)
{
int i;
union {
__u16 v16[4];
__u64 v64;
} val;
for (i = 0; i < 4; i++) {
unsigned long n;
char *endp;
n = strtoul(cp, &endp, 16);
if (n > 0xffff)
return -1; /* bogus network value */
if (endp == cp) /* no digits */
return -1;
val.v16[i] = htons(n);
if (*endp == '\0')
break;
if (i == 3 || *endp != ':')
return -1; /* extra characters */
cp = endp + 1;
}
*ap = val.v64;
return 1;
}
int get_addr_1(inet_prefix *addr, const char *name, int family)
{
memset(addr, 0, sizeof(*addr));
@ -531,7 +566,8 @@ done:
int get_addr(inet_prefix *dst, const char *arg, int family)
{
if (get_addr_1(dst, arg, family)) {
fprintf(stderr, "Error: an inet address is expected rather than \"%s\".\n", arg);
fprintf(stderr, "Error: %s address is expected rather than \"%s\".\n",
family_name(family) ,arg);
exit(1);
}
return 0;
@ -544,7 +580,8 @@ int get_prefix(inet_prefix *dst, char *arg, int family)
exit(1);
}
if (get_prefix_1(dst, arg, family)) {
fprintf(stderr, "Error: an inet prefix is expected rather than \"%s\".\n", arg);
fprintf(stderr, "Error: %s prefix is expected rather than \"%s\".\n",
family_name(family) ,arg);
exit(1);
}
return 0;
@ -836,6 +873,30 @@ __u8* hexstring_a2n(const char *str, __u8 *buf, int blen)
return buf;
}
int addr64_n2a(__u64 addr, char *buff, size_t len)
{
__u16 *words = (__u16 *)&addr;
__u16 v;
int i, ret;
size_t written = 0;
char *sep = ":";
for (i = 0; i < 4; i++) {
v = ntohs(words[i]);
if (i == 3)
sep = "";
ret = snprintf(&buff[written], len - written, "%x%s", v, sep);
if (ret < 0)
return ret;
written += ret;
}
return written;
}
int print_timestamp(FILE *fp)
{
struct timeval tv;
@ -914,12 +975,31 @@ int makeargs(char *line, char *argv[], int maxargs)
char *cp;
int argc = 0;
for (cp = strtok(line, ws); cp; cp = strtok(NULL, ws)) {
for (cp = line + strspn(line, ws); *cp; cp += strspn(cp, ws)) {
if (argc >= (maxargs - 1)) {
fprintf(stderr, "Too many arguments to command\n");
exit(1);
}
/* word begins with quote */
if (*cp == '\'' || *cp == '"') {
char quote = *cp++;
argv[argc++] = cp;
/* find ending quote */
cp = strchr(cp, quote);
if (cp == NULL) {
fprintf(stderr, "Unterminated quoted string\n");
exit(1);
}
*cp++ = 0;
continue;
}
argv[argc++] = cp;
/* find end of word */
cp += strcspn(cp, ws);
*cp++ = 0;
}
argv[argc] = NULL;

View File

@ -10,7 +10,11 @@ MAN8PAGES = $(TARGETS) ip.8 arpd.8 lnstat.8 routel.8 rtacct.8 rtmon.8 rtpr.8 ss.
ip-addrlabel.8 ip-fou.8 ip-gue.8 ip-l2tp.8 \
ip-maddress.8 ip-monitor.8 ip-mroute.8 ip-neighbour.8 \
ip-netns.8 ip-ntable.8 ip-rule.8 ip-tunnel.8 ip-xfrm.8 \
ip-tcp_metrics.8 ip-netconf.8 ip-token.8
ip-tcp_metrics.8 ip-netconf.8 ip-token.8 \
tipc.8 tipc-bearer.8 tipc-link.8 tipc-media.8 tipc-nametable.8 \
tipc-node.8 tipc-socket.8 \
tc-basic.8 tc-cgroup.8 tc-flow.8 tc-flower.8 tc-fw.8 tc-route.8 \
tc-tcindex.8 tc-u32.8
all: $(TARGETS)

View File

@ -21,17 +21,18 @@ bridge \- show / manipulate bridge addresses and devices
\fB\-V\fR[\fIersion\fR] |
\fB\-s\fR[\fItatistics\fR] |
\fB\-n\fR[\fIetns\fR] name }
\fB\-b\fR[\fIatch\fR] filename }
.ti -8
.BR "bridge link set"
.B dev
.B dev
.IR DEV
.IR " [ "
.B cost
.B cost
.IR COST " ] [ "
.B priority
.IR PRIO " ] [ "
.B state
.B priority
.IR PRIO " ] [ "
.B state
.IR STATE "] ["
.BR guard " { " on " | " off " } ] [ "
.BR hairpin " { " on " | " off " } ] [ "
@ -41,21 +42,21 @@ bridge \- show / manipulate bridge addresses and devices
.BR learning_sync " { " on " | " off " } ] [ "
.BR flood " { " on " | " off " } ] [ "
.BR hwmode " { " vepa " | " veb " } ] [ "
.BR self " ] [ " master " ] "
.BR self " ] [ " master " ] "
.ti -8
.BR "bridge link" " [ " show " ] [ "
.B dev
.B dev
.IR DEV " ]"
.ti -8
.BR "bridge fdb" " { " add " | " append " | " del " } "
.BR "bridge fdb" " { " add " | " append " | " del " | " replace " } "
.I LLADDR
.B dev
.B dev
.IR DEV " { "
.BR local " | " temp " } [ "
.BR self " ] [ " master " ] [ " router " ] [ " use " ] [ "
.B dst
.B dst
.IR IPADDR " ] [ "
.B vni
.IR VNI " ] ["
@ -66,12 +67,12 @@ bridge \- show / manipulate bridge addresses and devices
.ti -8
.BR "bridge fdb" " [ " show " ] [ "
.B dev
.B dev
.IR DEV " ]"
.ti -8
.BR "bridge mdb" " { " add " | " del " } "
.B dev
.B dev
.IR DEV
.B port
.IR PORT
@ -83,21 +84,21 @@ bridge \- show / manipulate bridge addresses and devices
.ti -8
.BR "bridge mdb show " [ "
.B dev
.B dev
.IR DEV " ]"
.ti -8
.BR "bridge vlan" " { " add " | " del " } "
.B dev
.B dev
.IR DEV
.B vid
.B vid
.IR VID " [ "
.BR pvid " ] [ " untagged " ] [ "
.BR self " ] [ " master " ] "
.BR pvid " ] [ " untagged " ] [ "
.BR self " ] [ " master " ] "
.ti -8
.BR "bridge vlan" " [ " show " ] [ "
.B dev
.B dev
.IR DEV " ]"
.ti -8
@ -137,6 +138,16 @@ to
.RI "-n[etns] " NETNS " [ " OPTIONS " ] " OBJECT " { " COMMAND " | "
.BR help " }"
.TP
.BR "\-b", " \-batch " <FILENAME>
Read commands from provided file or standard input and invoke them.
First failure will cause termination of bridge command.
.TP
.BR "\-force"
Don't terminate bridge command on errors in batch mode.
If there were any errors during execution of the commands, the application
return code will be non zero.
.SH BRIDGE - COMMAND SYNTAX
@ -148,7 +159,7 @@ to
- Bridge port.
.TP
.B fdb
.B fdb
- Forwarding Database entry.
.TP
@ -226,7 +237,7 @@ state the port for list for STP BPDUs and drop all other traffic.
.B 2
- STP LEARNING state. Only valid if STP is enabled on the bridge. In this
state the port will accept traffic only for the purpose of updating MAC
adress tables.
address tables.
.sp
.B 3
@ -297,6 +308,9 @@ link setting is configured on specified physical device
.BI master
link setting is configured on the software bridge (default)
.TP
.BR "\-t" , " \-timestamp"
display current time when using monitor option.
.SS bridge link show - list bridge port configuration.
@ -305,7 +319,7 @@ This command displays the current bridge port configuration and flags.
.SH bridge fdb - forwarding database management
.B fdb
objects contain known Ethernet addresses on a link.
objects contain known Ethernet addresses on a link.
.P
The corresponding commands display fdb entries, add new entries,
@ -370,7 +384,7 @@ If omitted the default value is used.
.BI via " DEVICE"
device name of the outgoing interface for the
VXLAN device driver to reach the
remote VXLAN tunnel endpoint.
remote VXLAN tunnel endpoint.
.SS bridge fdb append - append a forwarding database entry
This command adds a new fdb entry with an already known
@ -384,14 +398,21 @@ sends a copy of the data packet to each entry found.
.PP
The arguments are the same as with
.BR "bridge fdb add" ,
.BR "bridge fdb add" .
.SS bridge fdb delete - delete a forwarding database entry
This command removes an existing fdb entry.
.PP
The arguments are the same as with
.BR "bridge fdb add" ,
.BR "bridge fdb add" .
.SS bridge fdb replace - replace a forwarding database entry
If no matching entry is found, a new one will be created instead.
.PP
The arguments are the same as with
.BR "bridge fdb add" .
.SS bridge fdb show - list forwarding entries.
@ -527,7 +548,7 @@ This command displays the current VLAN filter table.
The
.B bridge
utility can monitor the state of devices and addresses
utility can monitor the state of devices and addresses
continuously. This option has a slightly different format.
Namely, the
.B monitor
@ -539,7 +560,7 @@ command is the first in the command line and then the object list follows:
.I OBJECT-LIST
is the list of object types that we want to monitor.
It may contain
.BR link ", " fdb ", and " mdb "."
.BR link ", " fdb ", and " mdb "."
If no
.B file
argument is given,

77
man/man8/genl.8 Normal file
View File

@ -0,0 +1,77 @@
.TH GENL 8 "29 Oct 2015" "iproute2" "Linux"
.SH NAME
genl \- generic netlink utility frontend
.SH SYNOPSIS
.in +8
.ti -8
.BR genl " [ " -s [ tatistics "] ] [ " -d [ etails "] ] [ " -r [ aw "] ] " OBJECT
.ti -8
.BR genl " { " -V [ ersion "] | " -h [ elp "] }"
.ti -8
.IR OBJECT " := { "
.B ctrl
.IR CTRL_OPTS " }"
.ti -8
.IR CTRL_OPTS " := { "
.BR help " | " list " | " monitor " | " get
.IR PARMS " }"
.ti -8
.IR PARMS " := { "
.B name
.IR NAME " | "
.B id
.IR ID " }"
.SH DESCRIPTION
The
.B genl
utility provides a simple frontend to the generic netlink library. Although it's
designed to support multiple
.IR OBJECT s,
for now only the
.B ctrl
object is available, which is used to query the generic netlink controller.
.SS ctrl
The generic netlink controller can be queried in various ways:
.TP
.B help
This command just prints a help text for the
.B ctrl
object.
.TP
.B list
Show the registered netlink users.
.TP
.B monitor
Listen for generic netlink notifications.
.TP
.B get
Query the controller for a given user, identified either by
.BR name " or " id .
.SH OPTIONS
genl supports the following options.
.TP
.B \-h, \-help
Show summary of options.
.TP
.B \-V, \-Version
Show version of program.
.TP
.B \-s, \-stats, \-statistics
Show object statistics.
.TP
.B \-d, \-details
Show object details.
.TP
.B \-r, \-raw
Dump raw output only.
.SH SEE ALSO
.BR ip (8)
.br
.SH AUTHOR
genl was written by Jamal Hadi Salim <hadi@cyberus.ca>.
.PP
This manual page was written by Petr Sabata <contyk@redhat.com>.

48
man/man8/ifcfg.8 Normal file
View File

@ -0,0 +1,48 @@
.TH IFCFG 8 "September 24 2009" "iproute2" "Linux"
.SH NAME
ifcfg \- simplistic script which replaces ifconfig IP management
.SH SYNOPSIS
.ad l
.in +8
.ti -8
.B ifcfg
.RI "[ " DEVICE " ] [ " command " ] " ADDRESS " [ " PEER " ] "
.sp
.SH DESCRIPTION
This manual page documents briefly the
.B ifcfg
command.
.PP
This is a simplistic script replacing one option of
.B ifconfig
, namely, IP address management. It not only adds
addresses, but also carries out Duplicate Address Detection RFC-DHCP,
sends unsolicited ARP to update the caches of other hosts sharing
the interface, adds some control routes and restarts Router Discovery
when it is necessary.
.SH IFCONFIG - COMMAND SYNTAX
.SS
.TP
.B DEVICE
- it may have alias, suffix, separated by colon.
.TP
.B command
- add, delete or stop.
.TP
.B ADDRESS
- optionally followed by prefix length.
.TP
.B peer
- optional peer address for pointpoint interfaces.
.SH NOTES
This script is not suitable for use with IPv6.
.SH SEE ALSO
.RB "IP Command reference " ip-cref.ps

59
man/man8/ifstat.8 Normal file
View File

@ -0,0 +1,59 @@
.TH IFSTAT 8 "28 Oct 2015" "iproute2" "Linux"
.SH NAME
ifstat \- handy utility to read network interface statistics
.SH SYNOPSIS
.in +8
.ti -8
.BR ifstat " [ "
.IR OPTIONS " ] [ " INTERFACE_LIST " ]"
.ti -8
.IR INTERFACE_LIST " := " INTERFACE_LIST " | " interface
.SH DESCRIPTION
\fBifstat\fP neatly prints out network interface statistics.
The utility keeps records of the previous data displayed in history files and
by default only shows difference between the last and the current call.
Location of the history files defaults to /tmp/.ifstat.u$UID but may be
overridden with the IFSTAT_HISTORY environment variable.
.SH OPTIONS
.TP
.B \-h, \-\-help
Show summary of options.
.TP
.B \-V, \-\-version
Show version of program.
.TP
.B \-a, \-\-ignore
Ignore the history file.
.TP
.B \-d, \-\-scan=SECS
Sample statistics every SECS second.
.TP
.B \-e, \-\-errors
Show errors.
.TP
.B \-n, \-\-nooutput
Don't display any output. Update the history file only.
.TP
.B \-r, \-\-reset
Reset history.
.TP
.B \-s, \-\-noupdate
Don't update the history file.
.TP
.B \-t, \-\-interval=SECS
Report average over the last SECS seconds.
.TP
.B \-z, \-\-zeros
Show entries with zero activity.
.SH ENVIRONMENT
.TP
.B IFSTAT_HISTORY
If set, it's value is interpreted as alternate history file path.
.SH SEE ALSO
.BR ip (8)
.br
.SH AUTHOR
ifstat was written by Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>.
.PP
This manual page was written by Petr Sabata <contyk@redhat.com>.

View File

@ -7,8 +7,8 @@ ip-addrlabel \- protocol address label management
.in +8
.ti -8
.B ip
.RI "[ " OPTIONS " ]"
.B addrlabel
.RI "[ " OPTIONS " ]"
.B addrlabel
.RI " { " COMMAND " | "
.BR help " }"
.sp
@ -66,4 +66,3 @@ flush all address labels in the kernel. This does not restore any default settin
.SH AUTHOR
Manpage by Yoshifuji Hideaki / 吉藤英明

View File

@ -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 " }"
@ -284,28 +284,28 @@ the following additional arguments are supported:
.BI link " DEVICE "
.BI name " NAME "
.BI type " vlan "
.R " [ "
[
.BI protocol " VLAN_PROTO "
.R " ] "
]
.BI id " VLANID "
.R " [ "
[
.BR reorder_hdr " { " on " | " off " } "
.R " ] "
.R " [ "
]
[
.BR gvrp " { " on " | " off " } "
.R " ] "
.R " [ "
]
[
.BR mvrp " { " on " | " off " } "
.R " ] "
.R " [ "
]
[
.BR loose_binding " { " on " | " off " } "
.R " ] "
.R " [ "
]
[
.BI ingress-qos-map " QOS-MAP "
.R " ] "
.R " [ "
]
[
.BI egress-qos-map " QOS-MAP "
.R " ] "
]
.in +8
.sp
@ -386,43 +386,44 @@ the following additional arguments are supported:
.BI "ip link add " DEVICE
.BI type " vxlan " id " ID"
.R " [ "
[
.BI dev " PHYS_DEV "
.RB " ] [ { " group " | " remote " } "
.I IPADDR
.R " ] [ "
.BI local " IPADDR "
.R " ] [ "
] [
.B local
.RI "{ "IPADDR " | "any " } "
] [
.BI ttl " TTL "
.R " ] [ "
] [
.BI tos " TOS "
.R " ] [ "
] [
.BI dstport " PORT "
.R " ] [ "
] [
.BI srcport " MIN MAX "
.R " ] [ "
] [
.I "[no]learning "
.R " ] [ "
] [
.I "[no]proxy "
.R " ] [ "
] [
.I "[no]rsc "
.R " ] [ "
] [
.I "[no]l2miss "
.R " ] [ "
] [
.I "[no]l3miss "
.R " ] [ "
] [
.I "[no]udpcsum "
.R " ] [ "
] [
.I "[no]udp6zerocsumtx "
.R " ] [ "
] [
.I "[no]udp6zerocsumrx "
.R " ] [ "
] [
.BI ageing " SECONDS "
.R " ] [ "
] [
.BI maxaddress " NUMBER "
.R " ] [ "
] [
.B gbp
.R " ]"
]
.in +8
.sp
@ -564,17 +565,17 @@ the following additional arguments are supported:
.BI "ip link add " DEVICE
.BR type " { gre | ipip | sit } "
.BI " remote " ADDR " local " ADDR
.R " [ "
[
.BR encap " { fou | gue | none } "
.R " ] [ "
] [
.BI "encap-sport { " PORT " | auto } "
.R " ] [ "
] [
.BI "encap-dport " PORT
.R " ] [ "
] [
.I " [no]encap-csum "
.R " ] [ "
] [
.I " [no]encap-remcsum "
.R " ]"
]
.in +8
.sp
@ -620,25 +621,25 @@ the following additional arguments are supported:
.BI "ip link add " DEVICE
.BI type " { ip6gre | ip6gretap } " remote " ADDR " local " ADDR
.R " [ "
[
.I "[i|o]seq]"
.R " ] [ "
] [
.I "[i|o]key" KEY
.R " ] [ "
] [
.I " [i|o]csum "
.R " ] [ "
] [
.BI hoplimit " TTL "
.R " ] [ "
] [
.BI encaplimit " ELIM "
.R " ] [ "
] [
.BI tclass " TCLASS "
.R " ] [ "
] [
.BI flowlabel " FLOWLABEL "
.R " ] [ "
] [
.BI "dscp inherit"
.R " ] [ "
] [
.BI dev " PHYS_DEV "
.R " ]"
]
.in +8
.sp
@ -743,11 +744,11 @@ the following additional arguments are supported:
.BI "ip link add " DEVICE
.BI type " geneve " id " ID " remote " IPADDR"
.R " [ "
[
.BI ttl " TTL "
.R " ] [ "
] [
.BI tos " TOS "
.R " ]"
]
.in +8
.sp
@ -768,6 +769,56 @@ the following additional arguments are supported:
.in -8
.TP
MACVLAN and MACVTAP Type Support
For a link of type
.I MACVLAN
or
.I MACVTAP
the following additional arguments are supported:
.BI "ip link add link " DEVICE " name " NAME
.BR type " { " macvlan " | " macvtap " } "
.BR mode " { " private " | " vepa " | " bridge " | " passthru
.BR " [ " nopromisc " ] } "
.in +8
.sp
.BR type " { " macvlan " | " macvtap " } "
- specifies the link type to use.
.BR macvlan " creates just a virtual interface, while "
.BR macvtap " in addition creates a character device "
.BR /dev/tapX " to be used just like a " tuntap " device."
.B mode private
- Do not allow communication between
.B macvlan
instances on the same physical interface, even if the external switch supports
hairpin mode.
.B mode vepa
- Virtual Ethernet Port Aggregator mode. Data from one
.B macvlan
instance to the other on the same physical interface is transmitted over the
physical interface. Either the attached switch needs to support hairpin mode,
or there must be a TCP/IP router forwarding the packets in order to allow
communication. This is the default mode.
.B mode bridge
- In bridge mode, all endpoints are directly connected to each other,
communication is not redirected through the physical interface's peer.
.BR mode " " passthru " [ " nopromisc " ] "
- This mode gives more power to a single endpoint, usually in
.BR macvtap " mode. It is not allowed for more than one endpoint on the same "
physical interface. All traffic will be forwarded to this endpoint, allowing
virtio guests to change MAC address or set promiscuous mode in order to bridge
the interface or create vlan interfaces on top of it. By default, this mode
forces the underlying interface into promiscuous mode. Passing the
.BR nopromisc " flag prevents this, so the promisc flag may be controlled "
using standard tools.
.in -8
.SS ip link delete - delete virtual link
.TP
@ -979,8 +1030,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 "

View File

@ -33,9 +33,9 @@ ip-neighbour \- neighbour/arp tables management.
.SH DESCRIPTION
The
The
.B ip neigh
command manipulates
command manipulates
.I neighbour
objects that establish bindings between protocol addresses and
link layer addresses for hosts sharing the same link.

View File

@ -55,7 +55,7 @@ ip-ntable - neighbour table configuration
.SH DESCRIPTION
.I ip ntable
controls the parameters for the neighbour tables.
controls the parameters for the neighbour tables.
.SS ip ntable show - list the ip neighbour tables
@ -98,4 +98,4 @@ default value (3) to 8 packets.
.BR ip (8)
.SH AUTHOR
Manpage by Stephen Hemminger
Manpage by Stephen Hemminger

View File

@ -80,6 +80,8 @@ replace " } "
.ti -8
.IR NH " := [ "
.B encap
.IR ENCAP " ] [ "
.B via
[
.IR FAMILY " ] " ADDRESS " ] [ "
@ -128,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 " := [ "
@ -164,6 +168,26 @@ throw " | " unreachable " | " prohibit " | " blackhole " | " nat " ]"
.IR PREF " := [ "
.BR low " | " medium " | " high " ]"
.ti -8
.IR ENCAP " := [ "
.IR MPLS " | " IP " ]"
.ti -8
.IR ENCAP_MPLS " := "
.BR mpls " [ "
.IR LABEL " ]"
.ti -8
.IR ENCAP_IP " := "
.B ip
.B id
.IR TUNNEL_ID
.B dst
.IR REMOTE_IP " [ "
.B tos
.IR TOS " ] ["
.B ttl
.IR TTL " ]"
.SH DESCRIPTION
.B ip route
@ -589,9 +613,57 @@ Discovery messages. Namely:
- the route has a highest priority
.sp
.TP
.BI encap " ENCAPTYPE ENCAPHDR"
attach tunnel encapsulation attributes to this route.
.sp
.I ENCAPTYPE
is a string specifying the supported encapsulation type. Namely:
.in +8
.BI mpls
- encapsulation type MPLS
.sp
.BI ip
- IP encapsulation (Geneve, GRE, VXLAN, ...)
.sp
.in -8
.I ENCAPHDR
is a set of encapsulation attributes specific to the
.I ENCAPTYPE.
.in +8
.B mpls
.in +2
.I MPLSLABEL
- mpls label stack with labels separated by
.I "/"
.in -2
.sp
.B ip
.in +2
.B id
.I TUNNEL_ID
.B dst
.IR REMOTE_IP " [ "
.B tos
.IR TOS " ] ["
.B ttl
.IR TTL " ]"
.in -2
.sp
.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
@ -847,7 +919,11 @@ ip route add default via 192.168.1.1 dev eth0
Adds a default route (for all addresses) via the local gateway 192.168.1.1 that can
be reached on device eth0.
.RE
.PP
ip route add 10.1.1.0/30 encap mpls 200/300 via 10.1.1.1 dev eth0
.RS 4
Adds an ipv4 route with mpls encapsulation attributes attached to it.
.RE
.SH SEE ALSO
.br
.BR ip (8)

View File

@ -15,9 +15,12 @@ ip-rule \- routing policy database management
.ti -8
.B ip rule
.RB " [ " list " | " add " | " del " | " flush " ]"
.RB " [ " list " | " add " | " del " | " flush " | " save " ]"
.I SELECTOR ACTION
.ti -8
.B ip rule " restore "
.ti -8
.IR SELECTOR " := [ "
.B from
@ -41,7 +44,7 @@ ip-rule \- routing policy database management
.IR TABLE_ID " ] [ "
.B nat
.IR ADDRESS " ] [ "
.BR prohibit " | " reject " | " unreachable " ] [ " realms
.B realms
.RI "[" SRCREALM "/]" DSTREALM " ]"
.I SUPPRESSOR
@ -59,7 +62,7 @@ ip-rule \- routing policy database management
.SH DESCRIPTION
.I ip rule
manipulates rules
manipulates rules
in the routing policy database control the route selection algorithm.
.P
@ -265,6 +268,27 @@ This command has no arguments.
This command has no arguments.
The options list or lst are synonyms with show.
.TP
.B ip rule save
save rules table information to stdout
.RS
This command behaves like
.BR "ip rule show"
except that the output is raw data suitable for passing to
.BR "ip rule restore" .
.RE
.TP
.B ip rule restore
restore rules table information from stdin
.RS
This command expects to read a data stream as returned from
.BR "ip rule save" .
It will attempt to restore the rules table information exactly as
it was at the time of the save. Any rules already in the table are
left unchanged, and duplicates are not ignored.
.RE
.SH SEE ALSO
.br
.BR ip (8)

View File

@ -121,7 +121,7 @@ ip-xfrm \- transform configuration
.ti -8
.IR ALGO " :="
.RB "{ " enc " | " auth " } "
.RB "{ " enc " | " auth " } "
.IR ALGO-NAME " " ALGO-KEYMAT " |"
.br
.B auth-trunc

View File

@ -12,7 +12,7 @@ ip \- show / manipulate routing, devices, policy routing and tunnels
.sp
.ti -8
.B ip
.B ip
.RB "[ " -force " ] "
.BI "-batch " filename
.sp
@ -175,6 +175,10 @@ executes specified command over all objects, it depends if command supports this
.BR "\-c" , " -color"
Use color output.
.TP
.BR "\-t" , " \-timestamp"
display current time when using monitor option.
.SH IP - COMMAND SYNTAX
.SS

View File

@ -172,7 +172,7 @@ Number of dropped conntrack entries to make room for new ones, if maximum table
size was reached.
.sp
.B icmp_error
Number of packets wich could not be tracked due to error situation. This is a
Number of packets which could not be tracked due to error situation. This is a
subset of \fBinvalid\fP.
.sp
.B expect_new

View File

@ -1,16 +1,16 @@
.TH "ROUTEL" "8" "3 Jan, 2008" "iproute2" "Linux"
.SH "NAME"
.LP
.LP
routel \- list routes with pretty output format
.br
routef \- flush routes
.SH "SYNTAX"
.LP
.LP
routel [\fItablenr\fP [\fIraw ip args...\fP]]
.br
.br
routef
.SH "DESCRIPTION"
.LP
.LP
These programs are a set of helper scripts you can use instead of raw iproute2 commands.
.br
The routel script will list routes in a format that some might consider easier to interpret then the ip route list equivalent.
@ -18,15 +18,15 @@ The routel script will list routes in a format that some might consider easier t
The routef script does not take any arguments and will simply flush the routing table down the drain. Beware! This means deleting all routes which will make your network unusable!
.SH "FILES"
.LP
\fI/usr/bin/routef\fP
.br
\fI/usr/bin/routel\fP
.LP
\fI/usr/bin/routef\fP
.br
\fI/usr/bin/routel\fP
.SH "AUTHORS"
.LP
.LP
The routel script was written by Stephen R. van den Berg <srb@cuci.nl>, 1999/04/18 and donated to the public domain.
.br
This manual page was written by Andreas Henriksson <andreas@fatal.se>, for the Debian GNU/Linux system.
.SH "SEE ALSO"
.LP
.LP
ip(8)

View File

@ -47,4 +47,3 @@ Time interval to average rates. Default value is 60 seconds.
.SH SEE ALSO
lnstat(8)

View File

@ -10,11 +10,11 @@ This manual page documents briefly the
command.
.PP
.B rtmon
listens on
.I netlink
listens on
.I netlink
socket and monitors routing table changes.
.I rtmon
.I rtmon
can be started before the first network configuration command is issued.
For example if you insert:
@ -61,7 +61,7 @@ to display logged output from file.
.SH SEE ALSO
.BR ip (8)
.SH AUTHOR
.B rtmon
.B rtmon
was written by Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>.
.PP
This manual page was written by Michael Prokop <mika@grml.org>,

View File

@ -12,7 +12,7 @@ to
It can display more TCP and state informations than other tools.
.SH OPTIONS
When no option is used ss displays a list of
When no option is used ss displays a list of
open non-listening sockets (e.g. TCP/UNIX/UDP) that have established connection.
.TP
.B \-h, \-\-help
@ -48,6 +48,11 @@ Show process using socket.
.B \-i, \-\-info
Show internal TCP information.
.TP
.B \-K, \-\-kill
Attempts to forcibly close sockets. This option displays sockets that are
successfully closed and silently skips sockets that the kernel does not support
closing. It supports IPv4 and IPv6 sockets only.
.TP
.B \-s, \-\-summary
Print summary statistics. This option does not parse socket lists obtaining
summary from various sources. It is useful when amount of sockets is so huge
@ -189,10 +194,10 @@ List all the tcp sockets in state FIN-WAIT-1 for our apache to network 193.233.7
.BR /usr/share/doc/iproute-doc/ss.html " (package iproute­doc)",
.br
.BR RFC " 793 "
- https://tools.ietf.org/rfc/rfc793.txt (TCP states)
- https://tools.ietf.org/rfc/rfc793.txt (TCP states)
.SH AUTHOR
.I ss
.I ss
was written by Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>.
.PP
This manual page was written by Michael Prokop <mika@grml.org>

34
man/man8/tc-basic.8 Normal file
View File

@ -0,0 +1,34 @@
.TH "Basic classifier in tc" 8 "21 Oct 2015" "iproute2" "Linux"
.SH NAME
basic \- basic traffic control filter
.SH SYNOPSIS
.in +8
.ti -8
.BR tc " " filter " ... " basic " [ " match
.IR EMATCH_TREE " ] [ "
.B action
.IR ACTION_SPEC " ] [ "
.B classid
.IR CLASSID " ]"
.SH DESCRIPTION
The
.B basic
filter allows to classify packets using the extended match infrastructure.
.SH OPTIONS
.TP
.BI action " ACTION_SPEC"
Apply an action from the generic actions framework on matching packets.
.TP
.BI classid " CLASSID"
Push matching packets into the class identified by
.IR CLASSID .
.TP
.BI match " EMATCH_TREE"
Match packets using the extended match infrastructure. See
.BR tc-ematch (8)
for a detailed description of the allowed syntax in
.IR EMATCH_TREE .
.SH SEE ALSO
.BR tc (8),
.BR tc-ematch (8)

View File

@ -6,37 +6,37 @@ bfifo \- Byte limited First In, First Out queue
.SH SYNOPSIS
.B tc qdisc ... add pfifo
.B [ limit
.B [ limit
packets
.B ]
.P
.B tc qdisc ... add bfifo
.B [ limit
.B [ limit
bytes
.B ]
.SH DESCRIPTION
The pfifo and bfifo qdiscs are unadorned First In, First Out queues. They are the
simplest queues possible and therefore have no overhead.
simplest queues possible and therefore have no overhead.
.B pfifo
constrains the queue size as measured in packets.
constrains the queue size as measured in packets.
.B bfifo
does so as measured in bytes.
Like all non-default qdiscs, they maintain statistics. This might be a reason to prefer
Like all non-default qdiscs, they maintain statistics. This might be a reason to prefer
pfifo or bfifo over the default.
.SH ALGORITHM
A list of packets is maintained, when a packet is enqueued it gets inserted at the tail of
a list. When a packet needs to be sent out to the network, it is taken from the head of the list.
a list. When a packet needs to be sent out to the network, it is taken from the head of the list.
If the list is too long, no further packets are allowed on. This is called 'tail drop'.
.SH PARAMETERS
.TP
.TP
limit
Maximum queue size. Specified in bytes for bfifo, in packets for pfifo. For pfifo, defaults
to the interface txqueuelen, as specified with
Maximum queue size. Specified in bytes for bfifo, in packets for pfifo. For pfifo, defaults
to the interface txqueuelen, as specified with
.BR ifconfig (8)
or
.BR ip (8).
@ -48,20 +48,20 @@ The range for this parameter is [0, UINT32_MAX] bytes.
Note: The link layer header was considered when counting packets length.
.SH OUTPUT
The output of
The output of
.B tc -s qdisc ls
contains the limit, either in packets or in bytes, and the number of bytes
and packets actually sent. An unsent and dropped packet only appears between braces
contains the limit, either in packets or in bytes, and the number of bytes
and packets actually sent. An unsent and dropped packet only appears between braces
and is not counted as 'Sent'.
In this example, the queue length is 100 packets, 45894 bytes were sent over 681 packets.
In this example, the queue length is 100 packets, 45894 bytes were sent over 681 packets.
No packets were dropped, and as the pfifo queue does not slow down packets, there were also no
overlimits:
.P
.nf
# tc -s qdisc ls dev eth0
# tc -s qdisc ls dev eth0
qdisc pfifo 8001: dev eth0 limit 100p
Sent 45894 bytes 681 pkts (dropped 0, overlimits 0)
Sent 45894 bytes 681 pkts (dropped 0, overlimits 0)
.fi
If a backlog occurs, this is displayed as well.
@ -72,5 +72,3 @@ If a backlog occurs, this is displayed as well.
Alexey N. Kuznetsov, <kuznet@ms2.inr.ac.ru>
This manpage maintained by bert hubert <ahu@ds9a.nl>

View File

@ -394,7 +394,7 @@ socket, and spawning an application such as
\&. This approach's advantage is that tc will place the file descriptors
into the environment and thus make them available just like stdin, stdout,
stderr file descriptors, meaning, in case user applications run from within
this fd-owner shell, they can terminate and restart without loosing eBPF
this fd-owner shell, they can terminate and restart without losing eBPF
maps file descriptors. Example invocation with the previous classifier and
action mixture:
@ -844,7 +844,7 @@ result in the default classid:
Basically, such a minimal generator is equivalent to:
.in +4n
.B tcpdump -iem1 -ddd 'tcp[tcpflags] & tcp-syn != 0' | tr '\\n' ',' > /var/bpf/tcp-syn
.B tcpdump -iem1 -ddd 'tcp[tcpflags] & tcp-syn != 0' | tr '\\\\n' ',' > /var/bpf/tcp-syn
.in
Since

Some files were not shown because too many files have changed in this diff Show More