diff options
Diffstat (limited to 'net/ipv4/af_inet.c')
-rw-r--r-- | net/ipv4/af_inet.c | 95 |
1 files changed, 58 insertions, 37 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 45b89d7bda5a..cc1463156cd0 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 | } |
@@ -1008,6 +1009,14 @@ static struct inet_protosw inetsw_array[] = | |||
1008 | .flags = INET_PROTOSW_PERMANENT, | 1009 | .flags = INET_PROTOSW_PERMANENT, |
1009 | }, | 1010 | }, |
1010 | 1011 | ||
1012 | { | ||
1013 | .type = SOCK_DGRAM, | ||
1014 | .protocol = IPPROTO_ICMP, | ||
1015 | .prot = &ping_prot, | ||
1016 | .ops = &inet_dgram_ops, | ||
1017 | .no_check = UDP_CSUM_DEFAULT, | ||
1018 | .flags = INET_PROTOSW_REUSE, | ||
1019 | }, | ||
1011 | 1020 | ||
1012 | { | 1021 | { |
1013 | .type = SOCK_RAW, | 1022 | .type = SOCK_RAW, |
@@ -1101,27 +1110,29 @@ int sysctl_ip_dynaddr __read_mostly; | |||
1101 | static int inet_sk_reselect_saddr(struct sock *sk) | 1110 | static int inet_sk_reselect_saddr(struct sock *sk) |
1102 | { | 1111 | { |
1103 | struct inet_sock *inet = inet_sk(sk); | 1112 | struct inet_sock *inet = inet_sk(sk); |
1104 | int err; | ||
1105 | struct rtable *rt; | ||
1106 | __be32 old_saddr = inet->inet_saddr; | 1113 | __be32 old_saddr = inet->inet_saddr; |
1107 | __be32 new_saddr; | ||
1108 | __be32 daddr = inet->inet_daddr; | 1114 | __be32 daddr = inet->inet_daddr; |
1115 | struct flowi4 *fl4; | ||
1116 | struct rtable *rt; | ||
1117 | __be32 new_saddr; | ||
1118 | struct ip_options_rcu *inet_opt; | ||
1109 | 1119 | ||
1110 | if (inet->opt && inet->opt->srr) | 1120 | inet_opt = rcu_dereference_protected(inet->inet_opt, |
1111 | daddr = inet->opt->faddr; | 1121 | sock_owned_by_user(sk)); |
1122 | if (inet_opt && inet_opt->opt.srr) | ||
1123 | daddr = inet_opt->opt.faddr; | ||
1112 | 1124 | ||
1113 | /* Query new route. */ | 1125 | /* Query new route. */ |
1114 | err = ip_route_connect(&rt, daddr, 0, | 1126 | fl4 = &inet->cork.fl.u.ip4; |
1115 | RT_CONN_FLAGS(sk), | 1127 | rt = ip_route_connect(fl4, daddr, 0, RT_CONN_FLAGS(sk), |
1116 | sk->sk_bound_dev_if, | 1128 | sk->sk_bound_dev_if, sk->sk_protocol, |
1117 | sk->sk_protocol, | 1129 | inet->inet_sport, inet->inet_dport, sk, false); |
1118 | inet->inet_sport, inet->inet_dport, sk, 0); | 1130 | if (IS_ERR(rt)) |
1119 | if (err) | 1131 | return PTR_ERR(rt); |
1120 | return err; | ||
1121 | 1132 | ||
1122 | sk_setup_caps(sk, &rt->dst); | 1133 | sk_setup_caps(sk, &rt->dst); |
1123 | 1134 | ||
1124 | new_saddr = rt->rt_src; | 1135 | new_saddr = fl4->saddr; |
1125 | 1136 | ||
1126 | if (new_saddr == old_saddr) | 1137 | if (new_saddr == old_saddr) |
1127 | return 0; | 1138 | return 0; |
@@ -1150,6 +1161,8 @@ int inet_sk_rebuild_header(struct sock *sk) | |||
1150 | struct inet_sock *inet = inet_sk(sk); | 1161 | struct inet_sock *inet = inet_sk(sk); |
1151 | struct rtable *rt = (struct rtable *)__sk_dst_check(sk, 0); | 1162 | struct rtable *rt = (struct rtable *)__sk_dst_check(sk, 0); |
1152 | __be32 daddr; | 1163 | __be32 daddr; |
1164 | struct ip_options_rcu *inet_opt; | ||
1165 | struct flowi4 *fl4; | ||
1153 | int err; | 1166 | int err; |
1154 | 1167 | ||
1155 | /* Route is OK, nothing to do. */ | 1168 | /* Route is OK, nothing to do. */ |
@@ -1157,28 +1170,23 @@ int inet_sk_rebuild_header(struct sock *sk) | |||
1157 | return 0; | 1170 | return 0; |
1158 | 1171 | ||
1159 | /* Reroute. */ | 1172 | /* Reroute. */ |
1173 | rcu_read_lock(); | ||
1174 | inet_opt = rcu_dereference(inet->inet_opt); | ||
1160 | daddr = inet->inet_daddr; | 1175 | daddr = inet->inet_daddr; |
1161 | if (inet->opt && inet->opt->srr) | 1176 | if (inet_opt && inet_opt->opt.srr) |
1162 | daddr = inet->opt->faddr; | 1177 | daddr = inet_opt->opt.faddr; |
1163 | { | 1178 | rcu_read_unlock(); |
1164 | struct flowi fl = { | 1179 | fl4 = &inet->cork.fl.u.ip4; |
1165 | .oif = sk->sk_bound_dev_if, | 1180 | rt = ip_route_output_ports(sock_net(sk), fl4, sk, daddr, inet->inet_saddr, |
1166 | .mark = sk->sk_mark, | 1181 | inet->inet_dport, inet->inet_sport, |
1167 | .fl4_dst = daddr, | 1182 | sk->sk_protocol, RT_CONN_FLAGS(sk), |
1168 | .fl4_src = inet->inet_saddr, | 1183 | sk->sk_bound_dev_if); |
1169 | .fl4_tos = RT_CONN_FLAGS(sk), | 1184 | if (!IS_ERR(rt)) { |
1170 | .proto = sk->sk_protocol, | 1185 | err = 0; |
1171 | .flags = inet_sk_flowi_flags(sk), | ||
1172 | .fl_ip_sport = inet->inet_sport, | ||
1173 | .fl_ip_dport = inet->inet_dport, | ||
1174 | }; | ||
1175 | |||
1176 | security_sk_classify_flow(sk, &fl); | ||
1177 | err = ip_route_output_flow(sock_net(sk), &rt, &fl, sk, 0); | ||
1178 | } | ||
1179 | if (!err) | ||
1180 | sk_setup_caps(sk, &rt->dst); | 1186 | sk_setup_caps(sk, &rt->dst); |
1181 | else { | 1187 | } else { |
1188 | err = PTR_ERR(rt); | ||
1189 | |||
1182 | /* Routing failed... */ | 1190 | /* Routing failed... */ |
1183 | sk->sk_route_caps = 0; | 1191 | sk->sk_route_caps = 0; |
1184 | /* | 1192 | /* |
@@ -1198,7 +1206,7 @@ EXPORT_SYMBOL(inet_sk_rebuild_header); | |||
1198 | 1206 | ||
1199 | static int inet_gso_send_check(struct sk_buff *skb) | 1207 | static int inet_gso_send_check(struct sk_buff *skb) |
1200 | { | 1208 | { |
1201 | struct iphdr *iph; | 1209 | const struct iphdr *iph; |
1202 | const struct net_protocol *ops; | 1210 | const struct net_protocol *ops; |
1203 | int proto; | 1211 | int proto; |
1204 | int ihl; | 1212 | int ihl; |
@@ -1231,7 +1239,7 @@ out: | |||
1231 | return err; | 1239 | return err; |
1232 | } | 1240 | } |
1233 | 1241 | ||
1234 | static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features) | 1242 | static struct sk_buff *inet_gso_segment(struct sk_buff *skb, u32 features) |
1235 | { | 1243 | { |
1236 | struct sk_buff *segs = ERR_PTR(-EINVAL); | 1244 | struct sk_buff *segs = ERR_PTR(-EINVAL); |
1237 | struct iphdr *iph; | 1245 | struct iphdr *iph; |
@@ -1305,7 +1313,7 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, | |||
1305 | const struct net_protocol *ops; | 1313 | const struct net_protocol *ops; |
1306 | struct sk_buff **pp = NULL; | 1314 | struct sk_buff **pp = NULL; |
1307 | struct sk_buff *p; | 1315 | struct sk_buff *p; |
1308 | struct iphdr *iph; | 1316 | const struct iphdr *iph; |
1309 | unsigned int hlen; | 1317 | unsigned int hlen; |
1310 | unsigned int off; | 1318 | unsigned int off; |
1311 | unsigned int id; | 1319 | unsigned int id; |
@@ -1528,6 +1536,7 @@ static const struct net_protocol udp_protocol = { | |||
1528 | 1536 | ||
1529 | static const struct net_protocol icmp_protocol = { | 1537 | static const struct net_protocol icmp_protocol = { |
1530 | .handler = icmp_rcv, | 1538 | .handler = icmp_rcv, |
1539 | .err_handler = ping_err, | ||
1531 | .no_policy = 1, | 1540 | .no_policy = 1, |
1532 | .netns_ok = 1, | 1541 | .netns_ok = 1, |
1533 | }; | 1542 | }; |
@@ -1643,6 +1652,10 @@ static int __init inet_init(void) | |||
1643 | if (rc) | 1652 | if (rc) |
1644 | goto out_unregister_udp_proto; | 1653 | goto out_unregister_udp_proto; |
1645 | 1654 | ||
1655 | rc = proto_register(&ping_prot, 1); | ||
1656 | if (rc) | ||
1657 | goto out_unregister_raw_proto; | ||
1658 | |||
1646 | /* | 1659 | /* |
1647 | * Tell SOCKET that we are alive... | 1660 | * Tell SOCKET that we are alive... |
1648 | */ | 1661 | */ |
@@ -1698,6 +1711,8 @@ static int __init inet_init(void) | |||
1698 | /* Add UDP-Lite (RFC 3828) */ | 1711 | /* Add UDP-Lite (RFC 3828) */ |
1699 | udplite4_register(); | 1712 | udplite4_register(); |
1700 | 1713 | ||
1714 | ping_init(); | ||
1715 | |||
1701 | /* | 1716 | /* |
1702 | * Set the ICMP layer up | 1717 | * Set the ICMP layer up |
1703 | */ | 1718 | */ |
@@ -1728,6 +1743,8 @@ static int __init inet_init(void) | |||
1728 | rc = 0; | 1743 | rc = 0; |
1729 | out: | 1744 | out: |
1730 | return rc; | 1745 | return rc; |
1746 | out_unregister_raw_proto: | ||
1747 | proto_unregister(&raw_prot); | ||
1731 | out_unregister_udp_proto: | 1748 | out_unregister_udp_proto: |
1732 | proto_unregister(&udp_prot); | 1749 | proto_unregister(&udp_prot); |
1733 | out_unregister_tcp_proto: | 1750 | out_unregister_tcp_proto: |
@@ -1752,11 +1769,15 @@ static int __init ipv4_proc_init(void) | |||
1752 | goto out_tcp; | 1769 | goto out_tcp; |
1753 | if (udp4_proc_init()) | 1770 | if (udp4_proc_init()) |
1754 | goto out_udp; | 1771 | goto out_udp; |
1772 | if (ping_proc_init()) | ||
1773 | goto out_ping; | ||
1755 | if (ip_misc_proc_init()) | 1774 | if (ip_misc_proc_init()) |
1756 | goto out_misc; | 1775 | goto out_misc; |
1757 | out: | 1776 | out: |
1758 | return rc; | 1777 | return rc; |
1759 | out_misc: | 1778 | out_misc: |
1779 | ping_proc_exit(); | ||
1780 | out_ping: | ||
1760 | udp4_proc_exit(); | 1781 | udp4_proc_exit(); |
1761 | out_udp: | 1782 | out_udp: |
1762 | tcp4_proc_exit(); | 1783 | tcp4_proc_exit(); |