diff options
Diffstat (limited to 'net/ipv4/af_inet.c')
-rw-r--r-- | net/ipv4/af_inet.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 318d4674faa1..c84a32070f8d 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
@@ -1097,6 +1097,40 @@ 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 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 | |||
1100 | static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features) | 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); |
@@ -1162,6 +1196,7 @@ static struct net_protocol igmp_protocol = { | |||
1162 | static struct net_protocol tcp_protocol = { | 1196 | static struct net_protocol tcp_protocol = { |
1163 | .handler = tcp_v4_rcv, | 1197 | .handler = tcp_v4_rcv, |
1164 | .err_handler = tcp_v4_err, | 1198 | .err_handler = tcp_v4_err, |
1199 | .gso_send_check = tcp_v4_gso_send_check, | ||
1165 | .gso_segment = tcp_tso_segment, | 1200 | .gso_segment = tcp_tso_segment, |
1166 | .no_policy = 1, | 1201 | .no_policy = 1, |
1167 | }; | 1202 | }; |
@@ -1208,6 +1243,7 @@ static int ipv4_proc_init(void); | |||
1208 | static struct packet_type ip_packet_type = { | 1243 | static struct packet_type ip_packet_type = { |
1209 | .type = __constant_htons(ETH_P_IP), | 1244 | .type = __constant_htons(ETH_P_IP), |
1210 | .func = ip_rcv, | 1245 | .func = ip_rcv, |
1246 | .gso_send_check = inet_gso_send_check, | ||
1211 | .gso_segment = inet_gso_segment, | 1247 | .gso_segment = inet_gso_segment, |
1212 | }; | 1248 | }; |
1213 | 1249 | ||