.. | .. |
---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-or-later */ |
---|
1 | 2 | /* |
---|
2 | 3 | * INET An implementation of the TCP/IP protocol suite for the LINUX |
---|
3 | 4 | * operating system. INET is implemented using the BSD Socket |
---|
.. | .. |
---|
13 | 14 | * |
---|
14 | 15 | * Changes: |
---|
15 | 16 | * Mike McLagan : Routing by source |
---|
16 | | - * |
---|
17 | | - * This program is free software; you can redistribute it and/or |
---|
18 | | - * modify it under the terms of the GNU General Public License |
---|
19 | | - * as published by the Free Software Foundation; either version |
---|
20 | | - * 2 of the License, or (at your option) any later version. |
---|
21 | 17 | */ |
---|
22 | 18 | #ifndef _IP_H |
---|
23 | 19 | #define _IP_H |
---|
.. | .. |
---|
27 | 23 | #include <linux/in.h> |
---|
28 | 24 | #include <linux/skbuff.h> |
---|
29 | 25 | #include <linux/jhash.h> |
---|
| 26 | +#include <linux/sockptr.h> |
---|
30 | 27 | |
---|
31 | 28 | #include <net/inet_sock.h> |
---|
32 | 29 | #include <net/route.h> |
---|
.. | .. |
---|
40 | 37 | |
---|
41 | 38 | #define IPV4_MAX_PMTU 65535U /* RFC 2675, Section 5.1 */ |
---|
42 | 39 | #define IPV4_MIN_MTU 68 /* RFC 791 */ |
---|
| 40 | + |
---|
| 41 | +extern unsigned int sysctl_fib_sync_mem; |
---|
| 42 | +extern unsigned int sysctl_fib_sync_mem_min; |
---|
| 43 | +extern unsigned int sysctl_fib_sync_mem_max; |
---|
43 | 44 | |
---|
44 | 45 | struct sock; |
---|
45 | 46 | |
---|
.. | .. |
---|
56 | 57 | #define IPSKB_DOREDIRECT BIT(5) |
---|
57 | 58 | #define IPSKB_FRAG_PMTU BIT(6) |
---|
58 | 59 | #define IPSKB_L3SLAVE BIT(7) |
---|
| 60 | +#define IPSKB_MULTIPATH BIT(9) |
---|
59 | 61 | |
---|
60 | 62 | u16 frag_max_size; |
---|
61 | 63 | }; |
---|
.. | .. |
---|
75 | 77 | __be32 addr; |
---|
76 | 78 | int oif; |
---|
77 | 79 | struct ip_options_rcu *opt; |
---|
| 80 | + __u8 protocol; |
---|
78 | 81 | __u8 ttl; |
---|
79 | 82 | __s16 tos; |
---|
80 | 83 | char priority; |
---|
.. | .. |
---|
91 | 94 | { |
---|
92 | 95 | ipcm_init(ipcm); |
---|
93 | 96 | |
---|
| 97 | + ipcm->sockc.mark = inet->sk.sk_mark; |
---|
94 | 98 | ipcm->sockc.tsflags = inet->sk.sk_tsflags; |
---|
95 | 99 | ipcm->oif = inet->sk.sk_bound_dev_if; |
---|
96 | 100 | ipcm->addr = inet->inet_saddr; |
---|
| 101 | + ipcm->protocol = inet->inet_num; |
---|
97 | 102 | } |
---|
98 | 103 | |
---|
99 | 104 | #define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb)) |
---|
.. | .. |
---|
152 | 157 | |
---|
153 | 158 | int ip_build_and_send_pkt(struct sk_buff *skb, const struct sock *sk, |
---|
154 | 159 | __be32 saddr, __be32 daddr, |
---|
155 | | - struct ip_options_rcu *opt); |
---|
| 160 | + struct ip_options_rcu *opt, u8 tos); |
---|
156 | 161 | int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, |
---|
157 | 162 | struct net_device *orig_dev); |
---|
158 | 163 | void ip_list_rcv(struct list_head *head, struct packet_type *pt, |
---|
159 | 164 | struct net_device *orig_dev); |
---|
160 | 165 | int ip_local_deliver(struct sk_buff *skb); |
---|
| 166 | +void ip_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int proto); |
---|
161 | 167 | int ip_mr_input(struct sk_buff *skb); |
---|
162 | 168 | int ip_output(struct net *net, struct sock *sk, struct sk_buff *skb); |
---|
163 | 169 | int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb); |
---|
164 | 170 | int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, |
---|
165 | 171 | int (*output)(struct net *, struct sock *, struct sk_buff *)); |
---|
| 172 | + |
---|
| 173 | +struct ip_fraglist_iter { |
---|
| 174 | + struct sk_buff *frag; |
---|
| 175 | + struct iphdr *iph; |
---|
| 176 | + int offset; |
---|
| 177 | + unsigned int hlen; |
---|
| 178 | +}; |
---|
| 179 | + |
---|
| 180 | +void ip_fraglist_init(struct sk_buff *skb, struct iphdr *iph, |
---|
| 181 | + unsigned int hlen, struct ip_fraglist_iter *iter); |
---|
| 182 | +void ip_fraglist_prepare(struct sk_buff *skb, struct ip_fraglist_iter *iter); |
---|
| 183 | + |
---|
| 184 | +static inline struct sk_buff *ip_fraglist_next(struct ip_fraglist_iter *iter) |
---|
| 185 | +{ |
---|
| 186 | + struct sk_buff *skb = iter->frag; |
---|
| 187 | + |
---|
| 188 | + iter->frag = skb->next; |
---|
| 189 | + skb_mark_not_on_list(skb); |
---|
| 190 | + |
---|
| 191 | + return skb; |
---|
| 192 | +} |
---|
| 193 | + |
---|
| 194 | +struct ip_frag_state { |
---|
| 195 | + bool DF; |
---|
| 196 | + unsigned int hlen; |
---|
| 197 | + unsigned int ll_rs; |
---|
| 198 | + unsigned int mtu; |
---|
| 199 | + unsigned int left; |
---|
| 200 | + int offset; |
---|
| 201 | + int ptr; |
---|
| 202 | + __be16 not_last_frag; |
---|
| 203 | +}; |
---|
| 204 | + |
---|
| 205 | +void ip_frag_init(struct sk_buff *skb, unsigned int hlen, unsigned int ll_rs, |
---|
| 206 | + unsigned int mtu, bool DF, struct ip_frag_state *state); |
---|
| 207 | +struct sk_buff *ip_frag_next(struct sk_buff *skb, |
---|
| 208 | + struct ip_frag_state *state); |
---|
| 209 | + |
---|
166 | 210 | void ip_send_check(struct iphdr *ip); |
---|
167 | 211 | int __ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb); |
---|
168 | 212 | int ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb); |
---|
.. | .. |
---|
194 | 238 | struct ipcm_cookie *ipc, struct rtable **rtp, |
---|
195 | 239 | struct inet_cork *cork, unsigned int flags); |
---|
196 | 240 | |
---|
197 | | -static inline int ip_queue_xmit(struct sock *sk, struct sk_buff *skb, |
---|
198 | | - struct flowi *fl) |
---|
199 | | -{ |
---|
200 | | - return __ip_queue_xmit(sk, skb, fl, inet_sk(sk)->tos); |
---|
201 | | -} |
---|
| 241 | +int ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl); |
---|
202 | 242 | |
---|
203 | 243 | static inline struct sk_buff *ip_finish_skb(struct sock *sk, struct flowi4 *fl4) |
---|
204 | 244 | { |
---|
.. | .. |
---|
243 | 283 | const struct ip_options *sopt, |
---|
244 | 284 | __be32 daddr, __be32 saddr, |
---|
245 | 285 | const struct ip_reply_arg *arg, |
---|
246 | | - unsigned int len); |
---|
| 286 | + unsigned int len, u64 transmit_time); |
---|
247 | 287 | |
---|
248 | 288 | #define IP_INC_STATS(net, field) SNMP_INC_STATS64((net)->mib.ip_statistics, field) |
---|
249 | 289 | #define __IP_INC_STATS(net, field) __SNMP_INC_STATS64((net)->mib.ip_statistics, field) |
---|
.. | .. |
---|
302 | 342 | void inet_get_local_port_range(struct net *net, int *low, int *high); |
---|
303 | 343 | |
---|
304 | 344 | #ifdef CONFIG_SYSCTL |
---|
305 | | -static inline int inet_is_local_reserved_port(struct net *net, int port) |
---|
| 345 | +static inline bool inet_is_local_reserved_port(struct net *net, unsigned short port) |
---|
306 | 346 | { |
---|
307 | 347 | if (!net->ipv4.sysctl_local_reserved_ports) |
---|
308 | | - return 0; |
---|
| 348 | + return false; |
---|
309 | 349 | return test_bit(port, net->ipv4.sysctl_local_reserved_ports); |
---|
| 350 | +} |
---|
| 351 | + |
---|
| 352 | +static inline bool inet_is_local_unbindable_port(struct net *net, unsigned short port) |
---|
| 353 | +{ |
---|
| 354 | + if (!net->ipv4.sysctl_local_unbindable_ports) |
---|
| 355 | + return false; |
---|
| 356 | + return test_bit(port, net->ipv4.sysctl_local_unbindable_ports); |
---|
310 | 357 | } |
---|
311 | 358 | |
---|
312 | 359 | static inline bool sysctl_dev_name_is_allowed(const char *name) |
---|
.. | .. |
---|
314 | 361 | return strcmp(name, "default") != 0 && strcmp(name, "all") != 0; |
---|
315 | 362 | } |
---|
316 | 363 | |
---|
317 | | -static inline int inet_prot_sock(struct net *net) |
---|
| 364 | +static inline bool inet_port_requires_bind_service(struct net *net, unsigned short port) |
---|
318 | 365 | { |
---|
319 | | - return net->ipv4.sysctl_ip_prot_sock; |
---|
| 366 | + return port < READ_ONCE(net->ipv4.sysctl_ip_prot_sock); |
---|
320 | 367 | } |
---|
321 | 368 | |
---|
322 | 369 | #else |
---|
323 | | -static inline int inet_is_local_reserved_port(struct net *net, int port) |
---|
| 370 | +static inline bool inet_is_local_reserved_port(struct net *net, unsigned short port) |
---|
324 | 371 | { |
---|
325 | | - return 0; |
---|
| 372 | + return false; |
---|
326 | 373 | } |
---|
327 | 374 | |
---|
328 | | -static inline int inet_prot_sock(struct net *net) |
---|
| 375 | +static inline bool inet_is_local_unbindable_port(struct net *net, unsigned short port) |
---|
329 | 376 | { |
---|
330 | | - return PROT_SOCK; |
---|
| 377 | + return false; |
---|
| 378 | +} |
---|
| 379 | + |
---|
| 380 | +static inline bool inet_port_requires_bind_service(struct net *net, unsigned short port) |
---|
| 381 | +{ |
---|
| 382 | + return port < PROT_SOCK; |
---|
331 | 383 | } |
---|
332 | 384 | #endif |
---|
333 | 385 | |
---|
.. | .. |
---|
343 | 395 | void ip_static_sysctl_init(void); |
---|
344 | 396 | |
---|
345 | 397 | #define IP4_REPLY_MARK(net, mark) \ |
---|
346 | | - ((net)->ipv4.sysctl_fwmark_reflect ? (mark) : 0) |
---|
| 398 | + (READ_ONCE((net)->ipv4.sysctl_fwmark_reflect) ? (mark) : 0) |
---|
347 | 399 | |
---|
348 | 400 | static inline bool ip_is_fragment(const struct iphdr *iph) |
---|
349 | 401 | { |
---|
.. | .. |
---|
404 | 456 | struct net *net = dev_net(dst->dev); |
---|
405 | 457 | unsigned int mtu; |
---|
406 | 458 | |
---|
407 | | - if (net->ipv4.sysctl_ip_fwd_use_pmtu || |
---|
| 459 | + if (READ_ONCE(net->ipv4.sysctl_ip_fwd_use_pmtu) || |
---|
408 | 460 | ip_mtu_locked(dst) || |
---|
409 | 461 | !forwarding) |
---|
410 | 462 | return dst_mtu(dst); |
---|
.. | .. |
---|
432 | 484 | return mtu - lwtunnel_headroom(skb_dst(skb)->lwtstate, mtu); |
---|
433 | 485 | } |
---|
434 | 486 | |
---|
435 | | -int ip_metrics_convert(struct net *net, struct nlattr *fc_mx, int fc_mx_len, |
---|
436 | | - u32 *metrics); |
---|
| 487 | +struct dst_metrics *ip_fib_metrics_init(struct net *net, struct nlattr *fc_mx, |
---|
| 488 | + int fc_mx_len, |
---|
| 489 | + struct netlink_ext_ack *extack); |
---|
| 490 | +static inline void ip_fib_metrics_put(struct dst_metrics *fib_metrics) |
---|
| 491 | +{ |
---|
| 492 | + if (fib_metrics != &dst_default_metrics && |
---|
| 493 | + refcount_dec_and_test(&fib_metrics->refcnt)) |
---|
| 494 | + kfree(fib_metrics); |
---|
| 495 | +} |
---|
| 496 | + |
---|
| 497 | +/* ipv4 and ipv6 both use refcounted metrics if it is not the default */ |
---|
| 498 | +static inline |
---|
| 499 | +void ip_dst_init_metrics(struct dst_entry *dst, struct dst_metrics *fib_metrics) |
---|
| 500 | +{ |
---|
| 501 | + dst_init_metrics(dst, fib_metrics->metrics, true); |
---|
| 502 | + |
---|
| 503 | + if (fib_metrics != &dst_default_metrics) { |
---|
| 504 | + dst->_metrics |= DST_METRICS_REFCOUNTED; |
---|
| 505 | + refcount_inc(&fib_metrics->refcnt); |
---|
| 506 | + } |
---|
| 507 | +} |
---|
| 508 | + |
---|
| 509 | +static inline |
---|
| 510 | +void ip_dst_metrics_put(struct dst_entry *dst) |
---|
| 511 | +{ |
---|
| 512 | + struct dst_metrics *p = (struct dst_metrics *)DST_METRICS_PTR(dst); |
---|
| 513 | + |
---|
| 514 | + if (p != &dst_default_metrics && refcount_dec_and_test(&p->refcnt)) |
---|
| 515 | + kfree(p); |
---|
| 516 | +} |
---|
437 | 517 | |
---|
438 | 518 | u32 ip_idents_reserve(u32 hash, int segs); |
---|
439 | 519 | void __ip_select_ident(struct net *net, struct iphdr *iph, int segs); |
---|
.. | .. |
---|
481 | 561 | BUILD_BUG_ON(offsetof(typeof(flow->addrs), v4addrs.dst) != |
---|
482 | 562 | offsetof(typeof(flow->addrs), v4addrs.src) + |
---|
483 | 563 | sizeof(flow->addrs.v4addrs.src)); |
---|
484 | | - memcpy(&flow->addrs.v4addrs, &iph->saddr, sizeof(flow->addrs.v4addrs)); |
---|
| 564 | + memcpy(&flow->addrs.v4addrs, &iph->addrs, sizeof(flow->addrs.v4addrs)); |
---|
485 | 565 | flow->control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS; |
---|
486 | 566 | } |
---|
487 | 567 | |
---|
.. | .. |
---|
654 | 734 | int ip_options_compile(struct net *net, struct ip_options *opt, |
---|
655 | 735 | struct sk_buff *skb); |
---|
656 | 736 | int ip_options_get(struct net *net, struct ip_options_rcu **optp, |
---|
657 | | - unsigned char *data, int optlen); |
---|
658 | | -int ip_options_get_from_user(struct net *net, struct ip_options_rcu **optp, |
---|
659 | | - unsigned char __user *data, int optlen); |
---|
| 737 | + sockptr_t data, int optlen); |
---|
660 | 738 | void ip_options_undo(struct ip_options *opt); |
---|
661 | 739 | void ip_forward_options(struct sk_buff *skb); |
---|
662 | 740 | int ip_options_rcv_srr(struct sk_buff *skb, struct net_device *dev); |
---|
.. | .. |
---|
670 | 748 | struct sk_buff *skb, int tlen, int offset); |
---|
671 | 749 | int ip_cmsg_send(struct sock *sk, struct msghdr *msg, |
---|
672 | 750 | struct ipcm_cookie *ipc, bool allow_ipv6); |
---|
673 | | -int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, |
---|
| 751 | +int ip_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval, |
---|
674 | 752 | unsigned int optlen); |
---|
675 | 753 | int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, |
---|
676 | 754 | int __user *optlen); |
---|
677 | | -int compat_ip_setsockopt(struct sock *sk, int level, int optname, |
---|
678 | | - char __user *optval, unsigned int optlen); |
---|
679 | | -int compat_ip_getsockopt(struct sock *sk, int level, int optname, |
---|
680 | | - char __user *optval, int __user *optlen); |
---|
681 | 755 | int ip_ra_control(struct sock *sk, unsigned char on, |
---|
682 | 756 | void (*destructor)(struct sock *)); |
---|
683 | 757 | |
---|
.. | .. |
---|
708 | 782 | return likely(mtu >= IPV4_MIN_MTU); |
---|
709 | 783 | } |
---|
710 | 784 | |
---|
| 785 | +void ip_sock_set_freebind(struct sock *sk); |
---|
| 786 | +int ip_sock_set_mtu_discover(struct sock *sk, int val); |
---|
| 787 | +void ip_sock_set_pktinfo(struct sock *sk); |
---|
| 788 | +void ip_sock_set_recverr(struct sock *sk); |
---|
| 789 | +void ip_sock_set_tos(struct sock *sk, int val); |
---|
| 790 | + |
---|
711 | 791 | #endif /* _IP_H */ |
---|