| .. | .. |
|---|
| 28 | 28 | #include <linux/err.h> |
|---|
| 29 | 29 | #include <linux/sysctl.h> |
|---|
| 30 | 30 | #include <linux/workqueue.h> |
|---|
| 31 | +#include <linux/android_kabi.h> |
|---|
| 31 | 32 | #include <net/rtnetlink.h> |
|---|
| 32 | 33 | |
|---|
| 33 | 34 | /* |
|---|
| .. | .. |
|---|
| 72 | 73 | struct net_device *dev; |
|---|
| 73 | 74 | struct list_head list; |
|---|
| 74 | 75 | int (*neigh_setup)(struct neighbour *); |
|---|
| 75 | | - void (*neigh_cleanup)(struct neighbour *); |
|---|
| 76 | 76 | struct neigh_table *tbl; |
|---|
| 77 | 77 | |
|---|
| 78 | 78 | void *sysctl_table; |
|---|
| .. | .. |
|---|
| 84 | 84 | int reachable_time; |
|---|
| 85 | 85 | int data[NEIGH_VAR_DATA_MAX]; |
|---|
| 86 | 86 | DECLARE_BITMAP(data_state, NEIGH_VAR_DATA_MAX); |
|---|
| 87 | + |
|---|
| 88 | + ANDROID_KABI_RESERVE(1); |
|---|
| 87 | 89 | }; |
|---|
| 88 | 90 | |
|---|
| 89 | 91 | static inline void neigh_var_set(struct neigh_parms *p, int index, int val) |
|---|
| .. | .. |
|---|
| 140 | 142 | unsigned long updated; |
|---|
| 141 | 143 | rwlock_t lock; |
|---|
| 142 | 144 | refcount_t refcnt; |
|---|
| 143 | | - struct sk_buff_head arp_queue; |
|---|
| 144 | 145 | unsigned int arp_queue_len_bytes; |
|---|
| 146 | + struct sk_buff_head arp_queue; |
|---|
| 145 | 147 | struct timer_list timer; |
|---|
| 146 | 148 | unsigned long used; |
|---|
| 147 | 149 | atomic_t probes; |
|---|
| .. | .. |
|---|
| 149 | 151 | __u8 nud_state; |
|---|
| 150 | 152 | __u8 type; |
|---|
| 151 | 153 | __u8 dead; |
|---|
| 154 | + u8 protocol; |
|---|
| 152 | 155 | seqlock_t ha_lock; |
|---|
| 153 | | - unsigned char ha[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))]; |
|---|
| 156 | + unsigned char ha[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))] __aligned(8); |
|---|
| 154 | 157 | struct hh_cache hh; |
|---|
| 155 | 158 | int (*output)(struct neighbour *, struct sk_buff *); |
|---|
| 156 | 159 | const struct neigh_ops *ops; |
|---|
| 160 | + struct list_head gc_list; |
|---|
| 157 | 161 | struct rcu_head rcu; |
|---|
| 158 | 162 | struct net_device *dev; |
|---|
| 163 | + |
|---|
| 164 | + ANDROID_KABI_RESERVE(1); |
|---|
| 165 | + |
|---|
| 159 | 166 | u8 primary_key[0]; |
|---|
| 160 | 167 | } __randomize_layout; |
|---|
| 161 | 168 | |
|---|
| .. | .. |
|---|
| 172 | 179 | possible_net_t net; |
|---|
| 173 | 180 | struct net_device *dev; |
|---|
| 174 | 181 | u8 flags; |
|---|
| 175 | | - u8 key[0]; |
|---|
| 182 | + u8 protocol; |
|---|
| 183 | + u8 key[]; |
|---|
| 176 | 184 | }; |
|---|
| 177 | 185 | |
|---|
| 178 | 186 | /* |
|---|
| .. | .. |
|---|
| 202 | 210 | int (*pconstructor)(struct pneigh_entry *); |
|---|
| 203 | 211 | void (*pdestructor)(struct pneigh_entry *); |
|---|
| 204 | 212 | void (*proxy_redo)(struct sk_buff *skb); |
|---|
| 213 | + int (*is_multicast)(const void *pkey); |
|---|
| 214 | + bool (*allow_add)(const struct net_device *dev, |
|---|
| 215 | + struct netlink_ext_ack *extack); |
|---|
| 205 | 216 | char *id; |
|---|
| 206 | 217 | struct neigh_parms parms; |
|---|
| 207 | 218 | struct list_head parms_list; |
|---|
| .. | .. |
|---|
| 214 | 225 | struct timer_list proxy_timer; |
|---|
| 215 | 226 | struct sk_buff_head proxy_queue; |
|---|
| 216 | 227 | atomic_t entries; |
|---|
| 228 | + atomic_t gc_entries; |
|---|
| 229 | + struct list_head gc_list; |
|---|
| 217 | 230 | rwlock_t lock; |
|---|
| 218 | 231 | unsigned long last_rand; |
|---|
| 219 | 232 | struct neigh_statistics __percpu *stats; |
|---|
| 220 | 233 | struct neigh_hash_table __rcu *nht; |
|---|
| 221 | 234 | struct pneigh_entry **phash_buckets; |
|---|
| 235 | + |
|---|
| 236 | + ANDROID_KABI_RESERVE(1); |
|---|
| 222 | 237 | }; |
|---|
| 223 | 238 | |
|---|
| 224 | 239 | enum { |
|---|
| .. | .. |
|---|
| 246 | 261 | #define NEIGH_UPDATE_F_OVERRIDE 0x00000001 |
|---|
| 247 | 262 | #define NEIGH_UPDATE_F_WEAK_OVERRIDE 0x00000002 |
|---|
| 248 | 263 | #define NEIGH_UPDATE_F_OVERRIDE_ISROUTER 0x00000004 |
|---|
| 264 | +#define NEIGH_UPDATE_F_USE 0x10000000 |
|---|
| 249 | 265 | #define NEIGH_UPDATE_F_EXT_LEARNED 0x20000000 |
|---|
| 250 | 266 | #define NEIGH_UPDATE_F_ISROUTER 0x40000000 |
|---|
| 251 | 267 | #define NEIGH_UPDATE_F_ADMIN 0x80000000 |
|---|
| 252 | 268 | |
|---|
| 253 | | - |
|---|
| 254 | | -static inline bool neigh_key_eq16(const struct neighbour *n, const void *pkey) |
|---|
| 255 | | -{ |
|---|
| 256 | | - return *(const u16 *)n->primary_key == *(const u16 *)pkey; |
|---|
| 257 | | -} |
|---|
| 269 | +extern const struct nla_policy nda_policy[]; |
|---|
| 258 | 270 | |
|---|
| 259 | 271 | static inline bool neigh_key_eq32(const struct neighbour *n, const void *pkey) |
|---|
| 260 | 272 | { |
|---|
| .. | .. |
|---|
| 305 | 317 | int neigh_table_clear(int index, struct neigh_table *tbl); |
|---|
| 306 | 318 | struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey, |
|---|
| 307 | 319 | struct net_device *dev); |
|---|
| 308 | | -struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net, |
|---|
| 309 | | - const void *pkey); |
|---|
| 310 | 320 | struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey, |
|---|
| 311 | 321 | struct net_device *dev, bool want_ref); |
|---|
| 312 | 322 | static inline struct neighbour *neigh_create(struct neigh_table *tbl, |
|---|
| .. | .. |
|---|
| 323 | 333 | bool neigh_remove_one(struct neighbour *ndel, struct neigh_table *tbl); |
|---|
| 324 | 334 | void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev); |
|---|
| 325 | 335 | int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev); |
|---|
| 336 | +int neigh_carrier_down(struct neigh_table *tbl, struct net_device *dev); |
|---|
| 326 | 337 | int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb); |
|---|
| 327 | 338 | int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb); |
|---|
| 328 | 339 | int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb); |
|---|
| .. | .. |
|---|
| 384 | 395 | void neigh_seq_stop(struct seq_file *, void *); |
|---|
| 385 | 396 | |
|---|
| 386 | 397 | int neigh_proc_dointvec(struct ctl_table *ctl, int write, |
|---|
| 387 | | - void __user *buffer, size_t *lenp, loff_t *ppos); |
|---|
| 398 | + void *buffer, size_t *lenp, loff_t *ppos); |
|---|
| 388 | 399 | int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write, |
|---|
| 389 | | - void __user *buffer, |
|---|
| 400 | + void *buffer, |
|---|
| 390 | 401 | size_t *lenp, loff_t *ppos); |
|---|
| 391 | 402 | int neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write, |
|---|
| 392 | | - void __user *buffer, |
|---|
| 393 | | - size_t *lenp, loff_t *ppos); |
|---|
| 403 | + void *buffer, size_t *lenp, loff_t *ppos); |
|---|
| 394 | 404 | |
|---|
| 395 | 405 | int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p, |
|---|
| 396 | 406 | proc_handler *proc_handler); |
|---|
| .. | .. |
|---|
| 451 | 461 | } |
|---|
| 452 | 462 | #endif |
|---|
| 453 | 463 | |
|---|
| 454 | | -static inline int neigh_hh_output(struct hh_cache *hh, struct sk_buff *skb) |
|---|
| 464 | +static inline int neigh_hh_output(const struct hh_cache *hh, struct sk_buff *skb) |
|---|
| 455 | 465 | { |
|---|
| 456 | 466 | unsigned int hh_alen = 0; |
|---|
| 457 | 467 | unsigned int seq; |
|---|
| .. | .. |
|---|
| 491 | 501 | return dev_queue_xmit(skb); |
|---|
| 492 | 502 | } |
|---|
| 493 | 503 | |
|---|
| 494 | | -static inline int neigh_output(struct neighbour *n, struct sk_buff *skb) |
|---|
| 504 | +static inline int neigh_output(struct neighbour *n, struct sk_buff *skb, |
|---|
| 505 | + bool skip_cache) |
|---|
| 495 | 506 | { |
|---|
| 496 | | - struct hh_cache *hh = &n->hh; |
|---|
| 507 | + const struct hh_cache *hh = &n->hh; |
|---|
| 497 | 508 | |
|---|
| 498 | | - if ((n->nud_state & NUD_CONNECTED) && hh->hh_len) |
|---|
| 509 | + /* n->nud_state and hh->hh_len could be changed under us. |
|---|
| 510 | + * neigh_hh_output() is taking care of the race later. |
|---|
| 511 | + */ |
|---|
| 512 | + if (!skip_cache && |
|---|
| 513 | + (READ_ONCE(n->nud_state) & NUD_CONNECTED) && |
|---|
| 514 | + READ_ONCE(hh->hh_len)) |
|---|
| 499 | 515 | return neigh_hh_output(hh, skb); |
|---|
| 500 | | - else |
|---|
| 501 | | - return n->output(n, skb); |
|---|
| 516 | + |
|---|
| 517 | + return n->output(n, skb); |
|---|
| 502 | 518 | } |
|---|
| 503 | 519 | |
|---|
| 504 | 520 | static inline struct neighbour * |
|---|
| .. | .. |
|---|
| 534 | 550 | |
|---|
| 535 | 551 | #define NEIGH_CB(skb) ((struct neighbour_cb *)(skb)->cb) |
|---|
| 536 | 552 | |
|---|
| 537 | | -static inline void neigh_ha_snapshot(char *dst, struct neighbour *n, |
|---|
| 553 | +static inline void neigh_ha_snapshot(char *dst, const struct neighbour *n, |
|---|
| 538 | 554 | const struct net_device *dev) |
|---|
| 539 | 555 | { |
|---|
| 540 | 556 | unsigned int seq; |
|---|
| .. | .. |
|---|
| 545 | 561 | } while (read_seqretry(&n->ha_lock, seq)); |
|---|
| 546 | 562 | } |
|---|
| 547 | 563 | |
|---|
| 548 | | -static inline void neigh_update_ext_learned(struct neighbour *neigh, u32 flags, |
|---|
| 549 | | - int *notify) |
|---|
| 564 | +static inline void neigh_update_is_router(struct neighbour *neigh, u32 flags, |
|---|
| 565 | + int *notify) |
|---|
| 550 | 566 | { |
|---|
| 551 | 567 | u8 ndm_flags = 0; |
|---|
| 552 | 568 | |
|---|
| 553 | | - if (!(flags & NEIGH_UPDATE_F_ADMIN)) |
|---|
| 554 | | - return; |
|---|
| 555 | | - |
|---|
| 556 | | - ndm_flags |= (flags & NEIGH_UPDATE_F_EXT_LEARNED) ? NTF_EXT_LEARNED : 0; |
|---|
| 557 | | - if ((neigh->flags ^ ndm_flags) & NTF_EXT_LEARNED) { |
|---|
| 558 | | - if (ndm_flags & NTF_EXT_LEARNED) |
|---|
| 559 | | - neigh->flags |= NTF_EXT_LEARNED; |
|---|
| 569 | + ndm_flags |= (flags & NEIGH_UPDATE_F_ISROUTER) ? NTF_ROUTER : 0; |
|---|
| 570 | + if ((neigh->flags ^ ndm_flags) & NTF_ROUTER) { |
|---|
| 571 | + if (ndm_flags & NTF_ROUTER) |
|---|
| 572 | + neigh->flags |= NTF_ROUTER; |
|---|
| 560 | 573 | else |
|---|
| 561 | | - neigh->flags &= ~NTF_EXT_LEARNED; |
|---|
| 574 | + neigh->flags &= ~NTF_ROUTER; |
|---|
| 562 | 575 | *notify = 1; |
|---|
| 563 | 576 | } |
|---|
| 564 | 577 | } |
|---|