| .. | .. |
|---|
| 103 | 103 | if (gso_type && skb->network_header) { |
|---|
| 104 | 104 | struct flow_keys_basic keys; |
|---|
| 105 | 105 | |
|---|
| 106 | | - if (!skb->protocol) |
|---|
| 107 | | - virtio_net_hdr_set_proto(skb, hdr); |
|---|
| 106 | + if (!skb->protocol) { |
|---|
| 107 | + __be16 protocol = dev_parse_header_protocol(skb); |
|---|
| 108 | + |
|---|
| 109 | + if (!protocol) |
|---|
| 110 | + virtio_net_hdr_set_proto(skb, hdr); |
|---|
| 111 | + else if (!virtio_net_hdr_match_proto(protocol, hdr->gso_type)) |
|---|
| 112 | + return -EINVAL; |
|---|
| 113 | + else |
|---|
| 114 | + skb->protocol = protocol; |
|---|
| 115 | + } |
|---|
| 108 | 116 | retry: |
|---|
| 109 | | - if (!skb_flow_dissect_flow_keys_basic(skb, &keys, |
|---|
| 117 | + if (!skb_flow_dissect_flow_keys_basic(NULL, skb, &keys, |
|---|
| 110 | 118 | NULL, 0, 0, 0, |
|---|
| 111 | 119 | 0)) { |
|---|
| 112 | 120 | /* UFO does not specify ipv4 or 6: try both */ |
|---|
| .. | .. |
|---|
| 140 | 148 | if (gso_type & SKB_GSO_UDP) |
|---|
| 141 | 149 | nh_off -= thlen; |
|---|
| 142 | 150 | |
|---|
| 151 | + /* Kernel has a special handling for GSO_BY_FRAGS. */ |
|---|
| 152 | + if (gso_size == GSO_BY_FRAGS) |
|---|
| 153 | + return -EINVAL; |
|---|
| 154 | + |
|---|
| 143 | 155 | /* Too small packets are not really GSO ones. */ |
|---|
| 144 | 156 | if (skb->len - nh_off > gso_size) { |
|---|
| 145 | 157 | shinfo->gso_size = gso_size; |
|---|