^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* net/atm/svc.c - ATM SVC sockets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/net.h> /* struct socket, struct proto_ops */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/errno.h> /* error codes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/kernel.h> /* printk */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/wait.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/sched/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/fcntl.h> /* O_NONBLOCK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/atm.h> /* ATM stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/atmsap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/atmsvc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/atmdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <net/sock.h> /* for sock_no_* */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "resources.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include "common.h" /* common for PVCs and SVCs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include "signaling.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include "addr.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static int svc_create(struct net *net, struct socket *sock, int protocol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) int kern);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * Note: since all this is still nicely synchronized with the signaling demon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * there's no need to protect sleep loops with clis. If signaling is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * moved into the kernel, that would change.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static int svc_shutdown(struct socket *sock, int how)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static void svc_disconnect(struct atm_vcc *vcc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) DEFINE_WAIT(wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct sock *sk = sk_atm(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) pr_debug("%p\n", vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (test_bit(ATM_VF_REGIS, &vcc->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) sigd_enq(vcc, as_close, NULL, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (test_bit(ATM_VF_RELEASED, &vcc->flags) || !sigd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) finish_wait(sk_sleep(sk), &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /* beware - socket is still in use by atmsigd until the last
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) as_indicate has been answered */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) atm_return(vcc, skb->truesize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) pr_debug("LISTEN REL\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) sigd_enq2(NULL, as_reject, vcc, NULL, NULL, &vcc->qos, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) clear_bit(ATM_VF_REGIS, &vcc->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /* ... may retry later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static int svc_release(struct socket *sock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct atm_vcc *vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (sk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) vcc = ATM_SD(sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) pr_debug("%p\n", vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) clear_bit(ATM_VF_READY, &vcc->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * VCC pointer is used as a reference,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * so we must not free it (thereby subjecting it to re-use)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * before all pending connections are closed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) svc_disconnect(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) vcc_release(sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static int svc_bind(struct socket *sock, struct sockaddr *sockaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) int sockaddr_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) DEFINE_WAIT(wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct sockaddr_atmsvc *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct atm_vcc *vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (sockaddr_len != sizeof(struct sockaddr_atmsvc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (sock->state == SS_CONNECTED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) error = -EISCONN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (sock->state != SS_UNCONNECTED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) vcc = ATM_SD(sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) addr = (struct sockaddr_atmsvc *) sockaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (addr->sas_family != AF_ATMSVC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) error = -EAFNOSUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) clear_bit(ATM_VF_BOUND, &vcc->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /* failing rebind will kill old binding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /* @@@ check memory (de)allocation on rebind */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (!test_bit(ATM_VF_HASQOS, &vcc->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) error = -EBADFD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) vcc->local = *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) set_bit(ATM_VF_WAITING, &vcc->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) sigd_enq(vcc, as_bind, NULL, NULL, &vcc->local);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (!test_bit(ATM_VF_WAITING, &vcc->flags) || !sigd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) finish_wait(sk_sleep(sk), &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) clear_bit(ATM_VF_REGIS, &vcc->flags); /* doesn't count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (!sigd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) error = -EUNATCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (!sk->sk_err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) set_bit(ATM_VF_BOUND, &vcc->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) error = -sk->sk_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static int svc_connect(struct socket *sock, struct sockaddr *sockaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) int sockaddr_len, int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) DEFINE_WAIT(wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct sockaddr_atmsvc *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) struct atm_vcc *vcc = ATM_SD(sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) pr_debug("%p\n", vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (sockaddr_len != sizeof(struct sockaddr_atmsvc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) switch (sock->state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) case SS_CONNECTED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) error = -EISCONN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) case SS_CONNECTING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (test_bit(ATM_VF_WAITING, &vcc->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) error = -EALREADY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) sock->state = SS_UNCONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (sk->sk_err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) error = -sk->sk_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) case SS_UNCONNECTED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) addr = (struct sockaddr_atmsvc *) sockaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (addr->sas_family != AF_ATMSVC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) error = -EAFNOSUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (!test_bit(ATM_VF_HASQOS, &vcc->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) error = -EBADFD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (vcc->qos.txtp.traffic_class == ATM_ANYCLASS ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) vcc->qos.rxtp.traffic_class == ATM_ANYCLASS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (!vcc->qos.txtp.traffic_class &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) !vcc->qos.rxtp.traffic_class) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) vcc->remote = *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) set_bit(ATM_VF_WAITING, &vcc->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) sigd_enq(vcc, as_connect, NULL, NULL, &vcc->remote);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (flags & O_NONBLOCK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) sock->state = SS_CONNECTING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) error = -EINPROGRESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if (!signal_pending(current)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) prepare_to_wait(sk_sleep(sk), &wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) TASK_INTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) pr_debug("*ABORT*\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) * This is tricky:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * Kernel ---close--> Demon
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) * Kernel <--close--- Demon
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * Kernel ---close--> Demon
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * Kernel <--error--- Demon
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) * or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) * Kernel ---close--> Demon
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * Kernel <--okay---- Demon
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * Kernel <--close--- Demon
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) sigd_enq(vcc, as_close, NULL, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) prepare_to_wait(sk_sleep(sk), &wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) TASK_INTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (!sk->sk_err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) while (!test_bit(ATM_VF_RELEASED, &vcc->flags) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) sigd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) prepare_to_wait(sk_sleep(sk), &wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) TASK_INTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) clear_bit(ATM_VF_REGIS, &vcc->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) clear_bit(ATM_VF_RELEASED, &vcc->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) clear_bit(ATM_VF_CLOSE, &vcc->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) /* we're gone now but may connect later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) error = -EINTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) finish_wait(sk_sleep(sk), &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (!sigd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) error = -EUNATCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (sk->sk_err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) error = -sk->sk_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) vcc->qos.txtp.max_pcr = SELECT_TOP_PCR(vcc->qos.txtp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) vcc->qos.txtp.pcr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) vcc->qos.txtp.min_pcr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) error = vcc_connect(sock, vcc->itf, vcc->vpi, vcc->vci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (!error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) sock->state = SS_CONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) (void)svc_disconnect(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) static int svc_listen(struct socket *sock, int backlog)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) DEFINE_WAIT(wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) struct atm_vcc *vcc = ATM_SD(sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) pr_debug("%p\n", vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) /* let server handle listen on unbound sockets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (test_bit(ATM_VF_SESSION, &vcc->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (test_bit(ATM_VF_LISTEN, &vcc->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) error = -EADDRINUSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) set_bit(ATM_VF_WAITING, &vcc->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) sigd_enq(vcc, as_listen, NULL, NULL, &vcc->local);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (!test_bit(ATM_VF_WAITING, &vcc->flags) || !sigd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) finish_wait(sk_sleep(sk), &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (!sigd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) error = -EUNATCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) set_bit(ATM_VF_LISTEN, &vcc->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) vcc_insert_socket(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) sk->sk_max_ack_backlog = backlog > 0 ? backlog : ATM_BACKLOG_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) error = -sk->sk_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) static int svc_accept(struct socket *sock, struct socket *newsock, int flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) bool kern)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) struct atmsvc_msg *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) struct atm_vcc *old_vcc = ATM_SD(sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) struct atm_vcc *new_vcc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) error = svc_create(sock_net(sk), newsock, 0, kern);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) new_vcc = ATM_SD(newsock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) pr_debug("%p -> %p\n", old_vcc, new_vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) DEFINE_WAIT(wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) while (!(skb = skb_dequeue(&sk->sk_receive_queue)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) sigd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (test_bit(ATM_VF_RELEASED, &old_vcc->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (test_bit(ATM_VF_CLOSE, &old_vcc->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) error = -sk->sk_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (flags & O_NONBLOCK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) error = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (signal_pending(current)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) error = -ERESTARTSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) prepare_to_wait(sk_sleep(sk), &wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) TASK_INTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) finish_wait(sk_sleep(sk), &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (!skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) error = -EUNATCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) msg = (struct atmsvc_msg *)skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) new_vcc->qos = msg->qos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) set_bit(ATM_VF_HASQOS, &new_vcc->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) new_vcc->remote = msg->svc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) new_vcc->local = msg->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) new_vcc->sap = msg->sap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) error = vcc_connect(newsock, msg->pvc.sap_addr.itf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) msg->pvc.sap_addr.vpi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) msg->pvc.sap_addr.vci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) sk_acceptq_removed(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) sigd_enq2(NULL, as_reject, old_vcc, NULL, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) &old_vcc->qos, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) error = error == -EAGAIN ? -EBUSY : error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) /* wait should be short, so we ignore the non-blocking flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) set_bit(ATM_VF_WAITING, &new_vcc->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) sigd_enq(new_vcc, as_accept, old_vcc, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) prepare_to_wait(sk_sleep(sk_atm(new_vcc)), &wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) TASK_UNINTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) if (!test_bit(ATM_VF_WAITING, &new_vcc->flags) || !sigd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) finish_wait(sk_sleep(sk_atm(new_vcc)), &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) if (!sigd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) error = -EUNATCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (!sk_atm(new_vcc)->sk_err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) if (sk_atm(new_vcc)->sk_err != ERESTARTSYS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) error = -sk_atm(new_vcc)->sk_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) newsock->state = SS_CONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) static int svc_getname(struct socket *sock, struct sockaddr *sockaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) int peer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) struct sockaddr_atmsvc *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) addr = (struct sockaddr_atmsvc *) sockaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) memcpy(addr, peer ? &ATM_SD(sock)->remote : &ATM_SD(sock)->local,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) sizeof(struct sockaddr_atmsvc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) return sizeof(struct sockaddr_atmsvc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) int svc_change_qos(struct atm_vcc *vcc, struct atm_qos *qos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) struct sock *sk = sk_atm(vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) DEFINE_WAIT(wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) set_bit(ATM_VF_WAITING, &vcc->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) sigd_enq2(vcc, as_modify, NULL, NULL, &vcc->local, qos, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) if (!test_bit(ATM_VF_WAITING, &vcc->flags) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) test_bit(ATM_VF_RELEASED, &vcc->flags) || !sigd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) finish_wait(sk_sleep(sk), &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (!sigd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return -EUNATCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) return -sk->sk_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) static int svc_setsockopt(struct socket *sock, int level, int optname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) sockptr_t optval, unsigned int optlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) struct atm_vcc *vcc = ATM_SD(sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) int value, error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) switch (optname) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) case SO_ATMSAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) if (level != SOL_ATM || optlen != sizeof(struct atm_sap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) if (copy_from_sockptr(&vcc->sap, optval, optlen)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) error = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) set_bit(ATM_VF_HASSAP, &vcc->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) case SO_MULTIPOINT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) if (level != SOL_ATM || optlen != sizeof(int)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (copy_from_sockptr(&value, optval, sizeof(int))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) error = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) if (value == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) set_bit(ATM_VF_SESSION, &vcc->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) else if (value == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) clear_bit(ATM_VF_SESSION, &vcc->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) error = vcc_setsockopt(sock, level, optname, optval, optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) static int svc_getsockopt(struct socket *sock, int level, int optname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) char __user *optval, int __user *optlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) int error = 0, len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) if (!__SO_LEVEL_MATCH(optname, level) || optname != SO_ATMSAP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) error = vcc_getsockopt(sock, level, optname, optval, optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) if (get_user(len, optlen)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) error = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (len != sizeof(struct atm_sap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (copy_to_user(optval, &ATM_SD(sock)->sap, sizeof(struct atm_sap))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) error = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) static int svc_addparty(struct socket *sock, struct sockaddr *sockaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) int sockaddr_len, int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) DEFINE_WAIT(wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) struct atm_vcc *vcc = ATM_SD(sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) set_bit(ATM_VF_WAITING, &vcc->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) sigd_enq(vcc, as_addparty, NULL, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) (struct sockaddr_atmsvc *) sockaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (flags & O_NONBLOCK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) error = -EINPROGRESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) pr_debug("added wait queue\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) if (!test_bit(ATM_VF_WAITING, &vcc->flags) || !sigd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) finish_wait(sk_sleep(sk), &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) error = -xchg(&sk->sk_err_soft, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) static int svc_dropparty(struct socket *sock, int ep_ref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) DEFINE_WAIT(wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) struct atm_vcc *vcc = ATM_SD(sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) set_bit(ATM_VF_WAITING, &vcc->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) sigd_enq2(vcc, as_dropparty, NULL, NULL, NULL, NULL, ep_ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) if (!test_bit(ATM_VF_WAITING, &vcc->flags) || !sigd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) finish_wait(sk_sleep(sk), &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) if (!sigd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) error = -EUNATCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) error = -xchg(&sk->sk_err_soft, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) static int svc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) int error, ep_ref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) struct sockaddr_atmsvc sa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) struct atm_vcc *vcc = ATM_SD(sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) case ATM_ADDPARTY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) if (!test_bit(ATM_VF_SESSION, &vcc->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) if (copy_from_user(&sa, (void __user *) arg, sizeof(sa)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) error = svc_addparty(sock, (struct sockaddr *)&sa, sizeof(sa),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) case ATM_DROPPARTY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) if (!test_bit(ATM_VF_SESSION, &vcc->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if (copy_from_user(&ep_ref, (void __user *) arg, sizeof(int)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) error = svc_dropparty(sock, ep_ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) error = vcc_ioctl(sock, cmd, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) static int svc_compat_ioctl(struct socket *sock, unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) /* The definition of ATM_ADDPARTY uses the size of struct atm_iobuf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) But actually it takes a struct sockaddr_atmsvc, which doesn't need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) compat handling. So all we have to do is fix up cmd... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) if (cmd == COMPAT_ATM_ADDPARTY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) cmd = ATM_ADDPARTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) if (cmd == ATM_ADDPARTY || cmd == ATM_DROPPARTY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) return svc_ioctl(sock, cmd, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) return vcc_compat_ioctl(sock, cmd, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) #endif /* CONFIG_COMPAT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) static const struct proto_ops svc_proto_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) .family = PF_ATMSVC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) .release = svc_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) .bind = svc_bind,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) .connect = svc_connect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) .socketpair = sock_no_socketpair,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) .accept = svc_accept,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) .getname = svc_getname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) .poll = vcc_poll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) .ioctl = svc_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) .compat_ioctl = svc_compat_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) .gettstamp = sock_gettstamp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) .listen = svc_listen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) .shutdown = svc_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) .setsockopt = svc_setsockopt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) .getsockopt = svc_getsockopt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) .sendmsg = vcc_sendmsg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) .recvmsg = vcc_recvmsg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) .mmap = sock_no_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) .sendpage = sock_no_sendpage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) static int svc_create(struct net *net, struct socket *sock, int protocol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) int kern)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) if (!net_eq(net, &init_net))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) return -EAFNOSUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) sock->ops = &svc_proto_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) error = vcc_create(net, sock, protocol, AF_ATMSVC, kern);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) ATM_SD(sock)->local.sas_family = AF_ATMSVC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) ATM_SD(sock)->remote.sas_family = AF_ATMSVC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) static const struct net_proto_family svc_family_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) .family = PF_ATMSVC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) .create = svc_create,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) * Initialize the ATM SVC protocol family
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) int __init atmsvc_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) return sock_register(&svc_family_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) void atmsvc_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) sock_unregister(PF_ATMSVC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }