Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2
This commit is contained in:
commit
62392ecbbb
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -135,6 +135,8 @@ int print_mdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
|
|||
}
|
||||
}
|
||||
|
||||
fflush(fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
#
|
||||
# subpath mappings from mount point for pinning
|
||||
#
|
||||
#3 tracing
|
||||
#4 foo/bar
|
||||
#5 tc/cls1
|
||||
|
|
@ -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'.
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
#include "../../include/bpf_api.h"
|
||||
|
||||
/* Cyclic dependency example to test the kernel's runtime upper
|
||||
* bound on loops. Also demonstrates on how to use direct-actions,
|
||||
* loaded as: tc filter add [...] bpf da obj [...]
|
||||
*/
|
||||
#define JMP_MAP_ID 0xabccba
|
||||
|
||||
BPF_PROG_ARRAY(jmp_tc, JMP_MAP_ID, PIN_OBJECT_NS, 1);
|
||||
|
||||
__section_tail(JMP_MAP_ID, 0)
|
||||
int cls_loop(struct __sk_buff *skb)
|
||||
{
|
||||
char fmt[] = "cb: %u\n";
|
||||
|
||||
trace_printk(fmt, sizeof(fmt), skb->cb[0]++);
|
||||
tail_call(skb, &jmp_tc, 0);
|
||||
|
||||
skb->tc_classid = TC_H_MAKE(1, 42);
|
||||
return TC_ACT_OK;
|
||||
}
|
||||
|
||||
__section_cls_entry
|
||||
int cls_entry(struct __sk_buff *skb)
|
||||
{
|
||||
tail_call(skb, &jmp_tc, 0);
|
||||
return TC_ACT_SHOT;
|
||||
}
|
||||
|
||||
BPF_LICENSE("GPL");
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
#ifndef __BPF_FUNCS__
|
||||
#define __BPF_FUNCS__
|
||||
|
||||
/* Misc macros. */
|
||||
#ifndef __maybe_unused
|
||||
# define __maybe_unused __attribute__ ((__unused__))
|
||||
#endif
|
||||
|
||||
#ifndef __section
|
||||
# define __section(NAME) __attribute__((section(NAME), used))
|
||||
#endif
|
||||
|
||||
#ifndef offsetof
|
||||
# define offsetof __builtin_offsetof
|
||||
#endif
|
||||
|
||||
#ifndef htons
|
||||
# define htons(x) __constant_htons((x))
|
||||
#endif
|
||||
|
||||
#ifndef likely
|
||||
# define likely(x) __builtin_expect(!!(x), 1)
|
||||
#endif
|
||||
|
||||
#ifndef unlikely
|
||||
# define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#endif
|
||||
|
||||
/* The verifier will translate them to actual function calls. */
|
||||
static void *(*bpf_map_lookup_elem)(void *map, void *key) __maybe_unused =
|
||||
(void *) BPF_FUNC_map_lookup_elem;
|
||||
|
||||
static int (*bpf_map_update_elem)(void *map, void *key, void *value,
|
||||
unsigned long long flags) __maybe_unused =
|
||||
(void *) BPF_FUNC_map_update_elem;
|
||||
|
||||
static int (*bpf_map_delete_elem)(void *map, void *key) __maybe_unused =
|
||||
(void *) BPF_FUNC_map_delete_elem;
|
||||
|
||||
static unsigned int (*get_smp_processor_id)(void) __maybe_unused =
|
||||
(void *) BPF_FUNC_get_smp_processor_id;
|
||||
|
||||
static unsigned int (*get_prandom_u32)(void) __maybe_unused =
|
||||
(void *) BPF_FUNC_get_prandom_u32;
|
||||
|
||||
/* LLVM built-in functions that an eBPF C program may use to emit
|
||||
* BPF_LD_ABS and BPF_LD_IND instructions.
|
||||
*/
|
||||
unsigned long long load_byte(void *skb, unsigned long long off)
|
||||
asm ("llvm.bpf.load.byte");
|
||||
|
||||
unsigned long long load_half(void *skb, unsigned long long off)
|
||||
asm ("llvm.bpf.load.half");
|
||||
|
||||
unsigned long long load_word(void *skb, unsigned long long off)
|
||||
asm ("llvm.bpf.load.word");
|
||||
|
||||
#endif /* __BPF_FUNCS__ */
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
#include "../../include/bpf_api.h"
|
||||
|
||||
/* This example demonstrates how classifier run-time behaviour
|
||||
* can be altered with tail calls. We start out with an empty
|
||||
* jmp_tc array, then add section aaa to the array slot 0, and
|
||||
* later on atomically replace it with section bbb. Note that
|
||||
* as shown in other examples, the tc loader can prepopulate
|
||||
* tail called sections, here we start out with an empty one
|
||||
* on purpose to show it can also be done this way.
|
||||
*
|
||||
* tc filter add dev foo parent ffff: bpf obj graft.o
|
||||
* tc exec bpf dbg
|
||||
* [...]
|
||||
* Socket Thread-20229 [001] ..s. 138993.003923: : fallthrough
|
||||
* <idle>-0 [001] ..s. 138993.202265: : fallthrough
|
||||
* Socket Thread-20229 [001] ..s. 138994.004149: : fallthrough
|
||||
* [...]
|
||||
*
|
||||
* tc exec bpf graft m:globals/jmp_tc key 0 obj graft.o sec aaa
|
||||
* tc exec bpf dbg
|
||||
* [...]
|
||||
* Socket Thread-19818 [002] ..s. 139012.053587: : aaa
|
||||
* <idle>-0 [002] ..s. 139012.172359: : aaa
|
||||
* Socket Thread-19818 [001] ..s. 139012.173556: : aaa
|
||||
* [...]
|
||||
*
|
||||
* tc exec bpf graft m:globals/jmp_tc key 0 obj graft.o sec bbb
|
||||
* tc exec bpf dbg
|
||||
* [...]
|
||||
* Socket Thread-19818 [002] ..s. 139022.102967: : bbb
|
||||
* <idle>-0 [002] ..s. 139022.155640: : bbb
|
||||
* Socket Thread-19818 [001] ..s. 139022.156730: : bbb
|
||||
* [...]
|
||||
*/
|
||||
|
||||
BPF_PROG_ARRAY(jmp_tc, 0, PIN_GLOBAL_NS, 1);
|
||||
|
||||
__section("aaa")
|
||||
int cls_aaa(struct __sk_buff *skb)
|
||||
{
|
||||
char fmt[] = "aaa\n";
|
||||
|
||||
trace_printk(fmt, sizeof(fmt));
|
||||
return TC_H_MAKE(1, 42);
|
||||
}
|
||||
|
||||
__section("bbb")
|
||||
int cls_bbb(struct __sk_buff *skb)
|
||||
{
|
||||
char fmt[] = "bbb\n";
|
||||
|
||||
trace_printk(fmt, sizeof(fmt));
|
||||
return TC_H_MAKE(1, 43);
|
||||
}
|
||||
|
||||
__section_cls_entry
|
||||
int cls_entry(struct __sk_buff *skb)
|
||||
{
|
||||
char fmt[] = "fallthrough\n";
|
||||
|
||||
tail_call(skb, &jmp_tc, 0);
|
||||
trace_printk(fmt, sizeof(fmt));
|
||||
|
||||
return BPF_H_DEFAULT;
|
||||
}
|
||||
|
||||
BPF_LICENSE("GPL");
|
||||
|
|
@ -168,8 +168,8 @@
|
|||
|
||||
/* Common, shared definitions with ebpf_agent.c. */
|
||||
#include "bpf_shared.h"
|
||||
/* Selection of BPF helper functions for our example. */
|
||||
#include "bpf_funcs.h"
|
||||
/* BPF helper functions for our example. */
|
||||
#include "../../include/bpf_api.h"
|
||||
|
||||
/* Could be defined here as well, or included from the header. */
|
||||
#define TC_ACT_UNSPEC (-1)
|
||||
|
|
@ -387,10 +387,10 @@ static inline void cls_update_proto_map(const struct __sk_buff *skb,
|
|||
uint8_t proto = flow->ip_proto;
|
||||
struct count_tuple *ct, _ct;
|
||||
|
||||
ct = bpf_map_lookup_elem(&map_proto, &proto);
|
||||
ct = map_lookup_elem(&map_proto, &proto);
|
||||
if (likely(ct)) {
|
||||
__sync_fetch_and_add(&ct->packets, 1);
|
||||
__sync_fetch_and_add(&ct->bytes, skb->len);
|
||||
lock_xadd(&ct->packets, 1);
|
||||
lock_xadd(&ct->bytes, skb->len);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -398,7 +398,7 @@ static inline void cls_update_proto_map(const struct __sk_buff *skb,
|
|||
_ct.packets = 1;
|
||||
_ct.bytes = skb->len;
|
||||
|
||||
bpf_map_update_elem(&map_proto, &proto, &_ct, BPF_ANY);
|
||||
map_update_elem(&map_proto, &proto, &_ct, BPF_ANY);
|
||||
}
|
||||
|
||||
static inline void cls_update_queue_map(const struct __sk_buff *skb)
|
||||
|
|
@ -409,11 +409,11 @@ static inline void cls_update_queue_map(const struct __sk_buff *skb)
|
|||
|
||||
mismatch = skb->queue_mapping != get_smp_processor_id();
|
||||
|
||||
cq = bpf_map_lookup_elem(&map_queue, &queue);
|
||||
cq = map_lookup_elem(&map_queue, &queue);
|
||||
if (likely(cq)) {
|
||||
__sync_fetch_and_add(&cq->total, 1);
|
||||
lock_xadd(&cq->total, 1);
|
||||
if (mismatch)
|
||||
__sync_fetch_and_add(&cq->mismatch, 1);
|
||||
lock_xadd(&cq->mismatch, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -421,7 +421,7 @@ static inline void cls_update_queue_map(const struct __sk_buff *skb)
|
|||
_cq.total = 1;
|
||||
_cq.mismatch = mismatch ? 1 : 0;
|
||||
|
||||
bpf_map_update_elem(&map_queue, &queue, &_cq, BPF_ANY);
|
||||
map_update_elem(&map_queue, &queue, &_cq, BPF_ANY);
|
||||
}
|
||||
|
||||
/* eBPF program definitions, placed in various sections, which can
|
||||
|
|
@ -439,7 +439,8 @@ static inline void cls_update_queue_map(const struct __sk_buff *skb)
|
|||
* It is however not required to have multiple programs sharing
|
||||
* a file.
|
||||
*/
|
||||
__section("classifier") int cls_main(struct __sk_buff *skb)
|
||||
__section("classifier")
|
||||
int cls_main(struct __sk_buff *skb)
|
||||
{
|
||||
struct flow_keys flow;
|
||||
|
||||
|
|
@ -456,13 +457,14 @@ static inline void act_update_drop_map(void)
|
|||
{
|
||||
uint32_t *count, cpu = get_smp_processor_id();
|
||||
|
||||
count = bpf_map_lookup_elem(&map_drops, &cpu);
|
||||
count = map_lookup_elem(&map_drops, &cpu);
|
||||
if (count)
|
||||
/* Only this cpu is accessing this element. */
|
||||
(*count)++;
|
||||
}
|
||||
|
||||
__section("action-mark") int act_mark_main(struct __sk_buff *skb)
|
||||
__section("action-mark")
|
||||
int act_mark_main(struct __sk_buff *skb)
|
||||
{
|
||||
/* You could also mangle skb data here with the helper function
|
||||
* BPF_FUNC_skb_store_bytes, etc. Or, alternatively you could
|
||||
|
|
@ -479,7 +481,8 @@ __section("action-mark") int act_mark_main(struct __sk_buff *skb)
|
|||
return TC_ACT_UNSPEC;
|
||||
}
|
||||
|
||||
__section("action-rand") int act_rand_main(struct __sk_buff *skb)
|
||||
__section("action-rand")
|
||||
int act_rand_main(struct __sk_buff *skb)
|
||||
{
|
||||
/* Sorry, we're near event horizon ... */
|
||||
if ((get_prandom_u32() & 3) == 0) {
|
||||
|
|
@ -493,4 +496,4 @@ __section("action-rand") int act_rand_main(struct __sk_buff *skb)
|
|||
/* Last but not least, the file contains a license. Some future helper
|
||||
* functions may only be available with a GPL license.
|
||||
*/
|
||||
char __license[] __section("license") = "GPL";
|
||||
BPF_LICENSE("GPL");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
#include "../../include/bpf_api.h"
|
||||
|
||||
/* Minimal, stand-alone toy map pinning example:
|
||||
*
|
||||
* clang -target bpf -O2 [...] -o bpf_shared.o -c bpf_shared.c
|
||||
* tc filter add dev foo parent 1: bpf obj bpf_shared.o sec egress
|
||||
* tc filter add dev foo parent ffff: bpf obj bpf_shared.o sec ingress
|
||||
*
|
||||
* Both classifier will share the very same map instance in this example,
|
||||
* so map content can be accessed from ingress *and* egress side!
|
||||
*
|
||||
* This example has a pinning of PIN_OBJECT_NS, so it's private and
|
||||
* thus shared among various program sections within the object.
|
||||
*
|
||||
* A setting of PIN_GLOBAL_NS would place it into a global namespace,
|
||||
* so that it can be shared among different object files. A setting
|
||||
* of PIN_NONE (= 0) means no sharing, so each tc invocation a new map
|
||||
* instance is being created.
|
||||
*/
|
||||
|
||||
BPF_ARRAY4(map_sh, 0, PIN_OBJECT_NS, 1); /* or PIN_GLOBAL_NS, or PIN_NONE */
|
||||
|
||||
__section("egress")
|
||||
int emain(struct __sk_buff *skb)
|
||||
{
|
||||
int key = 0, *val;
|
||||
|
||||
val = map_lookup_elem(&map_sh, &key);
|
||||
if (val)
|
||||
lock_xadd(val, 1);
|
||||
|
||||
return BPF_H_DEFAULT;
|
||||
}
|
||||
|
||||
__section("ingress")
|
||||
int imain(struct __sk_buff *skb)
|
||||
{
|
||||
char fmt[] = "map val: %d\n";
|
||||
int key = 0, *val;
|
||||
|
||||
val = map_lookup_elem(&map_sh, &key);
|
||||
if (val)
|
||||
trace_printk(fmt, sizeof(fmt), *val);
|
||||
|
||||
return BPF_H_DEFAULT;
|
||||
}
|
||||
|
||||
BPF_LICENSE("GPL");
|
||||
|
|
@ -1,10 +1,6 @@
|
|||
#ifndef __BPF_SHARED__
|
||||
#define __BPF_SHARED__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "../../include/bpf_elf.h"
|
||||
|
||||
enum {
|
||||
BPF_MAP_ID_PROTO,
|
||||
BPF_MAP_ID_QUEUE,
|
||||
|
|
@ -14,7 +10,7 @@ enum {
|
|||
};
|
||||
|
||||
struct count_tuple {
|
||||
long packets; /* type long for __sync_fetch_and_add() */
|
||||
long packets; /* type long for lock_xadd() */
|
||||
long bytes;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,99 @@
|
|||
#include "../../include/bpf_api.h"
|
||||
|
||||
#define ENTRY_INIT 3
|
||||
#define ENTRY_0 0
|
||||
#define ENTRY_1 1
|
||||
#define MAX_JMP_SIZE 2
|
||||
|
||||
#define FOO 42
|
||||
#define BAR 43
|
||||
|
||||
/* This example doesn't really do anything useful, but it's purpose is to
|
||||
* demonstrate eBPF tail calls on a very simple example.
|
||||
*
|
||||
* cls_entry() is our classifier entry point, from there we jump based on
|
||||
* skb->hash into cls_case1() or cls_case2(). They are both part of the
|
||||
* program array jmp_tc. Indicated via __section_tail(), the tc loader
|
||||
* populates the program arrays with the loaded file descriptors already.
|
||||
*
|
||||
* To demonstrate nested jumps, cls_case2() jumps within the same jmp_tc
|
||||
* array to cls_case1(). And whenever we arrive at cls_case1(), we jump
|
||||
* into cls_exit(), part of the jump array jmp_ex.
|
||||
*
|
||||
* Also, to show it's possible, all programs share map_sh and dump the value
|
||||
* that the entry point incremented. The sections that are loaded into a
|
||||
* program array can be atomically replaced during run-time, e.g. to change
|
||||
* classifier behaviour.
|
||||
*/
|
||||
|
||||
BPF_PROG_ARRAY(jmp_tc, FOO, PIN_OBJECT_NS, MAX_JMP_SIZE);
|
||||
BPF_PROG_ARRAY(jmp_ex, BAR, PIN_OBJECT_NS, 1);
|
||||
|
||||
BPF_ARRAY4(map_sh, 0, PIN_OBJECT_NS, 1);
|
||||
|
||||
__section_tail(FOO, ENTRY_0)
|
||||
int cls_case1(struct __sk_buff *skb)
|
||||
{
|
||||
char fmt[] = "case1: map-val: %d from:%u\n";
|
||||
int key = 0, *val;
|
||||
|
||||
val = map_lookup_elem(&map_sh, &key);
|
||||
if (val)
|
||||
trace_printk(fmt, sizeof(fmt), *val, skb->cb[0]);
|
||||
|
||||
skb->cb[0] = ENTRY_0;
|
||||
tail_call(skb, &jmp_ex, ENTRY_0);
|
||||
|
||||
return BPF_H_DEFAULT;
|
||||
}
|
||||
|
||||
__section_tail(FOO, ENTRY_1)
|
||||
int cls_case2(struct __sk_buff *skb)
|
||||
{
|
||||
char fmt[] = "case2: map-val: %d from:%u\n";
|
||||
int key = 0, *val;
|
||||
|
||||
val = map_lookup_elem(&map_sh, &key);
|
||||
if (val)
|
||||
trace_printk(fmt, sizeof(fmt), *val, skb->cb[0]);
|
||||
|
||||
skb->cb[0] = ENTRY_1;
|
||||
tail_call(skb, &jmp_tc, ENTRY_0);
|
||||
|
||||
return BPF_H_DEFAULT;
|
||||
}
|
||||
|
||||
__section_tail(BAR, ENTRY_0)
|
||||
int cls_exit(struct __sk_buff *skb)
|
||||
{
|
||||
char fmt[] = "exit: map-val: %d from:%u\n";
|
||||
int key = 0, *val;
|
||||
|
||||
val = map_lookup_elem(&map_sh, &key);
|
||||
if (val)
|
||||
trace_printk(fmt, sizeof(fmt), *val, skb->cb[0]);
|
||||
|
||||
/* Termination point. */
|
||||
return BPF_H_DEFAULT;
|
||||
}
|
||||
|
||||
__section_cls_entry
|
||||
int cls_entry(struct __sk_buff *skb)
|
||||
{
|
||||
char fmt[] = "fallthrough\n";
|
||||
int key = 0, *val;
|
||||
|
||||
/* For transferring state, we can use skb->cb[0] ... skb->cb[4]. */
|
||||
val = map_lookup_elem(&map_sh, &key);
|
||||
if (val) {
|
||||
lock_xadd(val, 1);
|
||||
|
||||
skb->cb[0] = ENTRY_INIT;
|
||||
tail_call(skb, &jmp_tc, skb->hash & (MAX_JMP_SIZE - 1));
|
||||
}
|
||||
|
||||
trace_printk(fmt, sizeof(fmt));
|
||||
return BPF_H_DEFAULT;
|
||||
}
|
||||
|
||||
BPF_LICENSE("GPL");
|
||||
|
|
@ -54,7 +54,7 @@ static int parse_nofopt(struct genl_util *f, int argc, char **argv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct genl_util *get_genl_kind(char *str)
|
||||
static struct genl_util *get_genl_kind(const char *str)
|
||||
{
|
||||
void *dlh;
|
||||
char buf[256];
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
static const char SNAPSHOT[] = "150831";
|
||||
static const char SNAPSHOT[] = "160111";
|
||||
|
|
|
|||
|
|
@ -0,0 +1,225 @@
|
|||
#ifndef __BPF_API__
|
||||
#define __BPF_API__
|
||||
|
||||
/* Note:
|
||||
*
|
||||
* This file can be included into eBPF kernel programs. It contains
|
||||
* a couple of useful helper functions, map/section ABI (bpf_elf.h),
|
||||
* misc macros and some eBPF specific LLVM built-ins.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <linux/pkt_cls.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/filter.h>
|
||||
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#include "bpf_elf.h"
|
||||
|
||||
/** Misc macros. */
|
||||
|
||||
#ifndef __stringify
|
||||
# define __stringify(X) #X
|
||||
#endif
|
||||
|
||||
#ifndef __maybe_unused
|
||||
# define __maybe_unused __attribute__((__unused__))
|
||||
#endif
|
||||
|
||||
#ifndef offsetof
|
||||
# define offsetof(TYPE, MEMBER) __builtin_offsetof(TYPE, MEMBER)
|
||||
#endif
|
||||
|
||||
#ifndef likely
|
||||
# define likely(X) __builtin_expect(!!(X), 1)
|
||||
#endif
|
||||
|
||||
#ifndef unlikely
|
||||
# define unlikely(X) __builtin_expect(!!(X), 0)
|
||||
#endif
|
||||
|
||||
#ifndef htons
|
||||
# define htons(X) __constant_htons((X))
|
||||
#endif
|
||||
|
||||
#ifndef ntohs
|
||||
# define ntohs(X) __constant_ntohs((X))
|
||||
#endif
|
||||
|
||||
#ifndef htonl
|
||||
# define htonl(X) __constant_htonl((X))
|
||||
#endif
|
||||
|
||||
#ifndef ntohl
|
||||
# define ntohl(X) __constant_ntohl((X))
|
||||
#endif
|
||||
|
||||
/** Section helper macros. */
|
||||
|
||||
#ifndef __section
|
||||
# define __section(NAME) \
|
||||
__attribute__((section(NAME), used))
|
||||
#endif
|
||||
|
||||
#ifndef __section_tail
|
||||
# define __section_tail(ID, KEY) \
|
||||
__section(__stringify(ID) "/" __stringify(KEY))
|
||||
#endif
|
||||
|
||||
#ifndef __section_cls_entry
|
||||
# define __section_cls_entry \
|
||||
__section(ELF_SECTION_CLASSIFIER)
|
||||
#endif
|
||||
|
||||
#ifndef __section_act_entry
|
||||
# define __section_act_entry \
|
||||
__section(ELF_SECTION_ACTION)
|
||||
#endif
|
||||
|
||||
#ifndef __section_license
|
||||
# define __section_license \
|
||||
__section(ELF_SECTION_LICENSE)
|
||||
#endif
|
||||
|
||||
#ifndef __section_maps
|
||||
# define __section_maps \
|
||||
__section(ELF_SECTION_MAPS)
|
||||
#endif
|
||||
|
||||
/** Declaration helper macros. */
|
||||
|
||||
#ifndef BPF_LICENSE
|
||||
# define BPF_LICENSE(NAME) \
|
||||
char ____license[] __section_license = NAME
|
||||
#endif
|
||||
|
||||
#ifndef __BPF_MAP
|
||||
# define __BPF_MAP(NAME, TYPE, ID, SIZE_KEY, SIZE_VALUE, PIN, MAX_ELEM) \
|
||||
struct bpf_elf_map __section_maps NAME = { \
|
||||
.type = (TYPE), \
|
||||
.id = (ID), \
|
||||
.size_key = (SIZE_KEY), \
|
||||
.size_value = (SIZE_VALUE), \
|
||||
.pinning = (PIN), \
|
||||
.max_elem = (MAX_ELEM), \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef BPF_HASH
|
||||
# define BPF_HASH(NAME, ID, SIZE_KEY, SIZE_VALUE, PIN, MAX_ELEM) \
|
||||
__BPF_MAP(NAME, BPF_MAP_TYPE_HASH, ID, SIZE_KEY, SIZE_VALUE, \
|
||||
PIN, MAX_ELEM)
|
||||
#endif
|
||||
|
||||
#ifndef BPF_ARRAY
|
||||
# define BPF_ARRAY(NAME, ID, SIZE_VALUE, PIN, MAX_ELEM) \
|
||||
__BPF_MAP(NAME, BPF_MAP_TYPE_ARRAY, ID, sizeof(uint32_t), \
|
||||
SIZE_VALUE, PIN, MAX_ELEM)
|
||||
#endif
|
||||
|
||||
#ifndef BPF_ARRAY2
|
||||
# define BPF_ARRAY2(NAME, ID, PIN, MAX_ELEM) \
|
||||
BPF_ARRAY(NAME, ID, sizeof(uint16_t), PIN, MAX_ELEM)
|
||||
#endif
|
||||
|
||||
#ifndef BPF_ARRAY4
|
||||
# define BPF_ARRAY4(NAME, ID, PIN, MAX_ELEM) \
|
||||
BPF_ARRAY(NAME, ID, sizeof(uint32_t), PIN, MAX_ELEM)
|
||||
#endif
|
||||
|
||||
#ifndef BPF_ARRAY8
|
||||
# define BPF_ARRAY8(NAME, ID, PIN, MAX_ELEM) \
|
||||
BPF_ARRAY(NAME, ID, sizeof(uint64_t), PIN, MAX_ELEM)
|
||||
#endif
|
||||
|
||||
#ifndef BPF_PROG_ARRAY
|
||||
# define BPF_PROG_ARRAY(NAME, ID, PIN, MAX_ELEM) \
|
||||
__BPF_MAP(NAME, BPF_MAP_TYPE_PROG_ARRAY, ID, sizeof(uint32_t), \
|
||||
sizeof(uint32_t), PIN, MAX_ELEM)
|
||||
#endif
|
||||
|
||||
/** Classifier helper */
|
||||
|
||||
#ifndef BPF_H_DEFAULT
|
||||
# define BPF_H_DEFAULT -1
|
||||
#endif
|
||||
|
||||
/** BPF helper functions for tc. */
|
||||
|
||||
#ifndef BPF_FUNC
|
||||
# define BPF_FUNC(NAME, ...) \
|
||||
(* NAME)(__VA_ARGS__) __maybe_unused = (void *) BPF_FUNC_##NAME
|
||||
#endif
|
||||
|
||||
/* Map access/manipulation */
|
||||
static void *BPF_FUNC(map_lookup_elem, void *map, const void *key);
|
||||
static int BPF_FUNC(map_update_elem, void *map, const void *key,
|
||||
const void *value, uint32_t flags);
|
||||
static int BPF_FUNC(map_delete_elem, void *map, const void *key);
|
||||
|
||||
/* Time access */
|
||||
static uint64_t BPF_FUNC(ktime_get_ns);
|
||||
|
||||
/* Debugging */
|
||||
static void BPF_FUNC(trace_printk, const char *fmt, int fmt_size, ...);
|
||||
|
||||
/* Random numbers */
|
||||
static uint32_t BPF_FUNC(get_prandom_u32);
|
||||
|
||||
/* Tail calls */
|
||||
static void BPF_FUNC(tail_call, struct __sk_buff *skb, void *map,
|
||||
uint32_t index);
|
||||
|
||||
/* System helpers */
|
||||
static uint32_t BPF_FUNC(get_smp_processor_id);
|
||||
|
||||
/* Packet misc meta data */
|
||||
static uint32_t BPF_FUNC(get_cgroup_classid, struct __sk_buff *skb);
|
||||
static uint32_t BPF_FUNC(get_route_realm, struct __sk_buff *skb);
|
||||
|
||||
/* Packet redirection */
|
||||
static int BPF_FUNC(redirect, int ifindex, uint32_t flags);
|
||||
static int BPF_FUNC(clone_redirect, struct __sk_buff *skb, int ifindex,
|
||||
uint32_t flags);
|
||||
|
||||
/* Packet manipulation */
|
||||
#define BPF_PSEUDO_HDR 0x10
|
||||
#define BPF_HAS_PSEUDO_HDR(flags) ((flags) & BPF_PSEUDO_HDR)
|
||||
#define BPF_HDR_FIELD_SIZE(flags) ((flags) & 0x0f)
|
||||
|
||||
static int BPF_FUNC(skb_store_bytes, struct __sk_buff *skb, uint32_t off,
|
||||
void *from, uint32_t len, uint32_t flags);
|
||||
static int BPF_FUNC(l3_csum_replace, struct __sk_buff *skb, uint32_t off,
|
||||
uint32_t from, uint32_t to, uint32_t flags);
|
||||
static int BPF_FUNC(l4_csum_replace, struct __sk_buff *skb, uint32_t off,
|
||||
uint32_t from, uint32_t to, uint32_t flags);
|
||||
|
||||
/* Packet vlan encap/decap */
|
||||
static int BPF_FUNC(skb_vlan_push, struct __sk_buff *skb, uint16_t proto,
|
||||
uint16_t vlan_tci);
|
||||
static int BPF_FUNC(skb_vlan_pop, struct __sk_buff *skb);
|
||||
|
||||
/* Packet tunnel encap/decap */
|
||||
static int BPF_FUNC(skb_get_tunnel_key, struct __sk_buff *skb,
|
||||
struct bpf_tunnel_key *to, uint32_t size, uint32_t flags);
|
||||
static int BPF_FUNC(skb_set_tunnel_key, struct __sk_buff *skb,
|
||||
struct bpf_tunnel_key *from, uint32_t size, uint32_t flags);
|
||||
|
||||
/** LLVM built-ins */
|
||||
|
||||
#ifndef lock_xadd
|
||||
# define lock_xadd(ptr, val) ((void) __sync_fetch_and_add(ptr, val))
|
||||
#endif
|
||||
|
||||
unsigned long long load_byte(void *skb, unsigned long long off)
|
||||
asm ("llvm.bpf.load.byte");
|
||||
|
||||
unsigned long long load_half(void *skb, unsigned long long off)
|
||||
asm ("llvm.bpf.load.half");
|
||||
|
||||
unsigned long long load_word(void *skb, unsigned long long off)
|
||||
asm ("llvm.bpf.load.word");
|
||||
|
||||
#endif /* __BPF_API__ */
|
||||
|
|
@ -21,6 +21,11 @@
|
|||
#define ELF_MAX_MAPS 64
|
||||
#define ELF_MAX_LICENSE_LEN 128
|
||||
|
||||
/* Object pinning settings */
|
||||
#define PIN_NONE 0
|
||||
#define PIN_OBJECT_NS 1
|
||||
#define PIN_GLOBAL_NS 2
|
||||
|
||||
/* ELF map definition */
|
||||
struct bpf_elf_map {
|
||||
__u32 type;
|
||||
|
|
@ -28,6 +33,7 @@ struct bpf_elf_map {
|
|||
__u32 size_value;
|
||||
__u32 max_elem;
|
||||
__u32 id;
|
||||
__u32 pinning;
|
||||
};
|
||||
|
||||
#endif /* __BPF_ELF__ */
|
||||
|
|
|
|||
|
|
@ -1,141 +1,20 @@
|
|||
#ifndef _IP6TABLES_USER_H
|
||||
#define _IP6TABLES_USER_H
|
||||
|
||||
#include "iptables_common.h"
|
||||
#include "libiptc/libip6tc.h"
|
||||
|
||||
struct ip6tables_rule_match
|
||||
{
|
||||
struct ip6tables_rule_match *next;
|
||||
|
||||
struct ip6tables_match *match;
|
||||
};
|
||||
|
||||
/* Include file for additions: new matches and targets. */
|
||||
struct ip6tables_match
|
||||
{
|
||||
struct ip6tables_match *next;
|
||||
|
||||
ip6t_chainlabel name;
|
||||
|
||||
const char *version;
|
||||
|
||||
/* Size of match data. */
|
||||
size_t size;
|
||||
|
||||
/* Size of match data relevent for userspace comparison purposes */
|
||||
size_t userspacesize;
|
||||
|
||||
/* Function which prints out usage message. */
|
||||
void (*help)(void);
|
||||
|
||||
/* Initialize the match. */
|
||||
void (*init)(struct ip6t_entry_match *m, unsigned int *nfcache);
|
||||
|
||||
/* Function which parses command options; returns true if it
|
||||
ate an option */
|
||||
int (*parse)(int c, char **argv, int invert, unsigned int *flags,
|
||||
const struct ip6t_entry *entry,
|
||||
unsigned int *nfcache,
|
||||
struct ip6t_entry_match **match);
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
void (*final_check)(unsigned int flags);
|
||||
|
||||
/* Prints out the match iff non-NULL: put space at end */
|
||||
void (*print)(const struct ip6t_ip6 *ip,
|
||||
const struct ip6t_entry_match *match, int numeric);
|
||||
|
||||
/* Saves the union ipt_matchinfo in parsable form to stdout. */
|
||||
void (*save)(const struct ip6t_ip6 *ip,
|
||||
const struct ip6t_entry_match *match);
|
||||
|
||||
/* Pointer to list of extra command-line options */
|
||||
const struct option *extra_opts;
|
||||
|
||||
/* Ignore these men behind the curtain: */
|
||||
unsigned int option_offset;
|
||||
struct ip6t_entry_match *m;
|
||||
unsigned int mflags;
|
||||
#ifdef NO_SHARED_LIBS
|
||||
unsigned int loaded; /* simulate loading so options are merged properly */
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ip6tables_target
|
||||
{
|
||||
struct ip6tables_target *next;
|
||||
|
||||
ip6t_chainlabel name;
|
||||
|
||||
const char *version;
|
||||
|
||||
/* Size of target data. */
|
||||
size_t size;
|
||||
|
||||
/* Size of target data relevent for userspace comparison purposes */
|
||||
size_t userspacesize;
|
||||
|
||||
/* Function which prints out usage message. */
|
||||
void (*help)(void);
|
||||
|
||||
/* Initialize the target. */
|
||||
void (*init)(struct ip6t_entry_target *t, unsigned int *nfcache);
|
||||
|
||||
/* Function which parses command options; returns true if it
|
||||
ate an option */
|
||||
int (*parse)(int c, char **argv, int invert, unsigned int *flags,
|
||||
const struct ip6t_entry *entry,
|
||||
struct ip6t_entry_target **target);
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
void (*final_check)(unsigned int flags);
|
||||
|
||||
/* Prints out the target iff non-NULL: put space at end */
|
||||
void (*print)(const struct ip6t_ip6 *ip,
|
||||
const struct ip6t_entry_target *target, int numeric);
|
||||
|
||||
/* Saves the targinfo in parsable form to stdout. */
|
||||
void (*save)(const struct ip6t_ip6 *ip,
|
||||
const struct ip6t_entry_target *target);
|
||||
|
||||
/* Pointer to list of extra command-line options */
|
||||
struct option *extra_opts;
|
||||
|
||||
/* Ignore these men behind the curtain: */
|
||||
unsigned int option_offset;
|
||||
struct ip6t_entry_target *t;
|
||||
unsigned int tflags;
|
||||
unsigned int used;
|
||||
#ifdef NO_SHARED_LIBS
|
||||
unsigned int loaded; /* simulate loading so options are merged properly */
|
||||
#endif
|
||||
};
|
||||
|
||||
extern int line;
|
||||
#include <netinet/ip.h>
|
||||
#include <xtables.h>
|
||||
#include <libiptc/libip6tc.h>
|
||||
#include <iptables/internal.h>
|
||||
|
||||
/* Your shared library should call one of these. */
|
||||
extern void register_match6(struct ip6tables_match *me);
|
||||
extern void register_target6(struct ip6tables_target *me);
|
||||
|
||||
extern int do_command6(int argc, char *argv[], char **table,
|
||||
ip6tc_handle_t *handle);
|
||||
/* Keeping track of external matches and targets: linked lists. */
|
||||
extern struct ip6tables_match *ip6tables_matches;
|
||||
extern struct ip6tables_target *ip6tables_targets;
|
||||
struct xtc_handle **handle, bool restore);
|
||||
|
||||
enum ip6t_tryload {
|
||||
DONT_LOAD,
|
||||
TRY_LOAD,
|
||||
LOAD_MUST_SUCCEED
|
||||
};
|
||||
extern int for_each_chain6(int (*fn)(const xt_chainlabel, int, struct xtc_handle *), int verbose, int builtinstoo, struct xtc_handle *handle);
|
||||
extern int flush_entries6(const xt_chainlabel chain, int verbose, struct xtc_handle *handle);
|
||||
extern int delete_chain6(const xt_chainlabel chain, int verbose, struct xtc_handle *handle);
|
||||
void print_rule6(const struct ip6t_entry *e, struct xtc_handle *h, const char *chain, int counters);
|
||||
|
||||
extern struct ip6tables_target *find_target(const char *name, enum ip6t_tryload);
|
||||
extern struct ip6tables_match *find_match(const char *name, enum ip6t_tryload, struct ip6tables_rule_match **match);
|
||||
|
||||
extern int for_each_chain(int (*fn)(const ip6t_chainlabel, int, ip6tc_handle_t *), int verbose, int builtinstoo, ip6tc_handle_t *handle);
|
||||
extern int flush_entries(const ip6t_chainlabel chain, int verbose, ip6tc_handle_t *handle);
|
||||
extern int delete_chain(const ip6t_chainlabel chain, int verbose, ip6tc_handle_t *handle);
|
||||
extern int ip6tables_insmod(const char *modname, const char *modprobe);
|
||||
extern struct xtables_globals ip6tables_globals;
|
||||
|
||||
#endif /*_IP6TABLES_USER_H*/
|
||||
|
|
|
|||
|
|
@ -1,179 +1,25 @@
|
|||
#ifndef _IPTABLES_USER_H
|
||||
#define _IPTABLES_USER_H
|
||||
|
||||
#include "iptables_common.h"
|
||||
#include "libiptc/libiptc.h"
|
||||
|
||||
#ifndef IPT_LIB_DIR
|
||||
#define IPT_LIB_DIR "/usr/local/lib/iptables"
|
||||
#endif
|
||||
|
||||
#ifndef IPPROTO_SCTP
|
||||
#define IPPROTO_SCTP 132
|
||||
#endif
|
||||
|
||||
#ifndef IPT_SO_GET_REVISION_MATCH /* Old kernel source. */
|
||||
#define IPT_SO_GET_REVISION_MATCH (IPT_BASE_CTL + 2)
|
||||
#define IPT_SO_GET_REVISION_TARGET (IPT_BASE_CTL + 3)
|
||||
|
||||
struct ipt_get_revision
|
||||
{
|
||||
char name[IPT_FUNCTION_MAXNAMELEN-1];
|
||||
|
||||
u_int8_t revision;
|
||||
};
|
||||
#endif /* IPT_SO_GET_REVISION_MATCH Old kernel source */
|
||||
|
||||
struct iptables_rule_match
|
||||
{
|
||||
struct iptables_rule_match *next;
|
||||
|
||||
struct iptables_match *match;
|
||||
};
|
||||
|
||||
/* Include file for additions: new matches and targets. */
|
||||
struct iptables_match
|
||||
{
|
||||
struct iptables_match *next;
|
||||
|
||||
ipt_chainlabel name;
|
||||
|
||||
/* Revision of match (0 by default). */
|
||||
u_int8_t revision;
|
||||
|
||||
const char *version;
|
||||
|
||||
/* Size of match data. */
|
||||
size_t size;
|
||||
|
||||
/* Size of match data relevent for userspace comparison purposes */
|
||||
size_t userspacesize;
|
||||
|
||||
/* Function which prints out usage message. */
|
||||
void (*help)(void);
|
||||
|
||||
/* Initialize the match. */
|
||||
void (*init)(struct ipt_entry_match *m, unsigned int *nfcache);
|
||||
|
||||
/* Function which parses command options; returns true if it
|
||||
ate an option */
|
||||
int (*parse)(int c, char **argv, int invert, unsigned int *flags,
|
||||
const struct ipt_entry *entry,
|
||||
unsigned int *nfcache,
|
||||
struct ipt_entry_match **match);
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
void (*final_check)(unsigned int flags);
|
||||
|
||||
/* Prints out the match iff non-NULL: put space at end */
|
||||
void (*print)(const struct ipt_ip *ip,
|
||||
const struct ipt_entry_match *match, int numeric);
|
||||
|
||||
/* Saves the match info in parsable form to stdout. */
|
||||
void (*save)(const struct ipt_ip *ip,
|
||||
const struct ipt_entry_match *match);
|
||||
|
||||
/* Pointer to list of extra command-line options */
|
||||
const struct option *extra_opts;
|
||||
|
||||
/* Ignore these men behind the curtain: */
|
||||
unsigned int option_offset;
|
||||
struct ipt_entry_match *m;
|
||||
unsigned int mflags;
|
||||
#ifdef NO_SHARED_LIBS
|
||||
unsigned int loaded; /* simulate loading so options are merged properly */
|
||||
#endif
|
||||
};
|
||||
|
||||
struct iptables_target
|
||||
{
|
||||
struct iptables_target *next;
|
||||
|
||||
ipt_chainlabel name;
|
||||
|
||||
/* Revision of target (0 by default). */
|
||||
u_int8_t revision;
|
||||
|
||||
const char *version;
|
||||
|
||||
/* Size of target data. */
|
||||
size_t size;
|
||||
|
||||
/* Size of target data relevent for userspace comparison purposes */
|
||||
size_t userspacesize;
|
||||
|
||||
/* Function which prints out usage message. */
|
||||
void (*help)(void);
|
||||
|
||||
/* Initialize the target. */
|
||||
void (*init)(struct ipt_entry_target *t, unsigned int *nfcache);
|
||||
|
||||
/* Function which parses command options; returns true if it
|
||||
ate an option */
|
||||
int (*parse)(int c, char **argv, int invert, unsigned int *flags,
|
||||
const struct ipt_entry *entry,
|
||||
struct ipt_entry_target **target);
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
void (*final_check)(unsigned int flags);
|
||||
|
||||
/* Prints out the target iff non-NULL: put space at end */
|
||||
void (*print)(const struct ipt_ip *ip,
|
||||
const struct ipt_entry_target *target, int numeric);
|
||||
|
||||
/* Saves the targinfo in parsable form to stdout. */
|
||||
void (*save)(const struct ipt_ip *ip,
|
||||
const struct ipt_entry_target *target);
|
||||
|
||||
/* Pointer to list of extra command-line options */
|
||||
struct option *extra_opts;
|
||||
|
||||
/* Ignore these men behind the curtain: */
|
||||
unsigned int option_offset;
|
||||
struct ipt_entry_target *t;
|
||||
unsigned int tflags;
|
||||
unsigned int used;
|
||||
#ifdef NO_SHARED_LIBS
|
||||
unsigned int loaded; /* simulate loading so options are merged properly */
|
||||
#endif
|
||||
};
|
||||
|
||||
extern int line;
|
||||
#include <netinet/ip.h>
|
||||
#include <xtables.h>
|
||||
#include <libiptc/libiptc.h>
|
||||
#include <iptables/internal.h>
|
||||
|
||||
/* Your shared library should call one of these. */
|
||||
extern void register_match(struct iptables_match *me);
|
||||
extern void register_target(struct iptables_target *me);
|
||||
extern void xtables_register_target(struct iptables_target *me);
|
||||
extern int build_st(struct iptables_target *target, struct ipt_entry_target *t);
|
||||
extern int do_command4(int argc, char *argv[], char **table,
|
||||
struct xtc_handle **handle, bool restore);
|
||||
extern int delete_chain4(const xt_chainlabel chain, int verbose,
|
||||
struct xtc_handle *handle);
|
||||
extern int flush_entries4(const xt_chainlabel chain, int verbose,
|
||||
struct xtc_handle *handle);
|
||||
extern int for_each_chain4(int (*fn)(const xt_chainlabel, int, struct xtc_handle *),
|
||||
int verbose, int builtinstoo, struct xtc_handle *handle);
|
||||
extern void print_rule4(const struct ipt_entry *e,
|
||||
struct xtc_handle *handle, const char *chain, int counters);
|
||||
|
||||
extern struct in_addr *dotted_to_addr(const char *dotted);
|
||||
extern char *addr_to_dotted(const struct in_addr *addrp);
|
||||
extern char *addr_to_anyname(const struct in_addr *addr);
|
||||
extern char *mask_to_dotted(const struct in_addr *mask);
|
||||
extern struct xtables_globals iptables_globals;
|
||||
|
||||
extern void parse_hostnetworkmask(const char *name, struct in_addr **addrpp,
|
||||
struct in_addr *maskp, unsigned int *naddrs);
|
||||
extern u_int16_t parse_protocol(const char *s);
|
||||
extern struct xtables_globals xtables_globals;
|
||||
|
||||
extern int do_command(int argc, char *argv[], char **table,
|
||||
iptc_handle_t *handle);
|
||||
/* Keeping track of external matches and targets: linked lists. */
|
||||
extern struct iptables_match *iptables_matches;
|
||||
extern struct iptables_target *iptables_targets;
|
||||
|
||||
enum ipt_tryload {
|
||||
DONT_LOAD,
|
||||
TRY_LOAD,
|
||||
LOAD_MUST_SUCCEED
|
||||
};
|
||||
|
||||
extern struct iptables_target *find_target(const char *name, enum ipt_tryload);
|
||||
extern struct iptables_match *find_match(const char *name, enum ipt_tryload, struct iptables_rule_match **match);
|
||||
|
||||
extern int delete_chain(const ipt_chainlabel chain, int verbose,
|
||||
iptc_handle_t *handle);
|
||||
extern int flush_entries(const ipt_chainlabel chain, int verbose,
|
||||
iptc_handle_t *handle);
|
||||
extern int for_each_chain(int (*fn)(const ipt_chainlabel, int, iptc_handle_t *),
|
||||
int verbose, int builtinstoo, iptc_handle_t *handle);
|
||||
#endif /*_IPTABLES_USER_H*/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef IPTABLES_INTERNAL_H
|
||||
#define IPTABLES_INTERNAL_H 1
|
||||
|
||||
#define IPTABLES_VERSION "1.6.0"
|
||||
|
||||
/**
|
||||
* Program's own name and version.
|
||||
*/
|
||||
extern const char *program_name, *program_version;
|
||||
|
||||
extern int line;
|
||||
|
||||
#endif /* IPTABLES_INTERNAL_H */
|
||||
|
|
@ -5,22 +5,11 @@
|
|||
|
||||
#include <limits.h>
|
||||
|
||||
#if defined(__GLIBC__) && __GLIBC__ == 2
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <net/if.h>
|
||||
#include <sys/types.h>
|
||||
#else /* libc5 */
|
||||
#include <sys/socket.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/icmp.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/in6.h>
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -2,153 +2,160 @@
|
|||
#define _LIBIP6TC_H
|
||||
/* Library which manipulates firewall rules. Version 0.2. */
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <libiptc/ipt_kernel_headers.h>
|
||||
#include <linux/netfilter_ipv6/ip6_tables.h>
|
||||
|
||||
#ifndef IP6T_MIN_ALIGN
|
||||
#define IP6T_MIN_ALIGN (__alignof__(struct ip6t_entry))
|
||||
#ifdef __cplusplus
|
||||
# include <climits>
|
||||
#else
|
||||
# include <limits.h> /* INT_MAX in ip6_tables.h */
|
||||
#endif
|
||||
#define IP6T_ALIGN(s) (((s) + (IP6T_MIN_ALIGN-1)) & ~(IP6T_MIN_ALIGN-1))
|
||||
#include <linux/netfilter_ipv6/ip6_tables.h>
|
||||
#include <libiptc/xtcshared.h>
|
||||
|
||||
typedef char ip6t_chainlabel[32];
|
||||
#define ip6tc_handle xtc_handle
|
||||
#define ip6t_chainlabel xt_chainlabel
|
||||
|
||||
#define IP6TC_LABEL_ACCEPT "ACCEPT"
|
||||
#define IP6TC_LABEL_DROP "DROP"
|
||||
#define IP6TC_LABEL_QUEUE "QUEUE"
|
||||
#define IP6TC_LABEL_RETURN "RETURN"
|
||||
|
||||
/* Transparent handle type. */
|
||||
typedef struct ip6tc_handle *ip6tc_handle_t;
|
||||
|
||||
/* Does this chain exist? */
|
||||
int ip6tc_is_chain(const char *chain, const ip6tc_handle_t handle);
|
||||
int ip6tc_is_chain(const char *chain, struct xtc_handle *const handle);
|
||||
|
||||
/* Take a snapshot of the rules. Returns NULL on error. */
|
||||
ip6tc_handle_t ip6tc_init(const char *tablename);
|
||||
struct xtc_handle *ip6tc_init(const char *tablename);
|
||||
|
||||
/* Cleanup after ip6tc_init(). */
|
||||
void ip6tc_free(ip6tc_handle_t *h);
|
||||
void ip6tc_free(struct xtc_handle *h);
|
||||
|
||||
/* Iterator functions to run through the chains. Returns NULL at end. */
|
||||
const char *ip6tc_first_chain(ip6tc_handle_t *handle);
|
||||
const char *ip6tc_next_chain(ip6tc_handle_t *handle);
|
||||
const char *ip6tc_first_chain(struct xtc_handle *handle);
|
||||
const char *ip6tc_next_chain(struct xtc_handle *handle);
|
||||
|
||||
/* Get first rule in the given chain: NULL for empty chain. */
|
||||
const struct ip6t_entry *ip6tc_first_rule(const char *chain,
|
||||
ip6tc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Returns NULL when rules run out. */
|
||||
const struct ip6t_entry *ip6tc_next_rule(const struct ip6t_entry *prev,
|
||||
ip6tc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Returns a pointer to the target name of this position. */
|
||||
const char *ip6tc_get_target(const struct ip6t_entry *e,
|
||||
ip6tc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Is this a built-in chain? */
|
||||
int ip6tc_builtin(const char *chain, const ip6tc_handle_t handle);
|
||||
int ip6tc_builtin(const char *chain, struct xtc_handle *const handle);
|
||||
|
||||
/* Get the policy of a given built-in chain */
|
||||
const char *ip6tc_get_policy(const char *chain,
|
||||
struct ip6t_counters *counters,
|
||||
ip6tc_handle_t *handle);
|
||||
struct xt_counters *counters,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* These functions return TRUE for OK or 0 and set errno. If errno ==
|
||||
0, it means there was a version error (ie. upgrade libiptc). */
|
||||
/* Rule numbers start at 1 for the first rule. */
|
||||
|
||||
/* Insert the entry `fw' in chain `chain' into position `rulenum'. */
|
||||
int ip6tc_insert_entry(const ip6t_chainlabel chain,
|
||||
int ip6tc_insert_entry(const xt_chainlabel chain,
|
||||
const struct ip6t_entry *e,
|
||||
unsigned int rulenum,
|
||||
ip6tc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Atomically replace rule `rulenum' in `chain' with `fw'. */
|
||||
int ip6tc_replace_entry(const ip6t_chainlabel chain,
|
||||
int ip6tc_replace_entry(const xt_chainlabel chain,
|
||||
const struct ip6t_entry *e,
|
||||
unsigned int rulenum,
|
||||
ip6tc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Append entry `fw' to chain `chain'. Equivalent to insert with
|
||||
rulenum = length of chain. */
|
||||
int ip6tc_append_entry(const ip6t_chainlabel chain,
|
||||
int ip6tc_append_entry(const xt_chainlabel chain,
|
||||
const struct ip6t_entry *e,
|
||||
ip6tc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Delete the first rule in `chain' which matches `fw'. */
|
||||
int ip6tc_delete_entry(const ip6t_chainlabel chain,
|
||||
/* Check whether a matching rule exists */
|
||||
int ip6tc_check_entry(const xt_chainlabel chain,
|
||||
const struct ip6t_entry *origfw,
|
||||
unsigned char *matchmask,
|
||||
ip6tc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Delete the first rule in `chain' which matches `fw'. */
|
||||
int ip6tc_delete_entry(const xt_chainlabel chain,
|
||||
const struct ip6t_entry *origfw,
|
||||
unsigned char *matchmask,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Delete the rule in position `rulenum' in `chain'. */
|
||||
int ip6tc_delete_num_entry(const ip6t_chainlabel chain,
|
||||
int ip6tc_delete_num_entry(const xt_chainlabel chain,
|
||||
unsigned int rulenum,
|
||||
ip6tc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Check the packet `fw' on chain `chain'. Returns the verdict, or
|
||||
NULL and sets errno. */
|
||||
const char *ip6tc_check_packet(const ip6t_chainlabel chain,
|
||||
const char *ip6tc_check_packet(const xt_chainlabel chain,
|
||||
struct ip6t_entry *,
|
||||
ip6tc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Flushes the entries in the given chain (ie. empties chain). */
|
||||
int ip6tc_flush_entries(const ip6t_chainlabel chain,
|
||||
ip6tc_handle_t *handle);
|
||||
int ip6tc_flush_entries(const xt_chainlabel chain,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Zeroes the counters in a chain. */
|
||||
int ip6tc_zero_entries(const ip6t_chainlabel chain,
|
||||
ip6tc_handle_t *handle);
|
||||
int ip6tc_zero_entries(const xt_chainlabel chain,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Creates a new chain. */
|
||||
int ip6tc_create_chain(const ip6t_chainlabel chain,
|
||||
ip6tc_handle_t *handle);
|
||||
int ip6tc_create_chain(const xt_chainlabel chain,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Deletes a chain. */
|
||||
int ip6tc_delete_chain(const ip6t_chainlabel chain,
|
||||
ip6tc_handle_t *handle);
|
||||
int ip6tc_delete_chain(const xt_chainlabel chain,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Renames a chain. */
|
||||
int ip6tc_rename_chain(const ip6t_chainlabel oldname,
|
||||
const ip6t_chainlabel newname,
|
||||
ip6tc_handle_t *handle);
|
||||
int ip6tc_rename_chain(const xt_chainlabel oldname,
|
||||
const xt_chainlabel newname,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Sets the policy on a built-in chain. */
|
||||
int ip6tc_set_policy(const ip6t_chainlabel chain,
|
||||
const ip6t_chainlabel policy,
|
||||
struct ip6t_counters *counters,
|
||||
ip6tc_handle_t *handle);
|
||||
int ip6tc_set_policy(const xt_chainlabel chain,
|
||||
const xt_chainlabel policy,
|
||||
struct xt_counters *counters,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Get the number of references to this chain */
|
||||
int ip6tc_get_references(unsigned int *ref, const ip6t_chainlabel chain,
|
||||
ip6tc_handle_t *handle);
|
||||
int ip6tc_get_references(unsigned int *ref, const xt_chainlabel chain,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* read packet and byte counters for a specific rule */
|
||||
struct ip6t_counters *ip6tc_read_counter(const ip6t_chainlabel chain,
|
||||
struct xt_counters *ip6tc_read_counter(const xt_chainlabel chain,
|
||||
unsigned int rulenum,
|
||||
ip6tc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* zero packet and byte counters for a specific rule */
|
||||
int ip6tc_zero_counter(const ip6t_chainlabel chain,
|
||||
int ip6tc_zero_counter(const xt_chainlabel chain,
|
||||
unsigned int rulenum,
|
||||
ip6tc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* set packet and byte counters for a specific rule */
|
||||
int ip6tc_set_counter(const ip6t_chainlabel chain,
|
||||
int ip6tc_set_counter(const xt_chainlabel chain,
|
||||
unsigned int rulenum,
|
||||
struct ip6t_counters *counters,
|
||||
ip6tc_handle_t *handle);
|
||||
struct xt_counters *counters,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Makes the actual changes. */
|
||||
int ip6tc_commit(ip6tc_handle_t *handle);
|
||||
int ip6tc_commit(struct xtc_handle *handle);
|
||||
|
||||
/* Get raw socket. */
|
||||
int ip6tc_get_raw_socket();
|
||||
int ip6tc_get_raw_socket(void);
|
||||
|
||||
/* Translates errno numbers into more human-readable form than strerror. */
|
||||
const char *ip6tc_strerror(int err);
|
||||
|
||||
/* Return prefix length, or -1 if not contiguous */
|
||||
int ipv6_prefix_length(const struct in6_addr *a);
|
||||
extern void dump_entries6(struct xtc_handle *const);
|
||||
|
||||
extern const struct xtc_ops ip6tc_ops;
|
||||
|
||||
#endif /* _LIBIP6TC_H */
|
||||
|
|
|
|||
|
|
@ -2,155 +2,157 @@
|
|||
#define _LIBIPTC_H
|
||||
/* Library which manipulates filtering rules. */
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <libiptc/ipt_kernel_headers.h>
|
||||
#ifdef __cplusplus
|
||||
# include <climits>
|
||||
#else
|
||||
# include <limits.h> /* INT_MAX in ip_tables.h */
|
||||
#endif
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#include <libiptc/xtcshared.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef IPT_MIN_ALIGN
|
||||
/* ipt_entry has pointers and u_int64_t's in it, so if you align to
|
||||
it, you'll also align to any crazy matches and targets someone
|
||||
might write */
|
||||
#define IPT_MIN_ALIGN (__alignof__(struct ipt_entry))
|
||||
#endif
|
||||
|
||||
#define IPT_ALIGN(s) (((s) + ((IPT_MIN_ALIGN)-1)) & ~((IPT_MIN_ALIGN)-1))
|
||||
|
||||
typedef char ipt_chainlabel[32];
|
||||
#define iptc_handle xtc_handle
|
||||
#define ipt_chainlabel xt_chainlabel
|
||||
|
||||
#define IPTC_LABEL_ACCEPT "ACCEPT"
|
||||
#define IPTC_LABEL_DROP "DROP"
|
||||
#define IPTC_LABEL_QUEUE "QUEUE"
|
||||
#define IPTC_LABEL_RETURN "RETURN"
|
||||
|
||||
/* Transparent handle type. */
|
||||
typedef struct iptc_handle *iptc_handle_t;
|
||||
|
||||
/* Does this chain exist? */
|
||||
int iptc_is_chain(const char *chain, const iptc_handle_t handle);
|
||||
int iptc_is_chain(const char *chain, struct xtc_handle *const handle);
|
||||
|
||||
/* Take a snapshot of the rules. Returns NULL on error. */
|
||||
iptc_handle_t iptc_init(const char *tablename);
|
||||
struct xtc_handle *iptc_init(const char *tablename);
|
||||
|
||||
/* Cleanup after iptc_init(). */
|
||||
void iptc_free(iptc_handle_t *h);
|
||||
void iptc_free(struct xtc_handle *h);
|
||||
|
||||
/* Iterator functions to run through the chains. Returns NULL at end. */
|
||||
const char *iptc_first_chain(iptc_handle_t *handle);
|
||||
const char *iptc_next_chain(iptc_handle_t *handle);
|
||||
const char *iptc_first_chain(struct xtc_handle *handle);
|
||||
const char *iptc_next_chain(struct xtc_handle *handle);
|
||||
|
||||
/* Get first rule in the given chain: NULL for empty chain. */
|
||||
const struct ipt_entry *iptc_first_rule(const char *chain,
|
||||
iptc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Returns NULL when rules run out. */
|
||||
const struct ipt_entry *iptc_next_rule(const struct ipt_entry *prev,
|
||||
iptc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Returns a pointer to the target name of this entry. */
|
||||
const char *iptc_get_target(const struct ipt_entry *e,
|
||||
iptc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Is this a built-in chain? */
|
||||
int iptc_builtin(const char *chain, const iptc_handle_t handle);
|
||||
int iptc_builtin(const char *chain, struct xtc_handle *const handle);
|
||||
|
||||
/* Get the policy of a given built-in chain */
|
||||
const char *iptc_get_policy(const char *chain,
|
||||
struct ipt_counters *counter,
|
||||
iptc_handle_t *handle);
|
||||
struct xt_counters *counter,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* These functions return TRUE for OK or 0 and set errno. If errno ==
|
||||
0, it means there was a version error (ie. upgrade libiptc). */
|
||||
/* Rule numbers start at 1 for the first rule. */
|
||||
|
||||
/* Insert the entry `e' in chain `chain' into position `rulenum'. */
|
||||
int iptc_insert_entry(const ipt_chainlabel chain,
|
||||
int iptc_insert_entry(const xt_chainlabel chain,
|
||||
const struct ipt_entry *e,
|
||||
unsigned int rulenum,
|
||||
iptc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Atomically replace rule `rulenum' in `chain' with `e'. */
|
||||
int iptc_replace_entry(const ipt_chainlabel chain,
|
||||
int iptc_replace_entry(const xt_chainlabel chain,
|
||||
const struct ipt_entry *e,
|
||||
unsigned int rulenum,
|
||||
iptc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Append entry `e' to chain `chain'. Equivalent to insert with
|
||||
rulenum = length of chain. */
|
||||
int iptc_append_entry(const ipt_chainlabel chain,
|
||||
int iptc_append_entry(const xt_chainlabel chain,
|
||||
const struct ipt_entry *e,
|
||||
iptc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Check whether a mathching rule exists */
|
||||
int iptc_check_entry(const xt_chainlabel chain,
|
||||
const struct ipt_entry *origfw,
|
||||
unsigned char *matchmask,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Delete the first rule in `chain' which matches `e', subject to
|
||||
matchmask (array of length == origfw) */
|
||||
int iptc_delete_entry(const ipt_chainlabel chain,
|
||||
int iptc_delete_entry(const xt_chainlabel chain,
|
||||
const struct ipt_entry *origfw,
|
||||
unsigned char *matchmask,
|
||||
iptc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Delete the rule in position `rulenum' in `chain'. */
|
||||
int iptc_delete_num_entry(const ipt_chainlabel chain,
|
||||
int iptc_delete_num_entry(const xt_chainlabel chain,
|
||||
unsigned int rulenum,
|
||||
iptc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Check the packet `e' on chain `chain'. Returns the verdict, or
|
||||
NULL and sets errno. */
|
||||
const char *iptc_check_packet(const ipt_chainlabel chain,
|
||||
const char *iptc_check_packet(const xt_chainlabel chain,
|
||||
struct ipt_entry *entry,
|
||||
iptc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Flushes the entries in the given chain (ie. empties chain). */
|
||||
int iptc_flush_entries(const ipt_chainlabel chain,
|
||||
iptc_handle_t *handle);
|
||||
int iptc_flush_entries(const xt_chainlabel chain,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Zeroes the counters in a chain. */
|
||||
int iptc_zero_entries(const ipt_chainlabel chain,
|
||||
iptc_handle_t *handle);
|
||||
int iptc_zero_entries(const xt_chainlabel chain,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Creates a new chain. */
|
||||
int iptc_create_chain(const ipt_chainlabel chain,
|
||||
iptc_handle_t *handle);
|
||||
int iptc_create_chain(const xt_chainlabel chain,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Deletes a chain. */
|
||||
int iptc_delete_chain(const ipt_chainlabel chain,
|
||||
iptc_handle_t *handle);
|
||||
int iptc_delete_chain(const xt_chainlabel chain,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Renames a chain. */
|
||||
int iptc_rename_chain(const ipt_chainlabel oldname,
|
||||
const ipt_chainlabel newname,
|
||||
iptc_handle_t *handle);
|
||||
int iptc_rename_chain(const xt_chainlabel oldname,
|
||||
const xt_chainlabel newname,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Sets the policy on a built-in chain. */
|
||||
int iptc_set_policy(const ipt_chainlabel chain,
|
||||
const ipt_chainlabel policy,
|
||||
struct ipt_counters *counters,
|
||||
iptc_handle_t *handle);
|
||||
int iptc_set_policy(const xt_chainlabel chain,
|
||||
const xt_chainlabel policy,
|
||||
struct xt_counters *counters,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Get the number of references to this chain */
|
||||
int iptc_get_references(unsigned int *ref,
|
||||
const ipt_chainlabel chain,
|
||||
iptc_handle_t *handle);
|
||||
const xt_chainlabel chain,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* read packet and byte counters for a specific rule */
|
||||
struct ipt_counters *iptc_read_counter(const ipt_chainlabel chain,
|
||||
struct xt_counters *iptc_read_counter(const xt_chainlabel chain,
|
||||
unsigned int rulenum,
|
||||
iptc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* zero packet and byte counters for a specific rule */
|
||||
int iptc_zero_counter(const ipt_chainlabel chain,
|
||||
int iptc_zero_counter(const xt_chainlabel chain,
|
||||
unsigned int rulenum,
|
||||
iptc_handle_t *handle);
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* set packet and byte counters for a specific rule */
|
||||
int iptc_set_counter(const ipt_chainlabel chain,
|
||||
int iptc_set_counter(const xt_chainlabel chain,
|
||||
unsigned int rulenum,
|
||||
struct ipt_counters *counters,
|
||||
iptc_handle_t *handle);
|
||||
struct xt_counters *counters,
|
||||
struct xtc_handle *handle);
|
||||
|
||||
/* Makes the actual changes. */
|
||||
int iptc_commit(iptc_handle_t *handle);
|
||||
int iptc_commit(struct xtc_handle *handle);
|
||||
|
||||
/* Get raw socket. */
|
||||
int iptc_get_raw_socket(void);
|
||||
|
|
@ -158,6 +160,10 @@ int iptc_get_raw_socket(void);
|
|||
/* Translates errno numbers into more human-readable form than strerror. */
|
||||
const char *iptc_strerror(int err);
|
||||
|
||||
extern void dump_entries(struct xtc_handle *const);
|
||||
|
||||
extern const struct xtc_ops iptc_ops;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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)))
|
||||
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
@ -196,6 +196,7 @@ struct in6_flowlabel_req {
|
|||
|
||||
#define IPV6_IPSEC_POLICY 34
|
||||
#define IPV6_XFRM_POLICY 35
|
||||
#define IPV6_HDRINCL 36
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
104
ip/ip6tunnel.c
104
ip/ip6tunnel.c
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
120
ip/ip_common.h
120
ip/ip_common.h
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
13
ip/iplink.c
13
ip/iplink.c
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -113,4 +113,3 @@ struct link_util bond_slave_link_util = {
|
|||
.parse_opt = bond_slave_parse_opt,
|
||||
.slave = true,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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]) {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
51
ip/ipneigh.c
51
ip/ipneigh.c
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,4 +107,3 @@ int print_prefix(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
79
ip/iproute.c
79
ip/iproute.c
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
106
ip/iprule.c
106
ip/iprule.c
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
323
ip/iptunnel.c
323
ip/iptunnel.c
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
|
|
|
|||
10
ip/rtm_map.c
10
ip/rtm_map.c
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -508,4 +508,3 @@ int do_tcp_metrics(int argc, char **argv)
|
|||
"try \"ip tcp_metrics help\".\n", *argv);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
|
|
|||
43
ip/tunnel.c
43
ip/tunnel.c
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
141
lib/rt_names.c
141
lib/rt_names.c
|
|
@ -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;
|
||||
|
|
|
|||
86
lib/utils.c
86
lib/utils.c
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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>.
|
||||
|
|
@ -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
|
||||
|
|
@ -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>.
|
||||
|
|
@ -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 / 吉藤英明
|
||||
|
||||
|
|
|
|||
|
|
@ -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 "
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -47,4 +47,3 @@ Time interval to average rates. Default value is 60 seconds.
|
|||
|
||||
.SH SEE ALSO
|
||||
lnstat(8)
|
||||
|
||||
|
|
|
|||
|
|
@ -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>,
|
||||
|
|
|
|||
|
|
@ -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 iproutedoc)",
|
||||
.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>
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -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>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in New Issue