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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [atm/] [common.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* net/atm/common.c - ATM sockets (common part for PVC and SVC) */
2
 
3
/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
4
 
5
 
6
#include <linux/config.h>
7
#include <linux/module.h>
8
#include <linux/kmod.h>
9
#include <linux/net.h>          /* struct socket, struct net_proto, struct
10
                                   proto_ops */
11
#include <linux/atm.h>          /* ATM stuff */
12
#include <linux/atmdev.h>
13
#include <linux/atmclip.h>      /* CLIP_*ENCAP */
14
#include <linux/atmarp.h>       /* manifest constants */
15
#include <linux/sonet.h>        /* for ioctls */
16
#include <linux/socket.h>       /* SOL_SOCKET */
17
#include <linux/errno.h>        /* error codes */
18
#include <linux/capability.h>
19
#include <linux/mm.h>           /* verify_area */
20
#include <linux/sched.h>
21
#include <linux/time.h>         /* struct timeval */
22
#include <linux/skbuff.h>
23
#include <linux/bitops.h>
24
#include <linux/init.h>
25
#include <net/sock.h>           /* struct sock */
26
 
27
#include <asm/uaccess.h>
28
#include <asm/atomic.h>
29
#include <asm/poll.h>
30
#include <asm/ioctls.h>
31
 
32
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
33
#include <linux/atmlec.h>
34
#include "lec.h"
35
#include "lec_arpc.h"
36
struct atm_lane_ops *atm_lane_ops;
37
static DECLARE_MUTEX(atm_lane_ops_mutex);
38
 
39
void atm_lane_ops_set(struct atm_lane_ops *hook)
40
{
41
        down(&atm_lane_ops_mutex);
42
        atm_lane_ops = hook;
43
        up(&atm_lane_ops_mutex);
44
}
45
 
46
int try_atm_lane_ops(void)
47
{
48
        down(&atm_lane_ops_mutex);
49
        if (atm_lane_ops && try_inc_mod_count(atm_lane_ops->owner)) {
50
                up(&atm_lane_ops_mutex);
51
                return 1;
52
        }
53
        up(&atm_lane_ops_mutex);
54
        return 0;
55
}
56
 
57
#if defined(CONFIG_ATM_LANE_MODULE) || defined(CONFIG_ATM_MPOA_MODULE)
58
EXPORT_SYMBOL(atm_lane_ops);
59
EXPORT_SYMBOL(try_atm_lane_ops);
60
EXPORT_SYMBOL(atm_lane_ops_set);
61
#endif
62
#endif
63
 
64
#if defined(CONFIG_ATM_MPOA) || defined(CONFIG_ATM_MPOA_MODULE)
65
#include <linux/atmmpc.h>
66
#include "mpc.h"
67
struct atm_mpoa_ops *atm_mpoa_ops;
68
static DECLARE_MUTEX(atm_mpoa_ops_mutex);
69
 
70
void atm_mpoa_ops_set(struct atm_mpoa_ops *hook)
71
{
72
        down(&atm_mpoa_ops_mutex);
73
        atm_mpoa_ops = hook;
74
        up(&atm_mpoa_ops_mutex);
75
}
76
 
77
int try_atm_mpoa_ops(void)
78
{
79
        down(&atm_mpoa_ops_mutex);
80
        if (atm_mpoa_ops && try_inc_mod_count(atm_mpoa_ops->owner)) {
81
                up(&atm_mpoa_ops_mutex);
82
                return 1;
83
        }
84
        up(&atm_mpoa_ops_mutex);
85
        return 0;
86
}
87
#ifdef CONFIG_ATM_MPOA_MODULE
88
EXPORT_SYMBOL(atm_mpoa_ops);
89
EXPORT_SYMBOL(try_atm_mpoa_ops);
90
EXPORT_SYMBOL(atm_mpoa_ops_set);
91
#endif
92
#endif
93
 
94
#if defined(CONFIG_ATM_TCP) || defined(CONFIG_ATM_TCP_MODULE)
95
#include <linux/atm_tcp.h>
96
#ifdef CONFIG_ATM_TCP_MODULE
97
struct atm_tcp_ops atm_tcp_ops;
98
EXPORT_SYMBOL(atm_tcp_ops);
99
#endif
100
#endif
101
 
102
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
103
#include <net/atmclip.h>
104
struct atm_clip_ops *atm_clip_ops;
105
static DECLARE_MUTEX(atm_clip_ops_mutex);
106
 
107
void atm_clip_ops_set(struct atm_clip_ops *hook)
108
{
109
        down(&atm_clip_ops_mutex);
110
        atm_clip_ops = hook;
111
        up(&atm_clip_ops_mutex);
112
}
113
 
114
int try_atm_clip_ops(void)
115
{
116
        down(&atm_clip_ops_mutex);
117
        if (atm_clip_ops && try_inc_mod_count(atm_clip_ops->owner)) {
118
                up(&atm_clip_ops_mutex);
119
                return 1;
120
        }
121
        up(&atm_clip_ops_mutex);
122
        return 0;
123
}
124
 
125
#ifdef CONFIG_ATM_CLIP_MODULE
126
EXPORT_SYMBOL(atm_clip_ops);
127
EXPORT_SYMBOL(try_atm_clip_ops);
128
EXPORT_SYMBOL(atm_clip_ops_set);
129
#endif
130
#endif
131
 
132
#if defined(CONFIG_PPPOATM) || defined(CONFIG_PPPOATM_MODULE)
133
static DECLARE_MUTEX(pppoatm_ioctl_mutex);
134
 
135
static int (*pppoatm_ioctl_hook)(struct atm_vcc *, unsigned int, unsigned long);
136
 
137
void pppoatm_ioctl_set(int (*hook)(struct atm_vcc *, unsigned int, unsigned long))
138
{
139
        down(&pppoatm_ioctl_mutex);
140
        pppoatm_ioctl_hook = hook;
141
        up(&pppoatm_ioctl_mutex);
142
}
143
#ifdef CONFIG_PPPOATM_MODULE
144
EXPORT_SYMBOL(pppoatm_ioctl_set);
145
#endif
146
#endif
147
 
148
#if defined(CONFIG_ATM_BR2684) || defined(CONFIG_ATM_BR2684_MODULE)
149
static DECLARE_MUTEX(br2684_ioctl_mutex);
150
 
151
static int (*br2684_ioctl_hook)(struct atm_vcc *, unsigned int, unsigned long);
152
 
153
void br2684_ioctl_set(int (*hook)(struct atm_vcc *, unsigned int, unsigned long))
154
{
155
        down(&br2684_ioctl_mutex);
156
        br2684_ioctl_hook = hook;
157
        up(&br2684_ioctl_mutex);
158
}
159
#ifdef CONFIG_ATM_BR2684_MODULE
160
EXPORT_SYMBOL(br2684_ioctl_set);
161
#endif
162
#endif
163
 
164
#include "resources.h"          /* atm_find_dev */
165
#include "common.h"             /* prototypes */
166
#include "protocols.h"          /* atm_init_<transport> */
167
#include "addr.h"               /* address registry */
168
#ifdef CONFIG_ATM_CLIP
169
#include <net/atmclip.h>        /* for clip_create */
170
#endif
171
#include "signaling.h"          /* for WAITING and sigd_attach */
172
 
173
 
174
#if 0
175
#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
176
#else
177
#define DPRINTK(format,args...)
178
#endif
179
 
180
 
181
struct sock *vcc_sklist;
182
rwlock_t vcc_sklist_lock = RW_LOCK_UNLOCKED;
183
 
184
void __vcc_insert_socket(struct sock *sk)
185
{
186
        sk->next = vcc_sklist;
187
        if (sk->next)
188
                vcc_sklist->pprev = &sk->next;
189
        vcc_sklist = sk;
190
        sk->pprev = &vcc_sklist;
191
}
192
 
193
void vcc_insert_socket(struct sock *sk)
194
{
195
        write_lock_irq(&vcc_sklist_lock);
196
        __vcc_insert_socket(sk);
197
        write_unlock_irq(&vcc_sklist_lock);
198
}
199
 
200
void vcc_remove_socket(struct sock *sk)
201
{
202
        write_lock_irq(&vcc_sklist_lock);
203
        if (sk->pprev) {
204
                if (sk->next)
205
                        sk->next->pprev = sk->pprev;
206
                *sk->pprev = sk->next;
207
                sk->pprev = NULL;
208
        }
209
        write_unlock_irq(&vcc_sklist_lock);
210
}
211
 
212
 
213
static struct sk_buff *alloc_tx(struct atm_vcc *vcc,unsigned int size)
214
{
215
        struct sk_buff *skb;
216
 
217
        if (atomic_read(&vcc->sk->wmem_alloc) && !atm_may_send(vcc,size)) {
218
                DPRINTK("Sorry: wmem_alloc = %d, size = %d, sndbuf = %d\n",
219
                    atomic_read(&vcc->sk->wmem_alloc),size,vcc->sk->sndbuf);
220
                return NULL;
221
        }
222
        while (!(skb = alloc_skb(size,GFP_KERNEL))) schedule();
223
        DPRINTK("AlTx %d += %d\n",atomic_read(&vcc->sk->wmem_alloc),skb->truesize);
224
        atomic_add(skb->truesize, &vcc->sk->wmem_alloc);
225
        return skb;
226
}
227
 
228
 
229
EXPORT_SYMBOL(vcc_sklist);
230
EXPORT_SYMBOL(vcc_sklist_lock);
231
EXPORT_SYMBOL(vcc_insert_socket);
232
EXPORT_SYMBOL(vcc_remove_socket);
233
 
234
static void vcc_sock_destruct(struct sock *sk)
235
{
236
        struct atm_vcc *vcc = sk->protinfo.af_atm;
237
 
238
        if (atomic_read(&vcc->sk->rmem_alloc))
239
                printk(KERN_DEBUG "vcc_sock_destruct: rmem leakage (%d bytes) detected.\n", atomic_read(&sk->rmem_alloc));
240
 
241
        if (atomic_read(&vcc->sk->wmem_alloc))
242
                printk(KERN_DEBUG "vcc_sock_destruct: wmem leakage (%d bytes) detected.\n", atomic_read(&sk->wmem_alloc));
243
 
244
        kfree(sk->protinfo.af_atm);
245
 
246
        MOD_DEC_USE_COUNT;
247
}
248
 
249
int vcc_create(struct socket *sock, int protocol, int family)
250
{
251
        struct sock *sk;
252
        struct atm_vcc *vcc;
253
 
254
        sock->sk = NULL;
255
        if (sock->type == SOCK_STREAM)
256
                return -EINVAL;
257
        sk = sk_alloc(family, GFP_KERNEL, 1);
258
        if (!sk)
259
                return -ENOMEM;
260
        sock_init_data(NULL, sk);
261
 
262
        vcc = sk->protinfo.af_atm = kmalloc(sizeof(*vcc), GFP_KERNEL);
263
        if (!vcc) {
264
                sk_free(sk);
265
                return -ENOMEM;
266
        }
267
 
268
        memset(vcc, 0, sizeof(*vcc));
269
        vcc->sk = sk;
270
 
271
        vcc->dev = NULL;
272
        vcc->callback = NULL;
273
        memset(&vcc->local,0,sizeof(struct sockaddr_atmsvc));
274
        memset(&vcc->remote,0,sizeof(struct sockaddr_atmsvc));
275
        vcc->qos.txtp.max_sdu = 1 << 16; /* for meta VCs */
276
        atomic_set(&vcc->sk->wmem_alloc,0);
277
        atomic_set(&vcc->sk->rmem_alloc,0);
278
        vcc->push = NULL;
279
        vcc->pop = NULL;
280
        vcc->push_oam = NULL;
281
        vcc->vpi = vcc->vci = 0; /* no VCI/VPI yet */
282
        vcc->atm_options = vcc->aal_options = 0;
283
        init_waitqueue_head(&vcc->sleep);
284
        sk->sleep = &vcc->sleep;
285
        sk->destruct = vcc_sock_destruct;
286
        sock->sk = sk;
287
 
288
        MOD_INC_USE_COUNT;
289
 
290
        return 0;
291
}
292
 
293
 
294
static void vcc_destroy_socket(struct sock *sk)
295
{
296
        struct atm_vcc *vcc;
297
        struct sk_buff *skb;
298
 
299
        vcc = sk->protinfo.af_atm;
300
        clear_bit(ATM_VF_READY, &vcc->flags);
301
        if (vcc->dev) {
302
                if (vcc->dev->ops->close)
303
                        vcc->dev->ops->close(vcc);
304
                if (vcc->push)
305
                        vcc->push(vcc, NULL); /* atmarpd has no push */
306
 
307
                vcc_remove_socket(sk);  /* no more receive */
308
 
309
                while ((skb = skb_dequeue(&vcc->sk->receive_queue))) {
310
                        atm_return(vcc,skb->truesize);
311
                        kfree_skb(skb);
312
                }
313
 
314
                if (vcc->dev->ops->owner)
315
                        __MOD_DEC_USE_COUNT(vcc->dev->ops->owner);
316
                atm_dev_put(vcc->dev);
317
        }
318
}
319
 
320
 
321
int vcc_release(struct socket *sock)
322
{
323
        struct sock *sk = sock->sk;
324
 
325
        if (sk) {
326
                lock_sock(sk);
327
                vcc_destroy_socket(sock->sk);
328
                release_sock(sk);
329
                sock_put(sk);
330
        }
331
 
332
        return 0;
333
}
334
 
335
 
336
void vcc_release_async(struct atm_vcc *vcc, int reply)
337
{
338
        set_bit(ATM_VF_CLOSE, &vcc->flags);
339
        vcc->reply = reply;
340
        vcc->sk->err = -reply;
341
        wake_up(&vcc->sleep);
342
}
343
 
344
 
345
EXPORT_SYMBOL(vcc_release_async);
346
 
347
 
348
static int adjust_tp(struct atm_trafprm *tp,unsigned char aal)
349
{
350
        int max_sdu;
351
 
352
        if (!tp->traffic_class) return 0;
353
        switch (aal) {
354
                case ATM_AAL0:
355
                        max_sdu = ATM_CELL_SIZE-1;
356
                        break;
357
                case ATM_AAL34:
358
                        max_sdu = ATM_MAX_AAL34_PDU;
359
                        break;
360
                default:
361
                        printk(KERN_WARNING "ATM: AAL problems ... "
362
                            "(%d)\n",aal);
363
                        /* fall through */
364
                case ATM_AAL5:
365
                        max_sdu = ATM_MAX_AAL5_PDU;
366
        }
367
        if (!tp->max_sdu) tp->max_sdu = max_sdu;
368
        else if (tp->max_sdu > max_sdu) return -EINVAL;
369
        if (!tp->max_cdv) tp->max_cdv = ATM_MAX_CDV;
370
        return 0;
371
}
372
 
373
 
374
static int __vcc_connect(struct atm_vcc *vcc, struct atm_dev *dev, int vpi,
375
                         int vci)
376
{
377
        int error;
378
 
379
        if ((vpi != ATM_VPI_UNSPEC && vpi != ATM_VPI_ANY &&
380
            vpi >> dev->ci_range.vpi_bits) || (vci != ATM_VCI_UNSPEC &&
381
            vci != ATM_VCI_ANY && vci >> dev->ci_range.vci_bits))
382
                return -EINVAL;
383
        if (vci > 0 && vci < ATM_NOT_RSV_VCI && !capable(CAP_NET_BIND_SERVICE))
384
                return -EPERM;
385
        error = 0;
386
        if (!try_inc_mod_count(dev->ops->owner))
387
                return -ENODEV;
388
        vcc->dev = dev;
389
        vcc_insert_socket(vcc->sk);
390
        switch (vcc->qos.aal) {
391
                case ATM_AAL0:
392
                        error = atm_init_aal0(vcc);
393
                        vcc->stats = &dev->stats.aal0;
394
                        break;
395
                case ATM_AAL34:
396
                        error = atm_init_aal34(vcc);
397
                        vcc->stats = &dev->stats.aal34;
398
                        break;
399
                case ATM_NO_AAL:
400
                        /* ATM_AAL5 is also used in the "0 for default" case */
401
                        vcc->qos.aal = ATM_AAL5;
402
                        /* fall through */
403
                case ATM_AAL5:
404
                        error = atm_init_aal5(vcc);
405
                        vcc->stats = &dev->stats.aal5;
406
                        break;
407
                default:
408
                        error = -EPROTOTYPE;
409
        }
410
        if (!error) error = adjust_tp(&vcc->qos.txtp,vcc->qos.aal);
411
        if (!error) error = adjust_tp(&vcc->qos.rxtp,vcc->qos.aal);
412
        if (error)
413
                goto fail;
414
        DPRINTK("VCC %d.%d, AAL %d\n",vpi,vci,vcc->qos.aal);
415
        DPRINTK("  TX: %d, PCR %d..%d, SDU %d\n",vcc->qos.txtp.traffic_class,
416
            vcc->qos.txtp.min_pcr,vcc->qos.txtp.max_pcr,vcc->qos.txtp.max_sdu);
417
        DPRINTK("  RX: %d, PCR %d..%d, SDU %d\n",vcc->qos.rxtp.traffic_class,
418
            vcc->qos.rxtp.min_pcr,vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu);
419
        if (dev->ops->open) {
420
                if ((error = dev->ops->open(vcc,vpi,vci)))
421
                        goto fail;
422
        }
423
        return 0;
424
 
425
fail:
426
        vcc_remove_socket(vcc->sk);
427
        if (dev->ops->owner)
428
                __MOD_DEC_USE_COUNT(dev->ops->owner);
429
        /* ensure we get dev module ref count correct */
430
        vcc->dev = NULL;
431
        return error;
432
 
433
}
434
 
435
 
436
int vcc_connect(struct socket *sock, int itf, short vpi, int vci)
437
{
438
        struct atm_dev *dev;
439
        struct atm_vcc *vcc = ATM_SD(sock);
440
        int error;
441
 
442
        DPRINTK("vcc_connect (vpi %d, vci %d)\n",vpi,vci);
443
        if (sock->state == SS_CONNECTED)
444
                return -EISCONN;
445
        if (sock->state != SS_UNCONNECTED)
446
                return -EINVAL;
447
        if (!(vpi || vci))
448
                return -EINVAL;
449
 
450
        if (vpi != ATM_VPI_UNSPEC && vci != ATM_VCI_UNSPEC)
451
                clear_bit(ATM_VF_PARTIAL,&vcc->flags);
452
        else
453
                if (test_bit(ATM_VF_PARTIAL,&vcc->flags))
454
                        return -EINVAL;
455
        DPRINTK("vcc_connect (TX: cl %d,bw %d-%d,sdu %d; "
456
            "RX: cl %d,bw %d-%d,sdu %d,AAL %s%d)\n",
457
            vcc->qos.txtp.traffic_class,vcc->qos.txtp.min_pcr,
458
            vcc->qos.txtp.max_pcr,vcc->qos.txtp.max_sdu,
459
            vcc->qos.rxtp.traffic_class,vcc->qos.rxtp.min_pcr,
460
            vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu,
461
            vcc->qos.aal == ATM_AAL5 ? "" : vcc->qos.aal == ATM_AAL0 ? "" :
462
            " ??? code ",vcc->qos.aal == ATM_AAL0 ? 0 : vcc->qos.aal);
463
        if (!test_bit(ATM_VF_HASQOS, &vcc->flags))
464
                return -EBADFD;
465
        if (vcc->qos.txtp.traffic_class == ATM_ANYCLASS ||
466
            vcc->qos.rxtp.traffic_class == ATM_ANYCLASS)
467
                return -EINVAL;
468
        if (itf != ATM_ITF_ANY) {
469
                dev = atm_dev_lookup(itf);
470
                if (!dev)
471
                        return -ENODEV;
472
                error = __vcc_connect(vcc, dev, vpi, vci);
473
                if (error) {
474
                        atm_dev_put(dev);
475
                        return error;
476
                }
477
        } else {
478
                struct list_head *p, *next;
479
 
480
                dev = NULL;
481
                spin_lock(&atm_dev_lock);
482
                list_for_each_safe(p, next, &atm_devs) {
483
                        dev = list_entry(p, struct atm_dev, dev_list);
484
                        atm_dev_hold(dev);
485
                        spin_unlock(&atm_dev_lock);
486
                        if (!__vcc_connect(vcc, dev, vpi, vci))
487
                                break;
488
                        atm_dev_put(dev);
489
                        dev = NULL;
490
                        spin_lock(&atm_dev_lock);
491
                }
492
                spin_unlock(&atm_dev_lock);
493
                if (!dev)
494
                        return -ENODEV;
495
        }
496
        if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC)
497
                set_bit(ATM_VF_PARTIAL,&vcc->flags);
498
        if (test_bit(ATM_VF_READY,&ATM_SD(sock)->flags))
499
                sock->state = SS_CONNECTED;
500
        return 0;
501
}
502
 
503
 
504
int vcc_recvmsg(struct socket *sock, struct msghdr *msg,
505
                int size, int flags, struct scm_cookie *scm)
506
{
507
        struct sock *sk = sock->sk;
508
        struct atm_vcc *vcc;
509
        struct sk_buff *skb;
510
        int copied, error = -EINVAL;
511
 
512
        if (sock->state != SS_CONNECTED)
513
                return -ENOTCONN;
514
        if (flags & ~MSG_DONTWAIT)              /* only handle MSG_DONTWAIT */
515
                return -EOPNOTSUPP;
516
        vcc = ATM_SD(sock);
517
        if (test_bit(ATM_VF_RELEASED,&vcc->flags) ||
518
            test_bit(ATM_VF_CLOSE, &vcc->flags) ||
519
            !test_bit(ATM_VF_READY, &vcc->flags))
520
                return 0;
521
 
522
        skb = skb_recv_datagram(sk, flags, flags & MSG_DONTWAIT, &error);
523
        if (!skb)
524
                return error;
525
 
526
        copied = skb->len;
527
        if (copied > size) {
528
                copied = size;
529
                msg->msg_flags |= MSG_TRUNC;
530
        }
531
 
532
        error = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
533
        if (error)
534
                 return error;
535
        sock_recv_timestamp(msg, sk, skb);
536
        if (vcc->dev->ops->feedback)
537
                vcc->dev->ops->feedback(vcc, skb, (unsigned long) skb->data,
538
                                        (unsigned long) msg->msg_iov->iov_base, copied);
539
        DPRINTK("RcvM %d -= %d\n", atomic_read(&vcc->sk->rmem_alloc), skb->truesize);
540
        atm_return(vcc, skb->truesize);
541
        skb_free_datagram(sk, skb);
542
        return copied;
543
}
544
 
545
 
546
 
547
int vcc_sendmsg(struct socket *sock, struct msghdr *m, int total_len,
548
                struct scm_cookie *scm)
549
{
550
        struct sock *sk = sock->sk;
551
        DECLARE_WAITQUEUE(wait,current);
552
        struct atm_vcc *vcc;
553
        struct sk_buff *skb;
554
        int eff,error;
555
        const void *buff;
556
        int size;
557
 
558
        lock_sock(sk);
559
        if (sock->state != SS_CONNECTED) {
560
                error = -ENOTCONN;
561
                goto out;
562
        }
563
        if (m->msg_name) {
564
                error = -EISCONN;
565
                goto out;
566
        }
567
        if (m->msg_iovlen != 1) {
568
                error = -ENOSYS; /* fix this later @@@ */
569
                goto out;
570
        }
571
        buff = m->msg_iov->iov_base;
572
        size = m->msg_iov->iov_len;
573
        vcc = ATM_SD(sock);
574
        if (test_bit(ATM_VF_RELEASED, &vcc->flags) ||
575
            test_bit(ATM_VF_CLOSE, &vcc->flags) ||
576
            !test_bit(ATM_VF_READY, &vcc->flags)) {
577
                error = -EPIPE;
578
                send_sig(SIGPIPE, current, 0);
579
                goto out;
580
        }
581
        if (!size) {
582
                error = 0;
583
                goto out;
584
        }
585
        if (size < 0 || size > vcc->qos.txtp.max_sdu) {
586
                error = -EMSGSIZE;
587
                goto out;
588
        }
589
        /* verify_area is done by net/socket.c */
590
        eff = (size+3) & ~3; /* align to word boundary */
591
        add_wait_queue(&vcc->sleep,&wait);
592
        set_current_state(TASK_INTERRUPTIBLE);
593
        error = 0;
594
        while (!(skb = alloc_tx(vcc,eff))) {
595
                if (m->msg_flags & MSG_DONTWAIT) {
596
                        error = -EAGAIN;
597
                        break;
598
                }
599
                schedule();
600
                set_current_state(TASK_INTERRUPTIBLE);
601
                if (signal_pending(current)) {
602
                        error = -ERESTARTSYS;
603
                        break;
604
                }
605
                if (test_bit(ATM_VF_RELEASED,&vcc->flags) ||
606
                    test_bit(ATM_VF_CLOSE, &vcc->flags) ||
607
                    !test_bit(ATM_VF_READY, &vcc->flags)) {
608
                        error = -EPIPE;
609
                        send_sig(SIGPIPE, current, 0);
610
                        break;
611
                }
612
        }
613
        set_current_state(TASK_RUNNING);
614
        remove_wait_queue(&vcc->sleep,&wait);
615
        if (error)
616
                goto out;
617
        skb->dev = NULL; /* for paths shared with net_device interfaces */
618
        ATM_SKB(skb)->atm_options = vcc->atm_options;
619
        if (copy_from_user(skb_put(skb,size),buff,size)) {
620
                kfree_skb(skb);
621
                error = -EFAULT;
622
                goto out;
623
        }
624
        if (eff != size) memset(skb->data+size,0,eff-size);
625
        error = vcc->dev->ops->send(vcc,skb);
626
        error = error ? error : size;
627
out:
628
        release_sock(sk);
629
        return error;
630
}
631
 
632
 
633
unsigned int atm_poll(struct file *file,struct socket *sock,poll_table *wait)
634
{
635
        struct atm_vcc *vcc;
636
        unsigned int mask;
637
 
638
        vcc = ATM_SD(sock);
639
        poll_wait(file,&vcc->sleep,wait);
640
        mask = 0;
641
        if (skb_peek(&vcc->sk->receive_queue))
642
                mask |= POLLIN | POLLRDNORM;
643
        if (test_bit(ATM_VF_RELEASED,&vcc->flags) ||
644
            test_bit(ATM_VF_CLOSE,&vcc->flags))
645
                mask |= POLLHUP;
646
        if (sock->state != SS_CONNECTING) {
647
                if (vcc->qos.txtp.traffic_class != ATM_NONE &&
648
                    vcc->qos.txtp.max_sdu+atomic_read(&vcc->sk->wmem_alloc) <= vcc->sk->sndbuf)
649
                        mask |= POLLOUT | POLLWRNORM;
650
        }
651
        else if (vcc->reply != WAITING) {
652
                        mask |= POLLOUT | POLLWRNORM;
653
                        if (vcc->reply) mask |= POLLERR;
654
                }
655
        return mask;
656
}
657
 
658
 
659
int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
660
{
661
        struct atm_vcc *vcc;
662
        int error;
663
 
664
        vcc = ATM_SD(sock);
665
        switch (cmd) {
666
                case SIOCOUTQ:
667
                        if (sock->state != SS_CONNECTED ||
668
                            !test_bit(ATM_VF_READY, &vcc->flags)) {
669
                                error =  -EINVAL;
670
                                goto done;
671
                        }
672
                        error =  put_user(vcc->sk->sndbuf-
673
                                          atomic_read(&vcc->sk->wmem_alloc),
674
                                          (int *) arg) ? -EFAULT : 0;
675
                        goto done;
676
                case SIOCINQ:
677
                        {
678
                                struct sk_buff *skb;
679
 
680
                                if (sock->state != SS_CONNECTED) {
681
                                        error = -EINVAL;
682
                                        goto done;
683
                                }
684
                                skb = skb_peek(&vcc->sk->receive_queue);
685
                                error = put_user(skb ? skb->len : 0,
686
                                                 (int *) arg) ? -EFAULT : 0;
687
                                goto done;
688
                        }
689
                case SIOCGSTAMP: /* borrowed from IP */
690
                        if (!vcc->sk->stamp.tv_sec) {
691
                                error = -ENOENT;
692
                                goto done;
693
                        }
694
                        error = copy_to_user((void *) arg, &vcc->sk->stamp,
695
                                             sizeof(struct timeval)) ? -EFAULT : 0;
696
                        goto done;
697
                case ATM_SETSC:
698
                        printk(KERN_WARNING "ATM_SETSC is obsolete\n");
699
                        error = 0;
700
                        goto done;
701
                case ATMSIGD_CTRL:
702
                        if (!capable(CAP_NET_ADMIN)) {
703
                                error = -EPERM;
704
                                goto done;
705
                        }
706
                        /*
707
                         * The user/kernel protocol for exchanging signalling
708
                         * info uses kernel pointers as opaque references,
709
                         * so the holder of the file descriptor can scribble
710
                         * on the kernel... so we should make sure that we
711
                         * have the same privledges that /proc/kcore needs
712
                         */
713
                        if (!capable(CAP_SYS_RAWIO)) {
714
                                error = -EPERM;
715
                                goto done;
716
                        }
717
                        error = sigd_attach(vcc);
718
                        if (!error)
719
                                sock->state = SS_CONNECTED;
720
                        goto done;
721
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
722
                case SIOCMKCLIP:
723
                        if (!capable(CAP_NET_ADMIN)) {
724
                                error = -EPERM;
725
                                goto done;
726
                        }
727
                        if (try_atm_clip_ops()) {
728
                                error = atm_clip_ops->clip_create(arg);
729
                                if (atm_clip_ops->owner)
730
                                        __MOD_DEC_USE_COUNT(atm_clip_ops->owner);
731
                        } else
732
                                error = -ENOSYS;
733
                        goto done;
734
                case ATMARPD_CTRL:
735
                        if (!capable(CAP_NET_ADMIN)) {
736
                                error = -EPERM;
737
                                goto done;
738
                        }
739
#if defined(CONFIG_ATM_CLIP_MODULE)
740
                        if (!atm_clip_ops)
741
                                request_module("clip");
742
#endif
743
                        if (try_atm_clip_ops()) {
744
                                error = atm_clip_ops->atm_init_atmarp(vcc);
745
                                if (atm_clip_ops->owner)
746
                                        __MOD_DEC_USE_COUNT(atm_clip_ops->owner);
747
                                if (!error)
748
                                        sock->state = SS_CONNECTED;
749
                        } else
750
                                error = -ENOSYS;
751
                        goto done;
752
                case ATMARP_MKIP:
753
                        if (!capable(CAP_NET_ADMIN)) {
754
                                error = -EPERM;
755
                                goto done;
756
                        }
757
                        if (try_atm_clip_ops()) {
758
                                error = atm_clip_ops->clip_mkip(vcc, arg);
759
                                if (atm_clip_ops->owner)
760
                                        __MOD_DEC_USE_COUNT(atm_clip_ops->owner);
761
                        } else
762
                                error = -ENOSYS;
763
                        goto done;
764
                case ATMARP_SETENTRY:
765
                        if (!capable(CAP_NET_ADMIN)) {
766
                                error = -EPERM;
767
                                goto done;
768
                        }
769
                        if (try_atm_clip_ops()) {
770
                                error = atm_clip_ops->clip_setentry(vcc, arg);
771
                                if (atm_clip_ops->owner)
772
                                        __MOD_DEC_USE_COUNT(atm_clip_ops->owner);
773
                        } else
774
                                error = -ENOSYS;
775
                        goto done;
776
                case ATMARP_ENCAP:
777
                        if (!capable(CAP_NET_ADMIN)) {
778
                                error = -EPERM;
779
                                goto done;
780
                        }
781
                        if (try_atm_clip_ops()) {
782
                                error = atm_clip_ops->clip_encap(vcc, arg);
783
                                if (atm_clip_ops->owner)
784
                                        __MOD_DEC_USE_COUNT(atm_clip_ops->owner);
785
                        } else
786
                                error = -ENOSYS;
787
                        goto done;
788
#endif
789
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
790
                case ATMLEC_CTRL:
791
                        if (!capable(CAP_NET_ADMIN)) {
792
                                error = -EPERM;
793
                                goto done;
794
                        }
795
#if defined(CONFIG_ATM_LANE_MODULE)
796
                        if (!atm_lane_ops)
797
                                request_module("lec");
798
#endif
799
                        if (try_atm_lane_ops()) {
800
                                error = atm_lane_ops->lecd_attach(vcc, (int) arg);
801
                                if (atm_lane_ops->owner)
802
                                        __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
803
                                if (error >= 0)
804
                                        sock->state = SS_CONNECTED;
805
                        } else
806
                                error = -ENOSYS;
807
                        goto done;
808
                case ATMLEC_MCAST:
809
                        if (!capable(CAP_NET_ADMIN)) {
810
                                error = -EPERM;
811
                                goto done;
812
                        }
813
                        if (try_atm_lane_ops()) {
814
                                error = atm_lane_ops->mcast_attach(vcc, (int) arg);
815
                                if (atm_lane_ops->owner)
816
                                        __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
817
                        } else
818
                                error = -ENOSYS;
819
                        goto done;
820
                case ATMLEC_DATA:
821
                        if (!capable(CAP_NET_ADMIN)) {
822
                                error = -EPERM;
823
                                goto done;
824
                        }
825
                        if (try_atm_lane_ops()) {
826
                                error = atm_lane_ops->vcc_attach(vcc, (void *) arg);
827
                                if (atm_lane_ops->owner)
828
                                        __MOD_DEC_USE_COUNT(atm_lane_ops->owner);
829
                        } else
830
                                error = -ENOSYS;
831
                        goto done;
832
#endif
833
#if defined(CONFIG_ATM_MPOA) || defined(CONFIG_ATM_MPOA_MODULE)
834
                case ATMMPC_CTRL:
835
                        if (!capable(CAP_NET_ADMIN)) {
836
                                error = -EPERM;
837
                                goto done;
838
                        }
839
#if defined(CONFIG_ATM_MPOA_MODULE)
840
                        if (!atm_mpoa_ops)
841
                                request_module("mpoa");
842
#endif
843
                        if (try_atm_mpoa_ops()) {
844
                                error = atm_mpoa_ops->mpoad_attach(vcc, (int) arg);
845
                                if (atm_mpoa_ops->owner)
846
                                        __MOD_DEC_USE_COUNT(atm_mpoa_ops->owner);
847
                                if (error >= 0)
848
                                        sock->state = SS_CONNECTED;
849
                        } else
850
                                error = -ENOSYS;
851
                        goto done;
852
                case ATMMPC_DATA:
853
                        if (!capable(CAP_NET_ADMIN)) {
854
                                error = -EPERM;
855
                                goto done;
856
                        }
857
                        if (try_atm_mpoa_ops()) {
858
                                error = atm_mpoa_ops->vcc_attach(vcc, arg);
859
                                if (atm_mpoa_ops->owner)
860
                                        __MOD_DEC_USE_COUNT(atm_mpoa_ops->owner);
861
                        } else
862
                                error = -ENOSYS;
863
                        goto done;
864
#endif
865
#if defined(CONFIG_ATM_TCP) || defined(CONFIG_ATM_TCP_MODULE)
866
                case SIOCSIFATMTCP:
867
                        if (!capable(CAP_NET_ADMIN)) {
868
                                error = -EPERM;
869
                                goto done;
870
                        }
871
                        if (!atm_tcp_ops.attach) {
872
                                error = -ENOPKG;
873
                                goto done;
874
                        }
875
                        fops_get(&atm_tcp_ops);
876
                        error = atm_tcp_ops.attach(vcc, (int) arg);
877
                        if (error >= 0)
878
                                sock->state = SS_CONNECTED;
879
                        else
880
                                fops_put(&atm_tcp_ops);
881
                        goto done;
882
                case ATMTCP_CREATE:
883
                        if (!capable(CAP_NET_ADMIN)) {
884
                                error = -EPERM;
885
                                goto done;
886
                        }
887
                        if (!atm_tcp_ops.create_persistent) {
888
                                error = -ENOPKG;
889
                                goto done;
890
                        }
891
                        error = atm_tcp_ops.create_persistent((int) arg);
892
                        if (error < 0)
893
                                fops_put(&atm_tcp_ops);
894
                        goto done;
895
                case ATMTCP_REMOVE:
896
                        if (!capable(CAP_NET_ADMIN)) {
897
                                error = -EPERM;
898
                                goto done;
899
                        }
900
                        if (!atm_tcp_ops.remove_persistent) {
901
                                error = -ENOPKG;
902
                                goto done;
903
                        }
904
                        error = atm_tcp_ops.remove_persistent((int) arg);
905
                        fops_put(&atm_tcp_ops);
906
                        goto done;
907
#endif
908
                default:
909
                        break;
910
        }
911
        error = -ENOIOCTLCMD;
912
#if defined(CONFIG_PPPOATM) || defined(CONFIG_PPPOATM_MODULE)
913
        down(&pppoatm_ioctl_mutex);
914
        if (pppoatm_ioctl_hook)
915
                error = pppoatm_ioctl_hook(vcc, cmd, arg);
916
        up(&pppoatm_ioctl_mutex);
917
        if (error != -ENOIOCTLCMD)
918
                goto done;
919
#endif
920
#if defined(CONFIG_ATM_BR2684) || defined(CONFIG_ATM_BR2684_MODULE)
921
        down(&br2684_ioctl_mutex);
922
        if (br2684_ioctl_hook)
923
                error = br2684_ioctl_hook(vcc, cmd, arg);
924
        up(&br2684_ioctl_mutex);
925
        if (error != -ENOIOCTLCMD)
926
                goto done;
927
#endif
928
 
929
        error = atm_dev_ioctl(cmd, arg);
930
 
931
done:
932
        return error;
933
}
934
 
935
 
936
static int atm_change_qos(struct atm_vcc *vcc,struct atm_qos *qos)
937
{
938
        int error;
939
 
940
        /*
941
         * Don't let the QoS change the already connected AAL type nor the
942
         * traffic class.
943
         */
944
        if (qos->aal != vcc->qos.aal ||
945
            qos->rxtp.traffic_class != vcc->qos.rxtp.traffic_class ||
946
            qos->txtp.traffic_class != vcc->qos.txtp.traffic_class)
947
                return -EINVAL;
948
        error = adjust_tp(&qos->txtp,qos->aal);
949
        if (!error) error = adjust_tp(&qos->rxtp,qos->aal);
950
        if (error) return error;
951
        if (!vcc->dev->ops->change_qos) return -EOPNOTSUPP;
952
        if (vcc->sk->family == AF_ATMPVC)
953
                return vcc->dev->ops->change_qos(vcc,qos,ATM_MF_SET);
954
        return svc_change_qos(vcc,qos);
955
}
956
 
957
 
958
static int check_tp(struct atm_trafprm *tp)
959
{
960
        /* @@@ Should be merged with adjust_tp */
961
        if (!tp->traffic_class || tp->traffic_class == ATM_ANYCLASS) return 0;
962
        if (tp->traffic_class != ATM_UBR && !tp->min_pcr && !tp->pcr &&
963
            !tp->max_pcr) return -EINVAL;
964
        if (tp->min_pcr == ATM_MAX_PCR) return -EINVAL;
965
        if (tp->min_pcr && tp->max_pcr && tp->max_pcr != ATM_MAX_PCR &&
966
            tp->min_pcr > tp->max_pcr) return -EINVAL;
967
        /*
968
         * We allow pcr to be outside [min_pcr,max_pcr], because later
969
         * adjustment may still push it in the valid range.
970
         */
971
        return 0;
972
}
973
 
974
 
975
static int check_qos(struct atm_qos *qos)
976
{
977
        int error;
978
 
979
        if (!qos->txtp.traffic_class && !qos->rxtp.traffic_class)
980
                return -EINVAL;
981
        if (qos->txtp.traffic_class != qos->rxtp.traffic_class &&
982
            qos->txtp.traffic_class && qos->rxtp.traffic_class &&
983
            qos->txtp.traffic_class != ATM_ANYCLASS &&
984
            qos->rxtp.traffic_class != ATM_ANYCLASS) return -EINVAL;
985
        error = check_tp(&qos->txtp);
986
        if (error) return error;
987
        return check_tp(&qos->rxtp);
988
}
989
 
990
int vcc_setsockopt(struct socket *sock, int level, int optname,
991
                   char *optval, int optlen)
992
{
993
        struct atm_vcc *vcc;
994
        unsigned long value;
995
        int error;
996
 
997
        if (__SO_LEVEL_MATCH(optname, level) && optlen != __SO_SIZE(optname))
998
                return -EINVAL;
999
 
1000
        vcc = ATM_SD(sock);
1001
        switch (optname) {
1002
                case SO_ATMQOS:
1003
                        {
1004
                                struct atm_qos qos;
1005
 
1006
                                if (copy_from_user(&qos,optval,sizeof(qos)))
1007
                                        return -EFAULT;
1008
                                error = check_qos(&qos);
1009
                                if (error) return error;
1010
                                if (sock->state == SS_CONNECTED)
1011
                                        return atm_change_qos(vcc,&qos);
1012
                                if (sock->state != SS_UNCONNECTED)
1013
                                        return -EBADFD;
1014
                                vcc->qos = qos;
1015
                                set_bit(ATM_VF_HASQOS,&vcc->flags);
1016
                                return 0;
1017
                        }
1018
                case SO_SETCLP:
1019
                        if (get_user(value,(unsigned long *) optval))
1020
                                return -EFAULT;
1021
                        if (value) vcc->atm_options |= ATM_ATMOPT_CLP;
1022
                        else vcc->atm_options &= ~ATM_ATMOPT_CLP;
1023
                        return 0;
1024
                default:
1025
                        if (level == SOL_SOCKET) return -EINVAL;
1026
                        break;
1027
        }
1028
        if (!vcc->dev || !vcc->dev->ops->setsockopt) return -EINVAL;
1029
        return vcc->dev->ops->setsockopt(vcc,level,optname,optval,optlen);
1030
}
1031
 
1032
 
1033
int vcc_getsockopt(struct socket *sock, int level, int optname,
1034
                   char *optval, int *optlen)
1035
{
1036
        struct atm_vcc *vcc;
1037
        int len;
1038
 
1039
        if (get_user(len, optlen))
1040
                return -EFAULT;
1041
        if (__SO_LEVEL_MATCH(optname, level) && len != __SO_SIZE(optname))
1042
                return -EINVAL;
1043
 
1044
        vcc = ATM_SD(sock);
1045
        switch (optname) {
1046
                case SO_ATMQOS:
1047
                        if (!test_bit(ATM_VF_HASQOS,&vcc->flags))
1048
                                return -EINVAL;
1049
                        return copy_to_user(optval,&vcc->qos,sizeof(vcc->qos)) ?
1050
                            -EFAULT : 0;
1051
                case SO_SETCLP:
1052
                        return put_user(vcc->atm_options & ATM_ATMOPT_CLP ? 1 :
1053
                          0,(unsigned long *) optval) ? -EFAULT : 0;
1054
                case SO_ATMPVC:
1055
                        {
1056
                                struct sockaddr_atmpvc pvc;
1057
 
1058
                                if (!vcc->dev ||
1059
                                    !test_bit(ATM_VF_ADDR,&vcc->flags))
1060
                                        return -ENOTCONN;
1061
                                pvc.sap_family = AF_ATMPVC;
1062
                                pvc.sap_addr.itf = vcc->dev->number;
1063
                                pvc.sap_addr.vpi = vcc->vpi;
1064
                                pvc.sap_addr.vci = vcc->vci;
1065
                                return copy_to_user(optval,&pvc,sizeof(pvc)) ?
1066
                                    -EFAULT : 0;
1067
                        }
1068
                default:
1069
                        if (level == SOL_SOCKET) return -EINVAL;
1070
                        break;
1071
        }
1072
        if (!vcc->dev || !vcc->dev->ops->getsockopt) return -EINVAL;
1073
        return vcc->dev->ops->getsockopt(vcc, level, optname, optval, len);
1074
}
1075
 
1076
 
1077
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
1078
#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
1079
struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
1080
                                                unsigned char *addr) = NULL;
1081
void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent) = NULL;
1082
#if defined(CONFIG_ATM_LANE_MODULE) || defined(CONFIG_BRIDGE_MODULE)
1083
EXPORT_SYMBOL(br_fdb_get_hook);
1084
EXPORT_SYMBOL(br_fdb_put_hook);
1085
#endif /* defined(CONFIG_ATM_LANE_MODULE) || defined(CONFIG_BRIDGE_MODULE) */
1086
#endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */
1087
#endif /* defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) */
1088
 
1089
 
1090
static int __init atm_init(void)
1091
{
1092
        int error;
1093
 
1094
        if ((error = atmpvc_init()) < 0) {
1095
                printk(KERN_ERR "atmpvc_init() failed with %d\n", error);
1096
                goto failure;
1097
        }
1098
        if ((error = atmsvc_init()) < 0) {
1099
                printk(KERN_ERR "atmsvc_init() failed with %d\n", error);
1100
                goto failure;
1101
        }
1102
#ifdef CONFIG_PROC_FS
1103
        if ((error = atm_proc_init()) < 0) {
1104
                printk(KERN_ERR "atm_proc_init() failed with %d\n",error);
1105
                goto failure;
1106
        }
1107
#endif
1108
        return 0;
1109
 
1110
failure:
1111
        atmsvc_exit();
1112
        atmpvc_exit();
1113
        return error;
1114
}
1115
 
1116
static void __exit atm_exit(void)
1117
{
1118
#ifdef CONFIG_PROC_FS
1119
        atm_proc_exit();
1120
#endif
1121
        atmsvc_exit();
1122
        atmpvc_exit();
1123
}
1124
 
1125
module_init(atm_init);
1126
module_exit(atm_exit);
1127
 
1128
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

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