1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /* net/atm/raw.c - Raw AAL0 and AAL5 transports */
31da177e4SLinus Torvalds
41da177e4SLinus Torvalds /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
51da177e4SLinus Torvalds
699824461SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
71da177e4SLinus Torvalds
81da177e4SLinus Torvalds #include <linux/module.h>
91da177e4SLinus Torvalds #include <linux/atmdev.h>
104fc268d2SRandy Dunlap #include <linux/capability.h>
111da177e4SLinus Torvalds #include <linux/kernel.h>
121da177e4SLinus Torvalds #include <linux/skbuff.h>
131da177e4SLinus Torvalds #include <linux/mm.h>
145a0e3ad6STejun Heo #include <linux/slab.h>
151da177e4SLinus Torvalds
161da177e4SLinus Torvalds #include "common.h"
171da177e4SLinus Torvalds #include "protocols.h"
181da177e4SLinus Torvalds
191da177e4SLinus Torvalds /*
201da177e4SLinus Torvalds * SKB == NULL indicates that the link is being closed
211da177e4SLinus Torvalds */
221da177e4SLinus Torvalds
atm_push_raw(struct atm_vcc * vcc,struct sk_buff * skb)231da177e4SLinus Torvalds static void atm_push_raw(struct atm_vcc *vcc, struct sk_buff *skb)
241da177e4SLinus Torvalds {
251da177e4SLinus Torvalds if (skb) {
261da177e4SLinus Torvalds struct sock *sk = sk_atm(vcc);
271da177e4SLinus Torvalds
281da177e4SLinus Torvalds skb_queue_tail(&sk->sk_receive_queue, skb);
29676d2369SDavid S. Miller sk->sk_data_ready(sk);
301da177e4SLinus Torvalds }
311da177e4SLinus Torvalds }
321da177e4SLinus Torvalds
atm_pop_raw(struct atm_vcc * vcc,struct sk_buff * skb)331da177e4SLinus Torvalds static void atm_pop_raw(struct atm_vcc *vcc, struct sk_buff *skb)
341da177e4SLinus Torvalds {
351da177e4SLinus Torvalds struct sock *sk = sk_atm(vcc);
361da177e4SLinus Torvalds
3799824461SJoe Perches pr_debug("(%d) %d -= %d\n",
389bbe60a6SDavid Woodhouse vcc->vci, sk_wmem_alloc_get(sk), ATM_SKB(skb)->acct_truesize);
399bbe60a6SDavid Woodhouse WARN_ON(refcount_sub_and_test(ATM_SKB(skb)->acct_truesize, &sk->sk_wmem_alloc));
401da177e4SLinus Torvalds dev_kfree_skb_any(skb);
411da177e4SLinus Torvalds sk->sk_write_space(sk);
421da177e4SLinus Torvalds }
431da177e4SLinus Torvalds
atm_send_aal0(struct atm_vcc * vcc,struct sk_buff * skb)441da177e4SLinus Torvalds static int atm_send_aal0(struct atm_vcc *vcc, struct sk_buff *skb)
451da177e4SLinus Torvalds {
461da177e4SLinus Torvalds /*
471da177e4SLinus Torvalds * Note that if vpi/vci are _ANY or _UNSPEC the below will
481da177e4SLinus Torvalds * still work
491da177e4SLinus Torvalds */
501da177e4SLinus Torvalds if (!capable(CAP_NET_ADMIN) &&
511da177e4SLinus Torvalds (((u32 *)skb->data)[0] & (ATM_HDR_VPI_MASK | ATM_HDR_VCI_MASK)) !=
52fa61f0caSJoe Perches ((vcc->vpi << ATM_HDR_VPI_SHIFT) |
53fa61f0caSJoe Perches (vcc->vci << ATM_HDR_VCI_SHIFT))) {
541da177e4SLinus Torvalds kfree_skb(skb);
551da177e4SLinus Torvalds return -EADDRNOTAVAIL;
561da177e4SLinus Torvalds }
57*f2bcc2faSSebastian Andrzej Siewior if (vcc->dev->ops->send_bh)
58*f2bcc2faSSebastian Andrzej Siewior return vcc->dev->ops->send_bh(vcc, skb);
591da177e4SLinus Torvalds return vcc->dev->ops->send(vcc, skb);
601da177e4SLinus Torvalds }
611da177e4SLinus Torvalds
atm_init_aal0(struct atm_vcc * vcc)621da177e4SLinus Torvalds int atm_init_aal0(struct atm_vcc *vcc)
631da177e4SLinus Torvalds {
641da177e4SLinus Torvalds vcc->push = atm_push_raw;
651da177e4SLinus Torvalds vcc->pop = atm_pop_raw;
661da177e4SLinus Torvalds vcc->push_oam = NULL;
671da177e4SLinus Torvalds vcc->send = atm_send_aal0;
681da177e4SLinus Torvalds return 0;
691da177e4SLinus Torvalds }
701da177e4SLinus Torvalds
atm_init_aal34(struct atm_vcc * vcc)711da177e4SLinus Torvalds int atm_init_aal34(struct atm_vcc *vcc)
721da177e4SLinus Torvalds {
731da177e4SLinus Torvalds vcc->push = atm_push_raw;
741da177e4SLinus Torvalds vcc->pop = atm_pop_raw;
751da177e4SLinus Torvalds vcc->push_oam = NULL;
76*f2bcc2faSSebastian Andrzej Siewior if (vcc->dev->ops->send_bh)
77*f2bcc2faSSebastian Andrzej Siewior vcc->send = vcc->dev->ops->send_bh;
78*f2bcc2faSSebastian Andrzej Siewior else
791da177e4SLinus Torvalds vcc->send = vcc->dev->ops->send;
801da177e4SLinus Torvalds return 0;
811da177e4SLinus Torvalds }
821da177e4SLinus Torvalds
atm_init_aal5(struct atm_vcc * vcc)831da177e4SLinus Torvalds int atm_init_aal5(struct atm_vcc *vcc)
841da177e4SLinus Torvalds {
851da177e4SLinus Torvalds vcc->push = atm_push_raw;
861da177e4SLinus Torvalds vcc->pop = atm_pop_raw;
871da177e4SLinus Torvalds vcc->push_oam = NULL;
88*f2bcc2faSSebastian Andrzej Siewior if (vcc->dev->ops->send_bh)
89*f2bcc2faSSebastian Andrzej Siewior vcc->send = vcc->dev->ops->send_bh;
90*f2bcc2faSSebastian Andrzej Siewior else
911da177e4SLinus Torvalds vcc->send = vcc->dev->ops->send;
921da177e4SLinus Torvalds return 0;
931da177e4SLinus Torvalds }
941da177e4SLinus Torvalds EXPORT_SYMBOL(atm_init_aal5);
95