aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/udp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/udp.c')
-rw-r--r--net/ipv4/udp.c120
1 files changed, 79 insertions, 41 deletions
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index f136cec96d95..77e265d7bb8f 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -118,14 +118,33 @@ DEFINE_SNMP_STAT(struct udp_mib, udp_statistics) __read_mostly;
118struct hlist_head udp_hash[UDP_HTABLE_SIZE]; 118struct hlist_head udp_hash[UDP_HTABLE_SIZE];
119DEFINE_RWLOCK(udp_hash_lock); 119DEFINE_RWLOCK(udp_hash_lock);
120 120
121/* Shared by v4/v6 udp. */ 121static int udp_port_rover;
122int udp_port_rover;
123 122
124static int udp_v4_get_port(struct sock *sk, unsigned short snum) 123static inline int udp_lport_inuse(u16 num)
124{
125 struct sock *sk;
126 struct hlist_node *node;
127
128 sk_for_each(sk, node, &udp_hash[num & (UDP_HTABLE_SIZE - 1)])
129 if (inet_sk(sk)->num == num)
130 return 1;
131 return 0;
132}
133
134/**
135 * udp_get_port - common port lookup for IPv4 and IPv6
136 *
137 * @sk: socket struct in question
138 * @snum: port number to look up
139 * @saddr_comp: AF-dependent comparison of bound local IP addresses
140 */
141int udp_get_port(struct sock *sk, unsigned short snum,
142 int (*saddr_cmp)(const struct sock *sk1, const struct sock *sk2))
125{ 143{
126 struct hlist_node *node; 144 struct hlist_node *node;
145 struct hlist_head *head;
127 struct sock *sk2; 146 struct sock *sk2;
128 struct inet_sock *inet = inet_sk(sk); 147 int error = 1;
129 148
130 write_lock_bh(&udp_hash_lock); 149 write_lock_bh(&udp_hash_lock);
131 if (snum == 0) { 150 if (snum == 0) {
@@ -137,11 +156,10 @@ static int udp_v4_get_port(struct sock *sk, unsigned short snum)
137 best_size_so_far = 32767; 156 best_size_so_far = 32767;
138 best = result = udp_port_rover; 157 best = result = udp_port_rover;
139 for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) { 158 for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) {
140 struct hlist_head *list;
141 int size; 159 int size;
142 160
143 list = &udp_hash[result & (UDP_HTABLE_SIZE - 1)]; 161 head = &udp_hash[result & (UDP_HTABLE_SIZE - 1)];
144 if (hlist_empty(list)) { 162 if (hlist_empty(head)) {
145 if (result > sysctl_local_port_range[1]) 163 if (result > sysctl_local_port_range[1])
146 result = sysctl_local_port_range[0] + 164 result = sysctl_local_port_range[0] +
147 ((result - sysctl_local_port_range[0]) & 165 ((result - sysctl_local_port_range[0]) &
@@ -149,12 +167,11 @@ static int udp_v4_get_port(struct sock *sk, unsigned short snum)
149 goto gotit; 167 goto gotit;
150 } 168 }
151 size = 0; 169 size = 0;
152 sk_for_each(sk2, node, list) 170 sk_for_each(sk2, node, head)
153 if (++size >= best_size_so_far) 171 if (++size < best_size_so_far) {
154 goto next; 172 best_size_so_far = size;
155 best_size_so_far = size; 173 best = result;
156 best = result; 174 }
157 next:;
158 } 175 }
159 result = best; 176 result = best;
160 for(i = 0; i < (1 << 16) / UDP_HTABLE_SIZE; i++, result += UDP_HTABLE_SIZE) { 177 for(i = 0; i < (1 << 16) / UDP_HTABLE_SIZE; i++, result += UDP_HTABLE_SIZE) {
@@ -170,38 +187,44 @@ static int udp_v4_get_port(struct sock *sk, unsigned short snum)
170gotit: 187gotit:
171 udp_port_rover = snum = result; 188 udp_port_rover = snum = result;
172 } else { 189 } else {
173 sk_for_each(sk2, node, 190 head = &udp_hash[snum & (UDP_HTABLE_SIZE - 1)];
174 &udp_hash[snum & (UDP_HTABLE_SIZE - 1)]) { 191
175 struct inet_sock *inet2 = inet_sk(sk2); 192 sk_for_each(sk2, node, head)
176 193 if (inet_sk(sk2)->num == snum &&
177 if (inet2->num == snum && 194 sk2 != sk &&
178 sk2 != sk && 195 (!sk2->sk_reuse || !sk->sk_reuse) &&
179 !ipv6_only_sock(sk2) && 196 (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if
180 (!sk2->sk_bound_dev_if || 197 || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
181 !sk->sk_bound_dev_if || 198 (*saddr_cmp)(sk, sk2) )
182 sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
183 (!inet2->rcv_saddr ||
184 !inet->rcv_saddr ||
185 inet2->rcv_saddr == inet->rcv_saddr) &&
186 (!sk2->sk_reuse || !sk->sk_reuse))
187 goto fail; 199 goto fail;
188 }
189 } 200 }
190 inet->num = snum; 201 inet_sk(sk)->num = snum;
191 if (sk_unhashed(sk)) { 202 if (sk_unhashed(sk)) {
192 struct hlist_head *h = &udp_hash[snum & (UDP_HTABLE_SIZE - 1)]; 203 head = &udp_hash[snum & (UDP_HTABLE_SIZE - 1)];
193 204 sk_add_node(sk, head);
194 sk_add_node(sk, h);
195 sock_prot_inc_use(sk->sk_prot); 205 sock_prot_inc_use(sk->sk_prot);
196 } 206 }
197 write_unlock_bh(&udp_hash_lock); 207 error = 0;
198 return 0;
199
200fail: 208fail:
201 write_unlock_bh(&udp_hash_lock); 209 write_unlock_bh(&udp_hash_lock);
202 return 1; 210 return error;
211}
212
213static inline int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
214{
215 struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2);
216
217 return ( !ipv6_only_sock(sk2) &&
218 (!inet1->rcv_saddr || !inet2->rcv_saddr ||
219 inet1->rcv_saddr == inet2->rcv_saddr ));
203} 220}
204 221
222static inline int udp_v4_get_port(struct sock *sk, unsigned short snum)
223{
224 return udp_get_port(sk, snum, ipv4_rcv_saddr_equal);
225}
226
227
205static void udp_v4_hash(struct sock *sk) 228static void udp_v4_hash(struct sock *sk)
206{ 229{
207 BUG(); 230 BUG();
@@ -429,7 +452,7 @@ static int udp_push_pending_frames(struct sock *sk, struct udp_sock *up)
429 /* 452 /*
430 * Only one fragment on the socket. 453 * Only one fragment on the socket.
431 */ 454 */
432 if (skb->ip_summed == CHECKSUM_HW) { 455 if (skb->ip_summed == CHECKSUM_PARTIAL) {
433 skb->csum = offsetof(struct udphdr, check); 456 skb->csum = offsetof(struct udphdr, check);
434 uh->check = ~csum_tcpudp_magic(fl->fl4_src, fl->fl4_dst, 457 uh->check = ~csum_tcpudp_magic(fl->fl4_src, fl->fl4_dst,
435 up->len, IPPROTO_UDP, 0); 458 up->len, IPPROTO_UDP, 0);
@@ -448,7 +471,7 @@ static int udp_push_pending_frames(struct sock *sk, struct udp_sock *up)
448 * fragments on the socket so that all csums of sk_buffs 471 * fragments on the socket so that all csums of sk_buffs
449 * should be together. 472 * should be together.
450 */ 473 */
451 if (skb->ip_summed == CHECKSUM_HW) { 474 if (skb->ip_summed == CHECKSUM_PARTIAL) {
452 int offset = (unsigned char *)uh - skb->data; 475 int offset = (unsigned char *)uh - skb->data;
453 skb->csum = skb_checksum(skb, offset, skb->len - offset, 0); 476 skb->csum = skb_checksum(skb, offset, skb->len - offset, 0);
454 477
@@ -603,6 +626,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
603 .uli_u = { .ports = 626 .uli_u = { .ports =
604 { .sport = inet->sport, 627 { .sport = inet->sport,
605 .dport = dport } } }; 628 .dport = dport } } };
629 security_sk_classify_flow(sk, &fl);
606 err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT)); 630 err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT));
607 if (err) 631 if (err)
608 goto out; 632 goto out;
@@ -661,6 +685,16 @@ out:
661 UDP_INC_STATS_USER(UDP_MIB_OUTDATAGRAMS); 685 UDP_INC_STATS_USER(UDP_MIB_OUTDATAGRAMS);
662 return len; 686 return len;
663 } 687 }
688 /*
689 * ENOBUFS = no kernel mem, SOCK_NOSPACE = no sndbuf space. Reporting
690 * ENOBUFS might not be good (it's not tunable per se), but otherwise
691 * we don't have a good statistic (IpOutDiscards but it can be too many
692 * things). We could add another new stat but at least for now that
693 * seems like overkill.
694 */
695 if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) {
696 UDP_INC_STATS_USER(UDP_MIB_SNDBUFERRORS);
697 }
664 return err; 698 return err;
665 699
666do_confirm: 700do_confirm:
@@ -980,6 +1014,7 @@ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb)
980static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) 1014static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
981{ 1015{
982 struct udp_sock *up = udp_sk(sk); 1016 struct udp_sock *up = udp_sk(sk);
1017 int rc;
983 1018
984 /* 1019 /*
985 * Charge it to the socket, dropping if the queue is full. 1020 * Charge it to the socket, dropping if the queue is full.
@@ -1026,7 +1061,10 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
1026 skb->ip_summed = CHECKSUM_UNNECESSARY; 1061 skb->ip_summed = CHECKSUM_UNNECESSARY;
1027 } 1062 }
1028 1063
1029 if (sock_queue_rcv_skb(sk,skb)<0) { 1064 if ((rc = sock_queue_rcv_skb(sk,skb)) < 0) {
1065 /* Note that an ENOMEM error is charged twice */
1066 if (rc == -ENOMEM)
1067 UDP_INC_STATS_BH(UDP_MIB_RCVBUFERRORS);
1030 UDP_INC_STATS_BH(UDP_MIB_INERRORS); 1068 UDP_INC_STATS_BH(UDP_MIB_INERRORS);
1031 kfree_skb(skb); 1069 kfree_skb(skb);
1032 return -1; 1070 return -1;
@@ -1087,7 +1125,7 @@ static void udp_checksum_init(struct sk_buff *skb, struct udphdr *uh,
1087{ 1125{
1088 if (uh->check == 0) { 1126 if (uh->check == 0) {
1089 skb->ip_summed = CHECKSUM_UNNECESSARY; 1127 skb->ip_summed = CHECKSUM_UNNECESSARY;
1090 } else if (skb->ip_summed == CHECKSUM_HW) { 1128 } else if (skb->ip_summed == CHECKSUM_COMPLETE) {
1091 if (!udp_check(uh, ulen, saddr, daddr, skb->csum)) 1129 if (!udp_check(uh, ulen, saddr, daddr, skb->csum))
1092 skb->ip_summed = CHECKSUM_UNNECESSARY; 1130 skb->ip_summed = CHECKSUM_UNNECESSARY;
1093 } 1131 }
@@ -1581,7 +1619,7 @@ EXPORT_SYMBOL(udp_disconnect);
1581EXPORT_SYMBOL(udp_hash); 1619EXPORT_SYMBOL(udp_hash);
1582EXPORT_SYMBOL(udp_hash_lock); 1620EXPORT_SYMBOL(udp_hash_lock);
1583EXPORT_SYMBOL(udp_ioctl); 1621EXPORT_SYMBOL(udp_ioctl);
1584EXPORT_SYMBOL(udp_port_rover); 1622EXPORT_SYMBOL(udp_get_port);
1585EXPORT_SYMBOL(udp_prot); 1623EXPORT_SYMBOL(udp_prot);
1586EXPORT_SYMBOL(udp_sendmsg); 1624EXPORT_SYMBOL(udp_sendmsg);
1587EXPORT_SYMBOL(udp_poll); 1625EXPORT_SYMBOL(udp_poll);