diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /net/ipv4/af_inet.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'net/ipv4/af_inet.c')
-rw-r--r-- | net/ipv4/af_inet.c | 133 |
1 files changed, 83 insertions, 50 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 6a1100c25a9f..ef1528af7abf 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
@@ -105,6 +105,7 @@ | |||
105 | #include <net/tcp.h> | 105 | #include <net/tcp.h> |
106 | #include <net/udp.h> | 106 | #include <net/udp.h> |
107 | #include <net/udplite.h> | 107 | #include <net/udplite.h> |
108 | #include <net/ping.h> | ||
108 | #include <linux/skbuff.h> | 109 | #include <linux/skbuff.h> |
109 | #include <net/sock.h> | 110 | #include <net/sock.h> |
110 | #include <net/raw.h> | 111 | #include <net/raw.h> |
@@ -153,7 +154,7 @@ void inet_sock_destruct(struct sock *sk) | |||
153 | WARN_ON(sk->sk_wmem_queued); | 154 | WARN_ON(sk->sk_wmem_queued); |
154 | WARN_ON(sk->sk_forward_alloc); | 155 | WARN_ON(sk->sk_forward_alloc); |
155 | 156 | ||
156 | kfree(inet->opt); | 157 | kfree(rcu_dereference_protected(inet->inet_opt, 1)); |
157 | dst_release(rcu_dereference_check(sk->sk_dst_cache, 1)); | 158 | dst_release(rcu_dereference_check(sk->sk_dst_cache, 1)); |
158 | sk_refcnt_debug_dec(sk); | 159 | sk_refcnt_debug_dec(sk); |
159 | } | 160 | } |
@@ -227,18 +228,16 @@ EXPORT_SYMBOL(inet_ehash_secret); | |||
227 | 228 | ||
228 | /* | 229 | /* |
229 | * inet_ehash_secret must be set exactly once | 230 | * inet_ehash_secret must be set exactly once |
230 | * Instead of using a dedicated spinlock, we (ab)use inetsw_lock | ||
231 | */ | 231 | */ |
232 | void build_ehash_secret(void) | 232 | void build_ehash_secret(void) |
233 | { | 233 | { |
234 | u32 rnd; | 234 | u32 rnd; |
235 | |||
235 | do { | 236 | do { |
236 | get_random_bytes(&rnd, sizeof(rnd)); | 237 | get_random_bytes(&rnd, sizeof(rnd)); |
237 | } while (rnd == 0); | 238 | } while (rnd == 0); |
238 | spin_lock_bh(&inetsw_lock); | 239 | |
239 | if (!inet_ehash_secret) | 240 | cmpxchg(&inet_ehash_secret, 0, rnd); |
240 | inet_ehash_secret = rnd; | ||
241 | spin_unlock_bh(&inetsw_lock); | ||
242 | } | 241 | } |
243 | EXPORT_SYMBOL(build_ehash_secret); | 242 | EXPORT_SYMBOL(build_ehash_secret); |
244 | 243 | ||
@@ -466,6 +465,11 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
466 | if (addr_len < sizeof(struct sockaddr_in)) | 465 | if (addr_len < sizeof(struct sockaddr_in)) |
467 | goto out; | 466 | goto out; |
468 | 467 | ||
468 | if (addr->sin_family != AF_INET) { | ||
469 | err = -EAFNOSUPPORT; | ||
470 | goto out; | ||
471 | } | ||
472 | |||
469 | chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr); | 473 | chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr); |
470 | 474 | ||
471 | /* Not specified by any standard per-se, however it breaks too | 475 | /* Not specified by any standard per-se, however it breaks too |
@@ -674,6 +678,7 @@ int inet_accept(struct socket *sock, struct socket *newsock, int flags) | |||
674 | 678 | ||
675 | lock_sock(sk2); | 679 | lock_sock(sk2); |
676 | 680 | ||
681 | sock_rps_record_flow(sk2); | ||
677 | WARN_ON(!((1 << sk2->sk_state) & | 682 | WARN_ON(!((1 << sk2->sk_state) & |
678 | (TCPF_ESTABLISHED | TCPF_CLOSE_WAIT | TCPF_CLOSE))); | 683 | (TCPF_ESTABLISHED | TCPF_CLOSE_WAIT | TCPF_CLOSE))); |
679 | 684 | ||
@@ -882,6 +887,19 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
882 | } | 887 | } |
883 | EXPORT_SYMBOL(inet_ioctl); | 888 | EXPORT_SYMBOL(inet_ioctl); |
884 | 889 | ||
890 | #ifdef CONFIG_COMPAT | ||
891 | int inet_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | ||
892 | { | ||
893 | struct sock *sk = sock->sk; | ||
894 | int err = -ENOIOCTLCMD; | ||
895 | |||
896 | if (sk->sk_prot->compat_ioctl) | ||
897 | err = sk->sk_prot->compat_ioctl(sk, cmd, arg); | ||
898 | |||
899 | return err; | ||
900 | } | ||
901 | #endif | ||
902 | |||
885 | const struct proto_ops inet_stream_ops = { | 903 | const struct proto_ops inet_stream_ops = { |
886 | .family = PF_INET, | 904 | .family = PF_INET, |
887 | .owner = THIS_MODULE, | 905 | .owner = THIS_MODULE, |
@@ -905,6 +923,7 @@ const struct proto_ops inet_stream_ops = { | |||
905 | #ifdef CONFIG_COMPAT | 923 | #ifdef CONFIG_COMPAT |
906 | .compat_setsockopt = compat_sock_common_setsockopt, | 924 | .compat_setsockopt = compat_sock_common_setsockopt, |
907 | .compat_getsockopt = compat_sock_common_getsockopt, | 925 | .compat_getsockopt = compat_sock_common_getsockopt, |
926 | .compat_ioctl = inet_compat_ioctl, | ||
908 | #endif | 927 | #endif |
909 | }; | 928 | }; |
910 | EXPORT_SYMBOL(inet_stream_ops); | 929 | EXPORT_SYMBOL(inet_stream_ops); |
@@ -931,6 +950,7 @@ const struct proto_ops inet_dgram_ops = { | |||
931 | #ifdef CONFIG_COMPAT | 950 | #ifdef CONFIG_COMPAT |
932 | .compat_setsockopt = compat_sock_common_setsockopt, | 951 | .compat_setsockopt = compat_sock_common_setsockopt, |
933 | .compat_getsockopt = compat_sock_common_getsockopt, | 952 | .compat_getsockopt = compat_sock_common_getsockopt, |
953 | .compat_ioctl = inet_compat_ioctl, | ||
934 | #endif | 954 | #endif |
935 | }; | 955 | }; |
936 | EXPORT_SYMBOL(inet_dgram_ops); | 956 | EXPORT_SYMBOL(inet_dgram_ops); |
@@ -961,6 +981,7 @@ static const struct proto_ops inet_sockraw_ops = { | |||
961 | #ifdef CONFIG_COMPAT | 981 | #ifdef CONFIG_COMPAT |
962 | .compat_setsockopt = compat_sock_common_setsockopt, | 982 | .compat_setsockopt = compat_sock_common_setsockopt, |
963 | .compat_getsockopt = compat_sock_common_getsockopt, | 983 | .compat_getsockopt = compat_sock_common_getsockopt, |
984 | .compat_ioctl = inet_compat_ioctl, | ||
964 | #endif | 985 | #endif |
965 | }; | 986 | }; |
966 | 987 | ||
@@ -994,6 +1015,14 @@ static struct inet_protosw inetsw_array[] = | |||
994 | .flags = INET_PROTOSW_PERMANENT, | 1015 | .flags = INET_PROTOSW_PERMANENT, |
995 | }, | 1016 | }, |
996 | 1017 | ||
1018 | { | ||
1019 | .type = SOCK_DGRAM, | ||
1020 | .protocol = IPPROTO_ICMP, | ||
1021 | .prot = &ping_prot, | ||
1022 | .ops = &inet_dgram_ops, | ||
1023 | .no_check = UDP_CSUM_DEFAULT, | ||
1024 | .flags = INET_PROTOSW_REUSE, | ||
1025 | }, | ||
997 | 1026 | ||
998 | { | 1027 | { |
999 | .type = SOCK_RAW, | 1028 | .type = SOCK_RAW, |
@@ -1087,27 +1116,29 @@ int sysctl_ip_dynaddr __read_mostly; | |||
1087 | static int inet_sk_reselect_saddr(struct sock *sk) | 1116 | static int inet_sk_reselect_saddr(struct sock *sk) |
1088 | { | 1117 | { |
1089 | struct inet_sock *inet = inet_sk(sk); | 1118 | struct inet_sock *inet = inet_sk(sk); |
1090 | int err; | ||
1091 | struct rtable *rt; | ||
1092 | __be32 old_saddr = inet->inet_saddr; | 1119 | __be32 old_saddr = inet->inet_saddr; |
1093 | __be32 new_saddr; | ||
1094 | __be32 daddr = inet->inet_daddr; | 1120 | __be32 daddr = inet->inet_daddr; |
1121 | struct flowi4 *fl4; | ||
1122 | struct rtable *rt; | ||
1123 | __be32 new_saddr; | ||
1124 | struct ip_options_rcu *inet_opt; | ||
1095 | 1125 | ||
1096 | if (inet->opt && inet->opt->srr) | 1126 | inet_opt = rcu_dereference_protected(inet->inet_opt, |
1097 | daddr = inet->opt->faddr; | 1127 | sock_owned_by_user(sk)); |
1128 | if (inet_opt && inet_opt->opt.srr) | ||
1129 | daddr = inet_opt->opt.faddr; | ||
1098 | 1130 | ||
1099 | /* Query new route. */ | 1131 | /* Query new route. */ |
1100 | err = ip_route_connect(&rt, daddr, 0, | 1132 | fl4 = &inet->cork.fl.u.ip4; |
1101 | RT_CONN_FLAGS(sk), | 1133 | rt = ip_route_connect(fl4, daddr, 0, RT_CONN_FLAGS(sk), |
1102 | sk->sk_bound_dev_if, | 1134 | sk->sk_bound_dev_if, sk->sk_protocol, |
1103 | sk->sk_protocol, | 1135 | inet->inet_sport, inet->inet_dport, sk, false); |
1104 | inet->inet_sport, inet->inet_dport, sk, 0); | 1136 | if (IS_ERR(rt)) |
1105 | if (err) | 1137 | return PTR_ERR(rt); |
1106 | return err; | ||
1107 | 1138 | ||
1108 | sk_setup_caps(sk, &rt->dst); | 1139 | sk_setup_caps(sk, &rt->dst); |
1109 | 1140 | ||
1110 | new_saddr = rt->rt_src; | 1141 | new_saddr = fl4->saddr; |
1111 | 1142 | ||
1112 | if (new_saddr == old_saddr) | 1143 | if (new_saddr == old_saddr) |
1113 | return 0; | 1144 | return 0; |
@@ -1136,6 +1167,8 @@ int inet_sk_rebuild_header(struct sock *sk) | |||
1136 | struct inet_sock *inet = inet_sk(sk); | 1167 | struct inet_sock *inet = inet_sk(sk); |
1137 | struct rtable *rt = (struct rtable *)__sk_dst_check(sk, 0); | 1168 | struct rtable *rt = (struct rtable *)__sk_dst_check(sk, 0); |
1138 | __be32 daddr; | 1169 | __be32 daddr; |
1170 | struct ip_options_rcu *inet_opt; | ||
1171 | struct flowi4 *fl4; | ||
1139 | int err; | 1172 | int err; |
1140 | 1173 | ||
1141 | /* Route is OK, nothing to do. */ | 1174 | /* Route is OK, nothing to do. */ |
@@ -1143,36 +1176,23 @@ int inet_sk_rebuild_header(struct sock *sk) | |||
1143 | return 0; | 1176 | return 0; |
1144 | 1177 | ||
1145 | /* Reroute. */ | 1178 | /* Reroute. */ |
1179 | rcu_read_lock(); | ||
1180 | inet_opt = rcu_dereference(inet->inet_opt); | ||
1146 | daddr = inet->inet_daddr; | 1181 | daddr = inet->inet_daddr; |
1147 | if (inet->opt && inet->opt->srr) | 1182 | if (inet_opt && inet_opt->opt.srr) |
1148 | daddr = inet->opt->faddr; | 1183 | daddr = inet_opt->opt.faddr; |
1149 | { | 1184 | rcu_read_unlock(); |
1150 | struct flowi fl = { | 1185 | fl4 = &inet->cork.fl.u.ip4; |
1151 | .oif = sk->sk_bound_dev_if, | 1186 | rt = ip_route_output_ports(sock_net(sk), fl4, sk, daddr, inet->inet_saddr, |
1152 | .mark = sk->sk_mark, | 1187 | inet->inet_dport, inet->inet_sport, |
1153 | .nl_u = { | 1188 | sk->sk_protocol, RT_CONN_FLAGS(sk), |
1154 | .ip4_u = { | 1189 | sk->sk_bound_dev_if); |
1155 | .daddr = daddr, | 1190 | if (!IS_ERR(rt)) { |
1156 | .saddr = inet->inet_saddr, | 1191 | err = 0; |
1157 | .tos = RT_CONN_FLAGS(sk), | ||
1158 | }, | ||
1159 | }, | ||
1160 | .proto = sk->sk_protocol, | ||
1161 | .flags = inet_sk_flowi_flags(sk), | ||
1162 | .uli_u = { | ||
1163 | .ports = { | ||
1164 | .sport = inet->inet_sport, | ||
1165 | .dport = inet->inet_dport, | ||
1166 | }, | ||
1167 | }, | ||
1168 | }; | ||
1169 | |||
1170 | security_sk_classify_flow(sk, &fl); | ||
1171 | err = ip_route_output_flow(sock_net(sk), &rt, &fl, sk, 0); | ||
1172 | } | ||
1173 | if (!err) | ||
1174 | sk_setup_caps(sk, &rt->dst); | 1192 | sk_setup_caps(sk, &rt->dst); |
1175 | else { | 1193 | } else { |
1194 | err = PTR_ERR(rt); | ||
1195 | |||
1176 | /* Routing failed... */ | 1196 | /* Routing failed... */ |
1177 | sk->sk_route_caps = 0; | 1197 | sk->sk_route_caps = 0; |
1178 | /* | 1198 | /* |
@@ -1192,7 +1212,7 @@ EXPORT_SYMBOL(inet_sk_rebuild_header); | |||
1192 | 1212 | ||
1193 | static int inet_gso_send_check(struct sk_buff *skb) | 1213 | static int inet_gso_send_check(struct sk_buff *skb) |
1194 | { | 1214 | { |
1195 | struct iphdr *iph; | 1215 | const struct iphdr *iph; |
1196 | const struct net_protocol *ops; | 1216 | const struct net_protocol *ops; |
1197 | int proto; | 1217 | int proto; |
1198 | int ihl; | 1218 | int ihl; |
@@ -1225,7 +1245,7 @@ out: | |||
1225 | return err; | 1245 | return err; |
1226 | } | 1246 | } |
1227 | 1247 | ||
1228 | static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features) | 1248 | static struct sk_buff *inet_gso_segment(struct sk_buff *skb, u32 features) |
1229 | { | 1249 | { |
1230 | struct sk_buff *segs = ERR_PTR(-EINVAL); | 1250 | struct sk_buff *segs = ERR_PTR(-EINVAL); |
1231 | struct iphdr *iph; | 1251 | struct iphdr *iph; |
@@ -1299,7 +1319,7 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, | |||
1299 | const struct net_protocol *ops; | 1319 | const struct net_protocol *ops; |
1300 | struct sk_buff **pp = NULL; | 1320 | struct sk_buff **pp = NULL; |
1301 | struct sk_buff *p; | 1321 | struct sk_buff *p; |
1302 | struct iphdr *iph; | 1322 | const struct iphdr *iph; |
1303 | unsigned int hlen; | 1323 | unsigned int hlen; |
1304 | unsigned int off; | 1324 | unsigned int off; |
1305 | unsigned int id; | 1325 | unsigned int id; |
@@ -1522,6 +1542,7 @@ static const struct net_protocol udp_protocol = { | |||
1522 | 1542 | ||
1523 | static const struct net_protocol icmp_protocol = { | 1543 | static const struct net_protocol icmp_protocol = { |
1524 | .handler = icmp_rcv, | 1544 | .handler = icmp_rcv, |
1545 | .err_handler = ping_err, | ||
1525 | .no_policy = 1, | 1546 | .no_policy = 1, |
1526 | .netns_ok = 1, | 1547 | .netns_ok = 1, |
1527 | }; | 1548 | }; |
@@ -1637,6 +1658,10 @@ static int __init inet_init(void) | |||
1637 | if (rc) | 1658 | if (rc) |
1638 | goto out_unregister_udp_proto; | 1659 | goto out_unregister_udp_proto; |
1639 | 1660 | ||
1661 | rc = proto_register(&ping_prot, 1); | ||
1662 | if (rc) | ||
1663 | goto out_unregister_raw_proto; | ||
1664 | |||
1640 | /* | 1665 | /* |
1641 | * Tell SOCKET that we are alive... | 1666 | * Tell SOCKET that we are alive... |
1642 | */ | 1667 | */ |
@@ -1692,6 +1717,8 @@ static int __init inet_init(void) | |||
1692 | /* Add UDP-Lite (RFC 3828) */ | 1717 | /* Add UDP-Lite (RFC 3828) */ |
1693 | udplite4_register(); | 1718 | udplite4_register(); |
1694 | 1719 | ||
1720 | ping_init(); | ||
1721 | |||
1695 | /* | 1722 | /* |
1696 | * Set the ICMP layer up | 1723 | * Set the ICMP layer up |
1697 | */ | 1724 | */ |
@@ -1722,6 +1749,8 @@ static int __init inet_init(void) | |||
1722 | rc = 0; | 1749 | rc = 0; |
1723 | out: | 1750 | out: |
1724 | return rc; | 1751 | return rc; |
1752 | out_unregister_raw_proto: | ||
1753 | proto_unregister(&raw_prot); | ||
1725 | out_unregister_udp_proto: | 1754 | out_unregister_udp_proto: |
1726 | proto_unregister(&udp_prot); | 1755 | proto_unregister(&udp_prot); |
1727 | out_unregister_tcp_proto: | 1756 | out_unregister_tcp_proto: |
@@ -1746,11 +1775,15 @@ static int __init ipv4_proc_init(void) | |||
1746 | goto out_tcp; | 1775 | goto out_tcp; |
1747 | if (udp4_proc_init()) | 1776 | if (udp4_proc_init()) |
1748 | goto out_udp; | 1777 | goto out_udp; |
1778 | if (ping_proc_init()) | ||
1779 | goto out_ping; | ||
1749 | if (ip_misc_proc_init()) | 1780 | if (ip_misc_proc_init()) |
1750 | goto out_misc; | 1781 | goto out_misc; |
1751 | out: | 1782 | out: |
1752 | return rc; | 1783 | return rc; |
1753 | out_misc: | 1784 | out_misc: |
1785 | ping_proc_exit(); | ||
1786 | out_ping: | ||
1754 | udp4_proc_exit(); | 1787 | udp4_proc_exit(); |
1755 | out_udp: | 1788 | out_udp: |
1756 | tcp4_proc_exit(); | 1789 | tcp4_proc_exit(); |