diff options
Diffstat (limited to 'net/ipv4/udp.c')
-rw-r--r-- | net/ipv4/udp.c | 238 |
1 files changed, 122 insertions, 116 deletions
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index fc620a7c1db4..cec0f2cc49b7 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -175,7 +175,8 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum, | |||
175 | ; | 175 | ; |
176 | } | 176 | } |
177 | result = best; | 177 | result = best; |
178 | for(i = 0; i < (1 << 16) / UDP_HTABLE_SIZE; i++, result += UDP_HTABLE_SIZE) { | 178 | for (i = 0; i < (1 << 16) / UDP_HTABLE_SIZE; |
179 | i++, result += UDP_HTABLE_SIZE) { | ||
179 | if (result > sysctl_local_port_range[1]) | 180 | if (result > sysctl_local_port_range[1]) |
180 | result = sysctl_local_port_range[0] | 181 | result = sysctl_local_port_range[0] |
181 | + ((result - sysctl_local_port_range[0]) & | 182 | + ((result - sysctl_local_port_range[0]) & |
@@ -212,13 +213,13 @@ fail: | |||
212 | return error; | 213 | return error; |
213 | } | 214 | } |
214 | 215 | ||
215 | __inline__ int udp_get_port(struct sock *sk, unsigned short snum, | 216 | int udp_get_port(struct sock *sk, unsigned short snum, |
216 | int (*scmp)(const struct sock *, const struct sock *)) | 217 | int (*scmp)(const struct sock *, const struct sock *)) |
217 | { | 218 | { |
218 | return __udp_lib_get_port(sk, snum, udp_hash, &udp_port_rover, scmp); | 219 | return __udp_lib_get_port(sk, snum, udp_hash, &udp_port_rover, scmp); |
219 | } | 220 | } |
220 | 221 | ||
221 | inline int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) | 222 | int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) |
222 | { | 223 | { |
223 | struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2); | 224 | struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2); |
224 | 225 | ||
@@ -270,10 +271,10 @@ static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport, | |||
270 | continue; | 271 | continue; |
271 | score+=2; | 272 | score+=2; |
272 | } | 273 | } |
273 | if(score == 9) { | 274 | if (score == 9) { |
274 | result = sk; | 275 | result = sk; |
275 | break; | 276 | break; |
276 | } else if(score > badness) { | 277 | } else if (score > badness) { |
277 | result = sk; | 278 | result = sk; |
278 | badness = score; | 279 | badness = score; |
279 | } | 280 | } |
@@ -329,8 +330,8 @@ void __udp4_lib_err(struct sk_buff *skb, u32 info, struct hlist_head udptable[]) | |||
329 | struct inet_sock *inet; | 330 | struct inet_sock *inet; |
330 | struct iphdr *iph = (struct iphdr*)skb->data; | 331 | struct iphdr *iph = (struct iphdr*)skb->data; |
331 | struct udphdr *uh = (struct udphdr*)(skb->data+(iph->ihl<<2)); | 332 | struct udphdr *uh = (struct udphdr*)(skb->data+(iph->ihl<<2)); |
332 | int type = skb->h.icmph->type; | 333 | const int type = icmp_hdr(skb)->type; |
333 | int code = skb->h.icmph->code; | 334 | const int code = icmp_hdr(skb)->code; |
334 | struct sock *sk; | 335 | struct sock *sk; |
335 | int harderr; | 336 | int harderr; |
336 | int err; | 337 | int err; |
@@ -390,7 +391,7 @@ out: | |||
390 | sock_put(sk); | 391 | sock_put(sk); |
391 | } | 392 | } |
392 | 393 | ||
393 | __inline__ void udp_err(struct sk_buff *skb, u32 info) | 394 | void udp_err(struct sk_buff *skb, u32 info) |
394 | { | 395 | { |
395 | return __udp4_lib_err(skb, info, udp_hash); | 396 | return __udp4_lib_err(skb, info, udp_hash); |
396 | } | 397 | } |
@@ -419,13 +420,14 @@ static void udp4_hwcsum_outgoing(struct sock *sk, struct sk_buff *skb, | |||
419 | __be32 src, __be32 dst, int len ) | 420 | __be32 src, __be32 dst, int len ) |
420 | { | 421 | { |
421 | unsigned int offset; | 422 | unsigned int offset; |
422 | struct udphdr *uh = skb->h.uh; | 423 | struct udphdr *uh = udp_hdr(skb); |
423 | __wsum csum = 0; | 424 | __wsum csum = 0; |
424 | 425 | ||
425 | if (skb_queue_len(&sk->sk_write_queue) == 1) { | 426 | if (skb_queue_len(&sk->sk_write_queue) == 1) { |
426 | /* | 427 | /* |
427 | * Only one fragment on the socket. | 428 | * Only one fragment on the socket. |
428 | */ | 429 | */ |
430 | skb->csum_start = skb_transport_header(skb) - skb->head; | ||
429 | skb->csum_offset = offsetof(struct udphdr, check); | 431 | skb->csum_offset = offsetof(struct udphdr, check); |
430 | uh->check = ~csum_tcpudp_magic(src, dst, len, IPPROTO_UDP, 0); | 432 | uh->check = ~csum_tcpudp_magic(src, dst, len, IPPROTO_UDP, 0); |
431 | } else { | 433 | } else { |
@@ -434,7 +436,7 @@ static void udp4_hwcsum_outgoing(struct sock *sk, struct sk_buff *skb, | |||
434 | * fragments on the socket so that all csums of sk_buffs | 436 | * fragments on the socket so that all csums of sk_buffs |
435 | * should be together | 437 | * should be together |
436 | */ | 438 | */ |
437 | offset = skb->h.raw - skb->data; | 439 | offset = skb_transport_offset(skb); |
438 | skb->csum = skb_checksum(skb, offset, skb->len - offset, 0); | 440 | skb->csum = skb_checksum(skb, offset, skb->len - offset, 0); |
439 | 441 | ||
440 | skb->ip_summed = CHECKSUM_NONE; | 442 | skb->ip_summed = CHECKSUM_NONE; |
@@ -469,7 +471,7 @@ static int udp_push_pending_frames(struct sock *sk) | |||
469 | /* | 471 | /* |
470 | * Create a UDP header | 472 | * Create a UDP header |
471 | */ | 473 | */ |
472 | uh = skb->h.uh; | 474 | uh = udp_hdr(skb); |
473 | uh->source = fl->fl_ip_sport; | 475 | uh->source = fl->fl_ip_sport; |
474 | uh->dest = fl->fl_ip_dport; | 476 | uh->dest = fl->fl_ip_dport; |
475 | uh->len = htons(up->len); | 477 | uh->len = htons(up->len); |
@@ -765,38 +767,38 @@ out: | |||
765 | 767 | ||
766 | int udp_ioctl(struct sock *sk, int cmd, unsigned long arg) | 768 | int udp_ioctl(struct sock *sk, int cmd, unsigned long arg) |
767 | { | 769 | { |
768 | switch(cmd) | 770 | switch (cmd) { |
771 | case SIOCOUTQ: | ||
769 | { | 772 | { |
770 | case SIOCOUTQ: | 773 | int amount = atomic_read(&sk->sk_wmem_alloc); |
771 | { | 774 | return put_user(amount, (int __user *)arg); |
772 | int amount = atomic_read(&sk->sk_wmem_alloc); | 775 | } |
773 | return put_user(amount, (int __user *)arg); | ||
774 | } | ||
775 | 776 | ||
776 | case SIOCINQ: | 777 | case SIOCINQ: |
777 | { | 778 | { |
778 | struct sk_buff *skb; | 779 | struct sk_buff *skb; |
779 | unsigned long amount; | 780 | unsigned long amount; |
780 | 781 | ||
781 | amount = 0; | 782 | amount = 0; |
782 | spin_lock_bh(&sk->sk_receive_queue.lock); | 783 | spin_lock_bh(&sk->sk_receive_queue.lock); |
783 | skb = skb_peek(&sk->sk_receive_queue); | 784 | skb = skb_peek(&sk->sk_receive_queue); |
784 | if (skb != NULL) { | 785 | if (skb != NULL) { |
785 | /* | 786 | /* |
786 | * We will only return the amount | 787 | * We will only return the amount |
787 | * of this packet since that is all | 788 | * of this packet since that is all |
788 | * that will be read. | 789 | * that will be read. |
789 | */ | 790 | */ |
790 | amount = skb->len - sizeof(struct udphdr); | 791 | amount = skb->len - sizeof(struct udphdr); |
791 | } | ||
792 | spin_unlock_bh(&sk->sk_receive_queue.lock); | ||
793 | return put_user(amount, (int __user *)arg); | ||
794 | } | 792 | } |
793 | spin_unlock_bh(&sk->sk_receive_queue.lock); | ||
794 | return put_user(amount, (int __user *)arg); | ||
795 | } | ||
795 | 796 | ||
796 | default: | 797 | default: |
797 | return -ENOIOCTLCMD; | 798 | return -ENOIOCTLCMD; |
798 | } | 799 | } |
799 | return(0); | 800 | |
801 | return 0; | ||
800 | } | 802 | } |
801 | 803 | ||
802 | /* | 804 | /* |
@@ -810,7 +812,9 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
810 | struct inet_sock *inet = inet_sk(sk); | 812 | struct inet_sock *inet = inet_sk(sk); |
811 | struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name; | 813 | struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name; |
812 | struct sk_buff *skb; | 814 | struct sk_buff *skb; |
813 | int copied, err, copy_only, is_udplite = IS_UDPLITE(sk); | 815 | unsigned int ulen, copied; |
816 | int err; | ||
817 | int is_udplite = IS_UDPLITE(sk); | ||
814 | 818 | ||
815 | /* | 819 | /* |
816 | * Check any passed addresses | 820 | * Check any passed addresses |
@@ -826,28 +830,25 @@ try_again: | |||
826 | if (!skb) | 830 | if (!skb) |
827 | goto out; | 831 | goto out; |
828 | 832 | ||
829 | copied = skb->len - sizeof(struct udphdr); | 833 | ulen = skb->len - sizeof(struct udphdr); |
830 | if (copied > len) { | 834 | copied = len; |
831 | copied = len; | 835 | if (copied > ulen) |
836 | copied = ulen; | ||
837 | else if (copied < ulen) | ||
832 | msg->msg_flags |= MSG_TRUNC; | 838 | msg->msg_flags |= MSG_TRUNC; |
833 | } | ||
834 | 839 | ||
835 | /* | 840 | /* |
836 | * Decide whether to checksum and/or copy data. | 841 | * If checksum is needed at all, try to do it while copying the |
837 | * | 842 | * data. If the data is truncated, or if we only want a partial |
838 | * UDP: checksum may have been computed in HW, | 843 | * coverage checksum (UDP-Lite), do it before the copy. |
839 | * (re-)compute it if message is truncated. | ||
840 | * UDP-Lite: always needs to checksum, no HW support. | ||
841 | */ | 844 | */ |
842 | copy_only = (skb->ip_summed==CHECKSUM_UNNECESSARY); | ||
843 | 845 | ||
844 | if (is_udplite || (!copy_only && msg->msg_flags&MSG_TRUNC)) { | 846 | if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) { |
845 | if (__udp_lib_checksum_complete(skb)) | 847 | if (udp_lib_checksum_complete(skb)) |
846 | goto csum_copy_err; | 848 | goto csum_copy_err; |
847 | copy_only = 1; | ||
848 | } | 849 | } |
849 | 850 | ||
850 | if (copy_only) | 851 | if (skb_csum_unnecessary(skb)) |
851 | err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), | 852 | err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), |
852 | msg->msg_iov, copied ); | 853 | msg->msg_iov, copied ); |
853 | else { | 854 | else { |
@@ -866,8 +867,8 @@ try_again: | |||
866 | if (sin) | 867 | if (sin) |
867 | { | 868 | { |
868 | sin->sin_family = AF_INET; | 869 | sin->sin_family = AF_INET; |
869 | sin->sin_port = skb->h.uh->source; | 870 | sin->sin_port = udp_hdr(skb)->source; |
870 | sin->sin_addr.s_addr = skb->nh.iph->saddr; | 871 | sin->sin_addr.s_addr = ip_hdr(skb)->saddr; |
871 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | 872 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); |
872 | } | 873 | } |
873 | if (inet->cmsg_flags) | 874 | if (inet->cmsg_flags) |
@@ -875,7 +876,7 @@ try_again: | |||
875 | 876 | ||
876 | err = copied; | 877 | err = copied; |
877 | if (flags & MSG_TRUNC) | 878 | if (flags & MSG_TRUNC) |
878 | err = skb->len - sizeof(struct udphdr); | 879 | err = ulen; |
879 | 880 | ||
880 | out_free: | 881 | out_free: |
881 | skb_free_datagram(sk, skb); | 882 | skb_free_datagram(sk, skb); |
@@ -949,7 +950,7 @@ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb) | |||
949 | return 1; | 950 | return 1; |
950 | 951 | ||
951 | /* Now we can get the pointers */ | 952 | /* Now we can get the pointers */ |
952 | uh = skb->h.uh; | 953 | uh = udp_hdr(skb); |
953 | udpdata = (__u8 *)uh + sizeof(struct udphdr); | 954 | udpdata = (__u8 *)uh + sizeof(struct udphdr); |
954 | udpdata32 = (__be32 *)udpdata; | 955 | udpdata32 = (__be32 *)udpdata; |
955 | 956 | ||
@@ -959,7 +960,7 @@ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb) | |||
959 | /* Check if this is a keepalive packet. If so, eat it. */ | 960 | /* Check if this is a keepalive packet. If so, eat it. */ |
960 | if (len == 1 && udpdata[0] == 0xff) { | 961 | if (len == 1 && udpdata[0] == 0xff) { |
961 | return 0; | 962 | return 0; |
962 | } else if (len > sizeof(struct ip_esp_hdr) && udpdata32[0] != 0 ) { | 963 | } else if (len > sizeof(struct ip_esp_hdr) && udpdata32[0] != 0) { |
963 | /* ESP Packet without Non-ESP header */ | 964 | /* ESP Packet without Non-ESP header */ |
964 | len = sizeof(struct udphdr); | 965 | len = sizeof(struct udphdr); |
965 | } else | 966 | } else |
@@ -990,7 +991,7 @@ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb) | |||
990 | return 0; | 991 | return 0; |
991 | 992 | ||
992 | /* Now we can update and verify the packet length... */ | 993 | /* Now we can update and verify the packet length... */ |
993 | iph = skb->nh.iph; | 994 | iph = ip_hdr(skb); |
994 | iphlen = iph->ihl << 2; | 995 | iphlen = iph->ihl << 2; |
995 | iph->tot_len = htons(ntohs(iph->tot_len) - len); | 996 | iph->tot_len = htons(ntohs(iph->tot_len) - len); |
996 | if (skb->len < iphlen + len) { | 997 | if (skb->len < iphlen + len) { |
@@ -1002,7 +1003,8 @@ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb) | |||
1002 | * transport header to point to ESP. Keep UDP on the stack | 1003 | * transport header to point to ESP. Keep UDP on the stack |
1003 | * for later. | 1004 | * for later. |
1004 | */ | 1005 | */ |
1005 | skb->h.raw = skb_pull(skb, len); | 1006 | __skb_pull(skb, len); |
1007 | skb_reset_transport_header(skb); | ||
1006 | 1008 | ||
1007 | /* modify the protocol (it's ESP!) */ | 1009 | /* modify the protocol (it's ESP!) */ |
1008 | iph->protocol = IPPROTO_ESP; | 1010 | iph->protocol = IPPROTO_ESP; |
@@ -1095,10 +1097,9 @@ int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) | |||
1095 | } | 1097 | } |
1096 | } | 1098 | } |
1097 | 1099 | ||
1098 | if (sk->sk_filter && skb->ip_summed != CHECKSUM_UNNECESSARY) { | 1100 | if (sk->sk_filter) { |
1099 | if (__udp_lib_checksum_complete(skb)) | 1101 | if (udp_lib_checksum_complete(skb)) |
1100 | goto drop; | 1102 | goto drop; |
1101 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
1102 | } | 1103 | } |
1103 | 1104 | ||
1104 | if ((rc = sock_queue_rcv_skb(sk,skb)) < 0) { | 1105 | if ((rc = sock_queue_rcv_skb(sk,skb)) < 0) { |
@@ -1143,10 +1144,10 @@ static int __udp4_lib_mcast_deliver(struct sk_buff *skb, | |||
1143 | 1144 | ||
1144 | sknext = udp_v4_mcast_next(sk_next(sk), uh->dest, daddr, | 1145 | sknext = udp_v4_mcast_next(sk_next(sk), uh->dest, daddr, |
1145 | uh->source, saddr, dif); | 1146 | uh->source, saddr, dif); |
1146 | if(sknext) | 1147 | if (sknext) |
1147 | skb1 = skb_clone(skb, GFP_ATOMIC); | 1148 | skb1 = skb_clone(skb, GFP_ATOMIC); |
1148 | 1149 | ||
1149 | if(skb1) { | 1150 | if (skb1) { |
1150 | int ret = udp_queue_rcv_skb(sk, skb1); | 1151 | int ret = udp_queue_rcv_skb(sk, skb1); |
1151 | if (ret > 0) | 1152 | if (ret > 0) |
1152 | /* we should probably re-process instead | 1153 | /* we should probably re-process instead |
@@ -1154,7 +1155,7 @@ static int __udp4_lib_mcast_deliver(struct sk_buff *skb, | |||
1154 | kfree_skb(skb1); | 1155 | kfree_skb(skb1); |
1155 | } | 1156 | } |
1156 | sk = sknext; | 1157 | sk = sknext; |
1157 | } while(sknext); | 1158 | } while (sknext); |
1158 | } else | 1159 | } else |
1159 | kfree_skb(skb); | 1160 | kfree_skb(skb); |
1160 | read_unlock(&udp_hash_lock); | 1161 | read_unlock(&udp_hash_lock); |
@@ -1166,25 +1167,37 @@ static int __udp4_lib_mcast_deliver(struct sk_buff *skb, | |||
1166 | * Otherwise, csum completion requires chacksumming packet body, | 1167 | * Otherwise, csum completion requires chacksumming packet body, |
1167 | * including udp header and folding it to skb->csum. | 1168 | * including udp header and folding it to skb->csum. |
1168 | */ | 1169 | */ |
1169 | static inline void udp4_csum_init(struct sk_buff *skb, struct udphdr *uh) | 1170 | static inline int udp4_csum_init(struct sk_buff *skb, struct udphdr *uh, |
1171 | int proto) | ||
1170 | { | 1172 | { |
1173 | const struct iphdr *iph; | ||
1174 | int err; | ||
1175 | |||
1176 | UDP_SKB_CB(skb)->partial_cov = 0; | ||
1177 | UDP_SKB_CB(skb)->cscov = skb->len; | ||
1178 | |||
1179 | if (proto == IPPROTO_UDPLITE) { | ||
1180 | err = udplite_checksum_init(skb, uh); | ||
1181 | if (err) | ||
1182 | return err; | ||
1183 | } | ||
1184 | |||
1185 | iph = ip_hdr(skb); | ||
1171 | if (uh->check == 0) { | 1186 | if (uh->check == 0) { |
1172 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 1187 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
1173 | } else if (skb->ip_summed == CHECKSUM_COMPLETE) { | 1188 | } else if (skb->ip_summed == CHECKSUM_COMPLETE) { |
1174 | if (!csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr, | 1189 | if (!csum_tcpudp_magic(iph->saddr, iph->daddr, skb->len, |
1175 | skb->len, IPPROTO_UDP, skb->csum )) | 1190 | proto, skb->csum)) |
1176 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 1191 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
1177 | } | 1192 | } |
1178 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) | 1193 | if (!skb_csum_unnecessary(skb)) |
1179 | skb->csum = csum_tcpudp_nofold(skb->nh.iph->saddr, | 1194 | skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr, |
1180 | skb->nh.iph->daddr, | 1195 | skb->len, proto, 0); |
1181 | skb->len, IPPROTO_UDP, 0); | ||
1182 | /* Probably, we should checksum udp header (it should be in cache | 1196 | /* Probably, we should checksum udp header (it should be in cache |
1183 | * in any case) and data in tiny packets (< rx copybreak). | 1197 | * in any case) and data in tiny packets (< rx copybreak). |
1184 | */ | 1198 | */ |
1185 | 1199 | ||
1186 | /* UDP = UDP-Lite with a non-partial checksum coverage */ | 1200 | return 0; |
1187 | UDP_SKB_CB(skb)->partial_cov = 0; | ||
1188 | } | 1201 | } |
1189 | 1202 | ||
1190 | /* | 1203 | /* |
@@ -1192,14 +1205,14 @@ static inline void udp4_csum_init(struct sk_buff *skb, struct udphdr *uh) | |||
1192 | */ | 1205 | */ |
1193 | 1206 | ||
1194 | int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[], | 1207 | int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[], |
1195 | int is_udplite) | 1208 | int proto) |
1196 | { | 1209 | { |
1197 | struct sock *sk; | 1210 | struct sock *sk; |
1198 | struct udphdr *uh = skb->h.uh; | 1211 | struct udphdr *uh = udp_hdr(skb); |
1199 | unsigned short ulen; | 1212 | unsigned short ulen; |
1200 | struct rtable *rt = (struct rtable*)skb->dst; | 1213 | struct rtable *rt = (struct rtable*)skb->dst; |
1201 | __be32 saddr = skb->nh.iph->saddr; | 1214 | __be32 saddr = ip_hdr(skb)->saddr; |
1202 | __be32 daddr = skb->nh.iph->daddr; | 1215 | __be32 daddr = ip_hdr(skb)->daddr; |
1203 | 1216 | ||
1204 | /* | 1217 | /* |
1205 | * Validate the packet. | 1218 | * Validate the packet. |
@@ -1211,20 +1224,17 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[], | |||
1211 | if (ulen > skb->len) | 1224 | if (ulen > skb->len) |
1212 | goto short_packet; | 1225 | goto short_packet; |
1213 | 1226 | ||
1214 | if(! is_udplite ) { /* UDP validates ulen. */ | 1227 | if (proto == IPPROTO_UDP) { |
1215 | 1228 | /* UDP validates ulen. */ | |
1216 | if (ulen < sizeof(*uh) || pskb_trim_rcsum(skb, ulen)) | 1229 | if (ulen < sizeof(*uh) || pskb_trim_rcsum(skb, ulen)) |
1217 | goto short_packet; | 1230 | goto short_packet; |
1218 | uh = skb->h.uh; | 1231 | uh = udp_hdr(skb); |
1219 | |||
1220 | udp4_csum_init(skb, uh); | ||
1221 | |||
1222 | } else { /* UDP-Lite validates cscov. */ | ||
1223 | if (udplite4_csum_init(skb, uh)) | ||
1224 | goto csum_error; | ||
1225 | } | 1232 | } |
1226 | 1233 | ||
1227 | if(rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST)) | 1234 | if (udp4_csum_init(skb, uh, proto)) |
1235 | goto csum_error; | ||
1236 | |||
1237 | if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST)) | ||
1228 | return __udp4_lib_mcast_deliver(skb, uh, saddr, daddr, udptable); | 1238 | return __udp4_lib_mcast_deliver(skb, uh, saddr, daddr, udptable); |
1229 | 1239 | ||
1230 | sk = __udp4_lib_lookup(saddr, uh->source, daddr, uh->dest, | 1240 | sk = __udp4_lib_lookup(saddr, uh->source, daddr, uh->dest, |
@@ -1250,7 +1260,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[], | |||
1250 | if (udp_lib_checksum_complete(skb)) | 1260 | if (udp_lib_checksum_complete(skb)) |
1251 | goto csum_error; | 1261 | goto csum_error; |
1252 | 1262 | ||
1253 | UDP_INC_STATS_BH(UDP_MIB_NOPORTS, is_udplite); | 1263 | UDP_INC_STATS_BH(UDP_MIB_NOPORTS, proto == IPPROTO_UDPLITE); |
1254 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); | 1264 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); |
1255 | 1265 | ||
1256 | /* | 1266 | /* |
@@ -1258,11 +1268,11 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[], | |||
1258 | * don't wanna listen. Ignore it. | 1268 | * don't wanna listen. Ignore it. |
1259 | */ | 1269 | */ |
1260 | kfree_skb(skb); | 1270 | kfree_skb(skb); |
1261 | return(0); | 1271 | return 0; |
1262 | 1272 | ||
1263 | short_packet: | 1273 | short_packet: |
1264 | LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: short packet: From %u.%u.%u.%u:%u %d/%d to %u.%u.%u.%u:%u\n", | 1274 | LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: short packet: From %u.%u.%u.%u:%u %d/%d to %u.%u.%u.%u:%u\n", |
1265 | is_udplite? "-Lite" : "", | 1275 | proto == IPPROTO_UDPLITE ? "-Lite" : "", |
1266 | NIPQUAD(saddr), | 1276 | NIPQUAD(saddr), |
1267 | ntohs(uh->source), | 1277 | ntohs(uh->source), |
1268 | ulen, | 1278 | ulen, |
@@ -1277,21 +1287,21 @@ csum_error: | |||
1277 | * the network is concerned, anyway) as per 4.1.3.4 (MUST). | 1287 | * the network is concerned, anyway) as per 4.1.3.4 (MUST). |
1278 | */ | 1288 | */ |
1279 | LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: bad checksum. From %d.%d.%d.%d:%d to %d.%d.%d.%d:%d ulen %d\n", | 1289 | LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: bad checksum. From %d.%d.%d.%d:%d to %d.%d.%d.%d:%d ulen %d\n", |
1280 | is_udplite? "-Lite" : "", | 1290 | proto == IPPROTO_UDPLITE ? "-Lite" : "", |
1281 | NIPQUAD(saddr), | 1291 | NIPQUAD(saddr), |
1282 | ntohs(uh->source), | 1292 | ntohs(uh->source), |
1283 | NIPQUAD(daddr), | 1293 | NIPQUAD(daddr), |
1284 | ntohs(uh->dest), | 1294 | ntohs(uh->dest), |
1285 | ulen); | 1295 | ulen); |
1286 | drop: | 1296 | drop: |
1287 | UDP_INC_STATS_BH(UDP_MIB_INERRORS, is_udplite); | 1297 | UDP_INC_STATS_BH(UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE); |
1288 | kfree_skb(skb); | 1298 | kfree_skb(skb); |
1289 | return(0); | 1299 | return 0; |
1290 | } | 1300 | } |
1291 | 1301 | ||
1292 | __inline__ int udp_rcv(struct sk_buff *skb) | 1302 | int udp_rcv(struct sk_buff *skb) |
1293 | { | 1303 | { |
1294 | return __udp4_lib_rcv(skb, udp_hash, 0); | 1304 | return __udp4_lib_rcv(skb, udp_hash, IPPROTO_UDP); |
1295 | } | 1305 | } |
1296 | 1306 | ||
1297 | int udp_destroy_sock(struct sock *sk) | 1307 | int udp_destroy_sock(struct sock *sk) |
@@ -1313,13 +1323,13 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname, | |||
1313 | int val; | 1323 | int val; |
1314 | int err = 0; | 1324 | int err = 0; |
1315 | 1325 | ||
1316 | if(optlen<sizeof(int)) | 1326 | if (optlen<sizeof(int)) |
1317 | return -EINVAL; | 1327 | return -EINVAL; |
1318 | 1328 | ||
1319 | if (get_user(val, (int __user *)optval)) | 1329 | if (get_user(val, (int __user *)optval)) |
1320 | return -EFAULT; | 1330 | return -EFAULT; |
1321 | 1331 | ||
1322 | switch(optname) { | 1332 | switch (optname) { |
1323 | case UDP_CORK: | 1333 | case UDP_CORK: |
1324 | if (val != 0) { | 1334 | if (val != 0) { |
1325 | up->corkflag = 1; | 1335 | up->corkflag = 1; |
@@ -1373,7 +1383,7 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname, | |||
1373 | default: | 1383 | default: |
1374 | err = -ENOPROTOOPT; | 1384 | err = -ENOPROTOOPT; |
1375 | break; | 1385 | break; |
1376 | }; | 1386 | } |
1377 | 1387 | ||
1378 | return err; | 1388 | return err; |
1379 | } | 1389 | } |
@@ -1404,15 +1414,15 @@ int udp_lib_getsockopt(struct sock *sk, int level, int optname, | |||
1404 | struct udp_sock *up = udp_sk(sk); | 1414 | struct udp_sock *up = udp_sk(sk); |
1405 | int val, len; | 1415 | int val, len; |
1406 | 1416 | ||
1407 | if(get_user(len,optlen)) | 1417 | if (get_user(len,optlen)) |
1408 | return -EFAULT; | 1418 | return -EFAULT; |
1409 | 1419 | ||
1410 | len = min_t(unsigned int, len, sizeof(int)); | 1420 | len = min_t(unsigned int, len, sizeof(int)); |
1411 | 1421 | ||
1412 | if(len < 0) | 1422 | if (len < 0) |
1413 | return -EINVAL; | 1423 | return -EINVAL; |
1414 | 1424 | ||
1415 | switch(optname) { | 1425 | switch (optname) { |
1416 | case UDP_CORK: | 1426 | case UDP_CORK: |
1417 | val = up->corkflag; | 1427 | val = up->corkflag; |
1418 | break; | 1428 | break; |
@@ -1433,11 +1443,11 @@ int udp_lib_getsockopt(struct sock *sk, int level, int optname, | |||
1433 | 1443 | ||
1434 | default: | 1444 | default: |
1435 | return -ENOPROTOOPT; | 1445 | return -ENOPROTOOPT; |
1436 | }; | 1446 | } |
1437 | 1447 | ||
1438 | if(put_user(len, optlen)) | 1448 | if (put_user(len, optlen)) |
1439 | return -EFAULT; | 1449 | return -EFAULT; |
1440 | if(copy_to_user(optval, &val,len)) | 1450 | if (copy_to_user(optval, &val,len)) |
1441 | return -EFAULT; | 1451 | return -EFAULT; |
1442 | return 0; | 1452 | return 0; |
1443 | } | 1453 | } |
@@ -1486,15 +1496,11 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait) | |||
1486 | struct sk_buff *skb; | 1496 | struct sk_buff *skb; |
1487 | 1497 | ||
1488 | spin_lock_bh(&rcvq->lock); | 1498 | spin_lock_bh(&rcvq->lock); |
1489 | while ((skb = skb_peek(rcvq)) != NULL) { | 1499 | while ((skb = skb_peek(rcvq)) != NULL && |
1490 | if (udp_lib_checksum_complete(skb)) { | 1500 | udp_lib_checksum_complete(skb)) { |
1491 | UDP_INC_STATS_BH(UDP_MIB_INERRORS, is_lite); | 1501 | UDP_INC_STATS_BH(UDP_MIB_INERRORS, is_lite); |
1492 | __skb_unlink(skb, rcvq); | 1502 | __skb_unlink(skb, rcvq); |
1493 | kfree_skb(skb); | 1503 | kfree_skb(skb); |
1494 | } else { | ||
1495 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
1496 | break; | ||
1497 | } | ||
1498 | } | 1504 | } |
1499 | spin_unlock_bh(&rcvq->lock); | 1505 | spin_unlock_bh(&rcvq->lock); |
1500 | 1506 | ||
@@ -1573,7 +1579,7 @@ static struct sock *udp_get_idx(struct seq_file *seq, loff_t pos) | |||
1573 | struct sock *sk = udp_get_first(seq); | 1579 | struct sock *sk = udp_get_first(seq); |
1574 | 1580 | ||
1575 | if (sk) | 1581 | if (sk) |
1576 | while(pos && (sk = udp_get_next(seq, sk)) != NULL) | 1582 | while (pos && (sk = udp_get_next(seq, sk)) != NULL) |
1577 | --pos; | 1583 | --pos; |
1578 | return pos ? NULL : sk; | 1584 | return pos ? NULL : sk; |
1579 | } | 1585 | } |