| .. | .. |
|---|
| 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 */ |
|---|