.. | .. |
---|
| 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 | |
---|
.. | .. |
---|
91 | 92 | { |
---|
92 | 93 | ipcm_init(ipcm); |
---|
93 | 94 | |
---|
| 95 | + ipcm->sockc.mark = inet->sk.sk_mark; |
---|
94 | 96 | ipcm->sockc.tsflags = inet->sk.sk_tsflags; |
---|
95 | 97 | ipcm->oif = inet->sk.sk_bound_dev_if; |
---|
96 | 98 | ipcm->addr = inet->inet_saddr; |
---|
.. | .. |
---|
152 | 154 | |
---|
153 | 155 | int ip_build_and_send_pkt(struct sk_buff *skb, const struct sock *sk, |
---|
154 | 156 | __be32 saddr, __be32 daddr, |
---|
155 | | - struct ip_options_rcu *opt); |
---|
| 157 | + struct ip_options_rcu *opt, u8 tos); |
---|
156 | 158 | int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, |
---|
157 | 159 | struct net_device *orig_dev); |
---|
158 | 160 | void ip_list_rcv(struct list_head *head, struct packet_type *pt, |
---|
159 | 161 | struct net_device *orig_dev); |
---|
160 | 162 | int ip_local_deliver(struct sk_buff *skb); |
---|
| 163 | +void ip_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int proto); |
---|
161 | 164 | int ip_mr_input(struct sk_buff *skb); |
---|
162 | 165 | int ip_output(struct net *net, struct sock *sk, struct sk_buff *skb); |
---|
163 | 166 | int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb); |
---|
164 | 167 | int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, |
---|
165 | 168 | int (*output)(struct net *, struct sock *, struct sk_buff *)); |
---|
| 169 | + |
---|
| 170 | +struct ip_fraglist_iter { |
---|
| 171 | + struct sk_buff *frag; |
---|
| 172 | + struct iphdr *iph; |
---|
| 173 | + int offset; |
---|
| 174 | + unsigned int hlen; |
---|
| 175 | +}; |
---|
| 176 | + |
---|
| 177 | +void ip_fraglist_init(struct sk_buff *skb, struct iphdr *iph, |
---|
| 178 | + unsigned int hlen, struct ip_fraglist_iter *iter); |
---|
| 179 | +void ip_fraglist_prepare(struct sk_buff *skb, struct ip_fraglist_iter *iter); |
---|
| 180 | + |
---|
| 181 | +static inline struct sk_buff *ip_fraglist_next(struct ip_fraglist_iter *iter) |
---|
| 182 | +{ |
---|
| 183 | + struct sk_buff *skb = iter->frag; |
---|
| 184 | + |
---|
| 185 | + iter->frag = skb->next; |
---|
| 186 | + skb_mark_not_on_list(skb); |
---|
| 187 | + |
---|
| 188 | + return skb; |
---|
| 189 | +} |
---|
| 190 | + |
---|
| 191 | +struct ip_frag_state { |
---|
| 192 | + bool DF; |
---|
| 193 | + unsigned int hlen; |
---|
| 194 | + unsigned int ll_rs; |
---|
| 195 | + unsigned int mtu; |
---|
| 196 | + unsigned int left; |
---|
| 197 | + int offset; |
---|
| 198 | + int ptr; |
---|
| 199 | + __be16 not_last_frag; |
---|
| 200 | +}; |
---|
| 201 | + |
---|
| 202 | +void ip_frag_init(struct sk_buff *skb, unsigned int hlen, unsigned int ll_rs, |
---|
| 203 | + unsigned int mtu, bool DF, struct ip_frag_state *state); |
---|
| 204 | +struct sk_buff *ip_frag_next(struct sk_buff *skb, |
---|
| 205 | + struct ip_frag_state *state); |
---|
| 206 | + |
---|
166 | 207 | void ip_send_check(struct iphdr *ip); |
---|
167 | 208 | int __ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb); |
---|
168 | 209 | int ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb); |
---|
.. | .. |
---|
194 | 235 | struct ipcm_cookie *ipc, struct rtable **rtp, |
---|
195 | 236 | struct inet_cork *cork, unsigned int flags); |
---|
196 | 237 | |
---|
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 | | -} |
---|
| 238 | +int ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl); |
---|
202 | 239 | |
---|
203 | 240 | static inline struct sk_buff *ip_finish_skb(struct sock *sk, struct flowi4 *fl4) |
---|
204 | 241 | { |
---|
.. | .. |
---|
243 | 280 | const struct ip_options *sopt, |
---|
244 | 281 | __be32 daddr, __be32 saddr, |
---|
245 | 282 | const struct ip_reply_arg *arg, |
---|
246 | | - unsigned int len); |
---|
| 283 | + unsigned int len, u64 transmit_time); |
---|
247 | 284 | |
---|
248 | 285 | #define IP_INC_STATS(net, field) SNMP_INC_STATS64((net)->mib.ip_statistics, field) |
---|
249 | 286 | #define __IP_INC_STATS(net, field) __SNMP_INC_STATS64((net)->mib.ip_statistics, field) |
---|
.. | .. |
---|
302 | 339 | void inet_get_local_port_range(struct net *net, int *low, int *high); |
---|
303 | 340 | |
---|
304 | 341 | #ifdef CONFIG_SYSCTL |
---|
305 | | -static inline int inet_is_local_reserved_port(struct net *net, int port) |
---|
| 342 | +static inline bool inet_is_local_reserved_port(struct net *net, unsigned short port) |
---|
306 | 343 | { |
---|
307 | 344 | if (!net->ipv4.sysctl_local_reserved_ports) |
---|
308 | | - return 0; |
---|
| 345 | + return false; |
---|
309 | 346 | return test_bit(port, net->ipv4.sysctl_local_reserved_ports); |
---|
| 347 | +} |
---|
| 348 | + |
---|
| 349 | +static inline bool inet_is_local_unbindable_port(struct net *net, unsigned short port) |
---|
| 350 | +{ |
---|
| 351 | + if (!net->ipv4.sysctl_local_unbindable_ports) |
---|
| 352 | + return false; |
---|
| 353 | + return test_bit(port, net->ipv4.sysctl_local_unbindable_ports); |
---|
310 | 354 | } |
---|
311 | 355 | |
---|
312 | 356 | static inline bool sysctl_dev_name_is_allowed(const char *name) |
---|
.. | .. |
---|
314 | 358 | return strcmp(name, "default") != 0 && strcmp(name, "all") != 0; |
---|
315 | 359 | } |
---|
316 | 360 | |
---|
317 | | -static inline int inet_prot_sock(struct net *net) |
---|
| 361 | +static inline bool inet_port_requires_bind_service(struct net *net, unsigned short port) |
---|
318 | 362 | { |
---|
319 | | - return net->ipv4.sysctl_ip_prot_sock; |
---|
| 363 | + return port < READ_ONCE(net->ipv4.sysctl_ip_prot_sock); |
---|
320 | 364 | } |
---|
321 | 365 | |
---|
322 | 366 | #else |
---|
323 | | -static inline int inet_is_local_reserved_port(struct net *net, int port) |
---|
| 367 | +static inline bool inet_is_local_reserved_port(struct net *net, unsigned short port) |
---|
324 | 368 | { |
---|
325 | | - return 0; |
---|
| 369 | + return false; |
---|
326 | 370 | } |
---|
327 | 371 | |
---|
328 | | -static inline int inet_prot_sock(struct net *net) |
---|
| 372 | +static inline bool inet_is_local_unbindable_port(struct net *net, unsigned short port) |
---|
329 | 373 | { |
---|
330 | | - return PROT_SOCK; |
---|
| 374 | + return false; |
---|
| 375 | +} |
---|
| 376 | + |
---|
| 377 | +static inline bool inet_port_requires_bind_service(struct net *net, unsigned short port) |
---|
| 378 | +{ |
---|
| 379 | + return port < PROT_SOCK; |
---|
331 | 380 | } |
---|
332 | 381 | #endif |
---|
333 | 382 | |
---|
.. | .. |
---|
343 | 392 | void ip_static_sysctl_init(void); |
---|
344 | 393 | |
---|
345 | 394 | #define IP4_REPLY_MARK(net, mark) \ |
---|
346 | | - ((net)->ipv4.sysctl_fwmark_reflect ? (mark) : 0) |
---|
| 395 | + (READ_ONCE((net)->ipv4.sysctl_fwmark_reflect) ? (mark) : 0) |
---|
347 | 396 | |
---|
348 | 397 | static inline bool ip_is_fragment(const struct iphdr *iph) |
---|
349 | 398 | { |
---|
.. | .. |
---|
404 | 453 | struct net *net = dev_net(dst->dev); |
---|
405 | 454 | unsigned int mtu; |
---|
406 | 455 | |
---|
407 | | - if (net->ipv4.sysctl_ip_fwd_use_pmtu || |
---|
| 456 | + if (READ_ONCE(net->ipv4.sysctl_ip_fwd_use_pmtu) || |
---|
408 | 457 | ip_mtu_locked(dst) || |
---|
409 | 458 | !forwarding) |
---|
410 | 459 | return dst_mtu(dst); |
---|
.. | .. |
---|
432 | 481 | return mtu - lwtunnel_headroom(skb_dst(skb)->lwtstate, mtu); |
---|
433 | 482 | } |
---|
434 | 483 | |
---|
435 | | -int ip_metrics_convert(struct net *net, struct nlattr *fc_mx, int fc_mx_len, |
---|
436 | | - u32 *metrics); |
---|
| 484 | +struct dst_metrics *ip_fib_metrics_init(struct net *net, struct nlattr *fc_mx, |
---|
| 485 | + int fc_mx_len, |
---|
| 486 | + struct netlink_ext_ack *extack); |
---|
| 487 | +static inline void ip_fib_metrics_put(struct dst_metrics *fib_metrics) |
---|
| 488 | +{ |
---|
| 489 | + if (fib_metrics != &dst_default_metrics && |
---|
| 490 | + refcount_dec_and_test(&fib_metrics->refcnt)) |
---|
| 491 | + kfree(fib_metrics); |
---|
| 492 | +} |
---|
| 493 | + |
---|
| 494 | +/* ipv4 and ipv6 both use refcounted metrics if it is not the default */ |
---|
| 495 | +static inline |
---|
| 496 | +void ip_dst_init_metrics(struct dst_entry *dst, struct dst_metrics *fib_metrics) |
---|
| 497 | +{ |
---|
| 498 | + dst_init_metrics(dst, fib_metrics->metrics, true); |
---|
| 499 | + |
---|
| 500 | + if (fib_metrics != &dst_default_metrics) { |
---|
| 501 | + dst->_metrics |= DST_METRICS_REFCOUNTED; |
---|
| 502 | + refcount_inc(&fib_metrics->refcnt); |
---|
| 503 | + } |
---|
| 504 | +} |
---|
| 505 | + |
---|
| 506 | +static inline |
---|
| 507 | +void ip_dst_metrics_put(struct dst_entry *dst) |
---|
| 508 | +{ |
---|
| 509 | + struct dst_metrics *p = (struct dst_metrics *)DST_METRICS_PTR(dst); |
---|
| 510 | + |
---|
| 511 | + if (p != &dst_default_metrics && refcount_dec_and_test(&p->refcnt)) |
---|
| 512 | + kfree(p); |
---|
| 513 | +} |
---|
437 | 514 | |
---|
438 | 515 | u32 ip_idents_reserve(u32 hash, int segs); |
---|
439 | 516 | void __ip_select_ident(struct net *net, struct iphdr *iph, int segs); |
---|
.. | .. |
---|
481 | 558 | BUILD_BUG_ON(offsetof(typeof(flow->addrs), v4addrs.dst) != |
---|
482 | 559 | offsetof(typeof(flow->addrs), v4addrs.src) + |
---|
483 | 560 | sizeof(flow->addrs.v4addrs.src)); |
---|
484 | | - memcpy(&flow->addrs.v4addrs, &iph->saddr, sizeof(flow->addrs.v4addrs)); |
---|
| 561 | + memcpy(&flow->addrs.v4addrs, &iph->addrs, sizeof(flow->addrs.v4addrs)); |
---|
485 | 562 | flow->control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS; |
---|
486 | 563 | } |
---|
487 | 564 | |
---|
.. | .. |
---|
654 | 731 | int ip_options_compile(struct net *net, struct ip_options *opt, |
---|
655 | 732 | struct sk_buff *skb); |
---|
656 | 733 | 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); |
---|
| 734 | + sockptr_t data, int optlen); |
---|
660 | 735 | void ip_options_undo(struct ip_options *opt); |
---|
661 | 736 | void ip_forward_options(struct sk_buff *skb); |
---|
662 | 737 | int ip_options_rcv_srr(struct sk_buff *skb, struct net_device *dev); |
---|
.. | .. |
---|
670 | 745 | struct sk_buff *skb, int tlen, int offset); |
---|
671 | 746 | int ip_cmsg_send(struct sock *sk, struct msghdr *msg, |
---|
672 | 747 | struct ipcm_cookie *ipc, bool allow_ipv6); |
---|
673 | | -int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, |
---|
| 748 | +int ip_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval, |
---|
674 | 749 | unsigned int optlen); |
---|
675 | 750 | int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, |
---|
676 | 751 | 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 | 752 | int ip_ra_control(struct sock *sk, unsigned char on, |
---|
682 | 753 | void (*destructor)(struct sock *)); |
---|
683 | 754 | |
---|
.. | .. |
---|
708 | 779 | return likely(mtu >= IPV4_MIN_MTU); |
---|
709 | 780 | } |
---|
710 | 781 | |
---|
| 782 | +void ip_sock_set_freebind(struct sock *sk); |
---|
| 783 | +int ip_sock_set_mtu_discover(struct sock *sk, int val); |
---|
| 784 | +void ip_sock_set_pktinfo(struct sock *sk); |
---|
| 785 | +void ip_sock_set_recverr(struct sock *sk); |
---|
| 786 | +void ip_sock_set_tos(struct sock *sk, int val); |
---|
| 787 | + |
---|
711 | 788 | #endif /* _IP_H */ |
---|