^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* net/atm/pppoatm.c - RFC2364 PPP over ATM/AAL5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) /* Copyright 1999-2000 by Mitchell Blank Jr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) /* Based on clip.c; 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) /* And on ppp_async.c; Copyright 1999 Paul Mackerras */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) /* And help from Jens Axboe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * This driver provides the encapsulation and framing for sending
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * and receiving PPP frames in ATM AAL5 PDUs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * One shortcoming of this driver is that it does not comply with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * section 8 of RFC2364 - we are supposed to detect a change
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * in encapsulation and immediately abort the connection (in order
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * to avoid a black-hole being created if our peer loses state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * and changes encapsulation unilaterally. However, since the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * ppp_generic layer actually does the decapsulation, we need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * a way of notifying it when we _think_ there might be a problem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * There's two cases:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * 1. LLC-encapsulation was missing when it was enabled. In
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * this case, we should tell the upper layer "tear down
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * this session if this skb looks ok to you"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * 2. LLC-encapsulation was present when it was disabled. Then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * we need to tell the upper layer "this packet may be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * ok, but if its in error tear down the session"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * These hooks are not yet available in ppp_generic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/atm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/atmdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <linux/capability.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <linux/ppp_defs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <linux/ppp-ioctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <linux/ppp_channel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include <linux/atmppp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include "common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) enum pppoatm_encaps {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) e_autodetect = PPPOATM_ENCAPS_AUTODETECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) e_vc = PPPOATM_ENCAPS_VC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) e_llc = PPPOATM_ENCAPS_LLC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct pppoatm_vcc {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct atm_vcc *atmvcc; /* VCC descriptor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) void (*old_push)(struct atm_vcc *, struct sk_buff *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) void (*old_pop)(struct atm_vcc *, struct sk_buff *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) void (*old_release_cb)(struct atm_vcc *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct module *old_owner;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /* keep old push/pop for detaching */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) enum pppoatm_encaps encaps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) atomic_t inflight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) unsigned long blocked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) int flags; /* SC_COMP_PROT - compress protocol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct ppp_channel chan; /* interface to generic ppp layer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct tasklet_struct wakeup_tasklet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * We want to allow two packets in the queue. The one that's currently in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * flight, and *one* queued up ready for the ATM device to send immediately
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * from its TX done IRQ. We want to be able to use atomic_inc_not_zero(), so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * inflight == -2 represents an empty queue, -1 one packet, and zero means
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * there are two packets in the queue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define NONE_INFLIGHT -2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define BLOCKED 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * Header used for LLC Encapsulated PPP (4 bytes) followed by the LCP protocol
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * ID (0xC021) used in autodetection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static const unsigned char pppllc[6] = { 0xFE, 0xFE, 0x03, 0xCF, 0xC0, 0x21 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define LLC_LEN (4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static inline struct pppoatm_vcc *atmvcc_to_pvcc(const struct atm_vcc *atmvcc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return (struct pppoatm_vcc *) (atmvcc->user_back);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static inline struct pppoatm_vcc *chan_to_pvcc(const struct ppp_channel *chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return (struct pppoatm_vcc *) (chan->private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * We can't do this directly from our _pop handler, since the ppp code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * doesn't want to be called in interrupt context, so we do it from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * a tasklet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static void pppoatm_wakeup_sender(unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) ppp_output_wakeup((struct ppp_channel *) arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static void pppoatm_release_cb(struct atm_vcc *atmvcc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) struct pppoatm_vcc *pvcc = atmvcc_to_pvcc(atmvcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * As in pppoatm_pop(), it's safe to clear the BLOCKED bit here because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * the wakeup *can't* race with pppoatm_send(). They both hold the PPP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * channel's ->downl lock. And the potential race with *setting* it,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * which leads to the double-check dance in pppoatm_may_send(), doesn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * exist here. In the sock_owned_by_user() case in pppoatm_send(), we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * set the BLOCKED bit while the socket is still locked. We know that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * ->release_cb() can't be called until that's done.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (test_and_clear_bit(BLOCKED, &pvcc->blocked))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) tasklet_schedule(&pvcc->wakeup_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (pvcc->old_release_cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) pvcc->old_release_cb(atmvcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * This gets called every time the ATM card has finished sending our
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * skb. The ->old_pop will take care up normal atm flow control,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * but we also need to wake up the device if we blocked it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static void pppoatm_pop(struct atm_vcc *atmvcc, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct pppoatm_vcc *pvcc = atmvcc_to_pvcc(atmvcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) pvcc->old_pop(atmvcc, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) atomic_dec(&pvcc->inflight);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * We always used to run the wakeup tasklet unconditionally here, for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * fear of race conditions where we clear the BLOCKED flag just as we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * refuse another packet in pppoatm_send(). This was quite inefficient.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * In fact it's OK. The PPP core will only ever call pppoatm_send()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * while holding the channel->downl lock. And ppp_output_wakeup() as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * called by the tasklet will *also* grab that lock. So even if another
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * CPU is in pppoatm_send() right now, the tasklet isn't going to race
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * with it. The wakeup *will* happen after the other CPU is safely out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * of pppoatm_send() again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * So if the CPU in pppoatm_send() has already set the BLOCKED bit and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * it about to return, that's fine. We trigger a wakeup which will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * happen later. And if the CPU in pppoatm_send() *hasn't* set the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * BLOCKED bit yet, that's fine too because of the double check in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * pppoatm_may_send() which is commented there.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (test_and_clear_bit(BLOCKED, &pvcc->blocked))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) tasklet_schedule(&pvcc->wakeup_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * Unbind from PPP - currently we only do this when closing the socket,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * but we could put this into an ioctl if need be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) static void pppoatm_unassign_vcc(struct atm_vcc *atmvcc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct pppoatm_vcc *pvcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) pvcc = atmvcc_to_pvcc(atmvcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) atmvcc->push = pvcc->old_push;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) atmvcc->pop = pvcc->old_pop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) atmvcc->release_cb = pvcc->old_release_cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) tasklet_kill(&pvcc->wakeup_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) ppp_unregister_channel(&pvcc->chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) atmvcc->user_back = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) kfree(pvcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) /* Called when an AAL5 PDU comes in */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static void pppoatm_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) struct pppoatm_vcc *pvcc = atmvcc_to_pvcc(atmvcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) pr_debug("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (skb == NULL) { /* VCC was closed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) struct module *module;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) pr_debug("removing ATMPPP VCC %p\n", pvcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) module = pvcc->old_owner;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) pppoatm_unassign_vcc(atmvcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) atmvcc->push(atmvcc, NULL); /* Pass along bad news */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) module_put(module);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) atm_return(atmvcc, skb->truesize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) switch (pvcc->encaps) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) case e_llc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (skb->len < LLC_LEN ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) memcmp(skb->data, pppllc, LLC_LEN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) skb_pull(skb, LLC_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) case e_autodetect:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (pvcc->chan.ppp == NULL) { /* Not bound yet! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (skb->len >= sizeof(pppllc) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) !memcmp(skb->data, pppllc, sizeof(pppllc))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) pvcc->encaps = e_llc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) skb_pull(skb, LLC_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (skb->len >= (sizeof(pppllc) - LLC_LEN) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) !memcmp(skb->data, &pppllc[LLC_LEN],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) sizeof(pppllc) - LLC_LEN)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) pvcc->encaps = e_vc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) pvcc->chan.mtu += LLC_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) pr_debug("Couldn't autodetect yet (skb: %6ph)\n", skb->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) case e_vc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) ppp_input(&pvcc->chan, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) ppp_input_error(&pvcc->chan, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) static int pppoatm_may_send(struct pppoatm_vcc *pvcc, int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * It's not clear that we need to bother with using atm_may_send()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * to check we don't exceed sk->sk_sndbuf. If userspace sets a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * value of sk_sndbuf which is lower than the MTU, we're going to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * block for ever. But the code always did that before we introduced
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * the packet count limit, so...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (atm_may_send(pvcc->atmvcc, size) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) atomic_inc_not_zero(&pvcc->inflight))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) * We use test_and_set_bit() rather than set_bit() here because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * we need to ensure there's a memory barrier after it. The bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * *must* be set before we do the atomic_inc() on pvcc->inflight.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) * There's no smp_mb__after_set_bit(), so it's this or abuse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * smp_mb__after_atomic().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) test_and_set_bit(BLOCKED, &pvcc->blocked);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * We may have raced with pppoatm_pop(). If it ran for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * last packet in the queue, *just* before we set the BLOCKED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * bit, then it might never run again and the channel could
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * remain permanently blocked. Cope with that race by checking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) * *again*. If it did run in that window, we'll have space on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) * the queue now and can return success. It's harmless to leave
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) * the BLOCKED flag set, since it's only used as a trigger to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) * run the wakeup tasklet. Another wakeup will never hurt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) * If pppoatm_pop() is running but hasn't got as far as making
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * space on the queue yet, then it hasn't checked the BLOCKED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) * flag yet either, so we're safe in that case too. It'll issue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) * an "immediate" wakeup... where "immediate" actually involves
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) * taking the PPP channel's ->downl lock, which is held by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * code path that calls pppoatm_send(), and is thus going to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) * wait for us to finish.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (atm_may_send(pvcc->atmvcc, size) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) atomic_inc_not_zero(&pvcc->inflight))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) * Called by the ppp_generic.c to send a packet - returns true if packet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) * was accepted. If we return false, then it's our job to call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) * ppp_output_wakeup(chan) when we're feeling more up to it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) * Note that in the ENOMEM case (as opposed to the !atm_may_send case)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) * we should really drop the packet, but the generic layer doesn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) * support this yet. We just return 'DROP_PACKET' which we actually define
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) * as success, just to be clear what we're really doing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) #define DROP_PACKET 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) struct pppoatm_vcc *pvcc = chan_to_pvcc(chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) struct atm_vcc *vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) ATM_SKB(skb)->vcc = pvcc->atmvcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) pr_debug("(skb=0x%p, vcc=0x%p)\n", skb, pvcc->atmvcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) if (skb->data[0] == '\0' && (pvcc->flags & SC_COMP_PROT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) (void) skb_pull(skb, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) vcc = ATM_SKB(skb)->vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) bh_lock_sock(sk_atm(vcc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (sock_owned_by_user(sk_atm(vcc))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * Needs to happen (and be flushed, hence test_and_) before we unlock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * the socket. It needs to be seen by the time our ->release_cb gets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) * called.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) test_and_set_bit(BLOCKED, &pvcc->blocked);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) goto nospace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (test_bit(ATM_VF_RELEASED, &vcc->flags) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) test_bit(ATM_VF_CLOSE, &vcc->flags) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) !test_bit(ATM_VF_READY, &vcc->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) bh_unlock_sock(sk_atm(vcc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return DROP_PACKET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) switch (pvcc->encaps) { /* LLC encapsulation needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) case e_llc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (skb_headroom(skb) < LLC_LEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) struct sk_buff *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) n = skb_realloc_headroom(skb, LLC_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) if (n != NULL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) !pppoatm_may_send(pvcc, n->truesize)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) kfree_skb(n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) goto nospace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) consume_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) skb = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (skb == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) bh_unlock_sock(sk_atm(vcc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return DROP_PACKET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) } else if (!pppoatm_may_send(pvcc, skb->truesize))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) goto nospace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) memcpy(skb_push(skb, LLC_LEN), pppllc, LLC_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) case e_vc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (!pppoatm_may_send(pvcc, skb->truesize))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) goto nospace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) case e_autodetect:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) bh_unlock_sock(sk_atm(vcc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) pr_debug("Trying to send without setting encaps!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) atm_account_tx(vcc, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) skb, ATM_SKB(skb)->vcc, ATM_SKB(skb)->vcc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) ret = ATM_SKB(skb)->vcc->send(ATM_SKB(skb)->vcc, skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) ? DROP_PACKET : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) bh_unlock_sock(sk_atm(vcc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) nospace:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) bh_unlock_sock(sk_atm(vcc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * We don't have space to send this SKB now, but we might have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) * already applied SC_COMP_PROT compression, so may need to undo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if ((pvcc->flags & SC_COMP_PROT) && skb_headroom(skb) > 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) skb->data[-1] == '\0')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) (void) skb_push(skb, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) /* This handles ioctls sent to the /dev/ppp interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) static int pppoatm_devppp_ioctl(struct ppp_channel *chan, unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) case PPPIOCGFLAGS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return put_user(chan_to_pvcc(chan)->flags, (int __user *) arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) ? -EFAULT : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) case PPPIOCSFLAGS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return get_user(chan_to_pvcc(chan)->flags, (int __user *) arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) ? -EFAULT : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) return -ENOTTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) static const struct ppp_channel_ops pppoatm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) .start_xmit = pppoatm_send,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) .ioctl = pppoatm_devppp_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) static int pppoatm_assign_vcc(struct atm_vcc *atmvcc, void __user *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) struct atm_backend_ppp be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) struct pppoatm_vcc *pvcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) * Each PPPoATM instance has its own tasklet - this is just a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) * prototypical one used to initialize them
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) static const DECLARE_TASKLET_OLD(tasklet_proto, pppoatm_wakeup_sender);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) if (copy_from_user(&be, arg, sizeof be))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if (be.encaps != PPPOATM_ENCAPS_AUTODETECT &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) be.encaps != PPPOATM_ENCAPS_VC && be.encaps != PPPOATM_ENCAPS_LLC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) pvcc = kzalloc(sizeof(*pvcc), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) if (pvcc == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) pvcc->atmvcc = atmvcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) /* Maximum is zero, so that we can use atomic_inc_not_zero() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) atomic_set(&pvcc->inflight, NONE_INFLIGHT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) pvcc->old_push = atmvcc->push;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) pvcc->old_pop = atmvcc->pop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) pvcc->old_owner = atmvcc->owner;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) pvcc->old_release_cb = atmvcc->release_cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) pvcc->encaps = (enum pppoatm_encaps) be.encaps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) pvcc->chan.private = pvcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) pvcc->chan.ops = &pppoatm_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) pvcc->chan.mtu = atmvcc->qos.txtp.max_sdu - PPP_HDRLEN -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) (be.encaps == e_vc ? 0 : LLC_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) pvcc->wakeup_tasklet = tasklet_proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) pvcc->wakeup_tasklet.data = (unsigned long) &pvcc->chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) err = ppp_register_channel(&pvcc->chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) if (err != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) kfree(pvcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) atmvcc->user_back = pvcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) atmvcc->push = pppoatm_push;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) atmvcc->pop = pppoatm_pop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) atmvcc->release_cb = pppoatm_release_cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) __module_get(THIS_MODULE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) atmvcc->owner = THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) /* re-process everything received between connection setup and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) backend setup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) vcc_process_recv_queue(atmvcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) * This handles ioctls actually performed on our vcc - we must return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) * -ENOIOCTLCMD for any unrecognized ioctl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) static int pppoatm_ioctl(struct socket *sock, unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) struct atm_vcc *atmvcc = ATM_SD(sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) void __user *argp = (void __user *)arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (cmd != ATM_SETBACKEND && atmvcc->push != pppoatm_push)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return -ENOIOCTLCMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) case ATM_SETBACKEND: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) atm_backend_t b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if (get_user(b, (atm_backend_t __user *) argp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) if (b != ATM_BACKEND_PPP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) return -ENOIOCTLCMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (!capable(CAP_NET_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (sock->state != SS_CONNECTED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) return pppoatm_assign_vcc(atmvcc, argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) case PPPIOCGCHAN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) return put_user(ppp_channel_index(&atmvcc_to_pvcc(atmvcc)->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) chan), (int __user *) argp) ? -EFAULT : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) case PPPIOCGUNIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) return put_user(ppp_unit_number(&atmvcc_to_pvcc(atmvcc)->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) chan), (int __user *) argp) ? -EFAULT : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) return -ENOIOCTLCMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) static struct atm_ioctl pppoatm_ioctl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) .ioctl = pppoatm_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) static int __init pppoatm_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) register_atm_ioctl(&pppoatm_ioctl_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) static void __exit pppoatm_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) deregister_atm_ioctl(&pppoatm_ioctl_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) module_init(pppoatm_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) module_exit(pppoatm_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) MODULE_AUTHOR("Mitchell Blank Jr <mitch@sfgoth.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) MODULE_DESCRIPTION("RFC2364 PPP over ATM/AAL5");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) MODULE_LICENSE("GPL");