xref: /openbmc/linux/net/atm/raw.c (revision cdd38c5f1ce4398ec58fec95904b75824daab7b5)
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