mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
Merge branch 'atm-remove-more-dead-code'
Jakub Kicinski says:
====================
atm: remove more dead code
Commit 6deb535950 ("net: remove unused ATM protocols and legacy
ATM device drivers") removed a good chunk of old ATM drivers.
Our goal going forward is to limit the ATM support to PPPoATM
used in ADSL deployments.
A recent burst of AI generated fixes for net/atm/signaling.c and
net/atm/svc.c made me look closer at the remaining code. PPPoATM runs
over permanent virtual circuits (PF_ATMPVC) with a statically
configured VPI/VCI. We can drop switched virtual circuits (SVCs)
and user-space signaling (atmsigd) support. While digging around
I noticed a few more obviously dead pieces of code.
Annoyingly, I have applied one "fix" to QoS config which will
now make net conflict with this series :/
====================
Link: https://patch.msgid.link/20260615194416.752559-1-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
e1f544466b
|
|
@ -1180,10 +1180,6 @@ static const struct atmdev_ops fpga_ops = {
|
|||
.close = pclose,
|
||||
.ioctl = NULL,
|
||||
.send = psend,
|
||||
.send_oam = NULL,
|
||||
.phy_put = NULL,
|
||||
.phy_get = NULL,
|
||||
.change_qos = NULL,
|
||||
.proc_read = NULL,
|
||||
.owner = THIS_MODULE
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,24 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* atm_tcp.h - Driver-specific declarations of the ATMTCP driver (for use by
|
||||
driver-specific utilities) */
|
||||
|
||||
/* Written 1997-2000 by Werner Almesberger, EPFL LRC/ICA */
|
||||
|
||||
#ifndef LINUX_ATM_TCP_H
|
||||
#define LINUX_ATM_TCP_H
|
||||
|
||||
#include <uapi/linux/atm_tcp.h>
|
||||
|
||||
struct atm_vcc;
|
||||
struct module;
|
||||
|
||||
struct atm_tcp_ops {
|
||||
int (*attach)(struct atm_vcc *vcc,int itf);
|
||||
int (*create_persistent)(int itf);
|
||||
int (*remove_persistent)(int itf);
|
||||
struct module *owner;
|
||||
};
|
||||
|
||||
extern struct atm_tcp_ops atm_tcp_ops;
|
||||
|
||||
#endif
|
||||
|
|
@ -51,33 +51,11 @@ enum {
|
|||
driver, cleared by anybody. */
|
||||
ATM_VF_PARTIAL, /* resources are bound to PVC (partial PVC
|
||||
setup), controlled by socket layer */
|
||||
ATM_VF_REGIS, /* registered with demon, controlled by SVC
|
||||
socket layer */
|
||||
ATM_VF_BOUND, /* local SAP is set, controlled by SVC socket
|
||||
layer */
|
||||
ATM_VF_RELEASED, /* demon has indicated/requested release,
|
||||
controlled by SVC socket layer */
|
||||
ATM_VF_HASQOS, /* QOS parameters have been set */
|
||||
ATM_VF_LISTEN, /* socket is used for listening */
|
||||
ATM_VF_META, /* SVC socket isn't used for normal data
|
||||
traffic and doesn't depend on signaling
|
||||
to be available */
|
||||
ATM_VF_SESSION, /* VCC is p2mp session control descriptor */
|
||||
ATM_VF_HASSAP, /* SAP has been set */
|
||||
ATM_VF_CLOSE, /* asynchronous close - treat like VF_RELEASED*/
|
||||
ATM_VF_WAITING, /* waiting for reply from sigd */
|
||||
ATM_VF_IS_CLIP, /* in use by CLIP protocol */
|
||||
ATM_VF_CLOSE, /* asynchronous close - VC is being torn down */
|
||||
};
|
||||
|
||||
|
||||
#define ATM_VF2VS(flags) \
|
||||
(test_bit(ATM_VF_READY,&(flags)) ? ATM_VS_CONNECTED : \
|
||||
test_bit(ATM_VF_RELEASED,&(flags)) ? ATM_VS_CLOSING : \
|
||||
test_bit(ATM_VF_LISTEN,&(flags)) ? ATM_VS_LISTEN : \
|
||||
test_bit(ATM_VF_REGIS,&(flags)) ? ATM_VS_INUSE : \
|
||||
test_bit(ATM_VF_BOUND,&(flags)) ? ATM_VS_BOUND : ATM_VS_IDLE)
|
||||
|
||||
|
||||
enum {
|
||||
ATM_DF_REMOVED, /* device was removed from atm_devs list */
|
||||
};
|
||||
|
|
@ -100,26 +78,16 @@ struct atm_vcc {
|
|||
unsigned long atm_options; /* ATM layer options */
|
||||
struct atm_dev *dev; /* device back pointer */
|
||||
struct atm_qos qos; /* QOS */
|
||||
struct atm_sap sap; /* SAP */
|
||||
void (*release_cb)(struct atm_vcc *vcc); /* release_sock callback */
|
||||
void (*push)(struct atm_vcc *vcc,struct sk_buff *skb);
|
||||
void (*pop)(struct atm_vcc *vcc,struct sk_buff *skb); /* optional */
|
||||
int (*push_oam)(struct atm_vcc *vcc,void *cell);
|
||||
int (*send)(struct atm_vcc *vcc,struct sk_buff *skb);
|
||||
void *dev_data; /* per-device data */
|
||||
void *proto_data; /* per-protocol data */
|
||||
struct k_atm_aal_stats *stats; /* pointer to AAL stats group */
|
||||
struct module *owner; /* owner of ->push function */
|
||||
/* SVC part --- may move later ------------------------------------- */
|
||||
short itf; /* interface number */
|
||||
struct sockaddr_atmsvc local;
|
||||
struct sockaddr_atmsvc remote;
|
||||
/* Multipoint part ------------------------------------------------- */
|
||||
struct atm_vcc *session; /* session VCC descriptor */
|
||||
/* Other stuff ----------------------------------------------------- */
|
||||
void *user_back; /* user backlink - not touched by */
|
||||
/* native ATM stack. Currently used */
|
||||
/* by CLIP and sch_atm. */
|
||||
void *user_back; /* user backlink - not touched by the */
|
||||
/* native ATM stack, used by sch_atm */
|
||||
};
|
||||
|
||||
static inline struct atm_vcc *atm_sk(struct sock *sk)
|
||||
|
|
@ -137,31 +105,19 @@ static inline struct sock *sk_atm(struct atm_vcc *vcc)
|
|||
return (struct sock *)vcc;
|
||||
}
|
||||
|
||||
struct atm_dev_addr {
|
||||
struct sockaddr_atmsvc addr; /* ATM address */
|
||||
struct list_head entry; /* next address */
|
||||
};
|
||||
|
||||
enum atm_addr_type_t { ATM_ADDR_LOCAL, ATM_ADDR_LECS };
|
||||
|
||||
struct atm_dev {
|
||||
const struct atmdev_ops *ops; /* device operations; NULL if unused */
|
||||
const struct atmphy_ops *phy; /* PHY operations, may be undefined */
|
||||
/* (NULL) */
|
||||
const char *type; /* device type name */
|
||||
int number; /* device index */
|
||||
void *dev_data; /* per-device data */
|
||||
void *phy_data; /* private PHY data */
|
||||
unsigned long flags; /* device flags (ATM_DF_*) */
|
||||
struct list_head local; /* local ATM addresses */
|
||||
struct list_head lecs; /* LECS ATM addresses learned via ILMI */
|
||||
unsigned char esi[ESI_LEN]; /* ESI ("MAC" addr) */
|
||||
struct atm_cirange ci_range; /* VPI/VCI range */
|
||||
struct k_atm_dev_stats stats; /* statistics */
|
||||
char signal; /* signal status (ATM_PHY_SIG_*) */
|
||||
int link_rate; /* link rate (default: OC3) */
|
||||
refcount_t refcnt; /* reference count */
|
||||
spinlock_t lock; /* protect internal members */
|
||||
#ifdef CONFIG_PROC_FS
|
||||
struct proc_dir_entry *proc_entry; /* proc entry */
|
||||
char *proc_name; /* proc entry name */
|
||||
|
|
@ -170,12 +126,6 @@ struct atm_dev {
|
|||
struct list_head dev_list; /* linkage */
|
||||
};
|
||||
|
||||
|
||||
/* OF: send_Oam Flags */
|
||||
|
||||
#define ATM_OF_IMMED 1 /* Attempt immediate delivery */
|
||||
#define ATM_OF_INRATE 2 /* Attempt in-rate delivery */
|
||||
|
||||
struct atmdev_ops { /* only send is required */
|
||||
void (*dev_close)(struct atm_dev *dev);
|
||||
int (*open)(struct atm_vcc *vcc);
|
||||
|
|
@ -185,25 +135,11 @@ struct atmdev_ops { /* only send is required */
|
|||
int (*compat_ioctl)(struct atm_dev *dev,unsigned int cmd,
|
||||
void __user *arg);
|
||||
#endif
|
||||
int (*pre_send)(struct atm_vcc *vcc, struct sk_buff *skb);
|
||||
int (*send)(struct atm_vcc *vcc,struct sk_buff *skb);
|
||||
int (*send_bh)(struct atm_vcc *vcc, struct sk_buff *skb);
|
||||
int (*send_oam)(struct atm_vcc *vcc,void *cell,int flags);
|
||||
void (*phy_put)(struct atm_dev *dev,unsigned char value,
|
||||
unsigned long addr);
|
||||
unsigned char (*phy_get)(struct atm_dev *dev,unsigned long addr);
|
||||
int (*change_qos)(struct atm_vcc *vcc,struct atm_qos *qos,int flags);
|
||||
int (*proc_read)(struct atm_dev *dev,loff_t *pos,char *page);
|
||||
struct module *owner;
|
||||
};
|
||||
|
||||
struct atmphy_ops {
|
||||
int (*start)(struct atm_dev *dev);
|
||||
int (*ioctl)(struct atm_dev *dev,unsigned int cmd,void __user *arg);
|
||||
void (*interrupt)(struct atm_dev *dev);
|
||||
int (*stop)(struct atm_dev *dev);
|
||||
};
|
||||
|
||||
struct atm_skb_data {
|
||||
struct atm_vcc *vcc; /* ATM VCC */
|
||||
unsigned long atm_options; /* ATM layer options */
|
||||
|
|
|
|||
|
|
@ -1,24 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/* atm_eni.h - Driver-specific declarations of the ENI driver (for use by
|
||||
driver-specific utilities) */
|
||||
|
||||
/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
|
||||
|
||||
|
||||
#ifndef LINUX_ATM_ENI_H
|
||||
#define LINUX_ATM_ENI_H
|
||||
|
||||
#include <linux/atmioc.h>
|
||||
|
||||
|
||||
struct eni_multipliers {
|
||||
int tx,rx; /* values are in percent and must be > 100 */
|
||||
};
|
||||
|
||||
|
||||
#define ENI_MEMDUMP _IOW('a',ATMIOC_SARPRV,struct atmif_sioc)
|
||||
/* printk memory map */
|
||||
#define ENI_SETMULT _IOW('a',ATMIOC_SARPRV+7,struct atmif_sioc)
|
||||
/* set buffer multipliers */
|
||||
|
||||
#endif
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/* atm_he.h */
|
||||
|
||||
#ifndef LINUX_ATM_HE_H
|
||||
#define LINUX_ATM_HE_H
|
||||
|
||||
#include <linux/atmioc.h>
|
||||
|
||||
#define HE_GET_REG _IOW('a', ATMIOC_SARPRV, struct atmif_sioc)
|
||||
|
||||
#define HE_REGTYPE_PCI 1
|
||||
#define HE_REGTYPE_RCM 2
|
||||
#define HE_REGTYPE_TCM 3
|
||||
#define HE_REGTYPE_MBOX 4
|
||||
|
||||
struct he_ioctl_reg {
|
||||
unsigned addr, val;
|
||||
char type;
|
||||
};
|
||||
|
||||
#endif /* LINUX_ATM_HE_H */
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/* atm_idt77105.h - Driver-specific declarations of the IDT77105 driver (for
|
||||
* use by driver-specific utilities) */
|
||||
|
||||
/* Written 1999 by Greg Banks <gnb@linuxfan.com>. Copied from atm_suni.h. */
|
||||
|
||||
|
||||
#ifndef LINUX_ATM_IDT77105_H
|
||||
#define LINUX_ATM_IDT77105_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/atmioc.h>
|
||||
#include <linux/atmdev.h>
|
||||
|
||||
/*
|
||||
* Structure for IDT77105_GETSTAT and IDT77105_GETSTATZ ioctls.
|
||||
* Pointed to by `arg' in atmif_sioc.
|
||||
*/
|
||||
struct idt77105_stats {
|
||||
__u32 symbol_errors; /* wire symbol errors */
|
||||
__u32 tx_cells; /* cells transmitted */
|
||||
__u32 rx_cells; /* cells received */
|
||||
__u32 rx_hec_errors; /* Header Error Check errors on receive */
|
||||
};
|
||||
|
||||
#define IDT77105_GETSTAT _IOW('a',ATMIOC_PHYPRV+2,struct atmif_sioc) /* get stats */
|
||||
#define IDT77105_GETSTATZ _IOW('a',ATMIOC_PHYPRV+3,struct atmif_sioc) /* get stats and zero */
|
||||
|
||||
#endif
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/******************************************************************************
|
||||
*
|
||||
* atm_nicstar.h
|
||||
*
|
||||
* Driver-specific declarations for use by NICSTAR driver specific utils.
|
||||
*
|
||||
* Author: Rui Prior
|
||||
*
|
||||
* (C) INESC 1998
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#ifndef LINUX_ATM_NICSTAR_H
|
||||
#define LINUX_ATM_NICSTAR_H
|
||||
|
||||
/* Note: non-kernel programs including this file must also include
|
||||
* sys/types.h for struct timeval
|
||||
*/
|
||||
|
||||
#include <linux/atmapi.h>
|
||||
#include <linux/atmioc.h>
|
||||
|
||||
#define NS_GETPSTAT _IOWR('a',ATMIOC_SARPRV+1,struct atmif_sioc)
|
||||
/* get pool statistics */
|
||||
#define NS_SETBUFLEV _IOW('a',ATMIOC_SARPRV+2,struct atmif_sioc)
|
||||
/* set buffer level markers */
|
||||
#define NS_ADJBUFLEV _IO('a',ATMIOC_SARPRV+3)
|
||||
/* adjust buffer level */
|
||||
|
||||
typedef struct buf_nr
|
||||
{
|
||||
unsigned min;
|
||||
unsigned init;
|
||||
unsigned max;
|
||||
}buf_nr;
|
||||
|
||||
|
||||
typedef struct pool_levels
|
||||
{
|
||||
int buftype;
|
||||
int count; /* (At least for now) only used in NS_GETPSTAT */
|
||||
buf_nr level;
|
||||
} pool_levels;
|
||||
|
||||
/* type must be one of the following: */
|
||||
#define NS_BUFTYPE_SMALL 1
|
||||
#define NS_BUFTYPE_LARGE 2
|
||||
#define NS_BUFTYPE_HUGE 3
|
||||
#define NS_BUFTYPE_IOVEC 4
|
||||
|
||||
|
||||
#endif /* LINUX_ATM_NICSTAR_H */
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/* atm_tcp.h - Driver-specific declarations of the ATMTCP driver (for use by
|
||||
driver-specific utilities) */
|
||||
|
||||
/* Written 1997-2000 by Werner Almesberger, EPFL LRC/ICA */
|
||||
|
||||
|
||||
#ifndef _UAPILINUX_ATM_TCP_H
|
||||
#define _UAPILINUX_ATM_TCP_H
|
||||
|
||||
#include <linux/atmapi.h>
|
||||
#include <linux/atm.h>
|
||||
#include <linux/atmioc.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
|
||||
/*
|
||||
* All values in struct atmtcp_hdr are in network byte order
|
||||
*/
|
||||
|
||||
struct atmtcp_hdr {
|
||||
__u16 vpi;
|
||||
__u16 vci;
|
||||
__u32 length; /* ... of data part */
|
||||
};
|
||||
|
||||
/*
|
||||
* All values in struct atmtcp_command are in host byte order
|
||||
*/
|
||||
|
||||
#define ATMTCP_HDR_MAGIC (~0) /* this length indicates a command */
|
||||
#define ATMTCP_CTRL_OPEN 1 /* request/reply */
|
||||
#define ATMTCP_CTRL_CLOSE 2 /* request/reply */
|
||||
|
||||
struct atmtcp_control {
|
||||
struct atmtcp_hdr hdr; /* must be first */
|
||||
int type; /* message type; both directions */
|
||||
atm_kptr_t vcc; /* both directions */
|
||||
struct sockaddr_atmpvc addr; /* suggested value from kernel */
|
||||
struct atm_qos qos; /* both directions */
|
||||
int result; /* to kernel only */
|
||||
} __ATM_API_ALIGN;
|
||||
|
||||
/*
|
||||
* Field usage:
|
||||
* Messge type dir. hdr.v?i type addr qos vcc result
|
||||
* ----------- ---- ------- ---- ---- --- --- ------
|
||||
* OPEN K->D Y Y Y Y Y 0
|
||||
* OPEN D->K - Y Y Y Y Y
|
||||
* CLOSE K->D - - Y - Y 0
|
||||
* CLOSE D->K - - - - Y Y
|
||||
*/
|
||||
|
||||
#define SIOCSIFATMTCP _IO('a',ATMIOC_ITF) /* set ATMTCP mode */
|
||||
#define ATMTCP_CREATE _IO('a',ATMIOC_ITF+14) /* create persistent ATMTCP
|
||||
interface */
|
||||
#define ATMTCP_REMOVE _IO('a',ATMIOC_ITF+15) /* destroy persistent ATMTCP
|
||||
interface */
|
||||
|
||||
|
||||
|
||||
#endif /* _UAPILINUX_ATM_TCP_H */
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/* atm_zatm.h - Driver-specific declarations of the ZATM driver (for use by
|
||||
driver-specific utilities) */
|
||||
|
||||
/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
|
||||
|
||||
|
||||
#ifndef LINUX_ATM_ZATM_H
|
||||
#define LINUX_ATM_ZATM_H
|
||||
|
||||
/*
|
||||
* Note: non-kernel programs including this file must also include
|
||||
* sys/types.h for struct timeval
|
||||
*/
|
||||
|
||||
#include <linux/atmapi.h>
|
||||
#include <linux/atmioc.h>
|
||||
|
||||
#define ZATM_GETPOOL _IOW('a',ATMIOC_SARPRV+1,struct atmif_sioc)
|
||||
/* get pool statistics */
|
||||
#define ZATM_GETPOOLZ _IOW('a',ATMIOC_SARPRV+2,struct atmif_sioc)
|
||||
/* get statistics and zero */
|
||||
#define ZATM_SETPOOL _IOW('a',ATMIOC_SARPRV+3,struct atmif_sioc)
|
||||
/* set pool parameters */
|
||||
|
||||
struct zatm_pool_info {
|
||||
int ref_count; /* free buffer pool usage counters */
|
||||
int low_water,high_water; /* refill parameters */
|
||||
int rqa_count,rqu_count; /* queue condition counters */
|
||||
int offset,next_off; /* alignment optimizations: offset */
|
||||
int next_cnt,next_thres; /* repetition counter and threshold */
|
||||
};
|
||||
|
||||
struct zatm_pool_req {
|
||||
int pool_num; /* pool number */
|
||||
struct zatm_pool_info info; /* actual information */
|
||||
};
|
||||
|
||||
#define ZATM_OAM_POOL 0 /* free buffer pool for OAM cells */
|
||||
#define ZATM_AAL0_POOL 1 /* free buffer pool for AAL0 cells */
|
||||
#define ZATM_AAL5_POOL_BASE 2 /* first AAL5 free buffer pool */
|
||||
#define ZATM_LAST_POOL ZATM_AAL5_POOL_BASE+10 /* max. 64 kB */
|
||||
|
||||
#define ZATM_TIMER_HISTORY_SIZE 16 /* number of timer adjustments to
|
||||
record; must be 2^n */
|
||||
|
||||
#endif
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/* atmarp.h - ATM ARP protocol and kernel-demon interface definitions */
|
||||
|
||||
/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
|
||||
|
||||
|
||||
#ifndef _LINUX_ATMARP_H
|
||||
#define _LINUX_ATMARP_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/atmapi.h>
|
||||
#include <linux/atmioc.h>
|
||||
|
||||
|
||||
#define ATMARP_RETRY_DELAY 30 /* request next resolution or forget
|
||||
NAK after 30 sec - should go into
|
||||
atmclip.h */
|
||||
#define ATMARP_MAX_UNRES_PACKETS 5 /* queue that many packets while
|
||||
waiting for the resolver */
|
||||
|
||||
|
||||
#define ATMARPD_CTRL _IO('a',ATMIOC_CLIP+1) /* become atmarpd ctrl sock */
|
||||
#define ATMARP_MKIP _IO('a',ATMIOC_CLIP+2) /* attach socket to IP */
|
||||
#define ATMARP_SETENTRY _IO('a',ATMIOC_CLIP+3) /* fill or hide ARP entry */
|
||||
#define ATMARP_ENCAP _IO('a',ATMIOC_CLIP+5) /* change encapsulation */
|
||||
|
||||
|
||||
enum atmarp_ctrl_type {
|
||||
act_invalid, /* catch uninitialized structures */
|
||||
act_need, /* need address resolution */
|
||||
act_up, /* interface is coming up */
|
||||
act_down, /* interface is going down */
|
||||
act_change /* interface configuration has changed */
|
||||
};
|
||||
|
||||
struct atmarp_ctrl {
|
||||
enum atmarp_ctrl_type type; /* message type */
|
||||
int itf_num;/* interface number (if present) */
|
||||
__be32 ip; /* IP address (act_need only) */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/* atmclip.h - Classical IP over ATM */
|
||||
|
||||
/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */
|
||||
|
||||
|
||||
#ifndef LINUX_ATMCLIP_H
|
||||
#define LINUX_ATMCLIP_H
|
||||
|
||||
#include <linux/sockios.h>
|
||||
#include <linux/atmioc.h>
|
||||
|
||||
|
||||
#define RFC1483LLC_LEN 8 /* LLC+OUI+PID = 8 */
|
||||
#define RFC1626_MTU 9180 /* RFC1626 default MTU */
|
||||
|
||||
#define CLIP_DEFAULT_IDLETIMER 1200 /* 20 minutes, see RFC1755 */
|
||||
#define CLIP_CHECK_INTERVAL 10 /* check every ten seconds */
|
||||
|
||||
#define SIOCMKCLIP _IO('a',ATMIOC_CLIP) /* create IP interface */
|
||||
|
||||
#endif
|
||||
|
|
@ -60,14 +60,6 @@ struct atm_dev_stats {
|
|||
/* get interface type name */
|
||||
#define ATM_GETESI _IOW('a',ATMIOC_ITF+5,struct atmif_sioc)
|
||||
/* get interface ESI */
|
||||
#define ATM_GETADDR _IOW('a',ATMIOC_ITF+6,struct atmif_sioc)
|
||||
/* get itf's local ATM addr. list */
|
||||
#define ATM_RSTADDR _IOW('a',ATMIOC_ITF+7,struct atmif_sioc)
|
||||
/* reset itf's ATM address list */
|
||||
#define ATM_ADDADDR _IOW('a',ATMIOC_ITF+8,struct atmif_sioc)
|
||||
/* add a local ATM address */
|
||||
#define ATM_DELADDR _IOW('a',ATMIOC_ITF+9,struct atmif_sioc)
|
||||
/* remove a local ATM address */
|
||||
#define ATM_GETCIRANGE _IOW('a',ATMIOC_ITF+10,struct atmif_sioc)
|
||||
/* get connection identifier range */
|
||||
#define ATM_SETCIRANGE _IOW('a',ATMIOC_ITF+11,struct atmif_sioc)
|
||||
|
|
@ -76,12 +68,6 @@ struct atm_dev_stats {
|
|||
/* set interface ESI */
|
||||
#define ATM_SETESIF _IOW('a',ATMIOC_ITF+13,struct atmif_sioc)
|
||||
/* force interface ESI */
|
||||
#define ATM_ADDLECSADDR _IOW('a', ATMIOC_ITF+14, struct atmif_sioc)
|
||||
/* register a LECS address */
|
||||
#define ATM_DELLECSADDR _IOW('a', ATMIOC_ITF+15, struct atmif_sioc)
|
||||
/* unregister a LECS address */
|
||||
#define ATM_GETLECSADDR _IOW('a', ATMIOC_ITF+16, struct atmif_sioc)
|
||||
/* retrieve LECS address(es) */
|
||||
|
||||
#define ATM_GETSTAT _IOW('a',ATMIOC_SARCOM+0,struct atmif_sioc)
|
||||
/* get AAL layer statistics */
|
||||
|
|
@ -99,10 +85,6 @@ struct atm_dev_stats {
|
|||
/* set backend handler */
|
||||
#define ATM_NEWBACKENDIF _IOW('a',ATMIOC_SPECIAL+3,atm_backend_t)
|
||||
/* use backend to make new if */
|
||||
#define ATM_ADDPARTY _IOW('a', ATMIOC_SPECIAL+4,struct atm_iobuf)
|
||||
/* add party to p2mp call */
|
||||
#define ATM_DROPPARTY _IOW('a', ATMIOC_SPECIAL+5,int)
|
||||
/* drop party from p2mp call */
|
||||
|
||||
/*
|
||||
* These are backend handkers that can be set via the ATM_SETBACKEND call
|
||||
|
|
|
|||
|
|
@ -1,92 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/*
|
||||
* ATM Lan Emulation Daemon driver interface
|
||||
*
|
||||
* Marko Kiiskila <mkiiskila@yahoo.com>
|
||||
*/
|
||||
|
||||
#ifndef _ATMLEC_H_
|
||||
#define _ATMLEC_H_
|
||||
|
||||
#include <linux/atmapi.h>
|
||||
#include <linux/atmioc.h>
|
||||
#include <linux/atm.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
/* ATM lec daemon control socket */
|
||||
#define ATMLEC_CTRL _IO('a', ATMIOC_LANE)
|
||||
#define ATMLEC_DATA _IO('a', ATMIOC_LANE+1)
|
||||
#define ATMLEC_MCAST _IO('a', ATMIOC_LANE+2)
|
||||
|
||||
/* Maximum number of LEC interfaces (tweakable) */
|
||||
#define MAX_LEC_ITF 48
|
||||
|
||||
typedef enum {
|
||||
l_set_mac_addr,
|
||||
l_del_mac_addr,
|
||||
l_svc_setup,
|
||||
l_addr_delete,
|
||||
l_topology_change,
|
||||
l_flush_complete,
|
||||
l_arp_update,
|
||||
l_narp_req, /* LANE2 mandates the use of this */
|
||||
l_config,
|
||||
l_flush_tran_id,
|
||||
l_set_lecid,
|
||||
l_arp_xmt,
|
||||
l_rdesc_arp_xmt,
|
||||
l_associate_req,
|
||||
l_should_bridge /* should we bridge this MAC? */
|
||||
} atmlec_msg_type;
|
||||
|
||||
#define ATMLEC_MSG_TYPE_MAX l_should_bridge
|
||||
|
||||
struct atmlec_config_msg {
|
||||
unsigned int maximum_unknown_frame_count;
|
||||
unsigned int max_unknown_frame_time;
|
||||
unsigned short max_retry_count;
|
||||
unsigned int aging_time;
|
||||
unsigned int forward_delay_time;
|
||||
unsigned int arp_response_time;
|
||||
unsigned int flush_timeout;
|
||||
unsigned int path_switching_delay;
|
||||
unsigned int lane_version; /* LANE2: 1 for LANEv1, 2 for LANEv2 */
|
||||
int mtu;
|
||||
int is_proxy;
|
||||
};
|
||||
|
||||
struct atmlec_msg {
|
||||
atmlec_msg_type type;
|
||||
int sizeoftlvs; /* LANE2: if != 0, tlvs follow */
|
||||
union {
|
||||
struct {
|
||||
unsigned char mac_addr[ETH_ALEN];
|
||||
unsigned char atm_addr[ATM_ESA_LEN];
|
||||
unsigned int flag; /*
|
||||
* Topology_change flag,
|
||||
* remoteflag, permanent flag,
|
||||
* lecid, transaction id
|
||||
*/
|
||||
unsigned int targetless_le_arp; /* LANE2 */
|
||||
unsigned int no_source_le_narp; /* LANE2 */
|
||||
} normal;
|
||||
struct atmlec_config_msg config;
|
||||
struct {
|
||||
__u16 lec_id; /* requestor lec_id */
|
||||
__u32 tran_id; /* transaction id */
|
||||
unsigned char mac_addr[ETH_ALEN]; /* dst mac addr */
|
||||
unsigned char atm_addr[ATM_ESA_LEN]; /* reqestor ATM addr */
|
||||
} proxy; /*
|
||||
* For mapping LE_ARP requests to responses. Filled by
|
||||
* zeppelin, returned by kernel. Used only when proxying
|
||||
*/
|
||||
} content;
|
||||
} __ATM_API_ALIGN;
|
||||
|
||||
struct atmlec_ioc {
|
||||
int dev_num;
|
||||
unsigned char atm_addr[ATM_ESA_LEN];
|
||||
unsigned char receive; /* 1= receive vcc, 0 = send vcc */
|
||||
};
|
||||
#endif /* _ATMLEC_H_ */
|
||||
|
|
@ -1,127 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef _ATMMPC_H_
|
||||
#define _ATMMPC_H_
|
||||
|
||||
#include <linux/atmapi.h>
|
||||
#include <linux/atmioc.h>
|
||||
#include <linux/atm.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#define ATMMPC_CTRL _IO('a', ATMIOC_MPOA)
|
||||
#define ATMMPC_DATA _IO('a', ATMIOC_MPOA+1)
|
||||
|
||||
#define MPC_SOCKET_INGRESS 1
|
||||
#define MPC_SOCKET_EGRESS 2
|
||||
|
||||
struct atmmpc_ioc {
|
||||
int dev_num;
|
||||
__be32 ipaddr; /* the IP address of the shortcut */
|
||||
int type; /* ingress or egress */
|
||||
};
|
||||
|
||||
typedef struct in_ctrl_info {
|
||||
__u8 Last_NHRP_CIE_code;
|
||||
__u8 Last_Q2931_cause_value;
|
||||
__u8 eg_MPC_ATM_addr[ATM_ESA_LEN];
|
||||
__be32 tag;
|
||||
__be32 in_dst_ip; /* IP address this ingress MPC sends packets to */
|
||||
__u16 holding_time;
|
||||
__u32 request_id;
|
||||
} in_ctrl_info;
|
||||
|
||||
typedef struct eg_ctrl_info {
|
||||
__u8 DLL_header[256];
|
||||
__u8 DH_length;
|
||||
__be32 cache_id;
|
||||
__be32 tag;
|
||||
__be32 mps_ip;
|
||||
__be32 eg_dst_ip; /* IP address to which ingress MPC sends packets */
|
||||
__u8 in_MPC_data_ATM_addr[ATM_ESA_LEN];
|
||||
__u16 holding_time;
|
||||
} eg_ctrl_info;
|
||||
|
||||
struct mpc_parameters {
|
||||
__u16 mpc_p1; /* Shortcut-Setup Frame Count */
|
||||
__u16 mpc_p2; /* Shortcut-Setup Frame Time */
|
||||
__u8 mpc_p3[8]; /* Flow-detection Protocols */
|
||||
__u16 mpc_p4; /* MPC Initial Retry Time */
|
||||
__u16 mpc_p5; /* MPC Retry Time Maximum */
|
||||
__u16 mpc_p6; /* Hold Down Time */
|
||||
} ;
|
||||
|
||||
struct k_message {
|
||||
__u16 type;
|
||||
__be32 ip_mask;
|
||||
__u8 MPS_ctrl[ATM_ESA_LEN];
|
||||
union {
|
||||
in_ctrl_info in_info;
|
||||
eg_ctrl_info eg_info;
|
||||
struct mpc_parameters params;
|
||||
} content;
|
||||
struct atm_qos qos;
|
||||
} __ATM_API_ALIGN;
|
||||
|
||||
struct llc_snap_hdr {
|
||||
/* RFC 1483 LLC/SNAP encapsulation for routed IP PDUs */
|
||||
__u8 dsap; /* Destination Service Access Point (0xAA) */
|
||||
__u8 ssap; /* Source Service Access Point (0xAA) */
|
||||
__u8 ui; /* Unnumbered Information (0x03) */
|
||||
__u8 org[3]; /* Organizational identification (0x000000) */
|
||||
__u8 type[2]; /* Ether type (for IP) (0x0800) */
|
||||
};
|
||||
|
||||
/* TLVs this MPC recognizes */
|
||||
#define TLV_MPOA_DEVICE_TYPE 0x00a03e2a
|
||||
|
||||
/* MPOA device types in MPOA Device Type TLV */
|
||||
#define NON_MPOA 0
|
||||
#define MPS 1
|
||||
#define MPC 2
|
||||
#define MPS_AND_MPC 3
|
||||
|
||||
|
||||
/* MPC parameter defaults */
|
||||
|
||||
#define MPC_P1 10 /* Shortcut-Setup Frame Count */
|
||||
#define MPC_P2 1 /* Shortcut-Setup Frame Time */
|
||||
#define MPC_P3 0 /* Flow-detection Protocols */
|
||||
#define MPC_P4 5 /* MPC Initial Retry Time */
|
||||
#define MPC_P5 40 /* MPC Retry Time Maximum */
|
||||
#define MPC_P6 160 /* Hold Down Time */
|
||||
#define HOLDING_TIME_DEFAULT 1200 /* same as MPS-p7 */
|
||||
|
||||
/* MPC constants */
|
||||
|
||||
#define MPC_C1 2 /* Retry Time Multiplier */
|
||||
#define MPC_C2 60 /* Initial Keep-Alive Lifetime */
|
||||
|
||||
/* Message types - to MPOA daemon */
|
||||
|
||||
#define SND_MPOA_RES_RQST 201
|
||||
#define SET_MPS_CTRL_ADDR 202
|
||||
#define SND_MPOA_RES_RTRY 203 /* Different type in a retry due to req id */
|
||||
#define STOP_KEEP_ALIVE_SM 204
|
||||
#define EGRESS_ENTRY_REMOVED 205
|
||||
#define SND_EGRESS_PURGE 206
|
||||
#define DIE 207 /* tell the daemon to exit() */
|
||||
#define DATA_PLANE_PURGE 208 /* Data plane purge because of egress cache hit miss or dead MPS */
|
||||
#define OPEN_INGRESS_SVC 209
|
||||
|
||||
/* Message types - from MPOA daemon */
|
||||
|
||||
#define MPOA_TRIGGER_RCVD 101
|
||||
#define MPOA_RES_REPLY_RCVD 102
|
||||
#define INGRESS_PURGE_RCVD 103
|
||||
#define EGRESS_PURGE_RCVD 104
|
||||
#define MPS_DEATH 105
|
||||
#define CACHE_IMPOS_RCVD 106
|
||||
#define SET_MPC_CTRL_ADDR 107 /* Our MPC's control ATM address */
|
||||
#define SET_MPS_MAC_ADDR 108
|
||||
#define CLEAN_UP_AND_EXIT 109
|
||||
#define SET_MPC_PARAMS 110 /* MPC configuration parameters */
|
||||
|
||||
/* Message types - bidirectional */
|
||||
|
||||
#define RELOAD 301 /* kill -HUP the daemon for reload */
|
||||
|
||||
#endif /* _ATMMPC_H_ */
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/* atmsvc.h - ATM signaling kernel-demon interface definitions */
|
||||
|
||||
/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
|
||||
|
||||
|
||||
#ifndef _LINUX_ATMSVC_H
|
||||
#define _LINUX_ATMSVC_H
|
||||
|
||||
#include <linux/atmapi.h>
|
||||
#include <linux/atm.h>
|
||||
#include <linux/atmioc.h>
|
||||
|
||||
|
||||
#define ATMSIGD_CTRL _IO('a',ATMIOC_SPECIAL)
|
||||
/* become ATM signaling demon control socket */
|
||||
|
||||
enum atmsvc_msg_type { as_catch_null, as_bind, as_connect, as_accept, as_reject,
|
||||
as_listen, as_okay, as_error, as_indicate, as_close,
|
||||
as_itf_notify, as_modify, as_identify, as_terminate,
|
||||
as_addparty, as_dropparty };
|
||||
|
||||
struct atmsvc_msg {
|
||||
enum atmsvc_msg_type type;
|
||||
atm_kptr_t vcc;
|
||||
atm_kptr_t listen_vcc; /* indicate */
|
||||
int reply; /* for okay and close: */
|
||||
/* < 0: error before active */
|
||||
/* (sigd has discarded ctx) */
|
||||
/* ==0: success */
|
||||
/* > 0: error when active (still */
|
||||
/* need to close) */
|
||||
struct sockaddr_atmpvc pvc; /* indicate, okay (connect) */
|
||||
struct sockaddr_atmsvc local; /* local SVC address */
|
||||
struct atm_qos qos; /* QOS parameters */
|
||||
struct atm_sap sap; /* SAP */
|
||||
unsigned int session; /* for p2pm */
|
||||
struct sockaddr_atmsvc svc; /* SVC address */
|
||||
} __ATM_API_ALIGN;
|
||||
|
||||
/*
|
||||
* Message contents: see ftp://icaftp.epfl.ch/pub/linux/atm/docs/isp-*.tar.gz
|
||||
*/
|
||||
|
||||
/*
|
||||
* Some policy stuff for atmsigd and for net/atm/svc.c. Both have to agree on
|
||||
* what PCR is used to request bandwidth from the device driver. net/atm/svc.c
|
||||
* tries to do better than that, but only if there's no routing decision (i.e.
|
||||
* if signaling only uses one ATM interface).
|
||||
*/
|
||||
|
||||
#define SELECT_TOP_PCR(tp) ((tp).pcr ? (tp).pcr : \
|
||||
(tp).max_pcr && (tp).max_pcr != ATM_MAX_PCR ? (tp).max_pcr : \
|
||||
(tp).min_pcr ? (tp).min_pcr : ATM_MAX_PCR)
|
||||
|
||||
#endif
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
# Makefile for the ATM Protocol Families.
|
||||
#
|
||||
|
||||
atm-y := addr.o pvc.o signaling.o svc.o ioctl.o common.o atm_misc.o raw.o resources.o atm_sysfs.o
|
||||
atm-y := pvc.o ioctl.o common.o atm_misc.o raw.o resources.o atm_sysfs.o
|
||||
|
||||
obj-$(CONFIG_ATM) += atm.o
|
||||
obj-$(CONFIG_ATM_BR2684) += br2684.o
|
||||
|
|
|
|||
162
net/atm/addr.c
162
net/atm/addr.c
|
|
@ -1,162 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* net/atm/addr.c - Local ATM address registry */
|
||||
|
||||
/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
|
||||
|
||||
#include <linux/atm.h>
|
||||
#include <linux/atmdev.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include "signaling.h"
|
||||
#include "addr.h"
|
||||
|
||||
static int check_addr(const struct sockaddr_atmsvc *addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (addr->sas_family != AF_ATMSVC)
|
||||
return -EAFNOSUPPORT;
|
||||
if (!*addr->sas_addr.pub)
|
||||
return *addr->sas_addr.prv ? 0 : -EINVAL;
|
||||
for (i = 1; i < ATM_E164_LEN + 1; i++) /* make sure it's \0-terminated */
|
||||
if (!addr->sas_addr.pub[i])
|
||||
return 0;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int identical(const struct sockaddr_atmsvc *a, const struct sockaddr_atmsvc *b)
|
||||
{
|
||||
if (*a->sas_addr.prv)
|
||||
if (memcmp(a->sas_addr.prv, b->sas_addr.prv, ATM_ESA_LEN))
|
||||
return 0;
|
||||
if (!*a->sas_addr.pub)
|
||||
return !*b->sas_addr.pub;
|
||||
if (!*b->sas_addr.pub)
|
||||
return 0;
|
||||
return !strcmp(a->sas_addr.pub, b->sas_addr.pub);
|
||||
}
|
||||
|
||||
static void notify_sigd(const struct atm_dev *dev)
|
||||
{
|
||||
struct sockaddr_atmpvc pvc;
|
||||
|
||||
pvc.sap_addr.itf = dev->number;
|
||||
sigd_enq(NULL, as_itf_notify, NULL, &pvc, NULL);
|
||||
}
|
||||
|
||||
void atm_reset_addr(struct atm_dev *dev, enum atm_addr_type_t atype)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct atm_dev_addr *this, *p;
|
||||
struct list_head *head;
|
||||
|
||||
spin_lock_irqsave(&dev->lock, flags);
|
||||
if (atype == ATM_ADDR_LECS)
|
||||
head = &dev->lecs;
|
||||
else
|
||||
head = &dev->local;
|
||||
list_for_each_entry_safe(this, p, head, entry) {
|
||||
list_del(&this->entry);
|
||||
kfree(this);
|
||||
}
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
if (head == &dev->local)
|
||||
notify_sigd(dev);
|
||||
}
|
||||
|
||||
int atm_add_addr(struct atm_dev *dev, const struct sockaddr_atmsvc *addr,
|
||||
enum atm_addr_type_t atype)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct atm_dev_addr *this;
|
||||
struct list_head *head;
|
||||
int error;
|
||||
|
||||
error = check_addr(addr);
|
||||
if (error)
|
||||
return error;
|
||||
spin_lock_irqsave(&dev->lock, flags);
|
||||
if (atype == ATM_ADDR_LECS)
|
||||
head = &dev->lecs;
|
||||
else
|
||||
head = &dev->local;
|
||||
list_for_each_entry(this, head, entry) {
|
||||
if (identical(&this->addr, addr)) {
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
return -EEXIST;
|
||||
}
|
||||
}
|
||||
this = kmalloc_obj(struct atm_dev_addr, GFP_ATOMIC);
|
||||
if (!this) {
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
return -ENOMEM;
|
||||
}
|
||||
this->addr = *addr;
|
||||
list_add(&this->entry, head);
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
if (head == &dev->local)
|
||||
notify_sigd(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int atm_del_addr(struct atm_dev *dev, const struct sockaddr_atmsvc *addr,
|
||||
enum atm_addr_type_t atype)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct atm_dev_addr *this;
|
||||
struct list_head *head;
|
||||
int error;
|
||||
|
||||
error = check_addr(addr);
|
||||
if (error)
|
||||
return error;
|
||||
spin_lock_irqsave(&dev->lock, flags);
|
||||
if (atype == ATM_ADDR_LECS)
|
||||
head = &dev->lecs;
|
||||
else
|
||||
head = &dev->local;
|
||||
list_for_each_entry(this, head, entry) {
|
||||
if (identical(&this->addr, addr)) {
|
||||
list_del(&this->entry);
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
kfree(this);
|
||||
if (head == &dev->local)
|
||||
notify_sigd(dev);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
int atm_get_addr(struct atm_dev *dev, struct sockaddr_atmsvc __user * buf,
|
||||
size_t size, enum atm_addr_type_t atype)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct atm_dev_addr *this;
|
||||
struct list_head *head;
|
||||
int total = 0, error;
|
||||
struct sockaddr_atmsvc *tmp_buf, *tmp_bufp;
|
||||
|
||||
spin_lock_irqsave(&dev->lock, flags);
|
||||
if (atype == ATM_ADDR_LECS)
|
||||
head = &dev->lecs;
|
||||
else
|
||||
head = &dev->local;
|
||||
list_for_each_entry(this, head, entry)
|
||||
total += sizeof(struct sockaddr_atmsvc);
|
||||
tmp_buf = tmp_bufp = kmalloc(total, GFP_ATOMIC);
|
||||
if (!tmp_buf) {
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
return -ENOMEM;
|
||||
}
|
||||
list_for_each_entry(this, head, entry)
|
||||
memcpy(tmp_bufp++, &this->addr, sizeof(struct sockaddr_atmsvc));
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
error = total > size ? -E2BIG : total;
|
||||
if (copy_to_user(buf, tmp_buf, total < size ? total : size))
|
||||
error = -EFAULT;
|
||||
kfree(tmp_buf);
|
||||
return error;
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* net/atm/addr.h - Local ATM address registry */
|
||||
|
||||
/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
|
||||
|
||||
|
||||
#ifndef NET_ATM_ADDR_H
|
||||
#define NET_ATM_ADDR_H
|
||||
|
||||
#include <linux/atm.h>
|
||||
#include <linux/atmdev.h>
|
||||
|
||||
void atm_reset_addr(struct atm_dev *dev, enum atm_addr_type_t type);
|
||||
int atm_add_addr(struct atm_dev *dev, const struct sockaddr_atmsvc *addr,
|
||||
enum atm_addr_type_t type);
|
||||
int atm_del_addr(struct atm_dev *dev, const struct sockaddr_atmsvc *addr,
|
||||
enum atm_addr_type_t type);
|
||||
int atm_get_addr(struct atm_dev *dev, struct sockaddr_atmsvc __user *buf,
|
||||
size_t size, enum atm_addr_type_t type);
|
||||
|
||||
#endif
|
||||
|
|
@ -27,29 +27,6 @@ static ssize_t address_show(struct device *cdev,
|
|||
return scnprintf(buf, PAGE_SIZE, "%pM\n", adev->esi);
|
||||
}
|
||||
|
||||
static ssize_t atmaddress_show(struct device *cdev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct atm_dev *adev = to_atm_dev(cdev);
|
||||
struct atm_dev_addr *aaddr;
|
||||
int count = 0;
|
||||
|
||||
spin_lock_irqsave(&adev->lock, flags);
|
||||
list_for_each_entry(aaddr, &adev->local, entry) {
|
||||
count += scnprintf(buf + count, PAGE_SIZE - count,
|
||||
"%1phN.%2phN.%10phN.%6phN.%1phN\n",
|
||||
&aaddr->addr.sas_addr.prv[0],
|
||||
&aaddr->addr.sas_addr.prv[1],
|
||||
&aaddr->addr.sas_addr.prv[3],
|
||||
&aaddr->addr.sas_addr.prv[13],
|
||||
&aaddr->addr.sas_addr.prv[19]);
|
||||
}
|
||||
spin_unlock_irqrestore(&adev->lock, flags);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t atmindex_show(struct device *cdev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
|
|
@ -91,14 +68,12 @@ static ssize_t link_rate_show(struct device *cdev,
|
|||
}
|
||||
|
||||
static DEVICE_ATTR_RO(address);
|
||||
static DEVICE_ATTR_RO(atmaddress);
|
||||
static DEVICE_ATTR_RO(atmindex);
|
||||
static DEVICE_ATTR_RO(carrier);
|
||||
static DEVICE_ATTR_RO(type);
|
||||
static DEVICE_ATTR_RO(link_rate);
|
||||
|
||||
static struct device_attribute *atm_attrs[] = {
|
||||
&dev_attr_atmaddress,
|
||||
&dev_attr_address,
|
||||
&dev_attr_atmindex,
|
||||
&dev_attr_carrier,
|
||||
|
|
|
|||
|
|
@ -311,8 +311,7 @@ static netdev_tx_t br2684_start_xmit(struct sk_buff *skb,
|
|||
|
||||
bh_lock_sock(sk_atm(atmvcc));
|
||||
|
||||
if (test_bit(ATM_VF_RELEASED, &atmvcc->flags) ||
|
||||
test_bit(ATM_VF_CLOSE, &atmvcc->flags) ||
|
||||
if (test_bit(ATM_VF_CLOSE, &atmvcc->flags) ||
|
||||
!test_bit(ATM_VF_READY, &atmvcc->flags)) {
|
||||
dev->stats.tx_dropped++;
|
||||
dev_kfree_skb(skb);
|
||||
|
|
|
|||
|
|
@ -30,8 +30,6 @@
|
|||
#include "resources.h" /* atm_find_dev */
|
||||
#include "common.h" /* prototypes */
|
||||
#include "protocols.h" /* atm_init_<transport> */
|
||||
#include "addr.h" /* address registry */
|
||||
#include "signaling.h" /* for WAITING and sigd_attach */
|
||||
|
||||
struct hlist_head vcc_hash[VCC_HTABLE_SIZE];
|
||||
EXPORT_SYMBOL(vcc_hash);
|
||||
|
|
@ -155,15 +153,12 @@ int vcc_create(struct net *net, struct socket *sock, int protocol, int family, i
|
|||
|
||||
vcc = atm_sk(sk);
|
||||
vcc->dev = NULL;
|
||||
memset(&vcc->local, 0, sizeof(struct sockaddr_atmsvc));
|
||||
memset(&vcc->remote, 0, sizeof(struct sockaddr_atmsvc));
|
||||
vcc->qos.txtp.max_sdu = 1 << 16; /* for meta VCs */
|
||||
refcount_set(&sk->sk_wmem_alloc, SK_WMEM_ALLOC_BIAS);
|
||||
atomic_set(&sk->sk_rmem_alloc, 0);
|
||||
vcc->push = NULL;
|
||||
vcc->pop = NULL;
|
||||
vcc->owner = NULL;
|
||||
vcc->push_oam = NULL;
|
||||
vcc->release_cb = NULL;
|
||||
vcc->vpi = vcc->vci = 0; /* no VCI/VPI yet */
|
||||
vcc->atm_options = vcc->aal_options = 0;
|
||||
|
|
@ -218,7 +213,6 @@ void vcc_release_async(struct atm_vcc *vcc, int reply)
|
|||
set_bit(ATM_VF_CLOSE, &vcc->flags);
|
||||
sk->sk_shutdown |= RCV_SHUTDOWN;
|
||||
sk->sk_err = -reply;
|
||||
clear_bit(ATM_VF_WAITING, &vcc->flags);
|
||||
sk->sk_state_change(sk);
|
||||
}
|
||||
EXPORT_SYMBOL(vcc_release_async);
|
||||
|
|
@ -293,9 +287,6 @@ static int adjust_tp(struct atm_trafprm *tp, unsigned char aal)
|
|||
case ATM_AAL0:
|
||||
max_sdu = ATM_CELL_SIZE-1;
|
||||
break;
|
||||
case ATM_AAL34:
|
||||
max_sdu = ATM_MAX_AAL34_PDU;
|
||||
break;
|
||||
default:
|
||||
pr_warn("AAL problems ... (%d)\n", aal);
|
||||
fallthrough;
|
||||
|
|
@ -411,10 +402,6 @@ static int __vcc_connect(struct atm_vcc *vcc, struct atm_dev *dev, short vpi,
|
|||
error = atm_init_aal0(vcc);
|
||||
vcc->stats = &dev->stats.aal0;
|
||||
break;
|
||||
case ATM_AAL34:
|
||||
error = atm_init_aal34(vcc);
|
||||
vcc->stats = &dev->stats.aal34;
|
||||
break;
|
||||
case ATM_NO_AAL:
|
||||
/* ATM_AAL5 is also used in the "0 for default" case */
|
||||
vcc->qos.aal = ATM_AAL5;
|
||||
|
|
@ -536,8 +523,7 @@ int vcc_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
|
|||
return -EOPNOTSUPP;
|
||||
|
||||
vcc = ATM_SD(sock);
|
||||
if (test_bit(ATM_VF_RELEASED, &vcc->flags) ||
|
||||
test_bit(ATM_VF_CLOSE, &vcc->flags) ||
|
||||
if (test_bit(ATM_VF_CLOSE, &vcc->flags) ||
|
||||
!test_bit(ATM_VF_READY, &vcc->flags))
|
||||
return 0;
|
||||
|
||||
|
|
@ -584,8 +570,7 @@ int vcc_sendmsg(struct socket *sock, struct msghdr *m, size_t size)
|
|||
goto out;
|
||||
}
|
||||
vcc = ATM_SD(sock);
|
||||
if (test_bit(ATM_VF_RELEASED, &vcc->flags) ||
|
||||
test_bit(ATM_VF_CLOSE, &vcc->flags) ||
|
||||
if (test_bit(ATM_VF_CLOSE, &vcc->flags) ||
|
||||
!test_bit(ATM_VF_READY, &vcc->flags)) {
|
||||
error = -EPIPE;
|
||||
send_sig(SIGPIPE, current, 0);
|
||||
|
|
@ -613,8 +598,7 @@ int vcc_sendmsg(struct socket *sock, struct msghdr *m, size_t size)
|
|||
error = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
if (test_bit(ATM_VF_RELEASED, &vcc->flags) ||
|
||||
test_bit(ATM_VF_CLOSE, &vcc->flags) ||
|
||||
if (test_bit(ATM_VF_CLOSE, &vcc->flags) ||
|
||||
!test_bit(ATM_VF_READY, &vcc->flags)) {
|
||||
error = -EPIPE;
|
||||
send_sig(SIGPIPE, current, 0);
|
||||
|
|
@ -642,12 +626,6 @@ int vcc_sendmsg(struct socket *sock, struct msghdr *m, size_t size)
|
|||
if (eff != size)
|
||||
memset(skb->data + size, 0, eff-size);
|
||||
|
||||
if (vcc->dev->ops->pre_send) {
|
||||
error = vcc->dev->ops->pre_send(vcc, skb);
|
||||
if (error)
|
||||
goto free_skb;
|
||||
}
|
||||
|
||||
error = vcc->dev->ops->send(vcc, skb);
|
||||
error = error ? error : size;
|
||||
out:
|
||||
|
|
@ -674,8 +652,7 @@ __poll_t vcc_poll(struct file *file, struct socket *sock, poll_table *wait)
|
|||
if (sk->sk_err)
|
||||
mask = EPOLLERR;
|
||||
|
||||
if (test_bit(ATM_VF_RELEASED, &vcc->flags) ||
|
||||
test_bit(ATM_VF_CLOSE, &vcc->flags))
|
||||
if (test_bit(ATM_VF_CLOSE, &vcc->flags))
|
||||
mask |= EPOLLHUP;
|
||||
|
||||
/* readable? */
|
||||
|
|
@ -683,10 +660,6 @@ __poll_t vcc_poll(struct file *file, struct socket *sock, poll_table *wait)
|
|||
mask |= EPOLLIN | EPOLLRDNORM;
|
||||
|
||||
/* writable? */
|
||||
if (sock->state == SS_CONNECTING &&
|
||||
test_bit(ATM_VF_WAITING, &vcc->flags))
|
||||
return mask;
|
||||
|
||||
if (vcc->qos.txtp.traffic_class != ATM_NONE &&
|
||||
vcc_writable(sk))
|
||||
mask |= EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND;
|
||||
|
|
@ -694,30 +667,6 @@ __poll_t vcc_poll(struct file *file, struct socket *sock, poll_table *wait)
|
|||
return mask;
|
||||
}
|
||||
|
||||
static int atm_change_qos(struct atm_vcc *vcc, struct atm_qos *qos)
|
||||
{
|
||||
int error;
|
||||
|
||||
/*
|
||||
* Don't let the QoS change the already connected AAL type nor the
|
||||
* traffic class.
|
||||
*/
|
||||
if (qos->aal != vcc->qos.aal ||
|
||||
qos->rxtp.traffic_class != vcc->qos.rxtp.traffic_class ||
|
||||
qos->txtp.traffic_class != vcc->qos.txtp.traffic_class)
|
||||
return -EINVAL;
|
||||
error = adjust_tp(&qos->txtp, qos->aal);
|
||||
if (!error)
|
||||
error = adjust_tp(&qos->rxtp, qos->aal);
|
||||
if (error)
|
||||
return error;
|
||||
if (!vcc->dev->ops->change_qos)
|
||||
return -EOPNOTSUPP;
|
||||
if (sk_atm(vcc)->sk_family == AF_ATMPVC)
|
||||
return vcc->dev->ops->change_qos(vcc, qos, ATM_MF_SET);
|
||||
return svc_change_qos(vcc, qos);
|
||||
}
|
||||
|
||||
static int check_tp(const struct atm_trafprm *tp)
|
||||
{
|
||||
/* @@@ Should be merged with adjust_tp */
|
||||
|
|
@ -776,8 +725,9 @@ int vcc_setsockopt(struct socket *sock, int level, int optname,
|
|||
error = check_qos(&qos);
|
||||
if (error)
|
||||
return error;
|
||||
/* QoS cannot be renegotiated on an already connected VCC. */
|
||||
if (sock->state == SS_CONNECTED)
|
||||
return atm_change_qos(vcc, &qos);
|
||||
return -EOPNOTSUPP;
|
||||
if (sock->state != SS_UNCONNECTED)
|
||||
return -EBADFD;
|
||||
vcc->qos = qos;
|
||||
|
|
@ -863,15 +813,10 @@ static int __init atm_init(void)
|
|||
pr_err("atmpvc_init() failed with %d\n", error);
|
||||
goto out_unregister_vcc_proto;
|
||||
}
|
||||
error = atmsvc_init();
|
||||
if (error < 0) {
|
||||
pr_err("atmsvc_init() failed with %d\n", error);
|
||||
goto out_atmpvc_exit;
|
||||
}
|
||||
error = atm_proc_init();
|
||||
if (error < 0) {
|
||||
pr_err("atm_proc_init() failed with %d\n", error);
|
||||
goto out_atmsvc_exit;
|
||||
goto out_atmpvc_exit;
|
||||
}
|
||||
error = atm_sysfs_init();
|
||||
if (error < 0) {
|
||||
|
|
@ -882,8 +827,6 @@ static int __init atm_init(void)
|
|||
return error;
|
||||
out_atmproc_exit:
|
||||
atm_proc_exit();
|
||||
out_atmsvc_exit:
|
||||
atmsvc_exit();
|
||||
out_atmpvc_exit:
|
||||
atmpvc_exit();
|
||||
out_unregister_vcc_proto:
|
||||
|
|
@ -895,7 +838,6 @@ static void __exit atm_exit(void)
|
|||
{
|
||||
atm_proc_exit();
|
||||
atm_sysfs_exit();
|
||||
atmsvc_exit();
|
||||
atmpvc_exit();
|
||||
proto_unregister(&vcc_proto);
|
||||
}
|
||||
|
|
@ -907,4 +849,3 @@ module_exit(atm_exit);
|
|||
MODULE_DESCRIPTION("Asynchronous Transfer Mode (ATM) networking core");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS_NETPROTO(PF_ATMPVC);
|
||||
MODULE_ALIAS_NETPROTO(PF_ATMSVC);
|
||||
|
|
|
|||
|
|
@ -28,8 +28,6 @@ void vcc_process_recv_queue(struct atm_vcc *vcc);
|
|||
|
||||
int atmpvc_init(void);
|
||||
void atmpvc_exit(void);
|
||||
int atmsvc_init(void);
|
||||
void atmsvc_exit(void);
|
||||
int atm_sysfs_init(void);
|
||||
void atm_sysfs_exit(void);
|
||||
|
||||
|
|
@ -48,9 +46,6 @@ static inline void atm_proc_exit(void)
|
|||
}
|
||||
#endif /* CONFIG_PROC_FS */
|
||||
|
||||
/* SVC */
|
||||
int svc_change_qos(struct atm_vcc *vcc,struct atm_qos *qos);
|
||||
|
||||
void atm_dev_release_vccs(struct atm_dev *dev);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -11,16 +11,12 @@
|
|||
#include <linux/net.h> /* struct socket, struct proto_ops */
|
||||
#include <linux/atm.h> /* ATM stuff */
|
||||
#include <linux/atmdev.h>
|
||||
#include <linux/atmarp.h> /* manifest constants */
|
||||
#include <linux/capability.h>
|
||||
#include <linux/sonet.h> /* for ioctls */
|
||||
#include <linux/atmsvc.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <asm/ioctls.h>
|
||||
#include <net/compat.h>
|
||||
|
||||
#include "resources.h"
|
||||
#include "signaling.h" /* for WAITING and sigd_attach */
|
||||
#include "common.h"
|
||||
|
||||
|
||||
|
|
@ -87,36 +83,6 @@ static int do_vcc_ioctl(struct socket *sock, unsigned int cmd,
|
|||
current->comm, task_pid_nr(current));
|
||||
error = 0;
|
||||
goto done;
|
||||
case ATMSIGD_CTRL:
|
||||
if (!capable(CAP_NET_ADMIN)) {
|
||||
error = -EPERM;
|
||||
goto done;
|
||||
}
|
||||
/*
|
||||
* The user/kernel protocol for exchanging signalling
|
||||
* info uses kernel pointers as opaque references,
|
||||
* so the holder of the file descriptor can scribble
|
||||
* on the kernel... so we should make sure that we
|
||||
* have the same privileges that /proc/kcore needs
|
||||
*/
|
||||
if (!capable(CAP_SYS_RAWIO)) {
|
||||
error = -EPERM;
|
||||
goto done;
|
||||
}
|
||||
#ifdef CONFIG_COMPAT
|
||||
/* WTF? I don't even want to _think_ about making this
|
||||
work for 32-bit userspace. TBH I don't really want
|
||||
to think about it at all. dwmw2. */
|
||||
if (compat) {
|
||||
net_warn_ratelimited("32-bit task cannot be atmsigd\n");
|
||||
error = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
error = sigd_attach(vcc);
|
||||
if (!error)
|
||||
sock->state = SS_CONNECTED;
|
||||
goto done;
|
||||
case ATM_SETBACKEND:
|
||||
case ATM_NEWBACKENDIF:
|
||||
{
|
||||
|
|
@ -221,10 +187,6 @@ int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
|
|||
#define ATM_GETNAMES32 _IOW('a', ATMIOC_ITF+3, struct compat_atm_iobuf)
|
||||
#define ATM_GETTYPE32 _IOW('a', ATMIOC_ITF+4, struct compat_atmif_sioc)
|
||||
#define ATM_GETESI32 _IOW('a', ATMIOC_ITF+5, struct compat_atmif_sioc)
|
||||
#define ATM_GETADDR32 _IOW('a', ATMIOC_ITF+6, struct compat_atmif_sioc)
|
||||
#define ATM_RSTADDR32 _IOW('a', ATMIOC_ITF+7, struct compat_atmif_sioc)
|
||||
#define ATM_ADDADDR32 _IOW('a', ATMIOC_ITF+8, struct compat_atmif_sioc)
|
||||
#define ATM_DELADDR32 _IOW('a', ATMIOC_ITF+9, struct compat_atmif_sioc)
|
||||
#define ATM_GETCIRANGE32 _IOW('a', ATMIOC_ITF+10, struct compat_atmif_sioc)
|
||||
#define ATM_SETCIRANGE32 _IOW('a', ATMIOC_ITF+11, struct compat_atmif_sioc)
|
||||
#define ATM_SETESI32 _IOW('a', ATMIOC_ITF+12, struct compat_atmif_sioc)
|
||||
|
|
@ -243,10 +205,6 @@ static struct {
|
|||
{ ATM_GETNAMES32, ATM_GETNAMES },
|
||||
{ ATM_GETTYPE32, ATM_GETTYPE },
|
||||
{ ATM_GETESI32, ATM_GETESI },
|
||||
{ ATM_GETADDR32, ATM_GETADDR },
|
||||
{ ATM_RSTADDR32, ATM_RSTADDR },
|
||||
{ ATM_ADDADDR32, ATM_ADDADDR },
|
||||
{ ATM_DELADDR32, ATM_DELADDR },
|
||||
{ ATM_GETCIRANGE32, ATM_GETCIRANGE },
|
||||
{ ATM_SETCIRANGE32, ATM_SETCIRANGE },
|
||||
{ ATM_SETESI32, ATM_SETESI },
|
||||
|
|
@ -290,18 +248,6 @@ static int do_atm_ioctl(struct socket *sock, unsigned int cmd32,
|
|||
int i;
|
||||
unsigned int cmd = 0;
|
||||
|
||||
switch (cmd32) {
|
||||
case SONET_GETSTAT:
|
||||
case SONET_GETSTATZ:
|
||||
case SONET_GETDIAG:
|
||||
case SONET_SETDIAG:
|
||||
case SONET_CLRDIAG:
|
||||
case SONET_SETFRAMING:
|
||||
case SONET_GETFRAMING:
|
||||
case SONET_GETFRSENSE:
|
||||
return do_atmif_sioc(sock, cmd32, arg);
|
||||
}
|
||||
|
||||
for (i = 0; i < NR_ATM_IOCTL; i++) {
|
||||
if (cmd32 == atm_ioctl_map[i].cmd32) {
|
||||
cmd = atm_ioctl_map[i].cmd;
|
||||
|
|
@ -318,10 +264,6 @@ static int do_atm_ioctl(struct socket *sock, unsigned int cmd32,
|
|||
case ATM_GETLINKRATE:
|
||||
case ATM_GETTYPE:
|
||||
case ATM_GETESI:
|
||||
case ATM_GETADDR:
|
||||
case ATM_RSTADDR:
|
||||
case ATM_ADDADDR:
|
||||
case ATM_DELADDR:
|
||||
case ATM_GETCIRANGE:
|
||||
case ATM_SETCIRANGE:
|
||||
case ATM_SETESI:
|
||||
|
|
|
|||
|
|
@ -308,8 +308,7 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
|
|||
test_and_set_bit(BLOCKED, &pvcc->blocked);
|
||||
goto nospace;
|
||||
}
|
||||
if (test_bit(ATM_VF_RELEASED, &vcc->flags) ||
|
||||
test_bit(ATM_VF_CLOSE, &vcc->flags) ||
|
||||
if (test_bit(ATM_VF_CLOSE, &vcc->flags) ||
|
||||
!test_bit(ATM_VF_READY, &vcc->flags)) {
|
||||
bh_unlock_sock(sk_atm(vcc));
|
||||
kfree_skb(skb);
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@
|
|||
#include <linux/atomic.h>
|
||||
#include "resources.h"
|
||||
#include "common.h" /* atm_proc_init prototype */
|
||||
#include "signaling.h" /* to get sigd - ugly too */
|
||||
|
||||
static ssize_t proc_dev_atm_read(struct file *file, char __user *buf,
|
||||
size_t count, loff_t *pos);
|
||||
|
|
@ -156,13 +155,6 @@ static void pvc_info(struct seq_file *seq, struct atm_vcc *vcc)
|
|||
seq_putc(seq, '\n');
|
||||
}
|
||||
|
||||
static const char *vcc_state(struct atm_vcc *vcc)
|
||||
{
|
||||
static const char *const map[] = { ATM_VS2TXT_MAP };
|
||||
|
||||
return map[ATM_VF2VS(vcc->flags)];
|
||||
}
|
||||
|
||||
static void vcc_info(struct seq_file *seq, struct atm_vcc *vcc)
|
||||
{
|
||||
struct sock *sk = sk_atm(vcc);
|
||||
|
|
@ -177,9 +169,6 @@ static void vcc_info(struct seq_file *seq, struct atm_vcc *vcc)
|
|||
case AF_ATMPVC:
|
||||
seq_printf(seq, "PVC");
|
||||
break;
|
||||
case AF_ATMSVC:
|
||||
seq_printf(seq, "SVC");
|
||||
break;
|
||||
default:
|
||||
seq_printf(seq, "%3d", sk->sk_family);
|
||||
}
|
||||
|
|
@ -190,26 +179,6 @@ static void vcc_info(struct seq_file *seq, struct atm_vcc *vcc)
|
|||
refcount_read(&sk->sk_refcnt));
|
||||
}
|
||||
|
||||
static void svc_info(struct seq_file *seq, struct atm_vcc *vcc)
|
||||
{
|
||||
if (!vcc->dev)
|
||||
seq_printf(seq, sizeof(void *) == 4 ?
|
||||
"N/A@%pK%10s" : "N/A@%pK%2s", vcc, "");
|
||||
else
|
||||
seq_printf(seq, "%3d %3d %5d ",
|
||||
vcc->dev->number, vcc->vpi, vcc->vci);
|
||||
seq_printf(seq, "%-10s ", vcc_state(vcc));
|
||||
seq_printf(seq, "%s%s", vcc->remote.sas_addr.pub,
|
||||
*vcc->remote.sas_addr.pub && *vcc->remote.sas_addr.prv ? "+" : "");
|
||||
if (*vcc->remote.sas_addr.prv) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ATM_ESA_LEN; i++)
|
||||
seq_printf(seq, "%02x", vcc->remote.sas_addr.prv[i]);
|
||||
}
|
||||
seq_putc(seq, '\n');
|
||||
}
|
||||
|
||||
static int atm_dev_seq_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
static char atm_dev_banner[] =
|
||||
|
|
@ -278,29 +247,6 @@ static const struct seq_operations vcc_seq_ops = {
|
|||
.show = vcc_seq_show,
|
||||
};
|
||||
|
||||
static int svc_seq_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
static const char atm_svc_banner[] =
|
||||
"Itf VPI VCI State Remote\n";
|
||||
|
||||
if (v == SEQ_START_TOKEN)
|
||||
seq_puts(seq, atm_svc_banner);
|
||||
else {
|
||||
struct vcc_state *state = seq->private;
|
||||
struct atm_vcc *vcc = atm_sk(state->sk);
|
||||
|
||||
svc_info(seq, vcc);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct seq_operations svc_seq_ops = {
|
||||
.start = vcc_seq_start,
|
||||
.next = vcc_seq_next,
|
||||
.stop = vcc_seq_stop,
|
||||
.show = svc_seq_show,
|
||||
};
|
||||
|
||||
static ssize_t proc_dev_atm_read(struct file *file, char __user *buf,
|
||||
size_t count, loff_t *pos)
|
||||
{
|
||||
|
|
@ -376,8 +322,6 @@ int __init atm_proc_init(void)
|
|||
proc_create_seq("devices", 0444, atm_proc_root, &atm_dev_seq_ops);
|
||||
proc_create_seq_private("pvc", 0444, atm_proc_root, &pvc_seq_ops,
|
||||
sizeof(struct vcc_state), (void *)(uintptr_t)PF_ATMPVC);
|
||||
proc_create_seq_private("svc", 0444, atm_proc_root, &svc_seq_ops,
|
||||
sizeof(struct vcc_state), (void *)(uintptr_t)PF_ATMSVC);
|
||||
proc_create_seq_private("vc", 0444, atm_proc_root, &vcc_seq_ops,
|
||||
sizeof(struct vcc_state), NULL);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
#define NET_ATM_PROTOCOLS_H
|
||||
|
||||
int atm_init_aal0(struct atm_vcc *vcc); /* "raw" AAL0 */
|
||||
int atm_init_aal34(struct atm_vcc *vcc);/* "raw" AAL3/4 transport */
|
||||
int atm_init_aal5(struct atm_vcc *vcc); /* "raw" AAL5 transport */
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -54,8 +54,6 @@ static int atm_send_aal0(struct atm_vcc *vcc, struct sk_buff *skb)
|
|||
kfree_skb(skb);
|
||||
return -EADDRNOTAVAIL;
|
||||
}
|
||||
if (vcc->dev->ops->send_bh)
|
||||
return vcc->dev->ops->send_bh(vcc, skb);
|
||||
return vcc->dev->ops->send(vcc, skb);
|
||||
}
|
||||
|
||||
|
|
@ -63,32 +61,15 @@ int atm_init_aal0(struct atm_vcc *vcc)
|
|||
{
|
||||
vcc->push = atm_push_raw;
|
||||
vcc->pop = atm_pop_raw;
|
||||
vcc->push_oam = NULL;
|
||||
vcc->send = atm_send_aal0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int atm_init_aal34(struct atm_vcc *vcc)
|
||||
{
|
||||
vcc->push = atm_push_raw;
|
||||
vcc->pop = atm_pop_raw;
|
||||
vcc->push_oam = NULL;
|
||||
if (vcc->dev->ops->send_bh)
|
||||
vcc->send = vcc->dev->ops->send_bh;
|
||||
else
|
||||
vcc->send = vcc->dev->ops->send;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int atm_init_aal5(struct atm_vcc *vcc)
|
||||
{
|
||||
vcc->push = atm_push_raw;
|
||||
vcc->pop = atm_pop_raw;
|
||||
vcc->push_oam = NULL;
|
||||
if (vcc->dev->ops->send_bh)
|
||||
vcc->send = vcc->dev->ops->send_bh;
|
||||
else
|
||||
vcc->send = vcc->dev->ops->send;
|
||||
vcc->send = vcc->dev->ops->send;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(atm_init_aal5);
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
#include <linux/ctype.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/atmdev.h>
|
||||
#include <linux/sonet.h>
|
||||
#include <linux/kernel.h> /* for barrier */
|
||||
#include <linux/module.h>
|
||||
#include <linux/bitops.h>
|
||||
|
|
@ -26,7 +25,6 @@
|
|||
|
||||
#include "common.h"
|
||||
#include "resources.h"
|
||||
#include "addr.h"
|
||||
|
||||
|
||||
LIST_HEAD(atm_devs);
|
||||
|
|
@ -42,9 +40,6 @@ static struct atm_dev *__alloc_atm_dev(const char *type)
|
|||
dev->type = type;
|
||||
dev->signal = ATM_PHY_SIG_UNKNOWN;
|
||||
dev->link_rate = ATM_OC3_PCR;
|
||||
spin_lock_init(&dev->lock);
|
||||
INIT_LIST_HEAD(&dev->local);
|
||||
INIT_LIST_HEAD(&dev->lecs);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
|
@ -228,11 +223,8 @@ int atm_getnames(void __user *buf, int __user *iobuf_len)
|
|||
int atm_dev_ioctl(unsigned int cmd, void __user *buf, int __user *sioc_len,
|
||||
int number, int compat)
|
||||
{
|
||||
int error, len, size = 0;
|
||||
struct atm_dev *dev;
|
||||
|
||||
if (get_user(len, sioc_len))
|
||||
return -EFAULT;
|
||||
int error, size = 0;
|
||||
|
||||
dev = try_then_request_module(atm_dev_lookup(number), "atm-device-%d",
|
||||
number);
|
||||
|
|
@ -307,51 +299,6 @@ int atm_dev_ioctl(unsigned int cmd, void __user *buf, int __user *sioc_len,
|
|||
goto done;
|
||||
}
|
||||
break;
|
||||
case ATM_RSTADDR:
|
||||
if (!capable(CAP_NET_ADMIN)) {
|
||||
error = -EPERM;
|
||||
goto done;
|
||||
}
|
||||
atm_reset_addr(dev, ATM_ADDR_LOCAL);
|
||||
break;
|
||||
case ATM_ADDADDR:
|
||||
case ATM_DELADDR:
|
||||
case ATM_ADDLECSADDR:
|
||||
case ATM_DELLECSADDR:
|
||||
{
|
||||
struct sockaddr_atmsvc addr;
|
||||
|
||||
if (!capable(CAP_NET_ADMIN)) {
|
||||
error = -EPERM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (copy_from_user(&addr, buf, sizeof(addr))) {
|
||||
error = -EFAULT;
|
||||
goto done;
|
||||
}
|
||||
if (cmd == ATM_ADDADDR || cmd == ATM_ADDLECSADDR)
|
||||
error = atm_add_addr(dev, &addr,
|
||||
(cmd == ATM_ADDADDR ?
|
||||
ATM_ADDR_LOCAL : ATM_ADDR_LECS));
|
||||
else
|
||||
error = atm_del_addr(dev, &addr,
|
||||
(cmd == ATM_DELADDR ?
|
||||
ATM_ADDR_LOCAL : ATM_ADDR_LECS));
|
||||
goto done;
|
||||
}
|
||||
case ATM_GETADDR:
|
||||
case ATM_GETLECSADDR:
|
||||
error = atm_get_addr(dev, buf, len,
|
||||
(cmd == ATM_GETADDR ?
|
||||
ATM_ADDR_LOCAL : ATM_ADDR_LECS));
|
||||
if (error < 0)
|
||||
goto done;
|
||||
size = error;
|
||||
/* may return 0, but later on size == 0 means "don't
|
||||
write the length" */
|
||||
error = put_user(size, sioc_len) ? -EFAULT : 0;
|
||||
goto done;
|
||||
case ATM_SETLOOP:
|
||||
if (__ATM_LM_XTRMT((int) (unsigned long) buf) &&
|
||||
__ATM_LM_XTLOC((int) (unsigned long) buf) >
|
||||
|
|
@ -361,10 +308,6 @@ int atm_dev_ioctl(unsigned int cmd, void __user *buf, int __user *sioc_len,
|
|||
}
|
||||
fallthrough;
|
||||
case ATM_SETCIRANGE:
|
||||
case SONET_GETSTATZ:
|
||||
case SONET_SETDIAG:
|
||||
case SONET_CLRDIAG:
|
||||
case SONET_SETFRAMING:
|
||||
if (!capable(CAP_NET_ADMIN)) {
|
||||
error = -EPERM;
|
||||
goto done;
|
||||
|
|
|
|||
|
|
@ -1,297 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* net/atm/signaling.c - ATM signaling */
|
||||
|
||||
/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
|
||||
|
||||
#include <linux/errno.h> /* error codes */
|
||||
#include <linux/kernel.h> /* printk */
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/sched.h> /* jiffies and HZ */
|
||||
#include <linux/atm.h> /* ATM stuff */
|
||||
#include <linux/atmsap.h>
|
||||
#include <linux/atmsvc.h>
|
||||
#include <linux/atmdev.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "resources.h"
|
||||
#include "signaling.h"
|
||||
|
||||
struct atm_vcc *sigd = NULL;
|
||||
|
||||
/*
|
||||
* find_get_vcc - validate and get a reference to a vcc pointer
|
||||
* @vcc: the vcc pointer to validate
|
||||
*
|
||||
* This function validates that @vcc points to a registered VCC in vcc_hash.
|
||||
* If found, it increments the socket reference count and returns the vcc.
|
||||
* The caller must call sock_put(sk_atm(vcc)) when done.
|
||||
*
|
||||
* Returns the vcc pointer if valid, NULL otherwise.
|
||||
*/
|
||||
static struct atm_vcc *find_get_vcc(struct atm_vcc *vcc)
|
||||
{
|
||||
int i;
|
||||
|
||||
read_lock(&vcc_sklist_lock);
|
||||
for (i = 0; i < VCC_HTABLE_SIZE; i++) {
|
||||
struct sock *s;
|
||||
|
||||
sk_for_each(s, &vcc_hash[i]) {
|
||||
if (atm_sk(s) == vcc) {
|
||||
sock_hold(s);
|
||||
read_unlock(&vcc_sklist_lock);
|
||||
return vcc;
|
||||
}
|
||||
}
|
||||
}
|
||||
read_unlock(&vcc_sklist_lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void sigd_put_skb(struct sk_buff *skb)
|
||||
{
|
||||
if (!sigd) {
|
||||
pr_debug("atmsvc: no signaling daemon\n");
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
atm_force_charge(sigd, skb->truesize);
|
||||
skb_queue_tail(&sk_atm(sigd)->sk_receive_queue, skb);
|
||||
sk_atm(sigd)->sk_data_ready(sk_atm(sigd));
|
||||
}
|
||||
|
||||
static void modify_qos(struct atm_vcc *vcc, struct atmsvc_msg *msg)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (test_bit(ATM_VF_RELEASED, &vcc->flags) ||
|
||||
!test_bit(ATM_VF_READY, &vcc->flags))
|
||||
return;
|
||||
msg->type = as_error;
|
||||
if (!vcc->dev->ops->change_qos)
|
||||
msg->reply = -EOPNOTSUPP;
|
||||
else {
|
||||
/* should lock VCC */
|
||||
msg->reply = vcc->dev->ops->change_qos(vcc, &msg->qos,
|
||||
msg->reply);
|
||||
if (!msg->reply)
|
||||
msg->type = as_okay;
|
||||
}
|
||||
/*
|
||||
* Should probably just turn around the old skb. But then, the buffer
|
||||
* space accounting needs to follow the change too. Maybe later.
|
||||
*/
|
||||
while (!(skb = alloc_skb(sizeof(struct atmsvc_msg), GFP_KERNEL)))
|
||||
schedule();
|
||||
*(struct atmsvc_msg *)skb_put(skb, sizeof(struct atmsvc_msg)) = *msg;
|
||||
sigd_put_skb(skb);
|
||||
}
|
||||
|
||||
static int sigd_send(struct atm_vcc *vcc, struct sk_buff *skb)
|
||||
{
|
||||
struct atmsvc_msg *msg;
|
||||
struct atm_vcc *session_vcc;
|
||||
struct sock *sk;
|
||||
|
||||
msg = (struct atmsvc_msg *) skb->data;
|
||||
WARN_ON(refcount_sub_and_test(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc));
|
||||
|
||||
vcc = find_get_vcc(*(struct atm_vcc **)&msg->vcc);
|
||||
if (!vcc) {
|
||||
pr_debug("invalid vcc pointer in msg\n");
|
||||
dev_kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pr_debug("%d (0x%lx)\n", (int)msg->type, (unsigned long)vcc);
|
||||
sk = sk_atm(vcc);
|
||||
|
||||
switch (msg->type) {
|
||||
case as_okay:
|
||||
sk->sk_err = -msg->reply;
|
||||
clear_bit(ATM_VF_WAITING, &vcc->flags);
|
||||
if (!*vcc->local.sas_addr.prv && !*vcc->local.sas_addr.pub) {
|
||||
vcc->local.sas_family = AF_ATMSVC;
|
||||
memcpy(vcc->local.sas_addr.prv,
|
||||
msg->local.sas_addr.prv, ATM_ESA_LEN);
|
||||
memcpy(vcc->local.sas_addr.pub,
|
||||
msg->local.sas_addr.pub, ATM_E164_LEN + 1);
|
||||
}
|
||||
session_vcc = vcc->session ? vcc->session : vcc;
|
||||
if (session_vcc->vpi || session_vcc->vci)
|
||||
break;
|
||||
session_vcc->itf = msg->pvc.sap_addr.itf;
|
||||
session_vcc->vpi = msg->pvc.sap_addr.vpi;
|
||||
session_vcc->vci = msg->pvc.sap_addr.vci;
|
||||
if (session_vcc->vpi || session_vcc->vci)
|
||||
session_vcc->qos = msg->qos;
|
||||
break;
|
||||
case as_error:
|
||||
clear_bit(ATM_VF_REGIS, &vcc->flags);
|
||||
clear_bit(ATM_VF_READY, &vcc->flags);
|
||||
sk->sk_err = -msg->reply;
|
||||
clear_bit(ATM_VF_WAITING, &vcc->flags);
|
||||
break;
|
||||
case as_indicate:
|
||||
/* Release the reference from msg->vcc, we'll use msg->listen_vcc instead */
|
||||
sock_put(sk);
|
||||
|
||||
vcc = find_get_vcc(*(struct atm_vcc **)&msg->listen_vcc);
|
||||
if (!vcc) {
|
||||
pr_debug("invalid listen_vcc pointer in msg\n");
|
||||
dev_kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sk = sk_atm(vcc);
|
||||
pr_debug("as_indicate!!!\n");
|
||||
lock_sock(sk);
|
||||
if (sk_acceptq_is_full(sk)) {
|
||||
sigd_enq(NULL, as_reject, vcc, NULL, NULL);
|
||||
dev_kfree_skb(skb);
|
||||
goto as_indicate_complete;
|
||||
}
|
||||
sk_acceptq_added(sk);
|
||||
skb_queue_tail(&sk->sk_receive_queue, skb);
|
||||
pr_debug("waking sk_sleep(sk) 0x%p\n", sk_sleep(sk));
|
||||
sk->sk_state_change(sk);
|
||||
as_indicate_complete:
|
||||
release_sock(sk);
|
||||
/* Paired with find_get_vcc(msg->listen_vcc) above */
|
||||
sock_put(sk);
|
||||
return 0;
|
||||
case as_close:
|
||||
set_bit(ATM_VF_RELEASED, &vcc->flags);
|
||||
vcc_release_async(vcc, msg->reply);
|
||||
goto out;
|
||||
case as_modify:
|
||||
modify_qos(vcc, msg);
|
||||
break;
|
||||
case as_addparty:
|
||||
case as_dropparty:
|
||||
WRITE_ONCE(sk->sk_err_soft, -msg->reply);
|
||||
/* < 0 failure, otherwise ep_ref */
|
||||
clear_bit(ATM_VF_WAITING, &vcc->flags);
|
||||
break;
|
||||
default:
|
||||
pr_alert("bad message type %d\n", (int)msg->type);
|
||||
dev_kfree_skb(skb);
|
||||
/* Paired with find_get_vcc(msg->vcc) above */
|
||||
sock_put(sk);
|
||||
return -EINVAL;
|
||||
}
|
||||
sk->sk_state_change(sk);
|
||||
out:
|
||||
dev_kfree_skb(skb);
|
||||
/* Paired with find_get_vcc(msg->vcc) above */
|
||||
sock_put(sk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sigd_enq2(struct atm_vcc *vcc, enum atmsvc_msg_type type,
|
||||
struct atm_vcc *listen_vcc, const struct sockaddr_atmpvc *pvc,
|
||||
const struct sockaddr_atmsvc *svc, const struct atm_qos *qos,
|
||||
int reply)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct atmsvc_msg *msg;
|
||||
static unsigned int session = 0;
|
||||
|
||||
pr_debug("%d (0x%p)\n", (int)type, vcc);
|
||||
while (!(skb = alloc_skb(sizeof(struct atmsvc_msg), GFP_KERNEL)))
|
||||
schedule();
|
||||
msg = skb_put_zero(skb, sizeof(struct atmsvc_msg));
|
||||
msg->type = type;
|
||||
*(struct atm_vcc **) &msg->vcc = vcc;
|
||||
*(struct atm_vcc **) &msg->listen_vcc = listen_vcc;
|
||||
msg->reply = reply;
|
||||
if (qos)
|
||||
msg->qos = *qos;
|
||||
if (vcc)
|
||||
msg->sap = vcc->sap;
|
||||
if (svc)
|
||||
msg->svc = *svc;
|
||||
if (vcc)
|
||||
msg->local = vcc->local;
|
||||
if (pvc)
|
||||
msg->pvc = *pvc;
|
||||
if (vcc) {
|
||||
if (type == as_connect && test_bit(ATM_VF_SESSION, &vcc->flags))
|
||||
msg->session = ++session;
|
||||
/* every new pmp connect gets the next session number */
|
||||
}
|
||||
sigd_put_skb(skb);
|
||||
if (vcc)
|
||||
set_bit(ATM_VF_REGIS, &vcc->flags);
|
||||
}
|
||||
|
||||
void sigd_enq(struct atm_vcc *vcc, enum atmsvc_msg_type type,
|
||||
struct atm_vcc *listen_vcc, const struct sockaddr_atmpvc *pvc,
|
||||
const struct sockaddr_atmsvc *svc)
|
||||
{
|
||||
sigd_enq2(vcc, type, listen_vcc, pvc, svc, vcc ? &vcc->qos : NULL, 0);
|
||||
/* other ISP applications may use "reply" */
|
||||
}
|
||||
|
||||
static void purge_vcc(struct atm_vcc *vcc)
|
||||
{
|
||||
if (sk_atm(vcc)->sk_family == PF_ATMSVC &&
|
||||
!test_bit(ATM_VF_META, &vcc->flags)) {
|
||||
set_bit(ATM_VF_RELEASED, &vcc->flags);
|
||||
clear_bit(ATM_VF_REGIS, &vcc->flags);
|
||||
vcc_release_async(vcc, -EUNATCH);
|
||||
}
|
||||
}
|
||||
|
||||
static void sigd_close(struct atm_vcc *vcc)
|
||||
{
|
||||
struct sock *s;
|
||||
int i;
|
||||
|
||||
pr_debug("\n");
|
||||
sigd = NULL;
|
||||
if (skb_peek(&sk_atm(vcc)->sk_receive_queue))
|
||||
pr_err("closing with requests pending\n");
|
||||
skb_queue_purge(&sk_atm(vcc)->sk_receive_queue);
|
||||
|
||||
read_lock(&vcc_sklist_lock);
|
||||
for (i = 0; i < VCC_HTABLE_SIZE; ++i) {
|
||||
struct hlist_head *head = &vcc_hash[i];
|
||||
|
||||
sk_for_each(s, head) {
|
||||
vcc = atm_sk(s);
|
||||
|
||||
purge_vcc(vcc);
|
||||
}
|
||||
}
|
||||
read_unlock(&vcc_sklist_lock);
|
||||
}
|
||||
|
||||
static const struct atmdev_ops sigd_dev_ops = {
|
||||
.close = sigd_close,
|
||||
.send = sigd_send
|
||||
};
|
||||
|
||||
static struct atm_dev sigd_dev = {
|
||||
.ops = &sigd_dev_ops,
|
||||
.type = "sig",
|
||||
.number = 999,
|
||||
.lock = __SPIN_LOCK_UNLOCKED(sigd_dev.lock)
|
||||
};
|
||||
|
||||
int sigd_attach(struct atm_vcc *vcc)
|
||||
{
|
||||
if (sigd)
|
||||
return -EADDRINUSE;
|
||||
pr_debug("\n");
|
||||
sigd = vcc;
|
||||
vcc->dev = &sigd_dev;
|
||||
vcc_insert_socket(sk_atm(vcc));
|
||||
set_bit(ATM_VF_META, &vcc->flags);
|
||||
set_bit(ATM_VF_READY, &vcc->flags);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* net/atm/signaling.h - ATM signaling */
|
||||
|
||||
/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
|
||||
|
||||
|
||||
#ifndef NET_ATM_SIGNALING_H
|
||||
#define NET_ATM_SIGNALING_H
|
||||
|
||||
#include <linux/atm.h>
|
||||
#include <linux/atmdev.h>
|
||||
#include <linux/atmsvc.h>
|
||||
|
||||
|
||||
extern struct atm_vcc *sigd; /* needed in svc_release */
|
||||
|
||||
|
||||
/*
|
||||
* sigd_enq is a wrapper for sigd_enq2, covering the more common cases, and
|
||||
* avoiding huge lists of null values.
|
||||
*/
|
||||
|
||||
void sigd_enq2(struct atm_vcc *vcc,enum atmsvc_msg_type type,
|
||||
struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc,
|
||||
const struct sockaddr_atmsvc *svc,const struct atm_qos *qos,int reply);
|
||||
void sigd_enq(struct atm_vcc *vcc,enum atmsvc_msg_type type,
|
||||
struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc,
|
||||
const struct sockaddr_atmsvc *svc);
|
||||
int sigd_attach(struct atm_vcc *vcc);
|
||||
|
||||
#endif
|
||||
695
net/atm/svc.c
695
net/atm/svc.c
|
|
@ -1,695 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* net/atm/svc.c - ATM SVC sockets */
|
||||
|
||||
/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
|
||||
|
||||
#include <linux/string.h>
|
||||
#include <linux/net.h> /* struct socket, struct proto_ops */
|
||||
#include <linux/errno.h> /* error codes */
|
||||
#include <linux/kernel.h> /* printk */
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/sched/signal.h>
|
||||
#include <linux/fcntl.h> /* O_NONBLOCK */
|
||||
#include <linux/init.h>
|
||||
#include <linux/atm.h> /* ATM stuff */
|
||||
#include <linux/atmsap.h>
|
||||
#include <linux/atmsvc.h>
|
||||
#include <linux/atmdev.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <net/sock.h> /* for sock_no_* */
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/uio.h>
|
||||
#include <linux/export.h>
|
||||
|
||||
#include "resources.h"
|
||||
#include "common.h" /* common for PVCs and SVCs */
|
||||
#include "signaling.h"
|
||||
#include "addr.h"
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
/* It actually takes struct sockaddr_atmsvc, not struct atm_iobuf */
|
||||
#define COMPAT_ATM_ADDPARTY _IOW('a', ATMIOC_SPECIAL + 4, struct compat_atm_iobuf)
|
||||
#endif
|
||||
|
||||
static int svc_create(struct net *net, struct socket *sock, int protocol,
|
||||
int kern);
|
||||
|
||||
/*
|
||||
* Note: since all this is still nicely synchronized with the signaling demon,
|
||||
* there's no need to protect sleep loops with clis. If signaling is
|
||||
* moved into the kernel, that would change.
|
||||
*/
|
||||
|
||||
|
||||
static int svc_shutdown(struct socket *sock, int how)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void svc_disconnect(struct atm_vcc *vcc)
|
||||
{
|
||||
DEFINE_WAIT(wait);
|
||||
struct sk_buff *skb;
|
||||
struct sock *sk = sk_atm(vcc);
|
||||
|
||||
pr_debug("%p\n", vcc);
|
||||
if (test_bit(ATM_VF_REGIS, &vcc->flags)) {
|
||||
sigd_enq(vcc, as_close, NULL, NULL, NULL);
|
||||
for (;;) {
|
||||
prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE);
|
||||
if (test_bit(ATM_VF_RELEASED, &vcc->flags) || !sigd)
|
||||
break;
|
||||
schedule();
|
||||
}
|
||||
finish_wait(sk_sleep(sk), &wait);
|
||||
}
|
||||
/* beware - socket is still in use by atmsigd until the last
|
||||
as_indicate has been answered */
|
||||
while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
|
||||
atm_return(vcc, skb->truesize);
|
||||
pr_debug("LISTEN REL\n");
|
||||
sigd_enq2(NULL, as_reject, vcc, NULL, NULL, &vcc->qos, 0);
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
clear_bit(ATM_VF_REGIS, &vcc->flags);
|
||||
/* ... may retry later */
|
||||
}
|
||||
|
||||
static int svc_release(struct socket *sock)
|
||||
{
|
||||
struct sock *sk = sock->sk;
|
||||
struct atm_vcc *vcc;
|
||||
|
||||
if (sk) {
|
||||
vcc = ATM_SD(sock);
|
||||
pr_debug("%p\n", vcc);
|
||||
clear_bit(ATM_VF_READY, &vcc->flags);
|
||||
/*
|
||||
* VCC pointer is used as a reference,
|
||||
* so we must not free it (thereby subjecting it to re-use)
|
||||
* before all pending connections are closed
|
||||
*/
|
||||
svc_disconnect(vcc);
|
||||
vcc_release(sock);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int svc_bind(struct socket *sock, struct sockaddr_unsized *sockaddr,
|
||||
int sockaddr_len)
|
||||
{
|
||||
DEFINE_WAIT(wait);
|
||||
struct sock *sk = sock->sk;
|
||||
struct sockaddr_atmsvc *addr;
|
||||
struct atm_vcc *vcc;
|
||||
int error;
|
||||
|
||||
if (sockaddr_len != sizeof(struct sockaddr_atmsvc))
|
||||
return -EINVAL;
|
||||
lock_sock(sk);
|
||||
if (sock->state == SS_CONNECTED) {
|
||||
error = -EISCONN;
|
||||
goto out;
|
||||
}
|
||||
if (sock->state != SS_UNCONNECTED) {
|
||||
error = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
vcc = ATM_SD(sock);
|
||||
addr = (struct sockaddr_atmsvc *) sockaddr;
|
||||
if (addr->sas_family != AF_ATMSVC) {
|
||||
error = -EAFNOSUPPORT;
|
||||
goto out;
|
||||
}
|
||||
clear_bit(ATM_VF_BOUND, &vcc->flags);
|
||||
/* failing rebind will kill old binding */
|
||||
/* @@@ check memory (de)allocation on rebind */
|
||||
if (!test_bit(ATM_VF_HASQOS, &vcc->flags)) {
|
||||
error = -EBADFD;
|
||||
goto out;
|
||||
}
|
||||
vcc->local = *addr;
|
||||
set_bit(ATM_VF_WAITING, &vcc->flags);
|
||||
sigd_enq(vcc, as_bind, NULL, NULL, &vcc->local);
|
||||
for (;;) {
|
||||
prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE);
|
||||
if (!test_bit(ATM_VF_WAITING, &vcc->flags) || !sigd)
|
||||
break;
|
||||
schedule();
|
||||
}
|
||||
finish_wait(sk_sleep(sk), &wait);
|
||||
clear_bit(ATM_VF_REGIS, &vcc->flags); /* doesn't count */
|
||||
if (!sigd) {
|
||||
error = -EUNATCH;
|
||||
goto out;
|
||||
}
|
||||
if (!sk->sk_err)
|
||||
set_bit(ATM_VF_BOUND, &vcc->flags);
|
||||
error = -sk->sk_err;
|
||||
out:
|
||||
release_sock(sk);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int svc_connect(struct socket *sock, struct sockaddr_unsized *sockaddr,
|
||||
int sockaddr_len, int flags)
|
||||
{
|
||||
DEFINE_WAIT(wait);
|
||||
struct sock *sk = sock->sk;
|
||||
struct sockaddr_atmsvc *addr;
|
||||
struct atm_vcc *vcc = ATM_SD(sock);
|
||||
int error;
|
||||
|
||||
pr_debug("%p\n", vcc);
|
||||
lock_sock(sk);
|
||||
if (sockaddr_len != sizeof(struct sockaddr_atmsvc)) {
|
||||
error = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (sock->state) {
|
||||
default:
|
||||
error = -EINVAL;
|
||||
goto out;
|
||||
case SS_CONNECTED:
|
||||
error = -EISCONN;
|
||||
goto out;
|
||||
case SS_CONNECTING:
|
||||
if (test_bit(ATM_VF_WAITING, &vcc->flags)) {
|
||||
error = -EALREADY;
|
||||
goto out;
|
||||
}
|
||||
sock->state = SS_UNCONNECTED;
|
||||
if (sk->sk_err) {
|
||||
error = -sk->sk_err;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
case SS_UNCONNECTED:
|
||||
addr = (struct sockaddr_atmsvc *) sockaddr;
|
||||
if (addr->sas_family != AF_ATMSVC) {
|
||||
error = -EAFNOSUPPORT;
|
||||
goto out;
|
||||
}
|
||||
if (!test_bit(ATM_VF_HASQOS, &vcc->flags)) {
|
||||
error = -EBADFD;
|
||||
goto out;
|
||||
}
|
||||
if (vcc->qos.txtp.traffic_class == ATM_ANYCLASS ||
|
||||
vcc->qos.rxtp.traffic_class == ATM_ANYCLASS) {
|
||||
error = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (!vcc->qos.txtp.traffic_class &&
|
||||
!vcc->qos.rxtp.traffic_class) {
|
||||
error = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
vcc->remote = *addr;
|
||||
set_bit(ATM_VF_WAITING, &vcc->flags);
|
||||
sigd_enq(vcc, as_connect, NULL, NULL, &vcc->remote);
|
||||
if (flags & O_NONBLOCK) {
|
||||
sock->state = SS_CONNECTING;
|
||||
error = -EINPROGRESS;
|
||||
goto out;
|
||||
}
|
||||
error = 0;
|
||||
prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
|
||||
while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) {
|
||||
schedule();
|
||||
if (!signal_pending(current)) {
|
||||
prepare_to_wait(sk_sleep(sk), &wait,
|
||||
TASK_INTERRUPTIBLE);
|
||||
continue;
|
||||
}
|
||||
pr_debug("*ABORT*\n");
|
||||
/*
|
||||
* This is tricky:
|
||||
* Kernel ---close--> Demon
|
||||
* Kernel <--close--- Demon
|
||||
* or
|
||||
* Kernel ---close--> Demon
|
||||
* Kernel <--error--- Demon
|
||||
* or
|
||||
* Kernel ---close--> Demon
|
||||
* Kernel <--okay---- Demon
|
||||
* Kernel <--close--- Demon
|
||||
*/
|
||||
sigd_enq(vcc, as_close, NULL, NULL, NULL);
|
||||
while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) {
|
||||
prepare_to_wait(sk_sleep(sk), &wait,
|
||||
TASK_INTERRUPTIBLE);
|
||||
schedule();
|
||||
}
|
||||
if (!sk->sk_err)
|
||||
while (!test_bit(ATM_VF_RELEASED, &vcc->flags) &&
|
||||
sigd) {
|
||||
prepare_to_wait(sk_sleep(sk), &wait,
|
||||
TASK_INTERRUPTIBLE);
|
||||
schedule();
|
||||
}
|
||||
clear_bit(ATM_VF_REGIS, &vcc->flags);
|
||||
clear_bit(ATM_VF_RELEASED, &vcc->flags);
|
||||
clear_bit(ATM_VF_CLOSE, &vcc->flags);
|
||||
/* we're gone now but may connect later */
|
||||
error = -EINTR;
|
||||
break;
|
||||
}
|
||||
finish_wait(sk_sleep(sk), &wait);
|
||||
if (error)
|
||||
goto out;
|
||||
if (!sigd) {
|
||||
error = -EUNATCH;
|
||||
goto out;
|
||||
}
|
||||
if (sk->sk_err) {
|
||||
error = -sk->sk_err;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
vcc->qos.txtp.max_pcr = SELECT_TOP_PCR(vcc->qos.txtp);
|
||||
vcc->qos.txtp.pcr = 0;
|
||||
vcc->qos.txtp.min_pcr = 0;
|
||||
|
||||
error = vcc_connect(sock, vcc->itf, vcc->vpi, vcc->vci);
|
||||
if (!error)
|
||||
sock->state = SS_CONNECTED;
|
||||
else
|
||||
(void)svc_disconnect(vcc);
|
||||
out:
|
||||
release_sock(sk);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int svc_listen(struct socket *sock, int backlog)
|
||||
{
|
||||
DEFINE_WAIT(wait);
|
||||
struct sock *sk = sock->sk;
|
||||
struct atm_vcc *vcc = ATM_SD(sock);
|
||||
int error;
|
||||
|
||||
pr_debug("%p\n", vcc);
|
||||
lock_sock(sk);
|
||||
/* let server handle listen on unbound sockets */
|
||||
if (test_bit(ATM_VF_SESSION, &vcc->flags)) {
|
||||
error = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (test_bit(ATM_VF_LISTEN, &vcc->flags)) {
|
||||
error = -EADDRINUSE;
|
||||
goto out;
|
||||
}
|
||||
set_bit(ATM_VF_WAITING, &vcc->flags);
|
||||
sigd_enq(vcc, as_listen, NULL, NULL, &vcc->local);
|
||||
for (;;) {
|
||||
prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE);
|
||||
if (!test_bit(ATM_VF_WAITING, &vcc->flags) || !sigd)
|
||||
break;
|
||||
schedule();
|
||||
}
|
||||
finish_wait(sk_sleep(sk), &wait);
|
||||
if (!sigd) {
|
||||
error = -EUNATCH;
|
||||
goto out;
|
||||
}
|
||||
set_bit(ATM_VF_LISTEN, &vcc->flags);
|
||||
vcc_insert_socket(sk);
|
||||
sk->sk_max_ack_backlog = backlog > 0 ? backlog : ATM_BACKLOG_DEFAULT;
|
||||
error = -sk->sk_err;
|
||||
out:
|
||||
release_sock(sk);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int svc_accept(struct socket *sock, struct socket *newsock,
|
||||
struct proto_accept_arg *arg)
|
||||
{
|
||||
struct sock *sk = sock->sk;
|
||||
struct sk_buff *skb;
|
||||
struct atmsvc_msg *msg;
|
||||
struct atm_vcc *old_vcc = ATM_SD(sock);
|
||||
struct atm_vcc *new_vcc;
|
||||
int error;
|
||||
|
||||
lock_sock(sk);
|
||||
|
||||
error = svc_create(sock_net(sk), newsock, 0, arg->kern);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
new_vcc = ATM_SD(newsock);
|
||||
|
||||
pr_debug("%p -> %p\n", old_vcc, new_vcc);
|
||||
while (1) {
|
||||
DEFINE_WAIT(wait);
|
||||
|
||||
prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
|
||||
while (!(skb = skb_dequeue(&sk->sk_receive_queue)) &&
|
||||
sigd) {
|
||||
if (test_bit(ATM_VF_RELEASED, &old_vcc->flags))
|
||||
break;
|
||||
if (test_bit(ATM_VF_CLOSE, &old_vcc->flags)) {
|
||||
error = -sk->sk_err;
|
||||
break;
|
||||
}
|
||||
if (arg->flags & O_NONBLOCK) {
|
||||
error = -EAGAIN;
|
||||
break;
|
||||
}
|
||||
release_sock(sk);
|
||||
schedule();
|
||||
lock_sock(sk);
|
||||
if (signal_pending(current)) {
|
||||
error = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
prepare_to_wait(sk_sleep(sk), &wait,
|
||||
TASK_INTERRUPTIBLE);
|
||||
}
|
||||
finish_wait(sk_sleep(sk), &wait);
|
||||
if (error)
|
||||
goto out;
|
||||
if (!skb) {
|
||||
error = -EUNATCH;
|
||||
goto out;
|
||||
}
|
||||
msg = (struct atmsvc_msg *)skb->data;
|
||||
new_vcc->qos = msg->qos;
|
||||
set_bit(ATM_VF_HASQOS, &new_vcc->flags);
|
||||
new_vcc->remote = msg->svc;
|
||||
new_vcc->local = msg->local;
|
||||
new_vcc->sap = msg->sap;
|
||||
error = vcc_connect(newsock, msg->pvc.sap_addr.itf,
|
||||
msg->pvc.sap_addr.vpi,
|
||||
msg->pvc.sap_addr.vci);
|
||||
dev_kfree_skb(skb);
|
||||
sk_acceptq_removed(sk);
|
||||
if (error) {
|
||||
sigd_enq2(NULL, as_reject, old_vcc, NULL, NULL,
|
||||
&old_vcc->qos, error);
|
||||
error = error == -EAGAIN ? -EBUSY : error;
|
||||
goto out;
|
||||
}
|
||||
/* wait should be short, so we ignore the non-blocking flag */
|
||||
set_bit(ATM_VF_WAITING, &new_vcc->flags);
|
||||
sigd_enq(new_vcc, as_accept, old_vcc, NULL, NULL);
|
||||
for (;;) {
|
||||
prepare_to_wait(sk_sleep(sk_atm(new_vcc)), &wait,
|
||||
TASK_UNINTERRUPTIBLE);
|
||||
if (!test_bit(ATM_VF_WAITING, &new_vcc->flags) || !sigd)
|
||||
break;
|
||||
release_sock(sk);
|
||||
schedule();
|
||||
lock_sock(sk);
|
||||
}
|
||||
finish_wait(sk_sleep(sk_atm(new_vcc)), &wait);
|
||||
if (!sigd) {
|
||||
error = -EUNATCH;
|
||||
goto out;
|
||||
}
|
||||
if (!sk_atm(new_vcc)->sk_err)
|
||||
break;
|
||||
if (sk_atm(new_vcc)->sk_err != ERESTARTSYS) {
|
||||
error = -sk_atm(new_vcc)->sk_err;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
newsock->state = SS_CONNECTED;
|
||||
out:
|
||||
release_sock(sk);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int svc_getname(struct socket *sock, struct sockaddr *sockaddr,
|
||||
int peer)
|
||||
{
|
||||
struct sockaddr_atmsvc *addr;
|
||||
|
||||
addr = (struct sockaddr_atmsvc *) sockaddr;
|
||||
memcpy(addr, peer ? &ATM_SD(sock)->remote : &ATM_SD(sock)->local,
|
||||
sizeof(struct sockaddr_atmsvc));
|
||||
return sizeof(struct sockaddr_atmsvc);
|
||||
}
|
||||
|
||||
int svc_change_qos(struct atm_vcc *vcc, struct atm_qos *qos)
|
||||
{
|
||||
struct sock *sk = sk_atm(vcc);
|
||||
DEFINE_WAIT(wait);
|
||||
|
||||
set_bit(ATM_VF_WAITING, &vcc->flags);
|
||||
sigd_enq2(vcc, as_modify, NULL, NULL, &vcc->local, qos, 0);
|
||||
for (;;) {
|
||||
prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE);
|
||||
if (!test_bit(ATM_VF_WAITING, &vcc->flags) ||
|
||||
test_bit(ATM_VF_RELEASED, &vcc->flags) || !sigd) {
|
||||
break;
|
||||
}
|
||||
schedule();
|
||||
}
|
||||
finish_wait(sk_sleep(sk), &wait);
|
||||
if (!sigd)
|
||||
return -EUNATCH;
|
||||
return -sk->sk_err;
|
||||
}
|
||||
|
||||
static int svc_setsockopt(struct socket *sock, int level, int optname,
|
||||
sockptr_t optval, unsigned int optlen)
|
||||
{
|
||||
struct sock *sk = sock->sk;
|
||||
struct atm_vcc *vcc = ATM_SD(sock);
|
||||
int value, error = 0;
|
||||
|
||||
lock_sock(sk);
|
||||
switch (optname) {
|
||||
case SO_ATMSAP:
|
||||
if (level != SOL_ATM || optlen != sizeof(struct atm_sap)) {
|
||||
error = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (copy_from_sockptr(&vcc->sap, optval, optlen)) {
|
||||
error = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
set_bit(ATM_VF_HASSAP, &vcc->flags);
|
||||
break;
|
||||
case SO_MULTIPOINT:
|
||||
if (level != SOL_ATM || optlen != sizeof(int)) {
|
||||
error = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (copy_from_sockptr(&value, optval, sizeof(int))) {
|
||||
error = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
if (value == 1)
|
||||
set_bit(ATM_VF_SESSION, &vcc->flags);
|
||||
else if (value == 0)
|
||||
clear_bit(ATM_VF_SESSION, &vcc->flags);
|
||||
else
|
||||
error = -EINVAL;
|
||||
break;
|
||||
default:
|
||||
error = vcc_setsockopt(sock, level, optname, optval, optlen);
|
||||
}
|
||||
|
||||
out:
|
||||
release_sock(sk);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int svc_getsockopt(struct socket *sock, int level, int optname,
|
||||
sockopt_t *opt)
|
||||
{
|
||||
struct sock *sk = sock->sk;
|
||||
int error = 0, len;
|
||||
|
||||
lock_sock(sk);
|
||||
if (!__SO_LEVEL_MATCH(optname, level) || optname != SO_ATMSAP) {
|
||||
error = vcc_getsockopt(sock, level, optname, opt);
|
||||
goto out;
|
||||
}
|
||||
len = opt->optlen;
|
||||
if (len != sizeof(struct atm_sap)) {
|
||||
error = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (copy_to_iter(&ATM_SD(sock)->sap, sizeof(struct atm_sap),
|
||||
&opt->iter_out) != sizeof(struct atm_sap)) {
|
||||
error = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
release_sock(sk);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int svc_addparty(struct socket *sock, struct sockaddr *sockaddr,
|
||||
int sockaddr_len, int flags)
|
||||
{
|
||||
DEFINE_WAIT(wait);
|
||||
struct sock *sk = sock->sk;
|
||||
struct atm_vcc *vcc = ATM_SD(sock);
|
||||
int error;
|
||||
|
||||
lock_sock(sk);
|
||||
set_bit(ATM_VF_WAITING, &vcc->flags);
|
||||
sigd_enq(vcc, as_addparty, NULL, NULL,
|
||||
(struct sockaddr_atmsvc *) sockaddr);
|
||||
if (flags & O_NONBLOCK) {
|
||||
error = -EINPROGRESS;
|
||||
goto out;
|
||||
}
|
||||
pr_debug("added wait queue\n");
|
||||
for (;;) {
|
||||
prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
|
||||
if (!test_bit(ATM_VF_WAITING, &vcc->flags) || !sigd)
|
||||
break;
|
||||
schedule();
|
||||
}
|
||||
finish_wait(sk_sleep(sk), &wait);
|
||||
error = -xchg(&sk->sk_err_soft, 0);
|
||||
out:
|
||||
release_sock(sk);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int svc_dropparty(struct socket *sock, int ep_ref)
|
||||
{
|
||||
DEFINE_WAIT(wait);
|
||||
struct sock *sk = sock->sk;
|
||||
struct atm_vcc *vcc = ATM_SD(sock);
|
||||
int error;
|
||||
|
||||
lock_sock(sk);
|
||||
set_bit(ATM_VF_WAITING, &vcc->flags);
|
||||
sigd_enq2(vcc, as_dropparty, NULL, NULL, NULL, NULL, ep_ref);
|
||||
for (;;) {
|
||||
prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
|
||||
if (!test_bit(ATM_VF_WAITING, &vcc->flags) || !sigd)
|
||||
break;
|
||||
schedule();
|
||||
}
|
||||
finish_wait(sk_sleep(sk), &wait);
|
||||
if (!sigd) {
|
||||
error = -EUNATCH;
|
||||
goto out;
|
||||
}
|
||||
error = -xchg(&sk->sk_err_soft, 0);
|
||||
out:
|
||||
release_sock(sk);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int svc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int error, ep_ref;
|
||||
struct sockaddr_atmsvc sa;
|
||||
struct atm_vcc *vcc = ATM_SD(sock);
|
||||
|
||||
switch (cmd) {
|
||||
case ATM_ADDPARTY:
|
||||
if (!test_bit(ATM_VF_SESSION, &vcc->flags))
|
||||
return -EINVAL;
|
||||
if (copy_from_user(&sa, (void __user *) arg, sizeof(sa)))
|
||||
return -EFAULT;
|
||||
error = svc_addparty(sock, (struct sockaddr *)&sa, sizeof(sa),
|
||||
0);
|
||||
break;
|
||||
case ATM_DROPPARTY:
|
||||
if (!test_bit(ATM_VF_SESSION, &vcc->flags))
|
||||
return -EINVAL;
|
||||
if (copy_from_user(&ep_ref, (void __user *) arg, sizeof(int)))
|
||||
return -EFAULT;
|
||||
error = svc_dropparty(sock, ep_ref);
|
||||
break;
|
||||
default:
|
||||
error = vcc_ioctl(sock, cmd, arg);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static int svc_compat_ioctl(struct socket *sock, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
/* The definition of ATM_ADDPARTY uses the size of struct atm_iobuf.
|
||||
But actually it takes a struct sockaddr_atmsvc, which doesn't need
|
||||
compat handling. So all we have to do is fix up cmd... */
|
||||
if (cmd == COMPAT_ATM_ADDPARTY)
|
||||
cmd = ATM_ADDPARTY;
|
||||
|
||||
if (cmd == ATM_ADDPARTY || cmd == ATM_DROPPARTY)
|
||||
return svc_ioctl(sock, cmd, arg);
|
||||
else
|
||||
return vcc_compat_ioctl(sock, cmd, arg);
|
||||
}
|
||||
#endif /* CONFIG_COMPAT */
|
||||
|
||||
static const struct proto_ops svc_proto_ops = {
|
||||
.family = PF_ATMSVC,
|
||||
.owner = THIS_MODULE,
|
||||
|
||||
.release = svc_release,
|
||||
.bind = svc_bind,
|
||||
.connect = svc_connect,
|
||||
.socketpair = sock_no_socketpair,
|
||||
.accept = svc_accept,
|
||||
.getname = svc_getname,
|
||||
.poll = vcc_poll,
|
||||
.ioctl = svc_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = svc_compat_ioctl,
|
||||
#endif
|
||||
.gettstamp = sock_gettstamp,
|
||||
.listen = svc_listen,
|
||||
.shutdown = svc_shutdown,
|
||||
.setsockopt = svc_setsockopt,
|
||||
.getsockopt_iter = svc_getsockopt,
|
||||
.sendmsg = vcc_sendmsg,
|
||||
.recvmsg = vcc_recvmsg,
|
||||
.mmap = sock_no_mmap,
|
||||
};
|
||||
|
||||
|
||||
static int svc_create(struct net *net, struct socket *sock, int protocol,
|
||||
int kern)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (!net_eq(net, &init_net))
|
||||
return -EAFNOSUPPORT;
|
||||
|
||||
sock->ops = &svc_proto_ops;
|
||||
error = vcc_create(net, sock, protocol, AF_ATMSVC, kern);
|
||||
if (error)
|
||||
return error;
|
||||
ATM_SD(sock)->local.sas_family = AF_ATMSVC;
|
||||
ATM_SD(sock)->remote.sas_family = AF_ATMSVC;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct net_proto_family svc_family_ops = {
|
||||
.family = PF_ATMSVC,
|
||||
.create = svc_create,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the ATM SVC protocol family
|
||||
*/
|
||||
|
||||
int __init atmsvc_init(void)
|
||||
{
|
||||
return sock_register(&svc_family_ops);
|
||||
}
|
||||
|
||||
void atmsvc_exit(void)
|
||||
{
|
||||
sock_unregister(PF_ATMSVC);
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user