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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [net/] [ipv6/] [udp.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 *      UDP over IPv6
3
 *      Linux INET6 implementation
4
 *
5
 *      Authors:
6
 *      Pedro Roque             <roque@di.fc.ul.pt>
7
 *
8
 *      Based on linux/ipv4/udp.c
9
 *
10
 *      $Id: udp.c,v 1.65 2002/02/01 22:01:04 davem Exp $
11
 *
12
 *      Fixes:
13
 *      Hideaki YOSHIFUJI       :       sin6_scope_id support
14
 *      YOSHIFUJI Hideaki @USAGI and:   Support IPV6_V6ONLY socket option, which
15
 *      Alexey Kuznetsov                allow both IPv4 and IPv6 sockets to bind
16
 *                                      a single port at the same time.
17
 *      Kazunori MIYAZAWA @USAGI:       change process style to use ip6_append_data
18
 *      YOSHIFUJI Hideaki @USAGI:       convert /proc/net/udp6 to seq_file.
19
 *
20
 *      This program is free software; you can redistribute it and/or
21
 *      modify it under the terms of the GNU General Public License
22
 *      as published by the Free Software Foundation; either version
23
 *      2 of the License, or (at your option) any later version.
24
 */
25
 
26
#include <linux/errno.h>
27
#include <linux/types.h>
28
#include <linux/socket.h>
29
#include <linux/sockios.h>
30
#include <linux/net.h>
31
#include <linux/in6.h>
32
#include <linux/netdevice.h>
33
#include <linux/if_arp.h>
34
#include <linux/ipv6.h>
35
#include <linux/icmpv6.h>
36
#include <linux/init.h>
37
#include <linux/skbuff.h>
38
#include <asm/uaccess.h>
39
 
40
#include <net/ndisc.h>
41
#include <net/protocol.h>
42
#include <net/transp_v6.h>
43
#include <net/ip6_route.h>
44
#include <net/raw.h>
45
#include <net/tcp_states.h>
46
#include <net/ip6_checksum.h>
47
#include <net/xfrm.h>
48
 
49
#include <linux/proc_fs.h>
50
#include <linux/seq_file.h>
51
#include "udp_impl.h"
52
 
53
DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly;
54
 
55
static inline int udp_v6_get_port(struct sock *sk, unsigned short snum)
56
{
57
        return udp_get_port(sk, snum, ipv6_rcv_saddr_equal);
58
}
59
 
60
static struct sock *__udp6_lib_lookup(struct in6_addr *saddr, __be16 sport,
61
                                      struct in6_addr *daddr, __be16 dport,
62
                                      int dif, struct hlist_head udptable[])
63
{
64
        struct sock *sk, *result = NULL;
65
        struct hlist_node *node;
66
        unsigned short hnum = ntohs(dport);
67
        int badness = -1;
68
 
69
        read_lock(&udp_hash_lock);
70
        sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) {
71
                struct inet_sock *inet = inet_sk(sk);
72
 
73
                if (sk->sk_hash == hnum && sk->sk_family == PF_INET6) {
74
                        struct ipv6_pinfo *np = inet6_sk(sk);
75
                        int score = 0;
76
                        if (inet->dport) {
77
                                if (inet->dport != sport)
78
                                        continue;
79
                                score++;
80
                        }
81
                        if (!ipv6_addr_any(&np->rcv_saddr)) {
82
                                if (!ipv6_addr_equal(&np->rcv_saddr, daddr))
83
                                        continue;
84
                                score++;
85
                        }
86
                        if (!ipv6_addr_any(&np->daddr)) {
87
                                if (!ipv6_addr_equal(&np->daddr, saddr))
88
                                        continue;
89
                                score++;
90
                        }
91
                        if (sk->sk_bound_dev_if) {
92
                                if (sk->sk_bound_dev_if != dif)
93
                                        continue;
94
                                score++;
95
                        }
96
                        if (score == 4) {
97
                                result = sk;
98
                                break;
99
                        } else if (score > badness) {
100
                                result = sk;
101
                                badness = score;
102
                        }
103
                }
104
        }
105
        if (result)
106
                sock_hold(result);
107
        read_unlock(&udp_hash_lock);
108
        return result;
109
}
110
 
111
/*
112
 *      This should be easy, if there is something there we
113
 *      return it, otherwise we block.
114
 */
115
 
116
int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
117
                  struct msghdr *msg, size_t len,
118
                  int noblock, int flags, int *addr_len)
119
{
120
        struct ipv6_pinfo *np = inet6_sk(sk);
121
        struct inet_sock *inet = inet_sk(sk);
122
        struct sk_buff *skb;
123
        unsigned int ulen, copied;
124
        int err;
125
        int is_udplite = IS_UDPLITE(sk);
126
 
127
        if (addr_len)
128
                *addr_len=sizeof(struct sockaddr_in6);
129
 
130
        if (flags & MSG_ERRQUEUE)
131
                return ipv6_recv_error(sk, msg, len);
132
 
133
try_again:
134
        skb = skb_recv_datagram(sk, flags, noblock, &err);
135
        if (!skb)
136
                goto out;
137
 
138
        ulen = skb->len - sizeof(struct udphdr);
139
        copied = len;
140
        if (copied > ulen)
141
                copied = ulen;
142
        else if (copied < ulen)
143
                msg->msg_flags |= MSG_TRUNC;
144
 
145
        /*
146
         * If checksum is needed at all, try to do it while copying the
147
         * data.  If the data is truncated, or if we only want a partial
148
         * coverage checksum (UDP-Lite), do it before the copy.
149
         */
150
 
151
        if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) {
152
                if (udp_lib_checksum_complete(skb))
153
                        goto csum_copy_err;
154
        }
155
 
156
        if (skb_csum_unnecessary(skb))
157
                err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr),
158
                                              msg->msg_iov, copied       );
159
        else {
160
                err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov);
161
                if (err == -EINVAL)
162
                        goto csum_copy_err;
163
        }
164
        if (err)
165
                goto out_free;
166
 
167
        sock_recv_timestamp(msg, sk, skb);
168
 
169
        /* Copy the address. */
170
        if (msg->msg_name) {
171
                struct sockaddr_in6 *sin6;
172
 
173
                sin6 = (struct sockaddr_in6 *) msg->msg_name;
174
                sin6->sin6_family = AF_INET6;
175
                sin6->sin6_port = udp_hdr(skb)->source;
176
                sin6->sin6_flowinfo = 0;
177
                sin6->sin6_scope_id = 0;
178
 
179
                if (skb->protocol == htons(ETH_P_IP))
180
                        ipv6_addr_set(&sin6->sin6_addr, 0, 0,
181
                                      htonl(0xffff), ip_hdr(skb)->saddr);
182
                else {
183
                        ipv6_addr_copy(&sin6->sin6_addr,
184
                                       &ipv6_hdr(skb)->saddr);
185
                        if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL)
186
                                sin6->sin6_scope_id = IP6CB(skb)->iif;
187
                }
188
 
189
        }
190
        if (skb->protocol == htons(ETH_P_IP)) {
191
                if (inet->cmsg_flags)
192
                        ip_cmsg_recv(msg, skb);
193
        } else {
194
                if (np->rxopt.all)
195
                        datagram_recv_ctl(sk, msg, skb);
196
        }
197
 
198
        err = copied;
199
        if (flags & MSG_TRUNC)
200
                err = ulen;
201
 
202
out_free:
203
        skb_free_datagram(sk, skb);
204
out:
205
        return err;
206
 
207
csum_copy_err:
208
        UDP6_INC_STATS_USER(UDP_MIB_INERRORS, is_udplite);
209
        skb_kill_datagram(sk, skb, flags);
210
 
211
        if (flags & MSG_DONTWAIT)
212
                return -EAGAIN;
213
        goto try_again;
214
}
215
 
216
void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
217
                    int type, int code, int offset, __be32 info,
218
                    struct hlist_head udptable[]                    )
219
{
220
        struct ipv6_pinfo *np;
221
        struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data;
222
        struct in6_addr *saddr = &hdr->saddr;
223
        struct in6_addr *daddr = &hdr->daddr;
224
        struct udphdr *uh = (struct udphdr*)(skb->data+offset);
225
        struct sock *sk;
226
        int err;
227
 
228
        sk = __udp6_lib_lookup(daddr, uh->dest,
229
                               saddr, uh->source, inet6_iif(skb), udptable);
230
        if (sk == NULL)
231
                return;
232
 
233
        np = inet6_sk(sk);
234
 
235
        if (!icmpv6_err_convert(type, code, &err) && !np->recverr)
236
                goto out;
237
 
238
        if (sk->sk_state != TCP_ESTABLISHED && !np->recverr)
239
                goto out;
240
 
241
        if (np->recverr)
242
                ipv6_icmp_error(sk, skb, err, uh->dest, ntohl(info), (u8 *)(uh+1));
243
 
244
        sk->sk_err = err;
245
        sk->sk_error_report(sk);
246
out:
247
        sock_put(sk);
248
}
249
 
250
static __inline__ void udpv6_err(struct sk_buff *skb,
251
                                 struct inet6_skb_parm *opt, int type,
252
                                 int code, int offset, __be32 info     )
253
{
254
        return __udp6_lib_err(skb, opt, type, code, offset, info, udp_hash);
255
}
256
 
257
int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
258
{
259
        struct udp_sock *up = udp_sk(sk);
260
        int rc;
261
 
262
        if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
263
                goto drop;
264
 
265
        /*
266
         * UDP-Lite specific tests, ignored on UDP sockets (see net/ipv4/udp.c).
267
         */
268
        if ((up->pcflag & UDPLITE_RECV_CC)  &&  UDP_SKB_CB(skb)->partial_cov) {
269
 
270
                if (up->pcrlen == 0) {          /* full coverage was set  */
271
                        LIMIT_NETDEBUG(KERN_WARNING "UDPLITE6: partial coverage"
272
                                " %d while full coverage %d requested\n",
273
                                UDP_SKB_CB(skb)->cscov, skb->len);
274
                        goto drop;
275
                }
276
                if (UDP_SKB_CB(skb)->cscov  <  up->pcrlen) {
277
                        LIMIT_NETDEBUG(KERN_WARNING "UDPLITE6: coverage %d "
278
                                                    "too small, need min %d\n",
279
                                       UDP_SKB_CB(skb)->cscov, up->pcrlen);
280
                        goto drop;
281
                }
282
        }
283
 
284
        if (sk->sk_filter) {
285
                if (udp_lib_checksum_complete(skb))
286
                        goto drop;
287
        }
288
 
289
        if ((rc = sock_queue_rcv_skb(sk,skb)) < 0) {
290
                /* Note that an ENOMEM error is charged twice */
291
                if (rc == -ENOMEM)
292
                        UDP6_INC_STATS_BH(UDP_MIB_RCVBUFERRORS, up->pcflag);
293
                goto drop;
294
        }
295
        UDP6_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag);
296
        return 0;
297
drop:
298
        UDP6_INC_STATS_BH(UDP_MIB_INERRORS, up->pcflag);
299
        kfree_skb(skb);
300
        return -1;
301
}
302
 
303
static struct sock *udp_v6_mcast_next(struct sock *sk,
304
                                      __be16 loc_port, struct in6_addr *loc_addr,
305
                                      __be16 rmt_port, struct in6_addr *rmt_addr,
306
                                      int dif)
307
{
308
        struct hlist_node *node;
309
        struct sock *s = sk;
310
        unsigned short num = ntohs(loc_port);
311
 
312
        sk_for_each_from(s, node) {
313
                struct inet_sock *inet = inet_sk(s);
314
 
315
                if (s->sk_hash == num && s->sk_family == PF_INET6) {
316
                        struct ipv6_pinfo *np = inet6_sk(s);
317
                        if (inet->dport) {
318
                                if (inet->dport != rmt_port)
319
                                        continue;
320
                        }
321
                        if (!ipv6_addr_any(&np->daddr) &&
322
                            !ipv6_addr_equal(&np->daddr, rmt_addr))
323
                                continue;
324
 
325
                        if (s->sk_bound_dev_if && s->sk_bound_dev_if != dif)
326
                                continue;
327
 
328
                        if (!ipv6_addr_any(&np->rcv_saddr)) {
329
                                if (!ipv6_addr_equal(&np->rcv_saddr, loc_addr))
330
                                        continue;
331
                        }
332
                        if (!inet6_mc_check(s, loc_addr, rmt_addr))
333
                                continue;
334
                        return s;
335
                }
336
        }
337
        return NULL;
338
}
339
 
340
/*
341
 * Note: called only from the BH handler context,
342
 * so we don't need to lock the hashes.
343
 */
344
static int __udp6_lib_mcast_deliver(struct sk_buff *skb, struct in6_addr *saddr,
345
                           struct in6_addr *daddr, struct hlist_head udptable[])
346
{
347
        struct sock *sk, *sk2;
348
        const struct udphdr *uh = udp_hdr(skb);
349
        int dif;
350
 
351
        read_lock(&udp_hash_lock);
352
        sk = sk_head(&udptable[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]);
353
        dif = inet6_iif(skb);
354
        sk = udp_v6_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif);
355
        if (!sk) {
356
                kfree_skb(skb);
357
                goto out;
358
        }
359
 
360
        sk2 = sk;
361
        while ((sk2 = udp_v6_mcast_next(sk_next(sk2), uh->dest, daddr,
362
                                        uh->source, saddr, dif))) {
363
                struct sk_buff *buff = skb_clone(skb, GFP_ATOMIC);
364
                if (buff)
365
                        udpv6_queue_rcv_skb(sk2, buff);
366
        }
367
        udpv6_queue_rcv_skb(sk, skb);
368
out:
369
        read_unlock(&udp_hash_lock);
370
        return 0;
371
}
372
 
373
static inline int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh,
374
                                 int proto)
375
{
376
        int err;
377
 
378
        UDP_SKB_CB(skb)->partial_cov = 0;
379
        UDP_SKB_CB(skb)->cscov = skb->len;
380
 
381
        if (proto == IPPROTO_UDPLITE) {
382
                err = udplite_checksum_init(skb, uh);
383
                if (err)
384
                        return err;
385
        }
386
 
387
        if (uh->check == 0) {
388
                /* RFC 2460 section 8.1 says that we SHOULD log
389
                   this error. Well, it is reasonable.
390
                 */
391
                LIMIT_NETDEBUG(KERN_INFO "IPv6: udp checksum is 0\n");
392
                return 1;
393
        }
394
        if (skb->ip_summed == CHECKSUM_COMPLETE &&
395
            !csum_ipv6_magic(&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
396
                             skb->len, proto, skb->csum))
397
                skb->ip_summed = CHECKSUM_UNNECESSARY;
398
 
399
        if (!skb_csum_unnecessary(skb))
400
                skb->csum = ~csum_unfold(csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
401
                                                         &ipv6_hdr(skb)->daddr,
402
                                                         skb->len, proto, 0));
403
 
404
        return 0;
405
}
406
 
407
int __udp6_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
408
                   int proto)
409
{
410
        struct sock *sk;
411
        struct udphdr *uh;
412
        struct net_device *dev = skb->dev;
413
        struct in6_addr *saddr, *daddr;
414
        u32 ulen = 0;
415
 
416
        if (!pskb_may_pull(skb, sizeof(struct udphdr)))
417
                goto short_packet;
418
 
419
        saddr = &ipv6_hdr(skb)->saddr;
420
        daddr = &ipv6_hdr(skb)->daddr;
421
        uh = udp_hdr(skb);
422
 
423
        ulen = ntohs(uh->len);
424
        if (ulen > skb->len)
425
                goto short_packet;
426
 
427
        if (proto == IPPROTO_UDP) {
428
                /* UDP validates ulen. */
429
 
430
                /* Check for jumbo payload */
431
                if (ulen == 0)
432
                        ulen = skb->len;
433
 
434
                if (ulen < sizeof(*uh))
435
                        goto short_packet;
436
 
437
                if (ulen < skb->len) {
438
                        if (pskb_trim_rcsum(skb, ulen))
439
                                goto short_packet;
440
                        saddr = &ipv6_hdr(skb)->saddr;
441
                        daddr = &ipv6_hdr(skb)->daddr;
442
                        uh = udp_hdr(skb);
443
                }
444
        }
445
 
446
        if (udp6_csum_init(skb, uh, proto))
447
                goto discard;
448
 
449
        /*
450
         *      Multicast receive code
451
         */
452
        if (ipv6_addr_is_multicast(daddr))
453
                return __udp6_lib_mcast_deliver(skb, saddr, daddr, udptable);
454
 
455
        /* Unicast */
456
 
457
        /*
458
         * check socket cache ... must talk to Alan about his plans
459
         * for sock caches... i'll skip this for now.
460
         */
461
        sk = __udp6_lib_lookup(saddr, uh->source,
462
                               daddr, uh->dest, inet6_iif(skb), udptable);
463
 
464
        if (sk == NULL) {
465
                if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
466
                        goto discard;
467
 
468
                if (udp_lib_checksum_complete(skb))
469
                        goto discard;
470
                UDP6_INC_STATS_BH(UDP_MIB_NOPORTS, proto == IPPROTO_UDPLITE);
471
 
472
                icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, dev);
473
 
474
                kfree_skb(skb);
475
                return 0;
476
        }
477
 
478
        /* deliver */
479
 
480
        udpv6_queue_rcv_skb(sk, skb);
481
        sock_put(sk);
482
        return 0;
483
 
484
short_packet:
485
        LIMIT_NETDEBUG(KERN_DEBUG "UDP%sv6: short packet: %d/%u\n",
486
                       proto == IPPROTO_UDPLITE ? "-Lite" : "",
487
                       ulen, skb->len);
488
 
489
discard:
490
        UDP6_INC_STATS_BH(UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE);
491
        kfree_skb(skb);
492
        return 0;
493
}
494
 
495
static __inline__ int udpv6_rcv(struct sk_buff *skb)
496
{
497
        return __udp6_lib_rcv(skb, udp_hash, IPPROTO_UDP);
498
}
499
 
500
/*
501
 * Throw away all pending data and cancel the corking. Socket is locked.
502
 */
503
static void udp_v6_flush_pending_frames(struct sock *sk)
504
{
505
        struct udp_sock *up = udp_sk(sk);
506
 
507
        if (up->pending) {
508
                up->len = 0;
509
                up->pending = 0;
510
                ip6_flush_pending_frames(sk);
511
        }
512
}
513
 
514
/*
515
 *      Sending
516
 */
517
 
518
static int udp_v6_push_pending_frames(struct sock *sk)
519
{
520
        struct sk_buff *skb;
521
        struct udphdr *uh;
522
        struct udp_sock  *up = udp_sk(sk);
523
        struct inet_sock *inet = inet_sk(sk);
524
        struct flowi *fl = &inet->cork.fl;
525
        int err = 0;
526
        __wsum csum = 0;
527
 
528
        /* Grab the skbuff where UDP header space exists. */
529
        if ((skb = skb_peek(&sk->sk_write_queue)) == NULL)
530
                goto out;
531
 
532
        /*
533
         * Create a UDP header
534
         */
535
        uh = udp_hdr(skb);
536
        uh->source = fl->fl_ip_sport;
537
        uh->dest = fl->fl_ip_dport;
538
        uh->len = htons(up->len);
539
        uh->check = 0;
540
 
541
        if (up->pcflag)
542
                csum = udplite_csum_outgoing(sk, skb);
543
         else
544
                csum = udp_csum_outgoing(sk, skb);
545
 
546
        /* add protocol-dependent pseudo-header */
547
        uh->check = csum_ipv6_magic(&fl->fl6_src, &fl->fl6_dst,
548
                                    up->len, fl->proto, csum   );
549
        if (uh->check == 0)
550
                uh->check = CSUM_MANGLED_0;
551
 
552
        err = ip6_push_pending_frames(sk);
553
out:
554
        up->len = 0;
555
        up->pending = 0;
556
        if (!err)
557
                UDP6_INC_STATS_USER(UDP_MIB_OUTDATAGRAMS, up->pcflag);
558
        return err;
559
}
560
 
561
int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk,
562
                  struct msghdr *msg, size_t len)
563
{
564
        struct ipv6_txoptions opt_space;
565
        struct udp_sock *up = udp_sk(sk);
566
        struct inet_sock *inet = inet_sk(sk);
567
        struct ipv6_pinfo *np = inet6_sk(sk);
568
        struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) msg->msg_name;
569
        struct in6_addr *daddr, *final_p = NULL, final;
570
        struct ipv6_txoptions *opt = NULL;
571
        struct ip6_flowlabel *flowlabel = NULL;
572
        struct flowi fl;
573
        struct dst_entry *dst;
574
        int addr_len = msg->msg_namelen;
575
        int ulen = len;
576
        int hlimit = -1;
577
        int tclass = -1;
578
        int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
579
        int err;
580
        int connected = 0;
581
        int is_udplite = up->pcflag;
582
        int (*getfrag)(void *, char *, int, int, int, struct sk_buff *);
583
 
584
        /* destination address check */
585
        if (sin6) {
586
                if (addr_len < offsetof(struct sockaddr, sa_data))
587
                        return -EINVAL;
588
 
589
                switch (sin6->sin6_family) {
590
                case AF_INET6:
591
                        if (addr_len < SIN6_LEN_RFC2133)
592
                                return -EINVAL;
593
                        daddr = &sin6->sin6_addr;
594
                        break;
595
                case AF_INET:
596
                        goto do_udp_sendmsg;
597
                case AF_UNSPEC:
598
                        msg->msg_name = sin6 = NULL;
599
                        msg->msg_namelen = addr_len = 0;
600
                        daddr = NULL;
601
                        break;
602
                default:
603
                        return -EINVAL;
604
                }
605
        } else if (!up->pending) {
606
                if (sk->sk_state != TCP_ESTABLISHED)
607
                        return -EDESTADDRREQ;
608
                daddr = &np->daddr;
609
        } else
610
                daddr = NULL;
611
 
612
        if (daddr) {
613
                if (ipv6_addr_v4mapped(daddr)) {
614
                        struct sockaddr_in sin;
615
                        sin.sin_family = AF_INET;
616
                        sin.sin_port = sin6 ? sin6->sin6_port : inet->dport;
617
                        sin.sin_addr.s_addr = daddr->s6_addr32[3];
618
                        msg->msg_name = &sin;
619
                        msg->msg_namelen = sizeof(sin);
620
do_udp_sendmsg:
621
                        if (__ipv6_only_sock(sk))
622
                                return -ENETUNREACH;
623
                        return udp_sendmsg(iocb, sk, msg, len);
624
                }
625
        }
626
 
627
        if (up->pending == AF_INET)
628
                return udp_sendmsg(iocb, sk, msg, len);
629
 
630
        /* Rough check on arithmetic overflow,
631
           better check is made in ip6_append_data().
632
           */
633
        if (len > INT_MAX - sizeof(struct udphdr))
634
                return -EMSGSIZE;
635
 
636
        if (up->pending) {
637
                /*
638
                 * There are pending frames.
639
                 * The socket lock must be held while it's corked.
640
                 */
641
                lock_sock(sk);
642
                if (likely(up->pending)) {
643
                        if (unlikely(up->pending != AF_INET6)) {
644
                                release_sock(sk);
645
                                return -EAFNOSUPPORT;
646
                        }
647
                        dst = NULL;
648
                        goto do_append_data;
649
                }
650
                release_sock(sk);
651
        }
652
        ulen += sizeof(struct udphdr);
653
 
654
        memset(&fl, 0, sizeof(fl));
655
 
656
        if (sin6) {
657
                if (sin6->sin6_port == 0)
658
                        return -EINVAL;
659
 
660
                fl.fl_ip_dport = sin6->sin6_port;
661
                daddr = &sin6->sin6_addr;
662
 
663
                if (np->sndflow) {
664
                        fl.fl6_flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK;
665
                        if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) {
666
                                flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel);
667
                                if (flowlabel == NULL)
668
                                        return -EINVAL;
669
                                daddr = &flowlabel->dst;
670
                        }
671
                }
672
 
673
                /*
674
                 * Otherwise it will be difficult to maintain
675
                 * sk->sk_dst_cache.
676
                 */
677
                if (sk->sk_state == TCP_ESTABLISHED &&
678
                    ipv6_addr_equal(daddr, &np->daddr))
679
                        daddr = &np->daddr;
680
 
681
                if (addr_len >= sizeof(struct sockaddr_in6) &&
682
                    sin6->sin6_scope_id &&
683
                    ipv6_addr_type(daddr)&IPV6_ADDR_LINKLOCAL)
684
                        fl.oif = sin6->sin6_scope_id;
685
        } else {
686
                if (sk->sk_state != TCP_ESTABLISHED)
687
                        return -EDESTADDRREQ;
688
 
689
                fl.fl_ip_dport = inet->dport;
690
                daddr = &np->daddr;
691
                fl.fl6_flowlabel = np->flow_label;
692
                connected = 1;
693
        }
694
 
695
        if (!fl.oif)
696
                fl.oif = sk->sk_bound_dev_if;
697
 
698
        if (msg->msg_controllen) {
699
                opt = &opt_space;
700
                memset(opt, 0, sizeof(struct ipv6_txoptions));
701
                opt->tot_len = sizeof(*opt);
702
 
703
                err = datagram_send_ctl(msg, &fl, opt, &hlimit, &tclass);
704
                if (err < 0) {
705
                        fl6_sock_release(flowlabel);
706
                        return err;
707
                }
708
                if ((fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) {
709
                        flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel);
710
                        if (flowlabel == NULL)
711
                                return -EINVAL;
712
                }
713
                if (!(opt->opt_nflen|opt->opt_flen))
714
                        opt = NULL;
715
                connected = 0;
716
        }
717
        if (opt == NULL)
718
                opt = np->opt;
719
        if (flowlabel)
720
                opt = fl6_merge_options(&opt_space, flowlabel, opt);
721
        opt = ipv6_fixup_options(&opt_space, opt);
722
 
723
        fl.proto = sk->sk_protocol;
724
        ipv6_addr_copy(&fl.fl6_dst, daddr);
725
        if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr))
726
                ipv6_addr_copy(&fl.fl6_src, &np->saddr);
727
        fl.fl_ip_sport = inet->sport;
728
 
729
        /* merge ip6_build_xmit from ip6_output */
730
        if (opt && opt->srcrt) {
731
                struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
732
                ipv6_addr_copy(&final, &fl.fl6_dst);
733
                ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
734
                final_p = &final;
735
                connected = 0;
736
        }
737
 
738
        if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) {
739
                fl.oif = np->mcast_oif;
740
                connected = 0;
741
        }
742
 
743
        security_sk_classify_flow(sk, &fl);
744
 
745
        err = ip6_sk_dst_lookup(sk, &dst, &fl);
746
        if (err)
747
                goto out;
748
        if (final_p)
749
                ipv6_addr_copy(&fl.fl6_dst, final_p);
750
 
751
        if ((err = __xfrm_lookup(&dst, &fl, sk, 1)) < 0) {
752
                if (err == -EREMOTE)
753
                        err = ip6_dst_blackhole(sk, &dst, &fl);
754
                if (err < 0)
755
                        goto out;
756
        }
757
 
758
        if (hlimit < 0) {
759
                if (ipv6_addr_is_multicast(&fl.fl6_dst))
760
                        hlimit = np->mcast_hops;
761
                else
762
                        hlimit = np->hop_limit;
763
                if (hlimit < 0)
764
                        hlimit = dst_metric(dst, RTAX_HOPLIMIT);
765
                if (hlimit < 0)
766
                        hlimit = ipv6_get_hoplimit(dst->dev);
767
        }
768
 
769
        if (tclass < 0) {
770
                tclass = np->tclass;
771
                if (tclass < 0)
772
                        tclass = 0;
773
        }
774
 
775
        if (msg->msg_flags&MSG_CONFIRM)
776
                goto do_confirm;
777
back_from_confirm:
778
 
779
        lock_sock(sk);
780
        if (unlikely(up->pending)) {
781
                /* The socket is already corked while preparing it. */
782
                /* ... which is an evident application bug. --ANK */
783
                release_sock(sk);
784
 
785
                LIMIT_NETDEBUG(KERN_DEBUG "udp cork app bug 2\n");
786
                err = -EINVAL;
787
                goto out;
788
        }
789
 
790
        up->pending = AF_INET6;
791
 
792
do_append_data:
793
        up->len += ulen;
794
        getfrag  =  is_udplite ?  udplite_getfrag : ip_generic_getfrag;
795
        err = ip6_append_data(sk, getfrag, msg->msg_iov, ulen,
796
                sizeof(struct udphdr), hlimit, tclass, opt, &fl,
797
                (struct rt6_info*)dst,
798
                corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags);
799
        if (err)
800
                udp_v6_flush_pending_frames(sk);
801
        else if (!corkreq)
802
                err = udp_v6_push_pending_frames(sk);
803
        else if (unlikely(skb_queue_empty(&sk->sk_write_queue)))
804
                up->pending = 0;
805
 
806
        if (dst) {
807
                if (connected) {
808
                        ip6_dst_store(sk, dst,
809
                                      ipv6_addr_equal(&fl.fl6_dst, &np->daddr) ?
810
                                      &np->daddr : NULL,
811
#ifdef CONFIG_IPV6_SUBTREES
812
                                      ipv6_addr_equal(&fl.fl6_src, &np->saddr) ?
813
                                      &np->saddr :
814
#endif
815
                                      NULL);
816
                } else {
817
                        dst_release(dst);
818
                }
819
        }
820
 
821
        if (err > 0)
822
                err = np->recverr ? net_xmit_errno(err) : 0;
823
        release_sock(sk);
824
out:
825
        fl6_sock_release(flowlabel);
826
        if (!err)
827
                return len;
828
        /*
829
         * ENOBUFS = no kernel mem, SOCK_NOSPACE = no sndbuf space.  Reporting
830
         * ENOBUFS might not be good (it's not tunable per se), but otherwise
831
         * we don't have a good statistic (IpOutDiscards but it can be too many
832
         * things).  We could add another new stat but at least for now that
833
         * seems like overkill.
834
         */
835
        if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) {
836
                UDP6_INC_STATS_USER(UDP_MIB_SNDBUFERRORS, is_udplite);
837
        }
838
        return err;
839
 
840
do_confirm:
841
        dst_confirm(dst);
842
        if (!(msg->msg_flags&MSG_PROBE) || len)
843
                goto back_from_confirm;
844
        err = 0;
845
        goto out;
846
}
847
 
848
int udpv6_destroy_sock(struct sock *sk)
849
{
850
        lock_sock(sk);
851
        udp_v6_flush_pending_frames(sk);
852
        release_sock(sk);
853
 
854
        inet6_destroy_sock(sk);
855
 
856
        return 0;
857
}
858
 
859
/*
860
 *      Socket option code for UDP
861
 */
862
int udpv6_setsockopt(struct sock *sk, int level, int optname,
863
                     char __user *optval, int optlen)
864
{
865
        if (level == SOL_UDP  ||  level == SOL_UDPLITE)
866
                return udp_lib_setsockopt(sk, level, optname, optval, optlen,
867
                                          udp_v6_push_pending_frames);
868
        return ipv6_setsockopt(sk, level, optname, optval, optlen);
869
}
870
 
871
#ifdef CONFIG_COMPAT
872
int compat_udpv6_setsockopt(struct sock *sk, int level, int optname,
873
                            char __user *optval, int optlen)
874
{
875
        if (level == SOL_UDP  ||  level == SOL_UDPLITE)
876
                return udp_lib_setsockopt(sk, level, optname, optval, optlen,
877
                                          udp_v6_push_pending_frames);
878
        return compat_ipv6_setsockopt(sk, level, optname, optval, optlen);
879
}
880
#endif
881
 
882
int udpv6_getsockopt(struct sock *sk, int level, int optname,
883
                     char __user *optval, int __user *optlen)
884
{
885
        if (level == SOL_UDP  ||  level == SOL_UDPLITE)
886
                return udp_lib_getsockopt(sk, level, optname, optval, optlen);
887
        return ipv6_getsockopt(sk, level, optname, optval, optlen);
888
}
889
 
890
#ifdef CONFIG_COMPAT
891
int compat_udpv6_getsockopt(struct sock *sk, int level, int optname,
892
                            char __user *optval, int __user *optlen)
893
{
894
        if (level == SOL_UDP  ||  level == SOL_UDPLITE)
895
                return udp_lib_getsockopt(sk, level, optname, optval, optlen);
896
        return compat_ipv6_getsockopt(sk, level, optname, optval, optlen);
897
}
898
#endif
899
 
900
static struct inet6_protocol udpv6_protocol = {
901
        .handler        =       udpv6_rcv,
902
        .err_handler    =       udpv6_err,
903
        .flags          =       INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
904
};
905
 
906
/* ------------------------------------------------------------------------ */
907
#ifdef CONFIG_PROC_FS
908
 
909
static void udp6_sock_seq_show(struct seq_file *seq, struct sock *sp, int bucket)
910
{
911
        struct inet_sock *inet = inet_sk(sp);
912
        struct ipv6_pinfo *np = inet6_sk(sp);
913
        struct in6_addr *dest, *src;
914
        __u16 destp, srcp;
915
 
916
        dest  = &np->daddr;
917
        src   = &np->rcv_saddr;
918
        destp = ntohs(inet->dport);
919
        srcp  = ntohs(inet->sport);
920
        seq_printf(seq,
921
                   "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
922
                   "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p\n",
923
                   bucket,
924
                   src->s6_addr32[0], src->s6_addr32[1],
925
                   src->s6_addr32[2], src->s6_addr32[3], srcp,
926
                   dest->s6_addr32[0], dest->s6_addr32[1],
927
                   dest->s6_addr32[2], dest->s6_addr32[3], destp,
928
                   sp->sk_state,
929
                   atomic_read(&sp->sk_wmem_alloc),
930
                   atomic_read(&sp->sk_rmem_alloc),
931
                   0, 0L, 0,
932
                   sock_i_uid(sp), 0,
933
                   sock_i_ino(sp),
934
                   atomic_read(&sp->sk_refcnt), sp);
935
}
936
 
937
int udp6_seq_show(struct seq_file *seq, void *v)
938
{
939
        if (v == SEQ_START_TOKEN)
940
                seq_printf(seq,
941
                           "  sl  "
942
                           "local_address                         "
943
                           "remote_address                        "
944
                           "st tx_queue rx_queue tr tm->when retrnsmt"
945
                           "   uid  timeout inode\n");
946
        else
947
                udp6_sock_seq_show(seq, v, ((struct udp_iter_state *)seq->private)->bucket);
948
        return 0;
949
}
950
 
951
static struct file_operations udp6_seq_fops;
952
static struct udp_seq_afinfo udp6_seq_afinfo = {
953
        .owner          = THIS_MODULE,
954
        .name           = "udp6",
955
        .family         = AF_INET6,
956
        .hashtable      = udp_hash,
957
        .seq_show       = udp6_seq_show,
958
        .seq_fops       = &udp6_seq_fops,
959
};
960
 
961
int __init udp6_proc_init(void)
962
{
963
        return udp_proc_register(&udp6_seq_afinfo);
964
}
965
 
966
void udp6_proc_exit(void) {
967
        udp_proc_unregister(&udp6_seq_afinfo);
968
}
969
#endif /* CONFIG_PROC_FS */
970
 
971
/* ------------------------------------------------------------------------ */
972
 
973
DEFINE_PROTO_INUSE(udpv6)
974
 
975
struct proto udpv6_prot = {
976
        .name              = "UDPv6",
977
        .owner             = THIS_MODULE,
978
        .close             = udp_lib_close,
979
        .connect           = ip6_datagram_connect,
980
        .disconnect        = udp_disconnect,
981
        .ioctl             = udp_ioctl,
982
        .destroy           = udpv6_destroy_sock,
983
        .setsockopt        = udpv6_setsockopt,
984
        .getsockopt        = udpv6_getsockopt,
985
        .sendmsg           = udpv6_sendmsg,
986
        .recvmsg           = udpv6_recvmsg,
987
        .backlog_rcv       = udpv6_queue_rcv_skb,
988
        .hash              = udp_lib_hash,
989
        .unhash            = udp_lib_unhash,
990
        .get_port          = udp_v6_get_port,
991
        .obj_size          = sizeof(struct udp6_sock),
992
#ifdef CONFIG_COMPAT
993
        .compat_setsockopt = compat_udpv6_setsockopt,
994
        .compat_getsockopt = compat_udpv6_getsockopt,
995
#endif
996
        REF_PROTO_INUSE(udpv6)
997
};
998
 
999
static struct inet_protosw udpv6_protosw = {
1000
        .type =      SOCK_DGRAM,
1001
        .protocol =  IPPROTO_UDP,
1002
        .prot =      &udpv6_prot,
1003
        .ops =       &inet6_dgram_ops,
1004
        .capability =-1,
1005
        .no_check =  UDP_CSUM_DEFAULT,
1006
        .flags =     INET_PROTOSW_PERMANENT,
1007
};
1008
 
1009
 
1010
void __init udpv6_init(void)
1011
{
1012
        if (inet6_add_protocol(&udpv6_protocol, IPPROTO_UDP) < 0)
1013
                printk(KERN_ERR "udpv6_init: Could not register protocol\n");
1014
        inet6_register_protosw(&udpv6_protosw);
1015
}

powered by: WebSVN 2.1.0

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