0001
0002
0003
0004
0005
0006 #define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
0007
0008 #include <linux/module.h>
0009 #include <linux/atmdev.h>
0010 #include <linux/capability.h>
0011 #include <linux/kernel.h>
0012 #include <linux/skbuff.h>
0013 #include <linux/mm.h>
0014 #include <linux/slab.h>
0015
0016 #include "common.h"
0017 #include "protocols.h"
0018
0019
0020
0021
0022
0023 static void atm_push_raw(struct atm_vcc *vcc, struct sk_buff *skb)
0024 {
0025 if (skb) {
0026 struct sock *sk = sk_atm(vcc);
0027
0028 skb_queue_tail(&sk->sk_receive_queue, skb);
0029 sk->sk_data_ready(sk);
0030 }
0031 }
0032
0033 static void atm_pop_raw(struct atm_vcc *vcc, struct sk_buff *skb)
0034 {
0035 struct sock *sk = sk_atm(vcc);
0036
0037 pr_debug("(%d) %d -= %d\n",
0038 vcc->vci, sk_wmem_alloc_get(sk), ATM_SKB(skb)->acct_truesize);
0039 WARN_ON(refcount_sub_and_test(ATM_SKB(skb)->acct_truesize, &sk->sk_wmem_alloc));
0040 dev_kfree_skb_any(skb);
0041 sk->sk_write_space(sk);
0042 }
0043
0044 static int atm_send_aal0(struct atm_vcc *vcc, struct sk_buff *skb)
0045 {
0046
0047
0048
0049
0050 if (!capable(CAP_NET_ADMIN) &&
0051 (((u32 *)skb->data)[0] & (ATM_HDR_VPI_MASK | ATM_HDR_VCI_MASK)) !=
0052 ((vcc->vpi << ATM_HDR_VPI_SHIFT) |
0053 (vcc->vci << ATM_HDR_VCI_SHIFT))) {
0054 kfree_skb(skb);
0055 return -EADDRNOTAVAIL;
0056 }
0057 if (vcc->dev->ops->send_bh)
0058 return vcc->dev->ops->send_bh(vcc, skb);
0059 return vcc->dev->ops->send(vcc, skb);
0060 }
0061
0062 int atm_init_aal0(struct atm_vcc *vcc)
0063 {
0064 vcc->push = atm_push_raw;
0065 vcc->pop = atm_pop_raw;
0066 vcc->push_oam = NULL;
0067 vcc->send = atm_send_aal0;
0068 return 0;
0069 }
0070
0071 int atm_init_aal34(struct atm_vcc *vcc)
0072 {
0073 vcc->push = atm_push_raw;
0074 vcc->pop = atm_pop_raw;
0075 vcc->push_oam = NULL;
0076 if (vcc->dev->ops->send_bh)
0077 vcc->send = vcc->dev->ops->send_bh;
0078 else
0079 vcc->send = vcc->dev->ops->send;
0080 return 0;
0081 }
0082
0083 int atm_init_aal5(struct atm_vcc *vcc)
0084 {
0085 vcc->push = atm_push_raw;
0086 vcc->pop = atm_pop_raw;
0087 vcc->push_oam = NULL;
0088 if (vcc->dev->ops->send_bh)
0089 vcc->send = vcc->dev->ops->send_bh;
0090 else
0091 vcc->send = vcc->dev->ops->send;
0092 return 0;
0093 }
0094 EXPORT_SYMBOL(atm_init_aal5);