00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
#include <asm/system.h>
00076
#include <asm/uaccess.h>
00077
#include <asm/ioctls.h>
00078
#include <linux/types.h>
00079
#include <linux/fcntl.h>
00080
#include <linux/socket.h>
00081
#include <linux/sockios.h>
00082
#include <linux/in.h>
00083
#include <linux/errno.h>
00084
#include <linux/timer.h>
00085
#include <linux/mm.h>
00086
#include <linux/config.h>
00087
#include <linux/inet.h>
00088
#include <linux/netdevice.h>
00089
#include <net/snmp.h>
00090
#include <net/ip.h>
00091
#include <net/ipv6.h>
00092
#include <net/protocol.h>
00093
#include <linux/skbuff.h>
00094
#include <net/sock.h>
00095
#include <net/udp.h>
00096
#include <net/icmp.h>
00097
#include <net/route.h>
00098
#include <net/inet_common.h>
00099
#include <net/checksum.h>
00100
00101
00102
00103
00104
00105 struct udp_mib udp_statistics[NR_CPUS*2];
00106
00107 struct sock *
udp_hash[
UDP_HTABLE_SIZE];
00108 rwlock_t
udp_hash_lock = RW_LOCK_UNLOCKED;
00109
00110
00111 int udp_port_rover;
00112
00113 static int udp_v4_get_port(
struct sock *sk,
unsigned short snum)
00114 {
00115 write_lock_bh(&
udp_hash_lock);
00116
if (snum == 0) {
00117
int best_size_so_far, best, result, i;
00118
00119
if (
udp_port_rover >
sysctl_local_port_range[1] ||
00120
udp_port_rover <
sysctl_local_port_range[0])
00121
udp_port_rover =
sysctl_local_port_range[0];
00122 best_size_so_far = 32767;
00123 best = result =
udp_port_rover;
00124
for (i = 0; i <
UDP_HTABLE_SIZE; i++, result++) {
00125
struct sock *sk;
00126
int size;
00127
00128 sk =
udp_hash[result & (
UDP_HTABLE_SIZE - 1)];
00129
if (!sk) {
00130
if (result >
sysctl_local_port_range[1])
00131 result =
sysctl_local_port_range[0] +
00132 ((result -
sysctl_local_port_range[0]) &
00133 (
UDP_HTABLE_SIZE - 1));
00134
goto gotit;
00135 }
00136 size = 0;
00137
do {
00138
if (++size >= best_size_so_far)
00139
goto next;
00140 }
while ((sk = sk->
next) != NULL);
00141 best_size_so_far = size;
00142 best = result;
00143 next:;
00144 }
00145 result = best;
00146
for(i = 0; i < (1 << 16) /
UDP_HTABLE_SIZE; i++, result +=
UDP_HTABLE_SIZE) {
00147
if (result >
sysctl_local_port_range[1])
00148 result =
sysctl_local_port_range[0]
00149 + ((result -
sysctl_local_port_range[0]) &
00150 (
UDP_HTABLE_SIZE - 1));
00151
if (!
udp_lport_inuse(result))
00152
break;
00153 }
00154
if (i >= (1 << 16) /
UDP_HTABLE_SIZE)
00155
goto fail;
00156 gotit:
00157
udp_port_rover = snum = result;
00158 }
else {
00159
struct sock *sk2;
00160
00161
for (sk2 =
udp_hash[snum & (
UDP_HTABLE_SIZE - 1)];
00162 sk2 != NULL;
00163 sk2 = sk2->
next) {
00164
if (sk2->num == snum &&
00165 sk2 != sk &&
00166 !
ipv6_only_sock(sk2) &&
00167 (!sk2->bound_dev_if ||
00168 !sk->
bound_dev_if ||
00169 sk2->bound_dev_if == sk->
bound_dev_if) &&
00170 (!sk2->rcv_saddr ||
00171 !sk->
rcv_saddr ||
00172 sk2->rcv_saddr == sk->
rcv_saddr) &&
00173 (!sk2->reuse || !sk->
reuse))
00174
goto fail;
00175 }
00176 }
00177 sk->
num = snum;
00178
if (sk->
pprev == NULL) {
00179
struct sock **skp = &
udp_hash[snum & (
UDP_HTABLE_SIZE - 1)];
00180
if ((sk->
next = *skp) != NULL)
00181 (*skp)->
pprev = &sk->
next;
00182 *skp = sk;
00183 sk->
pprev = skp;
00184
sock_prot_inc_use(sk->prot);
00185
sock_hold(sk);
00186 }
00187 write_unlock_bh(&
udp_hash_lock);
00188
return 0;
00189
00190 fail:
00191 write_unlock_bh(&
udp_hash_lock);
00192
return 1;
00193 }
00194
00195 static void udp_v4_hash(
struct sock *sk)
00196 {
00197 BUG();
00198 }
00199
00200 static void udp_v4_unhash(
struct sock *sk)
00201 {
00202 write_lock_bh(&
udp_hash_lock);
00203
if (sk->
pprev) {
00204
if (sk->
next)
00205 sk->
next->
pprev = sk->
pprev;
00206 *sk->
pprev = sk->
next;
00207 sk->
pprev = NULL;
00208 sk->
num = 0;
00209
sock_prot_dec_use(sk->
prot);
00210
__sock_put(sk);
00211 }
00212 write_unlock_bh(&
udp_hash_lock);
00213 }
00214
00215
00216
00217
00218 struct sock *
udp_v4_lookup_longway(u32 saddr, u16 sport, u32 daddr, u16 dport,
int dif)
00219 {
00220
struct sock *sk, *result = NULL;
00221
unsigned short hnum = ntohs(dport);
00222
int badness = -1;
00223
00224
for(sk =
udp_hash[hnum & (
UDP_HTABLE_SIZE - 1)]; sk != NULL; sk = sk->
next) {
00225
if(sk->num == hnum && !
ipv6_only_sock(sk)) {
00226
int score;
00227
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
00228
score = sk->family == PF_INET ? 1 : 0;
00229
#else
00230
score = 1;
00231
#endif
00232
if(sk->rcv_saddr) {
00233
if(sk->rcv_saddr != daddr)
00234
continue;
00235 score+=2;
00236 }
00237
if(sk->daddr) {
00238
if(sk->daddr != saddr)
00239
continue;
00240 score+=2;
00241 }
00242
if(sk->dport) {
00243
if(sk->dport != sport)
00244
continue;
00245 score+=2;
00246 }
00247
if(sk->bound_dev_if) {
00248
if(sk->bound_dev_if != dif)
00249
continue;
00250 score+=2;
00251 }
00252
if(score == 9) {
00253 result = sk;
00254
break;
00255 }
else if(score > badness) {
00256 result = sk;
00257 badness = score;
00258 }
00259 }
00260 }
00261
return result;
00262 }
00263
00264 __inline__
struct sock *
udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport,
int dif)
00265 {
00266
struct sock *sk;
00267
00268 read_lock(&
udp_hash_lock);
00269 sk =
udp_v4_lookup_longway(saddr, sport, daddr, dport, dif);
00270
if (sk)
00271
sock_hold(sk);
00272 read_unlock(&
udp_hash_lock);
00273
return sk;
00274 }
00275
00276
extern int ip_mc_sf_allow(
struct sock *sk, u32 local, u32 rmt,
int dif);
00277
00278 static inline struct sock *
udp_v4_mcast_next(
struct sock *sk,
00279 u16 loc_port, u32 loc_addr,
00280 u16 rmt_port, u32 rmt_addr,
00281
int dif)
00282 {
00283
struct sock *s = sk;
00284
unsigned short hnum = ntohs(loc_port);
00285
for(; s; s = s->next) {
00286
if ((s->num != hnum) ||
00287 (s->daddr && s->daddr!=rmt_addr) ||
00288 (s->dport != rmt_port && s->dport != 0) ||
00289 (s->rcv_saddr && s->rcv_saddr != loc_addr) ||
00290
ipv6_only_sock(s) ||
00291 (s->bound_dev_if && s->bound_dev_if != dif))
00292
continue;
00293
if (!
ip_mc_sf_allow(sk, loc_addr, rmt_addr, dif))
00294
continue;
00295
break;
00296 }
00297
return s;
00298 }
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311 void udp_err(
struct sk_buff *skb, u32 info)
00312 {
00313
struct iphdr *iph = (
struct iphdr*)skb->
data;
00314
struct udphdr *uh = (
struct udphdr*)(skb->
data+(iph->ihl<<2));
00315
int type = skb->
h.icmph->type;
00316
int code = skb->
h.icmph->code;
00317
struct sock *sk;
00318
int harderr;
00319
int err;
00320
00321 sk =
udp_v4_lookup(iph->daddr, uh->dest, iph->saddr, uh->source, skb->
dev->
ifindex);
00322
if (sk == NULL) {
00323
ICMP_INC_STATS_BH(IcmpInErrors);
00324
return;
00325 }
00326
00327 err = 0;
00328 harderr = 0;
00329
00330
switch (type) {
00331
default:
00332
case ICMP_TIME_EXCEEDED:
00333 err = EHOSTUNREACH;
00334
break;
00335
case ICMP_SOURCE_QUENCH:
00336
goto out;
00337
case ICMP_PARAMETERPROB:
00338 err = EPROTO;
00339 harderr = 1;
00340
break;
00341
case ICMP_DEST_UNREACH:
00342
if (code == ICMP_FRAG_NEEDED) {
00343
if (sk->protinfo.af_inet.pmtudisc !=
IP_PMTUDISC_DONT) {
00344 err = EMSGSIZE;
00345 harderr = 1;
00346
break;
00347 }
00348
goto out;
00349 }
00350 err = EHOSTUNREACH;
00351
if (code <= NR_ICMP_UNREACH) {
00352 harderr =
icmp_err_convert[code].
fatal;
00353 err =
icmp_err_convert[code].
errno;
00354 }
00355
break;
00356 }
00357
00358
00359
00360
00361
00362
if (!sk->protinfo.af_inet.recverr) {
00363
if (!harderr || sk->state != TCP_ESTABLISHED)
00364
goto out;
00365 }
else {
00366
ip_icmp_error(sk, skb, err, uh->dest, info, (u8*)(uh+1));
00367 }
00368 sk->err = err;
00369 sk->error_report(sk);
00370 out:
00371
sock_put(sk);
00372 }
00373
00374
00375 static unsigned short udp_check(
struct udphdr *uh,
int len,
unsigned long saddr,
unsigned long daddr,
unsigned long base)
00376 {
00377
return(
csum_tcpudp_magic(saddr, daddr, len,
IPPROTO_UDP, base));
00378 }
00379
00380 struct udpfakehdr
00381 {
00382 struct udphdr uh;
00383 u32
saddr;
00384 u32
daddr;
00385 struct iovec *
iov;
00386 u32
wcheck;
00387 };
00388
00389
00390
00391
00392
00393 static int udp_getfrag(
const void *p,
char * to,
unsigned int offset,
unsigned int fraglen)
00394 {
00395
struct udpfakehdr *ufh = (
struct udpfakehdr *)p;
00396
if (offset==0) {
00397
if (
csum_partial_copy_fromiovecend(to+
sizeof(
struct udphdr), ufh->iov, offset,
00398 fraglen-
sizeof(
struct udphdr), &ufh->wcheck))
00399
return -EFAULT;
00400 ufh->wcheck =
csum_partial((
char *)ufh,
sizeof(
struct udphdr),
00401 ufh->wcheck);
00402 ufh->uh.check =
csum_tcpudp_magic(ufh->saddr, ufh->daddr,
00403 ntohs(ufh->uh.len),
00404
IPPROTO_UDP, ufh->wcheck);
00405
if (ufh->uh.check == 0)
00406 ufh->uh.check = -1;
00407 memcpy(to, ufh,
sizeof(
struct udphdr));
00408
return 0;
00409 }
00410
if (
csum_partial_copy_fromiovecend(to, ufh->iov, offset-
sizeof(
struct udphdr),
00411 fraglen, &ufh->wcheck))
00412
return -EFAULT;
00413
return 0;
00414 }
00415
00416
00417
00418
00419
00420 static int udp_getfrag_nosum(
const void *p,
char * to,
unsigned int offset,
unsigned int fraglen)
00421 {
00422
struct udpfakehdr *ufh = (
struct udpfakehdr *)p;
00423
00424
if (offset==0) {
00425 memcpy(to, ufh,
sizeof(
struct udphdr));
00426
return memcpy_fromiovecend(to+
sizeof(
struct udphdr), ufh->iov, offset,
00427 fraglen-
sizeof(
struct udphdr));
00428 }
00429
return memcpy_fromiovecend(to, ufh->iov, offset-
sizeof(
struct udphdr),
00430 fraglen);
00431 }
00432
00461 int udp_sendmsg(
struct sock *sk,
struct msghdr *msg,
int len)
00462 {
00463
int ulen = len +
sizeof(
struct udphdr);
00464
struct ipcm_cookie ipc;
00465
struct udpfakehdr ufh;
00466
struct rtable *rt = NULL;
00467
int free = 0;
00468
int connected = 0;
00469 u32 daddr;
00470 u8 tos;
00471
int err;
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
if (len < 0 || len > 0xFFFF)
00485
return -EMSGSIZE;
00486
00487
00488
00489
00490
00491
if (msg->msg_flags&MSG_OOB)
00492
return -EOPNOTSUPP;
00493
00494
00495
00496
00497
00498
if (msg->msg_name) {
00499
struct sockaddr_in * usin = (
struct sockaddr_in*)msg->msg_name;
00500
if (msg->msg_namelen <
sizeof(*usin))
00501
return -EINVAL;
00502
if (usin->sin_family != AF_INET) {
00503
if (usin->sin_family != AF_UNSPEC)
00504
return -EINVAL;
00505 }
00506
00507 ufh.
daddr = usin->sin_addr.s_addr;
00508 ufh.
uh.dest = usin->sin_port;
00509
if (ufh.
uh.dest == 0)
00510
return -EINVAL;
00511 }
else {
00512
if (sk->
state != TCP_ESTABLISHED)
00513
return -EDESTADDRREQ;
00514 ufh.
daddr = sk->
daddr;
00515 ufh.
uh.dest = sk->
dport;
00516
00517
00518
00519 connected = 1;
00520 }
00521 ipc.
addr = sk->
saddr;
00522 ufh.
uh.source = sk->
sport;
00523
00524 ipc.
opt = NULL;
00525 ipc.
oif = sk->
bound_dev_if;
00526
if (msg->msg_controllen) {
00527 err =
ip_cmsg_send(msg, &ipc);
00528
if (err)
00529
return err;
00530
if (ipc.
opt)
00531 free = 1;
00532 connected = 0;
00533 }
00534
if (!ipc.
opt)
00535 ipc.
opt = sk->
protinfo.af_inet.opt;
00536
00537 ufh.
saddr = ipc.
addr;
00538 ipc.
addr = daddr = ufh.
daddr;
00539
00540
if (ipc.
opt && ipc.
opt->
srr) {
00541
if (!daddr)
00542
return -EINVAL;
00543 daddr = ipc.
opt->
faddr;
00544 connected = 0;
00545 }
00546 tos = RT_TOS(sk->
protinfo.af_inet.tos);
00547
if (sk->
localroute || (msg->msg_flags&MSG_DONTROUTE) ||
00548 (ipc.
opt && ipc.
opt->
is_strictroute)) {
00549 tos |=
RTO_ONLINK;
00550 connected = 0;
00551 }
00552
00553
if (
MULTICAST(daddr)) {
00554
if (!ipc.
oif)
00555 ipc.
oif = sk->
protinfo.af_inet.mc_index;
00556
if (!ufh.
saddr)
00557 ufh.
saddr = sk->
protinfo.af_inet.mc_addr;
00558 connected = 0;
00559 }
00560
00561
if (connected)
00562 rt = (
struct rtable*)
sk_dst_check(sk, 0);
00563
00564
if (rt == NULL) {
00565 err =
ip_route_output(&rt, daddr, ufh.
saddr, tos, ipc.
oif);
00566
if (err)
00567
goto out;
00568
00569 err = -EACCES;
00570
if (rt->rt_flags&RTCF_BROADCAST && !sk->
broadcast)
00571
goto out;
00572
if (connected)
00573
sk_dst_set(sk,
dst_clone(&rt->u.dst));
00574 }
00575
00576
if (msg->msg_flags&MSG_CONFIRM)
00577
goto do_confirm;
00578 back_from_confirm:
00579
00580 ufh.
saddr = rt->rt_src;
00581
if (!ipc.
addr)
00582 ufh.
daddr = ipc.
addr = rt->rt_dst;
00583 ufh.
uh.len = htons(ulen);
00584 ufh.
uh.check = 0;
00585 ufh.
iov = msg->msg_iov;
00586 ufh.
wcheck = 0;
00587
00588
00589
00590
00591
00592 err =
ip_build_xmit(sk,
00593 (sk->
no_check ==
UDP_CSUM_NOXMIT ?
00594
udp_getfrag_nosum :
00595
udp_getfrag),
00596 &ufh, ulen, &ipc, rt, msg->msg_flags);
00597
00598 out:
00599
ip_rt_put(rt);
00600
if (free)
00601 kfree(ipc.
opt);
00602
if (!err) {
00603
UDP_INC_STATS_USER(UdpOutDatagrams);
00604
return len;
00605 }
00606
return err;
00607
00608 do_confirm:
00609
dst_confirm(&rt->u.dst);
00610
if (!(msg->msg_flags&MSG_PROBE) || len)
00611
goto back_from_confirm;
00612 err = 0;
00613
goto out;
00614 }
00615
00616
00617
00618
00619
00620 int udp_ioctl(
struct sock *sk,
int cmd,
unsigned long arg)
00621 {
00622
switch(cmd)
00623 {
00624
case SIOCOUTQ:
00625 {
00626
int amount = atomic_read(&sk->
wmem_alloc);
00627
return put_user(amount, (
int *)arg);
00628 }
00629
00630
case SIOCINQ:
00631 {
00632
struct sk_buff *skb;
00633
unsigned long amount;
00634
00635 amount = 0;
00636 spin_lock_irq(&sk->
receive_queue.
lock);
00637 skb =
skb_peek(&sk->
receive_queue);
00638
if (skb != NULL) {
00639
00640
00641
00642
00643
00644 amount = skb->len -
sizeof(
struct udphdr);
00645 }
00646 spin_unlock_irq(&sk->
receive_queue.
lock);
00647
return put_user(amount, (
int *)arg);
00648 }
00649
00650
default:
00651
return -ENOIOCTLCMD;
00652 }
00653
return(0);
00654 }
00655
00656 static __inline__
int __udp_checksum_complete(
struct sk_buff *skb)
00657 {
00658
return (
unsigned short)
csum_fold(
skb_checksum(skb, 0, skb->
len, skb->
csum));
00659 }
00660
00661 static __inline__
int udp_checksum_complete(
struct sk_buff *skb)
00662 {
00663
return skb->
ip_summed !=
CHECKSUM_UNNECESSARY &&
00664
__udp_checksum_complete(skb);
00665 }
00666
00667
00668
00669
00670
00671
00672 int udp_recvmsg(
struct sock *sk,
struct msghdr *msg,
int len,
00673
int noblock,
int flags,
int *addr_len)
00674 {
00675
struct sockaddr_in *sin = (
struct sockaddr_in *)msg->msg_name;
00676
struct sk_buff *skb;
00677
int copied, err;
00678
00679
00680
00681
00682
if (addr_len)
00683 *addr_len=
sizeof(*sin);
00684
00685
if (flags & MSG_ERRQUEUE)
00686
return ip_recv_error(sk, msg, len);
00687
00688 skb =
skb_recv_datagram(sk, flags, noblock, &err);
00689
if (!skb)
00690
goto out;
00691
00692 copied = skb->len -
sizeof(
struct udphdr);
00693
if (copied > len) {
00694 copied = len;
00695 msg->msg_flags |= MSG_TRUNC;
00696 }
00697
00698
if (skb->ip_summed==
CHECKSUM_UNNECESSARY) {
00699 err =
skb_copy_datagram_iovec(skb,
sizeof(
struct udphdr), msg->msg_iov,
00700 copied);
00701 }
else if (msg->msg_flags&MSG_TRUNC) {
00702
if (
__udp_checksum_complete(skb))
00703
goto csum_copy_err;
00704 err =
skb_copy_datagram_iovec(skb,
sizeof(
struct udphdr), msg->msg_iov,
00705 copied);
00706 }
else {
00707 err =
skb_copy_and_csum_datagram_iovec(skb,
sizeof(
struct udphdr), msg->msg_iov);
00708
00709
if (err == -EINVAL)
00710
goto csum_copy_err;
00711 }
00712
00713
if (err)
00714
goto out_free;
00715
00716
sock_recv_timestamp(msg, sk, skb);
00717
00718
00719
if (sin)
00720 {
00721 sin->sin_family = AF_INET;
00722 sin->sin_port = skb->h.uh->source;
00723 sin->sin_addr.s_addr = skb->nh.iph->saddr;
00724 memset(sin->sin_zero, 0,
sizeof(sin->sin_zero));
00725 }
00726
if (sk->
protinfo.af_inet.cmsg_flags)
00727
ip_cmsg_recv(msg, skb);
00728 err = copied;
00729
00730 out_free:
00731
skb_free_datagram(sk, skb);
00732 out:
00733
return err;
00734
00735 csum_copy_err:
00736
UDP_INC_STATS_BH(UdpInErrors);
00737
00738
00739
if (flags&MSG_PEEK) {
00740
int clear = 0;
00741 spin_lock_irq(&sk->
receive_queue.
lock);
00742
if (skb ==
skb_peek(&sk->
receive_queue)) {
00743
__skb_unlink(skb, &sk->
receive_queue);
00744 clear = 1;
00745 }
00746 spin_unlock_irq(&sk->
receive_queue.
lock);
00747
if (clear)
00748
kfree_skb(skb);
00749 }
00750
00751
skb_free_datagram(sk, skb);
00752
00753
return -EAGAIN;
00754 }
00755
00756 int udp_connect(
struct sock *sk,
struct sockaddr *uaddr,
int addr_len)
00757 {
00758
struct sockaddr_in *usin = (
struct sockaddr_in *) uaddr;
00759
struct rtable *rt;
00760 u32 saddr;
00761
int oif;
00762
int err;
00763
00764
00765
if (addr_len <
sizeof(*usin))
00766
return -EINVAL;
00767
00768
if (usin->sin_family != AF_INET)
00769
return -EAFNOSUPPORT;
00770
00771
sk_dst_reset(sk);
00772
00773 oif = sk->
bound_dev_if;
00774 saddr = sk->
saddr;
00775
if (
MULTICAST(usin->sin_addr.s_addr)) {
00776
if (!oif)
00777 oif = sk->
protinfo.af_inet.mc_index;
00778
if (!saddr)
00779 saddr = sk->
protinfo.af_inet.mc_addr;
00780 }
00781 err =
ip_route_connect(&rt, usin->sin_addr.s_addr, saddr,
00782
RT_CONN_FLAGS(sk), oif);
00783
if (err)
00784
return err;
00785
if ((rt->rt_flags&RTCF_BROADCAST) && !sk->
broadcast) {
00786
ip_rt_put(rt);
00787
return -EACCES;
00788 }
00789
if(!sk->
saddr)
00790 sk->
saddr = rt->rt_src;
00791
if(!sk->
rcv_saddr)
00792 sk->
rcv_saddr = rt->rt_src;
00793 sk->
daddr = rt->rt_dst;
00794 sk->
dport = usin->sin_port;
00795 sk->
state = TCP_ESTABLISHED;
00796 sk->
protinfo.af_inet.id = jiffies;
00797
00798
sk_dst_set(sk, &rt->u.dst);
00799
return(0);
00800 }
00801
00802 int udp_disconnect(
struct sock *sk,
int flags)
00803 {
00804
00805
00806
00807
00808 sk->
state = TCP_CLOSE;
00809 sk->
daddr = 0;
00810 sk->
dport = 0;
00811 sk->
bound_dev_if = 0;
00812
if (!(sk->
userlocks&
SOCK_BINDADDR_LOCK)) {
00813 sk->
rcv_saddr = 0;
00814 sk->
saddr = 0;
00815
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
00816
memset(&sk->net_pinfo.af_inet6.
saddr, 0, 16);
00817 memset(&sk->net_pinfo.af_inet6.
rcv_saddr, 0, 16);
00818
#endif
00819
}
00820
if (!(sk->
userlocks&
SOCK_BINDPORT_LOCK)) {
00821 sk->
prot->
unhash(sk);
00822 sk->
sport = 0;
00823 }
00824
sk_dst_reset(sk);
00825
return 0;
00826 }
00827
00828 static void udp_close(
struct sock *sk,
long timeout)
00829 {
00830
inet_sock_release(sk);
00831 }
00832
00833 static int udp_queue_rcv_skb(
struct sock * sk,
struct sk_buff *skb)
00834 {
00835
00836
00837
00838
00839
#if defined(CONFIG_FILTER)
00840
if (sk->filter && skb->
ip_summed !=
CHECKSUM_UNNECESSARY) {
00841
if (
__udp_checksum_complete(skb)) {
00842
UDP_INC_STATS_BH(UdpInErrors);
00843
IP_INC_STATS_BH(IpInDiscards);
00844
ip_statistics[smp_processor_id()*2].
IpInDelivers--;
00845
kfree_skb(skb);
00846
return -1;
00847 }
00848 skb->
ip_summed =
CHECKSUM_UNNECESSARY;
00849 }
00850
#endif
00851
00852
if (
sock_queue_rcv_skb(sk,skb)<0) {
00853
UDP_INC_STATS_BH(UdpInErrors);
00854
IP_INC_STATS_BH(IpInDiscards);
00855
ip_statistics[smp_processor_id()*2].
IpInDelivers--;
00856
kfree_skb(skb);
00857
return -1;
00858 }
00859
UDP_INC_STATS_BH(UdpInDatagrams);
00860
return 0;
00861 }
00862
00863
00864
00865
00866
00867
00868
00869 static int udp_v4_mcast_deliver(
struct sk_buff *skb,
struct udphdr *uh,
00870 u32 saddr, u32 daddr)
00871 {
00872
struct sock *sk;
00873
int dif;
00874
00875 read_lock(&
udp_hash_lock);
00876 sk =
udp_hash[ntohs(uh->dest) & (
UDP_HTABLE_SIZE - 1)];
00877 dif = skb->
dev->
ifindex;
00878 sk =
udp_v4_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif);
00879
if (sk) {
00880
struct sock *sknext = NULL;
00881
00882
do {
00883
struct sk_buff *skb1 = skb;
00884
00885 sknext =
udp_v4_mcast_next(sk->next, uh->dest, daddr,
00886 uh->source, saddr, dif);
00887
if(sknext)
00888 skb1 =
skb_clone(skb, GFP_ATOMIC);
00889
00890
if(skb1)
00891
udp_queue_rcv_skb(sk, skb1);
00892 sk = sknext;
00893 }
while(sknext);
00894 }
else
00895
kfree_skb(skb);
00896 read_unlock(&
udp_hash_lock);
00897
return 0;
00898 }
00899
00900
00901
00902
00903
00904
00905 static int udp_checksum_init(
struct sk_buff *skb,
struct udphdr *uh,
00906
unsigned short ulen, u32 saddr, u32 daddr)
00907 {
00908
if (uh->check == 0) {
00909 skb->
ip_summed =
CHECKSUM_UNNECESSARY;
00910 }
else if (skb->
ip_summed ==
CHECKSUM_HW) {
00911 skb->
ip_summed =
CHECKSUM_UNNECESSARY;
00912
if (!
udp_check(uh, ulen, saddr, daddr, skb->
csum))
00913
return 0;
00914
NETDEBUG(
if (
net_ratelimit()) printk(KERN_DEBUG
"udp v4 hw csum failure.\n"));
00915 skb->
ip_summed =
CHECKSUM_NONE;
00916 }
00917
if (skb->
ip_summed !=
CHECKSUM_UNNECESSARY)
00918 skb->
csum =
csum_tcpudp_nofold(saddr, daddr, ulen,
IPPROTO_UDP, 0);
00919
00920
00921
00922
return 0;
00923 }
00924
00925
00926
00927
00928
00944 int udp_rcv(
struct sk_buff *skb)
00945 {
00946
struct sock *sk;
00947
struct udphdr *uh;
00948
unsigned short ulen;
00949
struct rtable *rt = (
struct rtable*)skb->
dst;
00950 u32 saddr = skb->
nh.iph->saddr;
00951 u32 daddr = skb->
nh.iph->daddr;
00952
int len = skb->
len;
00953
00954
IP_INC_STATS_BH(IpInDelivers);
00955
00956
00957
00958
00959
if (!
pskb_may_pull(skb,
sizeof(
struct udphdr)))
00960
goto no_header;
00961
00962 uh = skb->
h.uh;
00963
00964 ulen = ntohs(uh->len);
00965
00966
if (ulen > len || ulen <
sizeof(*uh))
00967
goto short_packet;
00968
00969
if (
pskb_trim(skb, ulen))
00970
goto short_packet;
00971
00972
if (
udp_checksum_init(skb, uh, ulen, saddr, daddr) < 0)
00973
goto csum_error;
00974
00975
if(rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))
00976
return udp_v4_mcast_deliver(skb, uh, saddr, daddr);
00977
00978 sk =
udp_v4_lookup(saddr, uh->source, daddr, uh->dest, skb->
dev->
ifindex);
00979
00980
if (sk != NULL) {
00981
udp_queue_rcv_skb(sk, skb);
00982
sock_put(sk);
00983
return 0;
00984 }
00985
00986
00987
if (
udp_checksum_complete(skb))
00988
goto csum_error;
00989
00990
UDP_INC_STATS_BH(UdpNoPorts);
00991
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
00992
00993
00994
00995
00996
00997
kfree_skb(skb);
00998
return(0);
00999
01000 short_packet:
01001
NETDEBUG(
if (
net_ratelimit())
01002 printk(KERN_DEBUG
"UDP: short packet: %u.%u.%u.%u:%u %d/%d to %u.%u.%u.%u:%u\n",
01003 NIPQUAD(saddr),
01004 ntohs(uh->source),
01005 ulen,
01006 len,
01007 NIPQUAD(daddr),
01008 ntohs(uh->dest)));
01009 no_header:
01010
UDP_INC_STATS_BH(UdpInErrors);
01011
kfree_skb(skb);
01012
return(0);
01013
01014 csum_error:
01015
01016
01017
01018
01019
NETDEBUG(
if (
net_ratelimit())
01020 printk(KERN_DEBUG
"UDP: bad checksum. From %d.%d.%d.%d:%d to %d.%d.%d.%d:%d ulen %d\n",
01021 NIPQUAD(saddr),
01022 ntohs(uh->source),
01023 NIPQUAD(daddr),
01024 ntohs(uh->dest),
01025 ulen));
01026
UDP_INC_STATS_BH(UdpInErrors);
01027
kfree_skb(skb);
01028
return(0);
01029 }
01030
01031 static void get_udp_sock(
struct sock *sp,
char *tmpbuf,
int i)
01032 {
01033
unsigned int dest, src;
01034 __u16 destp, srcp;
01035
01036 dest = sp->
daddr;
01037 src = sp->
rcv_saddr;
01038 destp = ntohs(sp->
dport);
01039 srcp = ntohs(sp->
sport);
01040 sprintf(tmpbuf,
"%4d: %08X:%04X %08X:%04X"
01041
" %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p",
01042 i, src, srcp, dest, destp, sp->
state,
01043 atomic_read(&sp->
wmem_alloc), atomic_read(&sp->
rmem_alloc),
01044 0, 0L, 0,
01045 sock_i_uid(sp), 0,
01046
sock_i_ino(sp),
01047 atomic_read(&sp->
refcnt), sp);
01048 }
01049
01050 int udp_get_info(
char *buffer,
char **start, off_t offset,
int length)
01051 {
01052
int len = 0, num = 0, i;
01053 off_t pos = 0;
01054 off_t begin;
01055
char tmpbuf[129];
01056
01057
if (offset < 128)
01058 len += sprintf(buffer,
"%-127s\n",
01059
" sl local_address rem_address st tx_queue "
01060
"rx_queue tr tm->when retrnsmt uid timeout inode");
01061 pos = 128;
01062 read_lock(&
udp_hash_lock);
01063
for (i = 0; i <
UDP_HTABLE_SIZE; i++) {
01064
struct sock *sk;
01065
01066
for (sk =
udp_hash[i]; sk; sk = sk->
next, num++) {
01067
if (sk->family != PF_INET)
01068
continue;
01069 pos += 128;
01070
if (pos <= offset)
01071
continue;
01072
get_udp_sock(sk, tmpbuf, i);
01073 len += sprintf(buffer+len,
"%-127s\n", tmpbuf);
01074
if(len >= length)
01075
goto out;
01076 }
01077 }
01078 out:
01079 read_unlock(&
udp_hash_lock);
01080 begin = len - (pos - offset);
01081 *start = buffer + begin;
01082 len -= begin;
01083
if(len > length)
01084 len = length;
01085
if (len < 0)
01086 len = 0;
01087
return len;
01088 }
01089
01090 struct proto udp_prot = {
01091 name:
"UDP",
01092 close:
udp_close,
01093 connect:
udp_connect,
01094 disconnect:
udp_disconnect,
01095 ioctl:
udp_ioctl,
01096 setsockopt:
ip_setsockopt,
01097 getsockopt:
ip_getsockopt,
01098 sendmsg:
udp_sendmsg,
01099 recvmsg:
udp_recvmsg,
01100 backlog_rcv:
udp_queue_rcv_skb,
01101 hash:
udp_v4_hash,
01102 unhash:
udp_v4_unhash,
01103 get_port:
udp_v4_get_port,
01104 };