huangcm
2024-08-23 d76fb8c8c6d079a3cee81da7072347dcb8bbbc70
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#ifndef __NET_FIB_RULES_H
#define __NET_FIB_RULES_H
 
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/netdevice.h>
#include <linux/fib_rules.h>
#include <net/flow.h>
#include <net/rtnetlink.h>
 
struct fib_kuid_range {
   kuid_t start;
   kuid_t end;
};
 
struct fib_rule {
   struct list_head    list;
   int            iifindex;
   int            oifindex;
   u32            mark;
   u32            mark_mask;
   u32            flags;
   u32            table;
   u8            action;
   u8            l3mdev;
   /* 2 bytes hole, try to use */
   u32            target;
   __be64            tun_id;
   struct fib_rule __rcu    *ctarget;
   struct net        *fr_net;
 
   atomic_t        refcnt;
   u32            pref;
   int            suppress_ifgroup;
   int            suppress_prefixlen;
   char            iifname[IFNAMSIZ];
   char            oifname[IFNAMSIZ];
   struct fib_kuid_range    uid_range;
   struct rcu_head        rcu;
};
 
struct fib_lookup_arg {
   void            *lookup_ptr;
   void            *result;
   struct fib_rule        *rule;
   u32            table;
   int            flags;
#define FIB_LOOKUP_NOREF        1
#define FIB_LOOKUP_IGNORE_LINKSTATE    2
};
 
struct fib_rules_ops {
   int            family;
   struct list_head    list;
   int            rule_size;
   int            addr_size;
   int            unresolved_rules;
   int            nr_goto_rules;
 
   int            (*action)(struct fib_rule *,
                     struct flowi *, int,
                     struct fib_lookup_arg *);
   bool            (*suppress)(struct fib_rule *,
                       struct fib_lookup_arg *);
   int            (*match)(struct fib_rule *,
                    struct flowi *, int);
   int            (*configure)(struct fib_rule *,
                        struct sk_buff *,
                        struct fib_rule_hdr *,
                        struct nlattr **);
   int            (*delete)(struct fib_rule *);
   int            (*compare)(struct fib_rule *,
                      struct fib_rule_hdr *,
                      struct nlattr **);
   int            (*fill)(struct fib_rule *, struct sk_buff *,
                   struct fib_rule_hdr *);
   size_t            (*nlmsg_payload)(struct fib_rule *);
 
   /* Called after modifications to the rules set, must flush
    * the route cache if one exists. */
   void            (*flush_cache)(struct fib_rules_ops *ops);
 
   int            nlgroup;
   const struct nla_policy    *policy;
   struct list_head    rules_list;
   struct module        *owner;
   struct net        *fro_net;
   struct rcu_head        rcu;
};
 
#define FRA_GENERIC_POLICY \
   [FRA_IIFNAME]    = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, \
   [FRA_OIFNAME]    = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, \
   [FRA_PRIORITY]    = { .type = NLA_U32 }, \
   [FRA_FWMARK]    = { .type = NLA_U32 }, \
   [FRA_FWMASK]    = { .type = NLA_U32 }, \
   [FRA_TABLE]     = { .type = NLA_U32 }, \
   [FRA_SUPPRESS_PREFIXLEN] = { .type = NLA_U32 }, \
   [FRA_SUPPRESS_IFGROUP] = { .type = NLA_U32 }, \
   [FRA_GOTO]    = { .type = NLA_U32 }, \
   [FRA_L3MDEV]    = { .type = NLA_U8 }, \
   [FRA_UID_RANGE]    = { .len = sizeof(struct fib_rule_uid_range) }
 
static inline void fib_rule_get(struct fib_rule *rule)
{
   atomic_inc(&rule->refcnt);
}
 
static inline void fib_rule_put(struct fib_rule *rule)
{
   if (atomic_dec_and_test(&rule->refcnt))
       kfree_rcu(rule, rcu);
}
 
#ifdef CONFIG_NET_L3_MASTER_DEV
static inline u32 fib_rule_get_table(struct fib_rule *rule,
                    struct fib_lookup_arg *arg)
{
   return rule->l3mdev ? arg->table : rule->table;
}
#else
static inline u32 fib_rule_get_table(struct fib_rule *rule,
                    struct fib_lookup_arg *arg)
{
   return rule->table;
}
#endif
 
static inline u32 frh_get_table(struct fib_rule_hdr *frh, struct nlattr **nla)
{
   if (nla[FRA_TABLE])
       return nla_get_u32(nla[FRA_TABLE]);
   return frh->table;
}
 
struct fib_rules_ops *fib_rules_register(const struct fib_rules_ops *,
                    struct net *);
void fib_rules_unregister(struct fib_rules_ops *);
 
int fib_rules_lookup(struct fib_rules_ops *, struct flowi *, int flags,
            struct fib_lookup_arg *);
int fib_default_rule_add(struct fib_rules_ops *, u32 pref, u32 table,
            u32 flags);
 
int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr *nlh);
int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr *nlh);
#endif