OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [net/] [ipv4/] [udp.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1629 jcastillo
/*
2
 * INET         An implementation of the TCP/IP protocol suite for the LINUX
3
 *              operating system.  INET is implemented using the  BSD Socket
4
 *              interface as the means of communication with the user level.
5
 *
6
 *              The User Datagram Protocol (UDP).
7
 *
8
 * Version:     @(#)udp.c       1.0.13  06/02/93
9
 *
10
 * Authors:     Ross Biro, <bir7@leland.Stanford.Edu>
11
 *              Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
12
 *              Arnt Gulbrandsen, <agulbra@nvg.unit.no>
13
 *              Alan Cox, <Alan.Cox@linux.org>
14
 *
15
 * Fixes:
16
 *              Alan Cox        :       verify_area() calls
17
 *              Alan Cox        :       stopped close while in use off icmp
18
 *                                      messages. Not a fix but a botch that
19
 *                                      for udp at least is 'valid'.
20
 *              Alan Cox        :       Fixed icmp handling properly
21
 *              Alan Cox        :       Correct error for oversized datagrams
22
 *              Alan Cox        :       Tidied select() semantics.
23
 *              Alan Cox        :       udp_err() fixed properly, also now
24
 *                                      select and read wake correctly on errors
25
 *              Alan Cox        :       udp_send verify_area moved to avoid mem leak
26
 *              Alan Cox        :       UDP can count its memory
27
 *              Alan Cox        :       send to an unknown connection causes
28
 *                                      an ECONNREFUSED off the icmp, but
29
 *                                      does NOT close.
30
 *              Alan Cox        :       Switched to new sk_buff handlers. No more backlog!
31
 *              Alan Cox        :       Using generic datagram code. Even smaller and the PEEK
32
 *                                      bug no longer crashes it.
33
 *              Fred Van Kempen :       Net2e support for sk->broadcast.
34
 *              Alan Cox        :       Uses skb_free_datagram
35
 *              Alan Cox        :       Added get/set sockopt support.
36
 *              Alan Cox        :       Broadcasting without option set returns EACCES.
37
 *              Alan Cox        :       No wakeup calls. Instead we now use the callbacks.
38
 *              Alan Cox        :       Use ip_tos and ip_ttl
39
 *              Alan Cox        :       SNMP Mibs
40
 *              Alan Cox        :       MSG_DONTROUTE, and 0.0.0.0 support.
41
 *              Matt Dillon     :       UDP length checks.
42
 *              Alan Cox        :       Smarter af_inet used properly.
43
 *              Alan Cox        :       Use new kernel side addressing.
44
 *              Alan Cox        :       Incorrect return on truncated datagram receive.
45
 *      Arnt Gulbrandsen        :       New udp_send and stuff
46
 *              Alan Cox        :       Cache last socket
47
 *              Alan Cox        :       Route cache
48
 *              Jon Peatfield   :       Minor efficiency fix to sendto().
49
 *              Mike Shaver     :       RFC1122 checks.
50
 *              Alan Cox        :       Nonblocking error fix.
51
 *      Willy Konynenberg       :       Transparent proxying support.
52
 *              David S. Miller :       New socket lookup architecture for ISS.
53
 *                                      Last socket cache retained as it
54
 *                                      does have a high hit rate.
55
 *              Elliot Poger    :       Added support for SO_BINDTODEVICE.
56
 *      Willy Konynenberg       :       Transparent proxy adapted to new
57
 *                                      socket hash code.
58
 *              Philip Gladstone:       Added missing ip_rt_put
59
 *
60
 *
61
 *              This program is free software; you can redistribute it and/or
62
 *              modify it under the terms of the GNU General Public License
63
 *              as published by the Free Software Foundation; either version
64
 *              2 of the License, or (at your option) any later version.
65
 */
66
 
67
/* RFC1122 Status:
68
   4.1.3.1 (Ports):
69
     SHOULD send ICMP_PORT_UNREACHABLE in response to datagrams to
70
       an un-listened port. (OK)
71
   4.1.3.2 (IP Options)
72
     MUST pass IP options from IP -> application (OK)
73
     MUST allow application to specify IP options (OK)
74
   4.1.3.3 (ICMP Messages)
75
     MUST pass ICMP error messages to application (OK)
76
   4.1.3.4 (UDP Checksums)
77
     MUST provide facility for checksumming (OK)
78
     MAY allow application to control checksumming (OK)
79
     MUST default to checksumming on (OK)
80
     MUST discard silently datagrams with bad csums (OK)
81
   4.1.3.5 (UDP Multihoming)
82
     MUST allow application to specify source address (OK)
83
     SHOULD be able to communicate the chosen src addr up to application
84
       when application doesn't choose (NOT YET - doesn't seem to be in the BSD API)
85
       [Does opening a SOCK_PACKET and snooping your output count 8)]
86
   4.1.3.6 (Invalid Addresses)
87
     MUST discard invalid source addresses (NOT YET -- will be implemented
88
       in IP, so UDP will eventually be OK.  Right now it's a violation.)
89
     MUST only send datagrams with one of our addresses (NOT YET - ought to be OK )
90
   950728 -- MS
91
*/
92
 
93
#include <asm/system.h>
94
#include <asm/segment.h>
95
#include <linux/types.h>
96
#include <linux/sched.h>
97
#include <linux/fcntl.h>
98
#include <linux/socket.h>
99
#include <linux/sockios.h>
100
#include <linux/in.h>
101
#include <linux/errno.h>
102
#include <linux/timer.h>
103
#include <linux/termios.h>
104
#include <linux/mm.h>
105
#include <linux/config.h>
106
#include <linux/inet.h>
107
#include <linux/netdevice.h>
108
#include <net/snmp.h>
109
#include <net/ip.h>
110
#include <net/protocol.h>
111
#include <net/tcp.h>
112
#include <linux/skbuff.h>
113
#include <net/sock.h>
114
#include <net/udp.h>
115
#include <net/icmp.h>
116
#include <net/route.h>
117
#include <net/checksum.h>
118
 
119
/*
120
 *      Snmp MIB for the UDP layer
121
 */
122
 
123
struct udp_mib          udp_statistics;
124
 
125
struct sock *udp_hash[UDP_HTABLE_SIZE];
126
 
127
static int udp_v4_verify_bind(struct sock *sk, unsigned short snum)
128
{
129
        struct sock *sk2;
130
        int retval = 0, sk_reuse = sk->reuse;
131
 
132
        SOCKHASH_LOCK();
133
        for(sk2 = udp_hash[snum & (UDP_HTABLE_SIZE - 1)]; sk2 != NULL; sk2 = sk2->next) {
134
                if((sk2->num == snum) && (sk2 != sk)) {
135
                        int sk2_reuse = sk2->reuse;
136
 
137
                        /* Two sockets can be bound to the same port if they're
138
                         * bound to different interfaces... */
139
                        if (sk->bound_device != sk2->bound_device)
140
                                continue;
141
 
142
                        if(!sk2->rcv_saddr || !sk->rcv_saddr) {
143
                                if((!sk2_reuse) || (!sk_reuse)) {
144
                                        retval = 1;
145
                                        break;
146
                                }
147
                        } else if(sk2->rcv_saddr == sk->rcv_saddr) {
148
                                if((!sk_reuse) || (!sk2_reuse)) {
149
                                        retval = 1;
150
                                        break;
151
                                }
152
                        }
153
                }
154
        }
155
        SOCKHASH_UNLOCK();
156
        return retval;
157
}
158
 
159
static inline int udp_lport_inuse(u16 num)
160
{
161
        struct sock *sk = udp_hash[num & (UDP_HTABLE_SIZE - 1)];
162
 
163
        for(; sk != NULL; sk = sk->next) {
164
                if(sk->num == num)
165
                        return 1;
166
        }
167
        return 0;
168
}
169
 
170
/* Shared by v4/v6 tcp. */
171
unsigned short udp_good_socknum(void)
172
{
173
        int result;
174
        static int start = 0;
175
        int i, best, best_size_so_far;
176
 
177
        SOCKHASH_LOCK();
178
 
179
        /* Select initial not-so-random "best" */
180
        best = PROT_SOCK + 1 + (start & 1023);
181
        best_size_so_far = 32767;       /* "big" num */
182
        result = best;
183
        for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) {
184
                struct sock *sk;
185
                int size;
186
 
187
                sk = udp_hash[result & (UDP_HTABLE_SIZE - 1)];
188
 
189
                /* No clashes - take it */
190
                if (!sk)
191
                        goto out;
192
 
193
                /* Is this one better than our best so far? */
194
                size = 0;
195
                do {
196
                        if(++size >= best_size_so_far)
197
                                goto next;
198
                } while((sk = sk->next) != NULL);
199
                best_size_so_far = size;
200
                best = result;
201
next:
202
        }
203
 
204
        while (udp_lport_inuse(best))
205
                best += UDP_HTABLE_SIZE;
206
        result = best;
207
out:
208
        start = result;
209
        SOCKHASH_UNLOCK();
210
        return result;
211
}
212
 
213
static void udp_v4_hash(struct sock *sk)
214
{
215
        struct sock **skp;
216
        int num = sk->num;
217
 
218
        num &= (UDP_HTABLE_SIZE - 1);
219
        skp = &udp_hash[num];
220
 
221
        SOCKHASH_LOCK();
222
        sk->next = *skp;
223
        *skp = sk;
224
        sk->hashent = num;
225
        SOCKHASH_UNLOCK();
226
}
227
 
228
static void udp_v4_unhash(struct sock *sk)
229
{
230
        struct sock **skp;
231
        int num = sk->num;
232
 
233
        num &= (UDP_HTABLE_SIZE - 1);
234
        skp = &udp_hash[num];
235
 
236
        SOCKHASH_LOCK();
237
        while(*skp != NULL) {
238
                if(*skp == sk) {
239
                        *skp = sk->next;
240
                        break;
241
                }
242
                skp = &((*skp)->next);
243
        }
244
        SOCKHASH_UNLOCK();
245
}
246
 
247
static void udp_v4_rehash(struct sock *sk)
248
{
249
        struct sock **skp;
250
        int num = sk->num;
251
        int oldnum = sk->hashent;
252
 
253
        num &= (UDP_HTABLE_SIZE - 1);
254
        skp = &udp_hash[oldnum];
255
 
256
        SOCKHASH_LOCK();
257
        while(*skp != NULL) {
258
                if(*skp == sk) {
259
                        *skp = sk->next;
260
                        break;
261
                }
262
                skp = &((*skp)->next);
263
        }
264
        sk->next = udp_hash[num];
265
        udp_hash[num] = sk;
266
        sk->hashent = num;
267
        SOCKHASH_UNLOCK();
268
}
269
 
270
/* UDP is nearly always wildcards out the wazoo, it makes no sense to try
271
 * harder than this. -DaveM
272
 */
273
__inline__ struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport,
274
                                      struct device *dev)
275
{
276
        struct sock *sk, *result = NULL;
277
        unsigned short hnum = ntohs(dport);
278
        int badness = -1;
279
 
280
        for(sk = udp_hash[hnum & (UDP_HTABLE_SIZE - 1)]; sk != NULL; sk = sk->next) {
281
                if((sk->num == hnum) && !(sk->dead && (sk->state == TCP_CLOSE))) {
282
                        int score = 0;
283
                        if(sk->rcv_saddr) {
284
                                if(sk->rcv_saddr != daddr)
285
                                        continue;
286
                                score++;
287
                        }
288
                        if(sk->daddr) {
289
                                if(sk->daddr != saddr)
290
                                        continue;
291
                                score++;
292
                        }
293
                        if(sk->dummy_th.dest) {
294
                                if(sk->dummy_th.dest != sport)
295
                                        continue;
296
                                score++;
297
                        }
298
                        /* If this socket is bound to a particular interface,
299
                         * did the packet come in on it? */
300
                        if (sk->bound_device) {
301
                                if (dev == sk->bound_device)
302
                                        score++;
303
                                else
304
                                        continue;  /* mismatch--not this sock */
305
                        }
306
                        if(score == 4) {
307
                                result = sk;
308
                                break;
309
                        } else if(score > badness) {
310
                                result = sk;
311
                                badness = score;
312
                        }
313
                }
314
        }
315
        return result;
316
}
317
 
318
#ifdef CONFIG_IP_TRANSPARENT_PROXY
319
struct sock *udp_v4_proxy_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, u32 paddr, u16 rport,
320
                                 struct device *dev)
321
{
322
        struct sock *hh[3], *sk, *result = NULL;
323
        int i;
324
        int badness = -1;
325
        unsigned short hnum = ntohs(dport);
326
        unsigned short hpnum = ntohs(rport);
327
 
328
        SOCKHASH_LOCK();
329
        hh[0] = udp_hash[hnum & (UDP_HTABLE_SIZE - 1)];
330
        hh[1] = udp_hash[hpnum & (UDP_HTABLE_SIZE - 1)];
331
        for (i = 0; i < 2; i++) {
332
                for(sk = hh[i]; sk != NULL; sk = sk->next) {
333
                        if(sk->num == hnum || sk->num == hpnum) {
334
                                int score = 0;
335
                                if(sk->dead && (sk->state == TCP_CLOSE))
336
                                        continue;
337
                                if(sk->rcv_saddr) {
338
                                        if((sk->num != hpnum || sk->rcv_saddr != paddr) &&
339
                                           (sk->num != hnum || sk->rcv_saddr != daddr))
340
                                                continue;
341
                                        score++;
342
                                }
343
                                if(sk->daddr) {
344
                                        if(sk->daddr != saddr)
345
                                                continue;
346
                                        score++;
347
                                }
348
                                if(sk->dummy_th.dest) {
349
                                        if(sk->dummy_th.dest != sport)
350
                                                continue;
351
                                        score++;
352
                                }
353
                                /* If this socket is bound to a particular interface,
354
                                 * did the packet come in on it? */
355
                                if(sk->bound_device) {
356
                                        if (sk->bound_device != dev)
357
                                                continue;
358
                                        score++;
359
                                }
360
                                if(score == 4 && sk->num == hnum) {
361
                                        result = sk;
362
                                        break;
363
                                } else if(score > badness && (sk->num == hpnum || sk->rcv_saddr)) {
364
                                        result = sk;
365
                                        badness = score;
366
                                }
367
                        }
368
                }
369
        }
370
        SOCKHASH_UNLOCK();
371
        return result;
372
}
373
#endif
374
 
375
static inline struct sock *udp_v4_mcast_next(struct sock *sk,
376
                                             unsigned short num,
377
                                             unsigned long raddr,
378
                                             unsigned short rnum,
379
                                             unsigned long laddr,
380
                                             struct device *dev)
381
{
382
        struct sock *s = sk;
383
        unsigned short hnum = ntohs(num);
384
        for(; s; s = s->next) {
385
                if ((s->num != hnum)                                    ||
386
                    (s->dead && (s->state == TCP_CLOSE))                ||
387
                    (s->daddr && s->daddr!=raddr)                       ||
388
                    (s->dummy_th.dest != rnum && s->dummy_th.dest != 0) ||
389
                    ((s->bound_device) && (s->bound_device!=dev))       ||
390
                    (s->rcv_saddr  && s->rcv_saddr != laddr))
391
                        continue;
392
                break;
393
        }
394
        return s;
395
}
396
 
397
#define min(a,b)        ((a)<(b)?(a):(b))
398
 
399
 
400
/*
401
 * This routine is called by the ICMP module when it gets some
402
 * sort of error condition.  If err < 0 then the socket should
403
 * be closed and the error returned to the user.  If err > 0
404
 * it's just the icmp type << 8 | icmp code.
405
 * Header points to the ip header of the error packet. We move
406
 * on past this. Then (as it used to claim before adjustment)
407
 * header points to the first 8 bytes of the udp header.  We need
408
 * to find the appropriate port.
409
 */
410
 
411
void udp_err(int type, int code, unsigned char *header, __u32 daddr,
412
        __u32 saddr, struct inet_protocol *protocol, int len)
413
{
414
        struct udphdr *uh;
415
        struct sock *sk;
416
 
417
        /*
418
         *      Find the 8 bytes of post IP header ICMP included for us
419
         */
420
 
421
        if(len<sizeof(struct udphdr))
422
                return;
423
 
424
        uh = (struct udphdr *)header;
425
 
426
        sk = udp_v4_lookup(daddr, uh->dest, saddr, uh->source, NULL);
427
        if (sk == NULL)
428
                return; /* No socket for error */
429
 
430
        if (type == ICMP_SOURCE_QUENCH)
431
        {       /* Slow down! */
432
                if (sk->cong_window > 1)
433
                        sk->cong_window = sk->cong_window/2;
434
                return;
435
        }
436
 
437
        if (type == ICMP_PARAMETERPROB)
438
        {
439
                sk->err = EPROTO;
440
                sk->error_report(sk);
441
                return;
442
        }
443
 
444
        /*
445
         *      Various people wanted BSD UDP semantics. Well they've come
446
         *      back out because they slow down response to stuff like dead
447
         *      or unreachable name servers and they screw term users something
448
         *      chronic. Oh and it violates RFC1122. So basically fix your
449
         *      client code people.
450
         */
451
 
452
        /* RFC1122: OK.  Passes ICMP errors back to application, as per */
453
        /* 4.1.3.3. */
454
        /* After the comment above, that should be no surprise. */
455
 
456
        if(code<=NR_ICMP_UNREACH && icmp_err_convert[code].fatal)
457
        {
458
                /*
459
                 *      4.x BSD compatibility item. Break RFC1122 to
460
                 *      get BSD socket semantics.
461
                 */
462
                if(sk->bsdism && sk->state!=TCP_ESTABLISHED)
463
                        return;
464
                sk->err = icmp_err_convert[code].errno;
465
                sk->error_report(sk);
466
        }
467
}
468
 
469
 
470
static unsigned short udp_check(struct udphdr *uh, int len, unsigned long saddr, unsigned long daddr, unsigned long base)
471
{
472
        return(csum_tcpudp_magic(saddr, daddr, len, IPPROTO_UDP, base));
473
}
474
 
475
struct udpfakehdr
476
{
477
        struct udphdr uh;
478
        __u32 daddr;
479
        __u32 other;
480
        const char *from;
481
        __u32 wcheck;
482
};
483
 
484
/*
485
 *      Copy and checksum a UDP packet from user space into a buffer. We still have to do the planning to
486
 *      get ip_build_xmit to spot direct transfer to network card and provide an additional callback mode
487
 *      for direct user->board I/O transfers. That one will be fun.
488
 */
489
 
490
static void udp_getfrag(const void *p, __u32 saddr, char * to, unsigned int offset, unsigned int fraglen)
491
{
492
        struct udpfakehdr *ufh = (struct udpfakehdr *)p;
493
        const char *src;
494
        char *dst;
495
        unsigned int len;
496
 
497
        if (offset)
498
        {
499
                len = fraglen;
500
                src = ufh->from+(offset-sizeof(struct udphdr));
501
                dst = to;
502
        }
503
        else
504
        {
505
                len = fraglen-sizeof(struct udphdr);
506
                src = ufh->from;
507
                dst = to+sizeof(struct udphdr);
508
        }
509
        ufh->wcheck = csum_partial_copy_fromuser(src, dst, len, ufh->wcheck);
510
        if (offset == 0)
511
        {
512
                ufh->wcheck = csum_partial((char *)ufh, sizeof(struct udphdr),
513
                                   ufh->wcheck);
514
                ufh->uh.check = csum_tcpudp_magic(saddr, ufh->daddr,
515
                                          ntohs(ufh->uh.len),
516
                                          IPPROTO_UDP, ufh->wcheck);
517
                if (ufh->uh.check == 0)
518
                        ufh->uh.check = -1;
519
                memcpy(to, ufh, sizeof(struct udphdr));
520
        }
521
}
522
 
523
/*
524
 *      Unchecksummed UDP is sufficiently critical to stuff like ATM video conferencing
525
 *      that we use two routines for this for speed. Probably we ought to have a CONFIG_FAST_NET
526
 *      set for >10Mb/second boards to activate this sort of coding. Timing needed to verify if
527
 *      this is a valid decision.
528
 */
529
 
530
static void udp_getfrag_nosum(const void *p, __u32 saddr, char * to, unsigned int offset, unsigned int fraglen)
531
{
532
        struct udpfakehdr *ufh = (struct udpfakehdr *)p;
533
        const char *src;
534
        char *dst;
535
        unsigned int len;
536
 
537
        if (offset)
538
        {
539
                len = fraglen;
540
                src = ufh->from+(offset-sizeof(struct udphdr));
541
                dst = to;
542
        }
543
        else
544
        {
545
                len = fraglen-sizeof(struct udphdr);
546
                src = ufh->from;
547
                dst = to+sizeof(struct udphdr);
548
        }
549
        memcpy_fromfs(dst,src,len);
550
        if (offset == 0)
551
                memcpy(to, ufh, sizeof(struct udphdr));
552
}
553
 
554
 
555
/*
556
 *      Send UDP frames.
557
 */
558
 
559
static int udp_send(struct sock *sk, struct sockaddr_in *sin,
560
                      const unsigned char *from, int len, int rt,
561
                    __u32 saddr, int noblock)
562
{
563
        int ulen = len + sizeof(struct udphdr);
564
        int a;
565
        struct udpfakehdr ufh;
566
 
567
        if(ulen>65535-sizeof(struct iphdr))
568
                return -EMSGSIZE;
569
 
570
        ufh.uh.source = sk->dummy_th.source;
571
        ufh.uh.dest = sin->sin_port;
572
        ufh.uh.len = htons(ulen);
573
        ufh.uh.check = 0;
574
        ufh.daddr = sin->sin_addr.s_addr;
575
        ufh.other = (htons(ulen) << 16) + IPPROTO_UDP*256;
576
        ufh.from = from;
577
        ufh.wcheck = 0;
578
 
579
#ifdef CONFIG_IP_TRANSPARENT_PROXY
580
        if (rt&MSG_PROXY)
581
        {
582
                /*
583
                 * We map the first 8 bytes of a second sockaddr_in
584
                 * into the last 8 (unused) bytes of a sockaddr_in.
585
                 * This _is_ ugly, but it's the only way to do it
586
                 * easily,  without adding system calls.
587
                 */
588
                struct sockaddr_in *sinfrom =
589
                        (struct sockaddr_in *) sin->sin_zero;
590
 
591
                if (!suser())
592
                        return(-EPERM);
593
                if (sinfrom->sin_family && sinfrom->sin_family != AF_INET)
594
                        return(-EINVAL);
595
                if (sinfrom->sin_port == 0)
596
                        return(-EINVAL);
597
                saddr = sinfrom->sin_addr.s_addr;
598
                ufh.uh.source = sinfrom->sin_port;
599
        }
600
#endif
601
 
602
        /* RFC1122: OK.  Provides the checksumming facility (MUST) as per */
603
        /* 4.1.3.4. It's configurable by the application via setsockopt() */
604
        /* (MAY) and it defaults to on (MUST).  Almost makes up for the */
605
        /* violation above. -- MS */
606
 
607
        if(sk->no_check)
608
                a = ip_build_xmit(sk, udp_getfrag_nosum, &ufh, ulen,
609
                        sin->sin_addr.s_addr, saddr, sk->opt, rt, IPPROTO_UDP, noblock);
610
        else
611
                a = ip_build_xmit(sk, udp_getfrag, &ufh, ulen,
612
                        sin->sin_addr.s_addr, saddr, sk->opt, rt, IPPROTO_UDP, noblock);
613
        if(a<0)
614
                return a;
615
        udp_statistics.UdpOutDatagrams++;
616
        return len;
617
}
618
 
619
 
620
static int udp_sendto(struct sock *sk, const unsigned char *from, int len, int noblock,
621
           unsigned flags, struct sockaddr_in *usin, int addr_len)
622
{
623
        struct sockaddr_in sin;
624
        int tmp;
625
        __u32 saddr=0;
626
 
627
        /*
628
         *      Check the flags. We support no flags for UDP sending
629
         */
630
 
631
#ifdef CONFIG_IP_TRANSPARENT_PROXY
632
        if (flags&~(MSG_DONTROUTE|MSG_PROXY))
633
#else
634
        if (flags&~MSG_DONTROUTE)
635
#endif
636
                return(-EINVAL);
637
        /*
638
         *      Get and verify the address.
639
         */
640
 
641
        if (usin)
642
        {
643
                if (addr_len < sizeof(sin))
644
                        return(-EINVAL);
645
                if (usin->sin_family && usin->sin_family != AF_INET)
646
                        return(-EINVAL);
647
                if (usin->sin_port == 0)
648
                        return(-EINVAL);
649
        }
650
        else
651
        {
652
#ifdef CONFIG_IP_TRANSPARENT_PROXY
653
                /* We need to provide a sockaddr_in when using MSG_PROXY. */
654
                if (flags&MSG_PROXY)
655
                        return(-EINVAL);
656
#endif
657
                if (sk->state != TCP_ESTABLISHED)
658
                        return(-EINVAL);
659
                sin.sin_family = AF_INET;
660
                sin.sin_port = sk->dummy_th.dest;
661
                sin.sin_addr.s_addr = sk->daddr;
662
                usin = &sin;
663
        }
664
 
665
        /*
666
         *      BSD socket semantics. You must set SO_BROADCAST to permit
667
         *      broadcasting of data.
668
         */
669
 
670
        /* RFC1122: OK.  Allows the application to select the specific */
671
        /* source address for an outgoing packet (MUST) as per 4.1.3.5. */
672
        /* Optional addition: a mechanism for telling the application what */
673
        /* address was used. (4.1.3.5, MAY) -- MS */
674
 
675
        /* RFC1122: MUST ensure that all outgoing packets have one */
676
        /* of this host's addresses as a source addr.(4.1.3.6) - bind in  */
677
        /* af_inet.c checks these. It does need work to allow BSD style */
678
        /* bind to multicast as is done by xntpd                */
679
 
680
        if(usin->sin_addr.s_addr==INADDR_ANY)
681
                usin->sin_addr.s_addr=ip_my_addr();
682
 
683
        if(!sk->broadcast && ip_chk_addr(usin->sin_addr.s_addr)==IS_BROADCAST)
684
                return -EACCES;                 /* Must turn broadcast on first */
685
 
686
        lock_sock(sk);
687
 
688
        /* Send the packet. */
689
        tmp = udp_send(sk, usin, from, len, flags, saddr, noblock);
690
 
691
        /* The datagram has been sent off.  Release the socket. */
692
        release_sock(sk);
693
        return(tmp);
694
}
695
 
696
/*
697
 *      Temporary
698
 */
699
 
700
static int udp_sendmsg(struct sock *sk, struct msghdr *msg, int len, int noblock,
701
        int flags)
702
{
703
        if(msg->msg_iovlen==1)
704
                return udp_sendto(sk,msg->msg_iov[0].iov_base,len, noblock, flags, msg->msg_name, msg->msg_namelen);
705
        else
706
        {
707
                /*
708
                 *      For awkward cases we linearise the buffer first. In theory this is only frames
709
                 *      whose iovec's don't split on 4 byte boundaries, and soon encrypted stuff (to keep
710
                 *      skip happy). We are a bit more general about it.
711
                 */
712
 
713
                unsigned char *buf;
714
                int fs;
715
                int err;
716
                if(len>65515)
717
                        return -EMSGSIZE;
718
                buf=kmalloc(len, GFP_KERNEL);
719
                if(buf==NULL)
720
                        return -ENOBUFS;
721
                memcpy_fromiovec(buf, msg->msg_iov, len);
722
                fs=get_fs();
723
                set_fs(get_ds());
724
                err=udp_sendto(sk,buf,len, noblock, flags, msg->msg_name, msg->msg_namelen);
725
                set_fs(fs);
726
                kfree_s(buf,len);
727
                return err;
728
        }
729
}
730
 
731
/*
732
 *      IOCTL requests applicable to the UDP protocol
733
 */
734
 
735
int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
736
{
737
        int err;
738
        switch(cmd)
739
        {
740
                case TIOCOUTQ:
741
                {
742
                        unsigned long amount;
743
 
744
                        if (sk->state == TCP_LISTEN) return(-EINVAL);
745
                        amount = sock_wspace(sk);
746
                        err=verify_area(VERIFY_WRITE,(void *)arg,
747
                                        sizeof(unsigned long));
748
                        if(err)
749
                                return(err);
750
                        put_fs_long(amount,(unsigned long *)arg);
751
                        return(0);
752
                }
753
 
754
                case TIOCINQ:
755
                {
756
                        struct sk_buff *skb;
757
                        unsigned long amount;
758
 
759
                        if (sk->state == TCP_LISTEN) return(-EINVAL);
760
                        amount = 0;
761
                        skb = skb_peek(&sk->receive_queue);
762
                        if (skb != NULL) {
763
                                /*
764
                                 * We will only return the amount
765
                                 * of this packet since that is all
766
                                 * that will be read.
767
                                 */
768
                                amount = skb->len-sizeof(struct udphdr);
769
                        }
770
                        err=verify_area(VERIFY_WRITE,(void *)arg,
771
                                                sizeof(unsigned long));
772
                        if(err)
773
                                return(err);
774
                        put_fs_long(amount,(unsigned long *)arg);
775
                        return(0);
776
                }
777
 
778
                default:
779
                        return(-EINVAL);
780
        }
781
        return(0);
782
}
783
 
784
 
785
/*
786
 *      This should be easy, if there is something there we\
787
 *      return it, otherwise we block.
788
 */
789
 
790
int udp_recvmsg(struct sock *sk, struct msghdr *msg, int len,
791
             int noblock, int flags,int *addr_len)
792
{
793
        int copied = 0;
794
        int truesize;
795
        struct sk_buff *skb;
796
        int er;
797
        struct sockaddr_in *sin=(struct sockaddr_in *)msg->msg_name;
798
 
799
        /*
800
         *      Check any passed addresses
801
         */
802
 
803
        if (addr_len)
804
                *addr_len=sizeof(*sin);
805
 
806
        /*
807
         *      From here the generic datagram does a lot of the work. Come
808
         *      the finished NET3, it will do _ALL_ the work!
809
         */
810
 
811
        skb=skb_recv_datagram(sk,flags,noblock,&er);
812
        if(skb==NULL)
813
                return er;
814
 
815
        truesize = skb->len - sizeof(struct udphdr);
816
        copied = min(len, truesize);
817
 
818
        /*
819
         *      FIXME : should use udp header size info value
820
         */
821
 
822
        skb_copy_datagram_iovec(skb,sizeof(struct udphdr),msg->msg_iov,copied);
823
        sk->stamp=skb->stamp;
824
 
825
        /* Copy the address. */
826
        if (sin)
827
        {
828
                sin->sin_family = AF_INET;
829
                sin->sin_port = skb->h.uh->source;
830
                sin->sin_addr.s_addr = skb->daddr;
831
#ifdef CONFIG_IP_TRANSPARENT_PROXY
832
                if (flags&MSG_PROXY)
833
                {
834
                        /*
835
                         * We map the first 8 bytes of a second sockaddr_in
836
                         * into the last 8 (unused) bytes of a sockaddr_in.
837
                         * This _is_ ugly, but it's the only way to do it
838
                         * easily,  without adding system calls.
839
                         */
840
                        struct sockaddr_in *sinto =
841
                                (struct sockaddr_in *) sin->sin_zero;
842
 
843
                        sinto->sin_family = AF_INET;
844
                        sinto->sin_port = skb->h.uh->dest;
845
                        sinto->sin_addr.s_addr = skb->saddr;
846
                }
847
#endif
848
        }
849
 
850
        skb_free_datagram(sk, skb);
851
        return(copied);
852
}
853
 
854
int udp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
855
{
856
        struct rtable *rt;
857
        if (addr_len < sizeof(*usin))
858
                return(-EINVAL);
859
 
860
        if (usin->sin_family && usin->sin_family != AF_INET)
861
                return(-EAFNOSUPPORT);
862
        if (usin->sin_addr.s_addr==INADDR_ANY)
863
                usin->sin_addr.s_addr=ip_my_addr();
864
 
865
        if(!sk->broadcast && ip_chk_addr(usin->sin_addr.s_addr)==IS_BROADCAST)
866
                return -EACCES;                 /* Must turn broadcast on first */
867
 
868
        rt=ip_rt_route((__u32)usin->sin_addr.s_addr, sk->localroute, sk->bound_device);
869
        if (rt==NULL)
870
                return -ENETUNREACH;
871
        if(!sk->saddr)
872
                sk->saddr = rt->rt_src;         /* Update source address */
873
        if(!sk->rcv_saddr)
874
                sk->rcv_saddr = rt->rt_src;
875
        sk->daddr = usin->sin_addr.s_addr;
876
        sk->dummy_th.dest = usin->sin_port;
877
        sk->state = TCP_ESTABLISHED;
878
        if (sk->ip_route_cache)
879
                ip_rt_put(sk->ip_route_cache);
880
        sk->ip_route_cache = rt;
881
        return(0);
882
}
883
 
884
 
885
static void udp_close(struct sock *sk, unsigned long timeout)
886
{
887
        lock_sock(sk);
888
        sk->state = TCP_CLOSE;
889
        sk->dead = 1;
890
        release_sock(sk);
891
        udp_v4_unhash(sk);
892
        destroy_sock(sk);
893
}
894
 
895
static inline void udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
896
{
897
        /*
898
         *      Charge it to the socket, dropping if the queue is full.
899
         */
900
 
901
        /* I assume this includes the IP options, as per RFC1122 (4.1.3.2). */
902
        /* If not, please let me know. -- MS */
903
 
904
        if (__sock_queue_rcv_skb(sk,skb)<0) {
905
                udp_statistics.UdpInErrors++;
906
                ip_statistics.IpInDiscards++;
907
                ip_statistics.IpInDelivers--;
908
                skb->sk = NULL;
909
                kfree_skb(skb, FREE_WRITE);
910
                return;
911
        }
912
        udp_statistics.UdpInDatagrams++;
913
}
914
 
915
 
916
static inline void udp_deliver(struct sock *sk, struct sk_buff *skb)
917
{
918
        skb->sk = sk;
919
 
920
        if (sk->users) {
921
                __skb_queue_tail(&sk->back_log, skb);
922
                return;
923
        }
924
        udp_queue_rcv_skb(sk, skb);
925
}
926
 
927
#ifdef CONFIG_IP_TRANSPARENT_PROXY
928
/*
929
 *      Check whether a received UDP packet might be for one of our
930
 *      sockets.
931
 */
932
 
933
int udp_chkaddr(struct sk_buff *skb)
934
{
935
        struct iphdr *iph = skb->h.iph;
936
        struct udphdr *uh = (struct udphdr *)(skb->h.raw + iph->ihl*4);
937
        struct sock *sk;
938
 
939
        sk = udp_v4_lookup(iph->saddr, uh->source, iph->daddr, uh->dest,
940
                           skb->dev);
941
        if (!sk)
942
                return 0;
943
        /* 0 means accept all LOCAL addresses here, not all the world... */
944
        if (sk->rcv_saddr == 0)
945
                return 0;
946
        return 1;
947
}
948
#endif
949
 
950
#ifdef CONFIG_IP_MULTICAST
951
/*
952
 *      Multicasts and broadcasts go to each listener.
953
 */
954
static int udp_v4_mcast_deliver(struct sk_buff *skb, struct udphdr *uh,
955
                                 u32 saddr, u32 daddr)
956
{
957
        struct sock *sk;
958
        int given = 0;
959
 
960
        SOCKHASH_LOCK();
961
        sk = udp_hash[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)];
962
        sk = udp_v4_mcast_next(sk, uh->dest, saddr, uh->source, daddr, skb->dev);
963
        if(sk) {
964
                struct sock *sknext = NULL;
965
 
966
                do {
967
                        struct sk_buff *skb1 = skb;
968
 
969
                        sknext = udp_v4_mcast_next(sk->next, uh->dest, saddr,
970
                                                   uh->source, daddr, skb->dev);
971
                        if(sknext)
972
                                skb1 = skb_clone(skb, GFP_ATOMIC);
973
 
974
                        if(skb1)
975
                                udp_deliver(sk, skb1);
976
                        sk = sknext;
977
                } while(sknext);
978
                given = 1;
979
        }
980
        SOCKHASH_UNLOCK();
981
        if(!given)
982
                kfree_skb(skb, FREE_READ);
983
        return 0;
984
}
985
#endif
986
 
987
/*
988
 *      All we need to do is get the socket, and then do a checksum.
989
 */
990
 
991
int udp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
992
        __u32 daddr, unsigned short len,
993
        __u32 saddr, int redo, struct inet_protocol *protocol)
994
{
995
        struct sock *sk;
996
        struct udphdr *uh;
997
        unsigned short ulen;
998
        int addr_type;
999
 
1000
        /*
1001
         * If we're doing a "redo" (the socket was busy last time
1002
         * around), we can just queue the packet now..
1003
         */
1004
        if (redo) {
1005
                udp_queue_rcv_skb(skb->sk, skb);
1006
                return 0;
1007
        }
1008
 
1009
        /*
1010
         * First time through the loop.. Do all the setup stuff
1011
         * (including finding out the socket we go to etc)
1012
         */
1013
 
1014
        addr_type = IS_MYADDR;
1015
        if(!dev || dev->pa_addr!=daddr)
1016
                addr_type=ip_chk_addr(daddr);
1017
 
1018
        /*
1019
         *      Get the header.
1020
         */
1021
 
1022
        uh = (struct udphdr *) skb->h.uh;
1023
 
1024
        ip_statistics.IpInDelivers++;
1025
 
1026
        /*
1027
         *      Validate the packet and the UDP length.
1028
         */
1029
 
1030
        ulen = ntohs(uh->len);
1031
 
1032
        if (ulen > len || len < sizeof(*uh) || ulen < sizeof(*uh))
1033
        {
1034
                NETDEBUG(printk("UDP: short packet: %d/%d\n", ulen, len));
1035
                udp_statistics.UdpInErrors++;
1036
                kfree_skb(skb, FREE_WRITE);
1037
                return(0);
1038
        }
1039
 
1040
        /* RFC1122 warning: According to 4.1.3.6, we MUST discard any */
1041
        /* datagram which has an invalid source address, either here or */
1042
        /* in IP. */
1043
        /* Right now, IP isn't doing it, and neither is UDP. It's on the */
1044
        /* FIXME list for IP, though, so I wouldn't worry about it. */
1045
        /* (That's the Right Place to do it, IMHO.) -- MS */
1046
 
1047
        if (uh->check && (
1048
                ( (skb->ip_summed == CHECKSUM_HW) && udp_check(uh, len, saddr, daddr, skb->csum ) ) ||
1049
                ( (skb->ip_summed == CHECKSUM_NONE) && udp_check(uh, len, saddr, daddr,csum_partial((char*)uh, len, 0)))
1050
                          /* skip if CHECKSUM_UNNECESSARY */
1051
                         )
1052
           )
1053
        {
1054
                /* <mea@utu.fi> wants to know, who sent it, to
1055
                   go and stomp on the garbage sender... */
1056
 
1057
          /* RFC1122: OK.  Discards the bad packet silently (as far as */
1058
          /* the network is concerned, anyway) as per 4.1.3.4 (MUST). */
1059
 
1060
                NETDEBUG(printk("UDP: bad checksum. From %08lX:%d to %08lX:%d ulen %d\n",
1061
                       ntohl(saddr),ntohs(uh->source),
1062
                       ntohl(daddr),ntohs(uh->dest),
1063
                       ulen));
1064
                udp_statistics.UdpInErrors++;
1065
                kfree_skb(skb, FREE_WRITE);
1066
                return(0);
1067
        }
1068
 
1069
        /*
1070
         *      These are supposed to be switched.
1071
         */
1072
 
1073
        skb->daddr = saddr;
1074
        skb->saddr = daddr;
1075
 
1076
        len=ulen;
1077
 
1078
        skb->dev = dev;
1079
        skb_trim(skb,len);
1080
 
1081
#ifdef CONFIG_IP_MULTICAST
1082
        if (addr_type==IS_BROADCAST || addr_type==IS_MULTICAST)
1083
                return udp_v4_mcast_deliver(skb, uh, saddr, daddr);
1084
#endif
1085
#ifdef CONFIG_IP_TRANSPARENT_PROXY
1086
        if(skb->redirport)
1087
                sk = udp_v4_proxy_lookup(saddr, uh->source, daddr, uh->dest,
1088
                                         dev->pa_addr, skb->redirport, dev);
1089
        else
1090
#endif
1091
        sk = udp_v4_lookup(saddr, uh->source, daddr, uh->dest, dev);
1092
 
1093
        if (sk == NULL)
1094
        {
1095
                udp_statistics.UdpNoPorts++;
1096
                if (addr_type != IS_BROADCAST && addr_type != IS_MULTICAST)
1097
                {
1098
                        icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0, dev);
1099
                }
1100
                /*
1101
                 * Hmm.  We got an UDP broadcast to a port to which we
1102
                 * don't wanna listen.  Ignore it.
1103
                 */
1104
                skb->sk = NULL;
1105
                kfree_skb(skb, FREE_WRITE);
1106
                return(0);
1107
        }
1108
        udp_deliver(sk, skb);
1109
        return 0;
1110
}
1111
 
1112
struct proto udp_prot = {
1113
        (struct sock *)&udp_prot,       /* sklist_next */
1114
        (struct sock *)&udp_prot,       /* sklist_prev */
1115
        udp_close,                      /* close */
1116
        ip_build_header,                /* build_header */
1117
        udp_connect,                    /* connect */
1118
        NULL,                           /* accept */
1119
        ip_queue_xmit,                  /* queue_xmit */
1120
        NULL,                           /* retransmit */
1121
        NULL,                           /* write_wakeup */
1122
        NULL,                           /* read_wakeup */
1123
        udp_rcv,                        /* rcv */
1124
        datagram_select,                /* select */
1125
        udp_ioctl,                      /* ioctl */
1126
        NULL,                           /* init */
1127
        NULL,                           /* shutdown */
1128
        ip_setsockopt,                  /* setsockopt */
1129
        ip_getsockopt,                  /* getsockopt */
1130
        udp_sendmsg,                    /* sendmsg */
1131
        udp_recvmsg,                    /* recvmsg */
1132
        NULL,                           /* bind */
1133
        udp_v4_hash,                    /* hash */
1134
        udp_v4_unhash,                  /* unhash */
1135
        udp_v4_rehash,                  /* rehash */
1136
        udp_good_socknum,               /* good_socknum */
1137
        udp_v4_verify_bind,             /* verify_bind */
1138
        128,                            /* max_header */
1139
        0,                               /* retransmits */
1140
        "UDP",                          /* name */
1141
        0,                               /* inuse */
1142
 
1143
};

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.