hc
2023-12-11 6778948f9de86c3cfaf36725a7c87dcff9ba247f
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 *    inet6 interface/address list definitions
 *    Linux INET6 implementation 
 *
 *    Authors:
 *    Pedro Roque        <roque@di.fc.ul.pt>    
 */
 
#ifndef _NET_IF_INET6_H
#define _NET_IF_INET6_H
 
#include <net/snmp.h>
#include <linux/ipv6.h>
#include <linux/refcount.h>
 
/* inet6_dev.if_flags */
 
#define IF_RA_OTHERCONF    0x80
#define IF_RA_MANAGED    0x40
#define IF_RA_RCVD    0x20
#define IF_RS_SENT    0x10
#define IF_READY    0x80000000
 
/* prefix flags */
#define IF_PREFIX_ONLINK    0x01
#define IF_PREFIX_AUTOCONF    0x02
 
enum {
   INET6_IFADDR_STATE_PREDAD,
   INET6_IFADDR_STATE_DAD,
   INET6_IFADDR_STATE_POSTDAD,
   INET6_IFADDR_STATE_ERRDAD,
   INET6_IFADDR_STATE_DEAD,
};
 
struct inet6_ifaddr {
   struct in6_addr        addr;
   __u32            prefix_len;
   __u32            rt_priority;
 
   /* In seconds, relative to tstamp. Expiry is at tstamp + HZ * lft. */
   __u32            valid_lft;
   __u32            prefered_lft;
   refcount_t        refcnt;
   spinlock_t        lock;
 
   int            state;
 
   __u32            flags;
   __u8            dad_probes;
   __u8            stable_privacy_retry;
 
   __u16            scope;
   __u64            dad_nonce;
 
   unsigned long        cstamp;    /* created timestamp */
   unsigned long        tstamp; /* updated timestamp */
 
   struct delayed_work    dad_work;
 
   struct inet6_dev    *idev;
   struct fib6_info    *rt;
 
   struct hlist_node    addr_lst;
   struct list_head    if_list;
   /*
    * Used to safely traverse idev->addr_list in process context
    * if the idev->lock needed to protect idev->addr_list cannot be held.
    * In that case, add the items to this list temporarily and iterate
    * without holding idev->lock.
    * See addrconf_ifdown and dev_forward_change.
    */
   struct list_head    if_list_aux;
 
   struct list_head    tmp_list;
   struct inet6_ifaddr    *ifpub;
   int            regen_count;
 
   bool            tokenized;
 
   struct rcu_head        rcu;
   struct in6_addr        peer_addr;
};
 
struct ip6_sf_socklist {
   unsigned int        sl_max;
   unsigned int        sl_count;
   struct in6_addr        sl_addr[];
};
 
#define IP6_SFLSIZE(count)    (sizeof(struct ip6_sf_socklist) + \
   (count) * sizeof(struct in6_addr))
 
#define IP6_SFBLOCK    10    /* allocate this many at once */
 
struct ipv6_mc_socklist {
   struct in6_addr        addr;
   int            ifindex;
   unsigned int        sfmode;        /* MCAST_{INCLUDE,EXCLUDE} */
   struct ipv6_mc_socklist __rcu *next;
   rwlock_t        sflock;
   struct ip6_sf_socklist    *sflist;
   struct rcu_head        rcu;
};
 
struct ip6_sf_list {
   struct ip6_sf_list    *sf_next;
   struct in6_addr        sf_addr;
   unsigned long        sf_count[2];    /* include/exclude counts */
   unsigned char        sf_gsresp;    /* include in g & s response? */
   unsigned char        sf_oldin;    /* change state */
   unsigned char        sf_crcount;    /* retrans. left to send */
};
 
#define MAF_TIMER_RUNNING    0x01
#define MAF_LAST_REPORTER    0x02
#define MAF_LOADED        0x04
#define MAF_NOREPORT        0x08
#define MAF_GSQUERY        0x10
 
struct ifmcaddr6 {
   struct in6_addr        mca_addr;
   struct inet6_dev    *idev;
   struct ifmcaddr6    *next;
   struct ip6_sf_list    *mca_sources;
   struct ip6_sf_list    *mca_tomb;
   unsigned int        mca_sfmode;
   unsigned char        mca_crcount;
   unsigned long        mca_sfcount[2];
   struct timer_list    mca_timer;
   unsigned int        mca_flags;
   int            mca_users;
   refcount_t        mca_refcnt;
   spinlock_t        mca_lock;
   unsigned long        mca_cstamp;
   unsigned long        mca_tstamp;
};
 
/* Anycast stuff */
 
struct ipv6_ac_socklist {
   struct in6_addr        acl_addr;
   int            acl_ifindex;
   struct ipv6_ac_socklist *acl_next;
};
 
struct ifacaddr6 {
   struct in6_addr        aca_addr;
   struct fib6_info    *aca_rt;
   struct ifacaddr6    *aca_next;
   struct hlist_node    aca_addr_lst;
   int            aca_users;
   refcount_t        aca_refcnt;
   unsigned long        aca_cstamp;
   unsigned long        aca_tstamp;
   struct rcu_head        rcu;
};
 
#define    IFA_HOST    IPV6_ADDR_LOOPBACK
#define    IFA_LINK    IPV6_ADDR_LINKLOCAL
#define    IFA_SITE    IPV6_ADDR_SITELOCAL
 
struct ipv6_devstat {
   struct proc_dir_entry    *proc_dir_entry;
   DEFINE_SNMP_STAT(struct ipstats_mib, ipv6);
   DEFINE_SNMP_STAT_ATOMIC(struct icmpv6_mib_device, icmpv6dev);
   DEFINE_SNMP_STAT_ATOMIC(struct icmpv6msg_mib_device, icmpv6msgdev);
};
 
struct inet6_dev {
   struct net_device    *dev;
 
   struct list_head    addr_list;
 
   struct ifmcaddr6    *mc_list;
   struct ifmcaddr6    *mc_tomb;
   spinlock_t        mc_lock;
 
   unsigned char        mc_qrv;        /* Query Robustness Variable */
   unsigned char        mc_gq_running;
   unsigned char        mc_ifc_count;
   unsigned char        mc_dad_count;
 
   unsigned long        mc_v1_seen;    /* Max time we stay in MLDv1 mode */
   unsigned long        mc_qi;        /* Query Interval */
   unsigned long        mc_qri;        /* Query Response Interval */
   unsigned long        mc_maxdelay;
 
   struct timer_list    mc_gq_timer;    /* general query timer */
   struct timer_list    mc_ifc_timer;    /* interface change timer */
   struct timer_list    mc_dad_timer;    /* dad complete mc timer */
 
   struct ifacaddr6    *ac_list;
   rwlock_t        lock;
   refcount_t        refcnt;
   __u32            if_flags;
   int            dead;
 
   u32            desync_factor;
   struct list_head    tempaddr_list;
 
   struct in6_addr        token;
 
   struct neigh_parms    *nd_parms;
   struct ipv6_devconf    cnf;
   struct ipv6_devstat    stats;
 
   struct timer_list    rs_timer;
   __s32            rs_interval;    /* in jiffies */
   __u8            rs_probes;
 
   unsigned long        tstamp; /* ipv6InterfaceTable update timestamp */
   struct rcu_head        rcu;
};
 
static inline void ipv6_eth_mc_map(const struct in6_addr *addr, char *buf)
{
   /*
    *    +-------+-------+-------+-------+-------+-------+
    *      |   33  |   33  | DST13 | DST14 | DST15 | DST16 |
    *      +-------+-------+-------+-------+-------+-------+
    */
 
   buf[0]= 0x33;
   buf[1]= 0x33;
 
   memcpy(buf + 2, &addr->s6_addr32[3], sizeof(__u32));
}
 
static inline void ipv6_arcnet_mc_map(const struct in6_addr *addr, char *buf)
{
   buf[0] = 0x00;
}
 
static inline void ipv6_ib_mc_map(const struct in6_addr *addr,
                 const unsigned char *broadcast, char *buf)
{
   unsigned char scope = broadcast[5] & 0xF;
 
   buf[0]  = 0;        /* Reserved */
   buf[1]  = 0xff;        /* Multicast QPN */
   buf[2]  = 0xff;
   buf[3]  = 0xff;
   buf[4]  = 0xff;
   buf[5]  = 0x10 | scope;    /* scope from broadcast address */
   buf[6]  = 0x60;        /* IPv6 signature */
   buf[7]  = 0x1b;
   buf[8]  = broadcast[8];    /* P_Key */
   buf[9]  = broadcast[9];
   memcpy(buf + 10, addr->s6_addr + 6, 10);
}
 
static inline int ipv6_ipgre_mc_map(const struct in6_addr *addr,
                   const unsigned char *broadcast, char *buf)
{
   if ((broadcast[0] | broadcast[1] | broadcast[2] | broadcast[3]) != 0) {
       memcpy(buf, broadcast, 4);
   } else {
       /* v4mapped? */
       if ((addr->s6_addr32[0] | addr->s6_addr32[1] |
            (addr->s6_addr32[2] ^ htonl(0x0000ffff))) != 0)
           return -EINVAL;
       memcpy(buf, &addr->s6_addr32[3], 4);
   }
   return 0;
}
 
#endif