.. | .. |
---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-or-later */ |
---|
1 | 2 | /* |
---|
2 | 3 | * Linux INET6 implementation |
---|
3 | 4 | * |
---|
4 | 5 | * Authors: |
---|
5 | 6 | * Pedro Roque <roque@di.fc.ul.pt> |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or |
---|
8 | | - * modify it under the terms of the GNU General Public License |
---|
9 | | - * as published by the Free Software Foundation; either version |
---|
10 | | - * 2 of the License, or (at your option) any later version. |
---|
11 | 7 | */ |
---|
12 | 8 | |
---|
13 | 9 | #ifndef _NET_IPV6_H |
---|
.. | .. |
---|
17 | 13 | #include <linux/hardirq.h> |
---|
18 | 14 | #include <linux/jhash.h> |
---|
19 | 15 | #include <linux/refcount.h> |
---|
| 16 | +#include <linux/jump_label_ratelimit.h> |
---|
20 | 17 | #include <net/if_inet6.h> |
---|
21 | 18 | #include <net/ndisc.h> |
---|
22 | 19 | #include <net/flow.h> |
---|
.. | .. |
---|
154 | 151 | #define IP6_MF 0x0001 |
---|
155 | 152 | #define IP6_OFFSET 0xFFF8 |
---|
156 | 153 | |
---|
| 154 | +struct ip6_fraglist_iter { |
---|
| 155 | + struct ipv6hdr *tmp_hdr; |
---|
| 156 | + struct sk_buff *frag; |
---|
| 157 | + int offset; |
---|
| 158 | + unsigned int hlen; |
---|
| 159 | + __be32 frag_id; |
---|
| 160 | + u8 nexthdr; |
---|
| 161 | +}; |
---|
| 162 | + |
---|
| 163 | +int ip6_fraglist_init(struct sk_buff *skb, unsigned int hlen, u8 *prevhdr, |
---|
| 164 | + u8 nexthdr, __be32 frag_id, |
---|
| 165 | + struct ip6_fraglist_iter *iter); |
---|
| 166 | +void ip6_fraglist_prepare(struct sk_buff *skb, struct ip6_fraglist_iter *iter); |
---|
| 167 | + |
---|
| 168 | +static inline struct sk_buff *ip6_fraglist_next(struct ip6_fraglist_iter *iter) |
---|
| 169 | +{ |
---|
| 170 | + struct sk_buff *skb = iter->frag; |
---|
| 171 | + |
---|
| 172 | + iter->frag = skb->next; |
---|
| 173 | + skb_mark_not_on_list(skb); |
---|
| 174 | + |
---|
| 175 | + return skb; |
---|
| 176 | +} |
---|
| 177 | + |
---|
| 178 | +struct ip6_frag_state { |
---|
| 179 | + u8 *prevhdr; |
---|
| 180 | + unsigned int hlen; |
---|
| 181 | + unsigned int mtu; |
---|
| 182 | + unsigned int left; |
---|
| 183 | + int offset; |
---|
| 184 | + int ptr; |
---|
| 185 | + int hroom; |
---|
| 186 | + int troom; |
---|
| 187 | + __be32 frag_id; |
---|
| 188 | + u8 nexthdr; |
---|
| 189 | +}; |
---|
| 190 | + |
---|
| 191 | +void ip6_frag_init(struct sk_buff *skb, unsigned int hlen, unsigned int mtu, |
---|
| 192 | + unsigned short needed_tailroom, int hdr_room, u8 *prevhdr, |
---|
| 193 | + u8 nexthdr, __be32 frag_id, struct ip6_frag_state *state); |
---|
| 194 | +struct sk_buff *ip6_frag_next(struct sk_buff *skb, |
---|
| 195 | + struct ip6_frag_state *state); |
---|
| 196 | + |
---|
157 | 197 | #define IP6_REPLY_MARK(net, mark) \ |
---|
158 | 198 | ((net)->ipv6.sysctl.fwmark_reflect ? (mark) : 0) |
---|
159 | 199 | |
---|
.. | .. |
---|
262 | 302 | /* Option buffer, as read by IPV6_PKTOPTIONS, starts here. */ |
---|
263 | 303 | }; |
---|
264 | 304 | |
---|
| 305 | +/* flowlabel_reflect sysctl values */ |
---|
| 306 | +enum flowlabel_reflect { |
---|
| 307 | + FLOWLABEL_REFLECT_ESTABLISHED = 1, |
---|
| 308 | + FLOWLABEL_REFLECT_TCP_RESET = 2, |
---|
| 309 | + FLOWLABEL_REFLECT_ICMPV6_ECHO_REPLIES = 4, |
---|
| 310 | +}; |
---|
| 311 | + |
---|
265 | 312 | struct ip6_flowlabel { |
---|
266 | 313 | struct ip6_flowlabel __rcu *next; |
---|
267 | 314 | __be32 label; |
---|
.. | .. |
---|
343 | 390 | kfree_rcu(opt, rcu); |
---|
344 | 391 | } |
---|
345 | 392 | |
---|
346 | | -struct ip6_flowlabel *fl6_sock_lookup(struct sock *sk, __be32 label); |
---|
| 393 | +struct ip6_flowlabel *__fl6_sock_lookup(struct sock *sk, __be32 label); |
---|
| 394 | + |
---|
| 395 | +extern struct static_key_false_deferred ipv6_flowlabel_exclusive; |
---|
| 396 | +static inline struct ip6_flowlabel *fl6_sock_lookup(struct sock *sk, |
---|
| 397 | + __be32 label) |
---|
| 398 | +{ |
---|
| 399 | + if (static_branch_unlikely(&ipv6_flowlabel_exclusive.key)) |
---|
| 400 | + return __fl6_sock_lookup(sk, label) ? : ERR_PTR(-ENOENT); |
---|
| 401 | + |
---|
| 402 | + return NULL; |
---|
| 403 | +} |
---|
| 404 | + |
---|
347 | 405 | struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions *opt_space, |
---|
348 | 406 | struct ip6_flowlabel *fl, |
---|
349 | 407 | struct ipv6_txoptions *fopt); |
---|
350 | 408 | void fl6_free_socklist(struct sock *sk); |
---|
351 | | -int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen); |
---|
| 409 | +int ipv6_flowlabel_opt(struct sock *sk, sockptr_t optval, int optlen); |
---|
352 | 410 | int ipv6_flowlabel_opt_get(struct sock *sk, struct in6_flowlabel_req *freq, |
---|
353 | 411 | int flags); |
---|
354 | 412 | int ip6_flowlabel_init(void); |
---|
.. | .. |
---|
638 | 696 | cpu_to_be32(0x0000ffff))) == 0UL; |
---|
639 | 697 | } |
---|
640 | 698 | |
---|
| 699 | +static inline bool ipv6_addr_v4mapped_loopback(const struct in6_addr *a) |
---|
| 700 | +{ |
---|
| 701 | + return ipv6_addr_v4mapped(a) && ipv4_is_loopback(a->s6_addr32[3]); |
---|
| 702 | +} |
---|
| 703 | + |
---|
641 | 704 | static inline u32 ipv6_portaddr_hash(const struct net *net, |
---|
642 | 705 | const struct in6_addr *addr6, |
---|
643 | 706 | unsigned int port) |
---|
.. | .. |
---|
776 | 839 | BUILD_BUG_ON(offsetof(typeof(flow->addrs), v6addrs.dst) != |
---|
777 | 840 | offsetof(typeof(flow->addrs), v6addrs.src) + |
---|
778 | 841 | sizeof(flow->addrs.v6addrs.src)); |
---|
779 | | - memcpy(&flow->addrs.v6addrs, &iph->saddr, sizeof(flow->addrs.v6addrs)); |
---|
| 842 | + memcpy(&flow->addrs.v6addrs, &iph->addrs, sizeof(flow->addrs.v6addrs)); |
---|
780 | 843 | flow->control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS; |
---|
781 | 844 | } |
---|
782 | 845 | |
---|
.. | .. |
---|
845 | 908 | } |
---|
846 | 909 | } |
---|
847 | 910 | #else |
---|
848 | | -static inline void ip6_set_txhash(struct sock *sk) { } |
---|
849 | 911 | static inline __be32 ip6_make_flowlabel(struct net *net, struct sk_buff *skb, |
---|
850 | 912 | __be32 flowlabel, bool autolabel, |
---|
851 | 913 | struct flowi6 *fl6) |
---|
.. | .. |
---|
923 | 985 | * upper-layer output functions |
---|
924 | 986 | */ |
---|
925 | 987 | int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6, |
---|
926 | | - __u32 mark, struct ipv6_txoptions *opt, int tclass); |
---|
| 988 | + __u32 mark, struct ipv6_txoptions *opt, int tclass, u32 priority); |
---|
927 | 989 | |
---|
928 | 990 | int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr); |
---|
929 | 991 | |
---|
.. | .. |
---|
964 | 1026 | struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6, |
---|
965 | 1027 | const struct in6_addr *final_dst, |
---|
966 | 1028 | bool connected); |
---|
| 1029 | +struct dst_entry *ip6_dst_lookup_tunnel(struct sk_buff *skb, |
---|
| 1030 | + struct net_device *dev, |
---|
| 1031 | + struct net *net, struct socket *sock, |
---|
| 1032 | + struct in6_addr *saddr, |
---|
| 1033 | + const struct ip_tunnel_info *info, |
---|
| 1034 | + u8 protocol, bool use_cache); |
---|
967 | 1035 | struct dst_entry *ip6_blackhole_route(struct net *net, |
---|
968 | 1036 | struct dst_entry *orig_dst); |
---|
969 | 1037 | |
---|
.. | .. |
---|
975 | 1043 | int ip6_forward(struct sk_buff *skb); |
---|
976 | 1044 | int ip6_input(struct sk_buff *skb); |
---|
977 | 1045 | int ip6_mc_input(struct sk_buff *skb); |
---|
| 1046 | +void ip6_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int nexthdr, |
---|
| 1047 | + bool have_final); |
---|
978 | 1048 | |
---|
979 | 1049 | int __ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb); |
---|
980 | 1050 | int ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb); |
---|
.. | .. |
---|
1014 | 1084 | * socket options (ipv6_sockglue.c) |
---|
1015 | 1085 | */ |
---|
1016 | 1086 | |
---|
1017 | | -int ipv6_setsockopt(struct sock *sk, int level, int optname, |
---|
1018 | | - char __user *optval, unsigned int optlen); |
---|
| 1087 | +int ipv6_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval, |
---|
| 1088 | + unsigned int optlen); |
---|
1019 | 1089 | int ipv6_getsockopt(struct sock *sk, int level, int optname, |
---|
1020 | 1090 | char __user *optval, int __user *optlen); |
---|
1021 | | -int compat_ipv6_setsockopt(struct sock *sk, int level, int optname, |
---|
1022 | | - char __user *optval, unsigned int optlen); |
---|
1023 | | -int compat_ipv6_getsockopt(struct sock *sk, int level, int optname, |
---|
1024 | | - char __user *optval, int __user *optlen); |
---|
1025 | 1091 | |
---|
1026 | 1092 | int __ip6_datagram_connect(struct sock *sk, struct sockaddr *addr, |
---|
1027 | 1093 | int addr_len); |
---|
.. | .. |
---|
1045 | 1111 | int inet6_getname(struct socket *sock, struct sockaddr *uaddr, |
---|
1046 | 1112 | int peer); |
---|
1047 | 1113 | int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg); |
---|
| 1114 | +int inet6_compat_ioctl(struct socket *sock, unsigned int cmd, |
---|
| 1115 | + unsigned long arg); |
---|
1048 | 1116 | |
---|
1049 | 1117 | int inet6_hash_connect(struct inet_timewait_death_row *death_row, |
---|
1050 | 1118 | struct sock *sk); |
---|
| 1119 | +int inet6_sendmsg(struct socket *sock, struct msghdr *msg, size_t size); |
---|
| 1120 | +int inet6_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, |
---|
| 1121 | + int flags); |
---|
1051 | 1122 | |
---|
1052 | 1123 | /* |
---|
1053 | 1124 | * reassembly.c |
---|
.. | .. |
---|
1061 | 1132 | |
---|
1062 | 1133 | int ip6_mc_source(int add, int omode, struct sock *sk, |
---|
1063 | 1134 | struct group_source_req *pgsr); |
---|
1064 | | -int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf); |
---|
| 1135 | +int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf, |
---|
| 1136 | + struct sockaddr_storage *list); |
---|
1065 | 1137 | int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf, |
---|
1066 | | - struct group_filter __user *optval, int __user *optlen); |
---|
| 1138 | + struct sockaddr_storage __user *p); |
---|
1067 | 1139 | |
---|
1068 | 1140 | #ifdef CONFIG_PROC_FS |
---|
1069 | 1141 | int ac6_proc_init(struct net *net); |
---|
.. | .. |
---|
1089 | 1161 | #endif |
---|
1090 | 1162 | |
---|
1091 | 1163 | #ifdef CONFIG_SYSCTL |
---|
1092 | | -extern struct ctl_table ipv6_route_table_template[]; |
---|
1093 | | - |
---|
1094 | 1164 | struct ctl_table *ipv6_icmp_sysctl_init(struct net *net); |
---|
1095 | 1165 | struct ctl_table *ipv6_route_sysctl_init(struct net *net); |
---|
1096 | 1166 | int ipv6_sysctl_register(void); |
---|
.. | .. |
---|
1103 | 1173 | const struct in6_addr *addr, unsigned int mode); |
---|
1104 | 1174 | int ipv6_sock_mc_drop(struct sock *sk, int ifindex, |
---|
1105 | 1175 | const struct in6_addr *addr); |
---|
| 1176 | + |
---|
| 1177 | +static inline int ip6_sock_set_v6only(struct sock *sk) |
---|
| 1178 | +{ |
---|
| 1179 | + if (inet_sk(sk)->inet_num) |
---|
| 1180 | + return -EINVAL; |
---|
| 1181 | + lock_sock(sk); |
---|
| 1182 | + sk->sk_ipv6only = true; |
---|
| 1183 | + release_sock(sk); |
---|
| 1184 | + return 0; |
---|
| 1185 | +} |
---|
| 1186 | + |
---|
| 1187 | +static inline void ip6_sock_set_recverr(struct sock *sk) |
---|
| 1188 | +{ |
---|
| 1189 | + lock_sock(sk); |
---|
| 1190 | + inet6_sk(sk)->recverr = true; |
---|
| 1191 | + release_sock(sk); |
---|
| 1192 | +} |
---|
| 1193 | + |
---|
| 1194 | +static inline int __ip6_sock_set_addr_preferences(struct sock *sk, int val) |
---|
| 1195 | +{ |
---|
| 1196 | + unsigned int pref = 0; |
---|
| 1197 | + unsigned int prefmask = ~0; |
---|
| 1198 | + |
---|
| 1199 | + /* check PUBLIC/TMP/PUBTMP_DEFAULT conflicts */ |
---|
| 1200 | + switch (val & (IPV6_PREFER_SRC_PUBLIC | |
---|
| 1201 | + IPV6_PREFER_SRC_TMP | |
---|
| 1202 | + IPV6_PREFER_SRC_PUBTMP_DEFAULT)) { |
---|
| 1203 | + case IPV6_PREFER_SRC_PUBLIC: |
---|
| 1204 | + pref |= IPV6_PREFER_SRC_PUBLIC; |
---|
| 1205 | + prefmask &= ~(IPV6_PREFER_SRC_PUBLIC | |
---|
| 1206 | + IPV6_PREFER_SRC_TMP); |
---|
| 1207 | + break; |
---|
| 1208 | + case IPV6_PREFER_SRC_TMP: |
---|
| 1209 | + pref |= IPV6_PREFER_SRC_TMP; |
---|
| 1210 | + prefmask &= ~(IPV6_PREFER_SRC_PUBLIC | |
---|
| 1211 | + IPV6_PREFER_SRC_TMP); |
---|
| 1212 | + break; |
---|
| 1213 | + case IPV6_PREFER_SRC_PUBTMP_DEFAULT: |
---|
| 1214 | + prefmask &= ~(IPV6_PREFER_SRC_PUBLIC | |
---|
| 1215 | + IPV6_PREFER_SRC_TMP); |
---|
| 1216 | + break; |
---|
| 1217 | + case 0: |
---|
| 1218 | + break; |
---|
| 1219 | + default: |
---|
| 1220 | + return -EINVAL; |
---|
| 1221 | + } |
---|
| 1222 | + |
---|
| 1223 | + /* check HOME/COA conflicts */ |
---|
| 1224 | + switch (val & (IPV6_PREFER_SRC_HOME | IPV6_PREFER_SRC_COA)) { |
---|
| 1225 | + case IPV6_PREFER_SRC_HOME: |
---|
| 1226 | + prefmask &= ~IPV6_PREFER_SRC_COA; |
---|
| 1227 | + break; |
---|
| 1228 | + case IPV6_PREFER_SRC_COA: |
---|
| 1229 | + pref |= IPV6_PREFER_SRC_COA; |
---|
| 1230 | + break; |
---|
| 1231 | + case 0: |
---|
| 1232 | + break; |
---|
| 1233 | + default: |
---|
| 1234 | + return -EINVAL; |
---|
| 1235 | + } |
---|
| 1236 | + |
---|
| 1237 | + /* check CGA/NONCGA conflicts */ |
---|
| 1238 | + switch (val & (IPV6_PREFER_SRC_CGA|IPV6_PREFER_SRC_NONCGA)) { |
---|
| 1239 | + case IPV6_PREFER_SRC_CGA: |
---|
| 1240 | + case IPV6_PREFER_SRC_NONCGA: |
---|
| 1241 | + case 0: |
---|
| 1242 | + break; |
---|
| 1243 | + default: |
---|
| 1244 | + return -EINVAL; |
---|
| 1245 | + } |
---|
| 1246 | + |
---|
| 1247 | + inet6_sk(sk)->srcprefs = (inet6_sk(sk)->srcprefs & prefmask) | pref; |
---|
| 1248 | + return 0; |
---|
| 1249 | +} |
---|
| 1250 | + |
---|
| 1251 | +static inline int ip6_sock_set_addr_preferences(struct sock *sk, bool val) |
---|
| 1252 | +{ |
---|
| 1253 | + int ret; |
---|
| 1254 | + |
---|
| 1255 | + lock_sock(sk); |
---|
| 1256 | + ret = __ip6_sock_set_addr_preferences(sk, val); |
---|
| 1257 | + release_sock(sk); |
---|
| 1258 | + return ret; |
---|
| 1259 | +} |
---|
| 1260 | + |
---|
| 1261 | +static inline void ip6_sock_set_recvpktinfo(struct sock *sk) |
---|
| 1262 | +{ |
---|
| 1263 | + lock_sock(sk); |
---|
| 1264 | + inet6_sk(sk)->rxopt.bits.rxinfo = true; |
---|
| 1265 | + release_sock(sk); |
---|
| 1266 | +} |
---|
| 1267 | + |
---|
1106 | 1268 | #endif /* _NET_IPV6_H */ |
---|