diff options
Diffstat (limited to 'net/ipv4/af_inet.c')
| -rw-r--r-- | net/ipv4/af_inet.c | 75 |
1 files changed, 58 insertions, 17 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 461216b47948..edcf0932ac6d 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
| @@ -67,7 +67,6 @@ | |||
| 67 | * 2 of the License, or (at your option) any later version. | 67 | * 2 of the License, or (at your option) any later version. |
| 68 | */ | 68 | */ |
| 69 | 69 | ||
| 70 | #include <linux/config.h> | ||
| 71 | #include <linux/err.h> | 70 | #include <linux/err.h> |
| 72 | #include <linux/errno.h> | 71 | #include <linux/errno.h> |
| 73 | #include <linux/types.h> | 72 | #include <linux/types.h> |
| @@ -392,7 +391,7 @@ int inet_release(struct socket *sock) | |||
| 392 | } | 391 | } |
| 393 | 392 | ||
| 394 | /* It is off by default, see below. */ | 393 | /* It is off by default, see below. */ |
| 395 | int sysctl_ip_nonlocal_bind; | 394 | int sysctl_ip_nonlocal_bind __read_mostly; |
| 396 | 395 | ||
| 397 | int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | 396 | int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) |
| 398 | { | 397 | { |
| @@ -988,7 +987,7 @@ void inet_unregister_protosw(struct inet_protosw *p) | |||
| 988 | * Shall we try to damage output packets if routing dev changes? | 987 | * Shall we try to damage output packets if routing dev changes? |
| 989 | */ | 988 | */ |
| 990 | 989 | ||
| 991 | int sysctl_ip_dynaddr; | 990 | int sysctl_ip_dynaddr __read_mostly; |
| 992 | 991 | ||
| 993 | static int inet_sk_reselect_saddr(struct sock *sk) | 992 | static int inet_sk_reselect_saddr(struct sock *sk) |
| 994 | { | 993 | { |
| @@ -997,7 +996,7 @@ static int inet_sk_reselect_saddr(struct sock *sk) | |||
| 997 | struct rtable *rt; | 996 | struct rtable *rt; |
| 998 | __u32 old_saddr = inet->saddr; | 997 | __u32 old_saddr = inet->saddr; |
| 999 | __u32 new_saddr; | 998 | __u32 new_saddr; |
| 1000 | __u32 daddr = inet->daddr; | 999 | __be32 daddr = inet->daddr; |
| 1001 | 1000 | ||
| 1002 | if (inet->opt && inet->opt->srr) | 1001 | if (inet->opt && inet->opt->srr) |
| 1003 | daddr = inet->opt->faddr; | 1002 | daddr = inet->opt->faddr; |
| @@ -1044,7 +1043,7 @@ int inet_sk_rebuild_header(struct sock *sk) | |||
| 1044 | { | 1043 | { |
| 1045 | struct inet_sock *inet = inet_sk(sk); | 1044 | struct inet_sock *inet = inet_sk(sk); |
| 1046 | struct rtable *rt = (struct rtable *)__sk_dst_check(sk, 0); | 1045 | struct rtable *rt = (struct rtable *)__sk_dst_check(sk, 0); |
| 1047 | u32 daddr; | 1046 | __be32 daddr; |
| 1048 | int err; | 1047 | int err; |
| 1049 | 1048 | ||
| 1050 | /* Route is OK, nothing to do. */ | 1049 | /* Route is OK, nothing to do. */ |
| @@ -1074,6 +1073,7 @@ int inet_sk_rebuild_header(struct sock *sk) | |||
| 1074 | }, | 1073 | }, |
| 1075 | }; | 1074 | }; |
| 1076 | 1075 | ||
| 1076 | security_sk_classify_flow(sk, &fl); | ||
| 1077 | err = ip_route_output_flow(&rt, &fl, sk, 0); | 1077 | err = ip_route_output_flow(&rt, &fl, sk, 0); |
| 1078 | } | 1078 | } |
| 1079 | if (!err) | 1079 | if (!err) |
| @@ -1097,7 +1097,41 @@ int inet_sk_rebuild_header(struct sock *sk) | |||
| 1097 | 1097 | ||
| 1098 | EXPORT_SYMBOL(inet_sk_rebuild_header); | 1098 | EXPORT_SYMBOL(inet_sk_rebuild_header); |
| 1099 | 1099 | ||
| 1100 | static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int sg) | 1100 | static int inet_gso_send_check(struct sk_buff *skb) |
| 1101 | { | ||
| 1102 | struct iphdr *iph; | ||
| 1103 | struct net_protocol *ops; | ||
| 1104 | int proto; | ||
| 1105 | int ihl; | ||
| 1106 | int err = -EINVAL; | ||
| 1107 | |||
| 1108 | if (unlikely(!pskb_may_pull(skb, sizeof(*iph)))) | ||
| 1109 | goto out; | ||
| 1110 | |||
| 1111 | iph = skb->nh.iph; | ||
| 1112 | ihl = iph->ihl * 4; | ||
| 1113 | if (ihl < sizeof(*iph)) | ||
| 1114 | goto out; | ||
| 1115 | |||
| 1116 | if (unlikely(!pskb_may_pull(skb, ihl))) | ||
| 1117 | goto out; | ||
| 1118 | |||
| 1119 | skb->h.raw = __skb_pull(skb, ihl); | ||
| 1120 | iph = skb->nh.iph; | ||
| 1121 | proto = iph->protocol & (MAX_INET_PROTOS - 1); | ||
| 1122 | err = -EPROTONOSUPPORT; | ||
| 1123 | |||
| 1124 | rcu_read_lock(); | ||
| 1125 | ops = rcu_dereference(inet_protos[proto]); | ||
| 1126 | if (likely(ops && ops->gso_send_check)) | ||
| 1127 | err = ops->gso_send_check(skb); | ||
| 1128 | rcu_read_unlock(); | ||
| 1129 | |||
| 1130 | out: | ||
| 1131 | return err; | ||
| 1132 | } | ||
| 1133 | |||
| 1134 | static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features) | ||
| 1101 | { | 1135 | { |
| 1102 | struct sk_buff *segs = ERR_PTR(-EINVAL); | 1136 | struct sk_buff *segs = ERR_PTR(-EINVAL); |
| 1103 | struct iphdr *iph; | 1137 | struct iphdr *iph; |
| @@ -1106,7 +1140,15 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int sg) | |||
| 1106 | int ihl; | 1140 | int ihl; |
| 1107 | int id; | 1141 | int id; |
| 1108 | 1142 | ||
| 1109 | if (!pskb_may_pull(skb, sizeof(*iph))) | 1143 | if (unlikely(skb_shinfo(skb)->gso_type & |
| 1144 | ~(SKB_GSO_TCPV4 | | ||
| 1145 | SKB_GSO_UDP | | ||
| 1146 | SKB_GSO_DODGY | | ||
| 1147 | SKB_GSO_TCP_ECN | | ||
| 1148 | 0))) | ||
| 1149 | goto out; | ||
| 1150 | |||
| 1151 | if (unlikely(!pskb_may_pull(skb, sizeof(*iph)))) | ||
| 1110 | goto out; | 1152 | goto out; |
| 1111 | 1153 | ||
| 1112 | iph = skb->nh.iph; | 1154 | iph = skb->nh.iph; |
| @@ -1114,7 +1156,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int sg) | |||
| 1114 | if (ihl < sizeof(*iph)) | 1156 | if (ihl < sizeof(*iph)) |
| 1115 | goto out; | 1157 | goto out; |
| 1116 | 1158 | ||
| 1117 | if (!pskb_may_pull(skb, ihl)) | 1159 | if (unlikely(!pskb_may_pull(skb, ihl))) |
| 1118 | goto out; | 1160 | goto out; |
| 1119 | 1161 | ||
| 1120 | skb->h.raw = __skb_pull(skb, ihl); | 1162 | skb->h.raw = __skb_pull(skb, ihl); |
| @@ -1125,11 +1167,11 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int sg) | |||
| 1125 | 1167 | ||
| 1126 | rcu_read_lock(); | 1168 | rcu_read_lock(); |
| 1127 | ops = rcu_dereference(inet_protos[proto]); | 1169 | ops = rcu_dereference(inet_protos[proto]); |
| 1128 | if (ops && ops->gso_segment) | 1170 | if (likely(ops && ops->gso_segment)) |
| 1129 | segs = ops->gso_segment(skb, sg); | 1171 | segs = ops->gso_segment(skb, features); |
| 1130 | rcu_read_unlock(); | 1172 | rcu_read_unlock(); |
| 1131 | 1173 | ||
| 1132 | if (IS_ERR(segs)) | 1174 | if (!segs || unlikely(IS_ERR(segs))) |
| 1133 | goto out; | 1175 | goto out; |
| 1134 | 1176 | ||
| 1135 | skb = segs; | 1177 | skb = segs; |
| @@ -1154,6 +1196,7 @@ static struct net_protocol igmp_protocol = { | |||
| 1154 | static struct net_protocol tcp_protocol = { | 1196 | static struct net_protocol tcp_protocol = { |
| 1155 | .handler = tcp_v4_rcv, | 1197 | .handler = tcp_v4_rcv, |
| 1156 | .err_handler = tcp_v4_err, | 1198 | .err_handler = tcp_v4_err, |
| 1199 | .gso_send_check = tcp_v4_gso_send_check, | ||
| 1157 | .gso_segment = tcp_tso_segment, | 1200 | .gso_segment = tcp_tso_segment, |
| 1158 | .no_policy = 1, | 1201 | .no_policy = 1, |
| 1159 | }; | 1202 | }; |
| @@ -1200,6 +1243,7 @@ static int ipv4_proc_init(void); | |||
| 1200 | static struct packet_type ip_packet_type = { | 1243 | static struct packet_type ip_packet_type = { |
| 1201 | .type = __constant_htons(ETH_P_IP), | 1244 | .type = __constant_htons(ETH_P_IP), |
| 1202 | .func = ip_rcv, | 1245 | .func = ip_rcv, |
| 1246 | .gso_send_check = inet_gso_send_check, | ||
| 1203 | .gso_segment = inet_gso_segment, | 1247 | .gso_segment = inet_gso_segment, |
| 1204 | }; | 1248 | }; |
| 1205 | 1249 | ||
| @@ -1210,10 +1254,7 @@ static int __init inet_init(void) | |||
| 1210 | struct list_head *r; | 1254 | struct list_head *r; |
| 1211 | int rc = -EINVAL; | 1255 | int rc = -EINVAL; |
| 1212 | 1256 | ||
| 1213 | if (sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb)) { | 1257 | BUILD_BUG_ON(sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb)); |
| 1214 | printk(KERN_CRIT "%s: panic\n", __FUNCTION__); | ||
| 1215 | goto out; | ||
| 1216 | } | ||
| 1217 | 1258 | ||
| 1218 | rc = proto_register(&tcp_prot, 1); | 1259 | rc = proto_register(&tcp_prot, 1); |
| 1219 | if (rc) | 1260 | if (rc) |
| @@ -1301,10 +1342,10 @@ static int __init inet_init(void) | |||
| 1301 | rc = 0; | 1342 | rc = 0; |
| 1302 | out: | 1343 | out: |
| 1303 | return rc; | 1344 | return rc; |
| 1304 | out_unregister_tcp_proto: | ||
| 1305 | proto_unregister(&tcp_prot); | ||
| 1306 | out_unregister_udp_proto: | 1345 | out_unregister_udp_proto: |
| 1307 | proto_unregister(&udp_prot); | 1346 | proto_unregister(&udp_prot); |
| 1347 | out_unregister_tcp_proto: | ||
| 1348 | proto_unregister(&tcp_prot); | ||
| 1308 | goto out; | 1349 | goto out; |
| 1309 | } | 1350 | } |
| 1310 | 1351 | ||
