mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-29 23:24:11 +08:00
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6: [TG3]: Bump driver version and reldate. [TG3]: Skip phy power down on some devices [TG3]: Fix SRAM access during tg3_init_one() [X25]: dte facilities 32 64 ioctl conversion [X25]: allow ITU-T DTE facilities for x25 [X25]: fix kernel error message 64 bit kernel [X25]: ioctl conversion 32 bit user to 64 bit kernel [NET]: socket timestamp 32 bit handler for 64 bit kernel [NET]: allow 32 bit socket ioctl in 64 bit kernel [BLUETOOTH]: Return negative error constant
This commit is contained in:
commit
36177ba655
@ -69,8 +69,8 @@
|
||||
|
||||
#define DRV_MODULE_NAME "tg3"
|
||||
#define PFX DRV_MODULE_NAME ": "
|
||||
#define DRV_MODULE_VERSION "3.52"
|
||||
#define DRV_MODULE_RELDATE "Mar 06, 2006"
|
||||
#define DRV_MODULE_VERSION "3.53"
|
||||
#define DRV_MODULE_RELDATE "Mar 22, 2006"
|
||||
|
||||
#define TG3_DEF_MAC_MODE 0
|
||||
#define TG3_DEF_RX_MODE 0
|
||||
@ -1148,6 +1148,19 @@ static int tg3_halt_cpu(struct tg3 *, u32);
|
||||
static int tg3_nvram_lock(struct tg3 *);
|
||||
static void tg3_nvram_unlock(struct tg3 *);
|
||||
|
||||
static void tg3_power_down_phy(struct tg3 *tp)
|
||||
{
|
||||
/* The PHY should not be powered down on some chips because
|
||||
* of bugs.
|
||||
*/
|
||||
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
|
||||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
|
||||
(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 &&
|
||||
(tp->tg3_flags2 & TG3_FLG2_MII_SERDES)))
|
||||
return;
|
||||
tg3_writephy(tp, MII_BMCR, BMCR_PDOWN);
|
||||
}
|
||||
|
||||
static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
|
||||
{
|
||||
u32 misc_host_ctrl;
|
||||
@ -1327,8 +1340,7 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
|
||||
tg3_writephy(tp, MII_TG3_EXT_CTRL,
|
||||
MII_TG3_EXT_CTRL_FORCE_LED_OFF);
|
||||
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x01b2);
|
||||
if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700)
|
||||
tg3_writephy(tp, MII_BMCR, BMCR_PDOWN);
|
||||
tg3_power_down_phy(tp);
|
||||
}
|
||||
}
|
||||
|
||||
@ -9436,12 +9448,18 @@ static inline struct subsys_tbl_ent *lookup_by_subsys(struct tg3 *tp)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Since this function may be called in D3-hot power state during
|
||||
* tg3_init_one(), only config cycles are allowed.
|
||||
*/
|
||||
static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
|
||||
{
|
||||
u32 val;
|
||||
u16 pmcsr;
|
||||
|
||||
/* On some early chips the SRAM cannot be accessed in D3hot state,
|
||||
* so need make sure we're in D0.
|
||||
*/
|
||||
pci_read_config_word(tp->pdev, tp->pm_cap + PCI_PM_CTRL, &pmcsr);
|
||||
pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
|
||||
pci_write_config_word(tp->pdev, tp->pm_cap + PCI_PM_CTRL, pmcsr);
|
||||
msleep(1);
|
||||
|
||||
/* Make sure register accesses (indirect or otherwise)
|
||||
* will function correctly.
|
||||
|
@ -143,6 +143,8 @@ struct proto_ops {
|
||||
struct poll_table_struct *wait);
|
||||
int (*ioctl) (struct socket *sock, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
int (*compat_ioctl) (struct socket *sock, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
int (*listen) (struct socket *sock, int len);
|
||||
int (*shutdown) (struct socket *sock, int flags);
|
||||
int (*setsockopt)(struct socket *sock, int level,
|
||||
@ -251,6 +253,8 @@ SOCKCALL_UWRAP(name, poll, (struct file *file, struct socket *sock, struct poll_
|
||||
(file, sock, wait)) \
|
||||
SOCKCALL_WRAP(name, ioctl, (struct socket *sock, unsigned int cmd, \
|
||||
unsigned long arg), (sock, cmd, arg)) \
|
||||
SOCKCALL_WRAP(name, compat_ioctl, (struct socket *sock, unsigned int cmd, \
|
||||
unsigned long arg), (sock, cmd, arg)) \
|
||||
SOCKCALL_WRAP(name, listen, (struct socket *sock, int len), (sock, len)) \
|
||||
SOCKCALL_WRAP(name, shutdown, (struct socket *sock, int flags), (sock, flags)) \
|
||||
SOCKCALL_WRAP(name, setsockopt, (struct socket *sock, int level, int optname, \
|
||||
@ -275,6 +279,7 @@ static const struct proto_ops name##_ops = { \
|
||||
.getname = __lock_##name##_getname, \
|
||||
.poll = __lock_##name##_poll, \
|
||||
.ioctl = __lock_##name##_ioctl, \
|
||||
.compat_ioctl = __lock_##name##_compat_ioctl, \
|
||||
.listen = __lock_##name##_listen, \
|
||||
.shutdown = __lock_##name##_shutdown, \
|
||||
.setsockopt = __lock_##name##_setsockopt, \
|
||||
@ -283,6 +288,7 @@ static const struct proto_ops name##_ops = { \
|
||||
.recvmsg = __lock_##name##_recvmsg, \
|
||||
.mmap = __lock_##name##_mmap, \
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#define MODULE_ALIAS_NETPROTO(proto) \
|
||||
|
@ -11,6 +11,8 @@
|
||||
#ifndef X25_KERNEL_H
|
||||
#define X25_KERNEL_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define SIOCX25GSUBSCRIP (SIOCPROTOPRIVATE + 0)
|
||||
#define SIOCX25SSUBSCRIP (SIOCPROTOPRIVATE + 1)
|
||||
#define SIOCX25GFACILITIES (SIOCPROTOPRIVATE + 2)
|
||||
@ -21,6 +23,8 @@
|
||||
#define SIOCX25SCUDMATCHLEN (SIOCPROTOPRIVATE + 7)
|
||||
#define SIOCX25CALLACCPTAPPRV (SIOCPROTOPRIVATE + 8)
|
||||
#define SIOCX25SENDCALLACCPT (SIOCPROTOPRIVATE + 9)
|
||||
#define SIOCX25GDTEFACILITIES (SIOCPROTOPRIVATE + 10)
|
||||
#define SIOCX25SDTEFACILITIES (SIOCPROTOPRIVATE + 11)
|
||||
|
||||
/*
|
||||
* Values for {get,set}sockopt.
|
||||
@ -77,6 +81,8 @@ struct x25_subscrip_struct {
|
||||
#define X25_MASK_PACKET_SIZE 0x04
|
||||
#define X25_MASK_WINDOW_SIZE 0x08
|
||||
|
||||
#define X25_MASK_CALLING_AE 0x10
|
||||
#define X25_MASK_CALLED_AE 0x20
|
||||
|
||||
|
||||
/*
|
||||
@ -98,6 +104,26 @@ struct x25_facilities {
|
||||
unsigned int reverse;
|
||||
};
|
||||
|
||||
/*
|
||||
* ITU DTE facilities
|
||||
* Only the called and calling address
|
||||
* extension are currently implemented.
|
||||
* The rest are in place to avoid the struct
|
||||
* changing size if someone needs them later
|
||||
*/
|
||||
|
||||
struct x25_dte_facilities {
|
||||
__u16 delay_cumul;
|
||||
__u16 delay_target;
|
||||
__u16 delay_max;
|
||||
__u8 min_throughput;
|
||||
__u8 expedited;
|
||||
__u8 calling_len;
|
||||
__u8 called_len;
|
||||
__u8 calling_ae[20];
|
||||
__u8 called_ae[20];
|
||||
};
|
||||
|
||||
/*
|
||||
* Call User Data structure.
|
||||
*/
|
||||
|
@ -23,6 +23,9 @@ struct compat_cmsghdr {
|
||||
compat_int_t cmsg_type;
|
||||
};
|
||||
|
||||
struct sock;
|
||||
extern int compat_sock_get_timestamp(struct sock *, struct timeval __user *);
|
||||
|
||||
#else /* defined(CONFIG_COMPAT) */
|
||||
#define compat_msghdr msghdr /* to avoid compiler warnings */
|
||||
#endif /* defined(CONFIG_COMPAT) */
|
||||
@ -34,7 +37,6 @@ extern asmlinkage long compat_sys_recvmsg(int,struct compat_msghdr __user *,unsi
|
||||
extern asmlinkage long compat_sys_getsockopt(int, int, int, char __user *, int __user *);
|
||||
extern int put_cmsg_compat(struct msghdr*, int, int, int, void *);
|
||||
|
||||
struct sock;
|
||||
extern int cmsghdr_from_user_compat_to_kern(struct msghdr *, struct sock *, unsigned char *, int);
|
||||
|
||||
#endif /* NET_COMPAT_H */
|
||||
|
@ -101,9 +101,17 @@ enum {
|
||||
#define X25_FAC_PACKET_SIZE 0x42
|
||||
#define X25_FAC_WINDOW_SIZE 0x43
|
||||
|
||||
#define X25_MAX_FAC_LEN 20 /* Plenty to spare */
|
||||
#define X25_MAX_FAC_LEN 60
|
||||
#define X25_MAX_CUD_LEN 128
|
||||
|
||||
#define X25_FAC_CALLING_AE 0xCB
|
||||
#define X25_FAC_CALLED_AE 0xC9
|
||||
|
||||
#define X25_MARKER 0x00
|
||||
#define X25_DTE_SERVICES 0x0F
|
||||
#define X25_MAX_AE_LEN 40 /* Max num of semi-octets in AE - OSI Nw */
|
||||
#define X25_MAX_DTE_FACIL_LEN 21 /* Max length of DTE facility params */
|
||||
|
||||
/**
|
||||
* struct x25_route - x25 routing entry
|
||||
* @node - entry in x25_list_lock
|
||||
@ -148,6 +156,7 @@ struct x25_sock {
|
||||
struct timer_list timer;
|
||||
struct x25_causediag causediag;
|
||||
struct x25_facilities facilities;
|
||||
struct x25_dte_facilities dte_facilities;
|
||||
struct x25_calluserdata calluserdata;
|
||||
unsigned long vc_facil_mask; /* inc_call facilities mask */
|
||||
};
|
||||
@ -180,9 +189,13 @@ extern void x25_establish_link(struct x25_neigh *);
|
||||
extern void x25_terminate_link(struct x25_neigh *);
|
||||
|
||||
/* x25_facilities.c */
|
||||
extern int x25_parse_facilities(struct sk_buff *, struct x25_facilities *, unsigned long *);
|
||||
extern int x25_create_facilities(unsigned char *, struct x25_facilities *, unsigned long);
|
||||
extern int x25_negotiate_facilities(struct sk_buff *, struct sock *, struct x25_facilities *);
|
||||
extern int x25_parse_facilities(struct sk_buff *, struct x25_facilities *,
|
||||
struct x25_dte_facilities *, unsigned long *);
|
||||
extern int x25_create_facilities(unsigned char *, struct x25_facilities *,
|
||||
struct x25_dte_facilities *, unsigned long);
|
||||
extern int x25_negotiate_facilities(struct sk_buff *, struct sock *,
|
||||
struct x25_facilities *,
|
||||
struct x25_dte_facilities *);
|
||||
extern void x25_limit_facilities(struct x25_facilities *, struct x25_neigh *);
|
||||
|
||||
/* x25_in.c */
|
||||
|
@ -532,8 +532,8 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
|
||||
dev = alloc_netdev(sizeof(struct bnep_session),
|
||||
(*req->device) ? req->device : "bnep%d",
|
||||
bnep_net_setup);
|
||||
if (!dev)
|
||||
return ENOMEM;
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
down_write(&bnep_session_sem);
|
||||
|
19
net/compat.c
19
net/compat.c
@ -543,6 +543,25 @@ static int compat_sock_getsockopt(struct socket *sock, int level, int optname,
|
||||
return sock_getsockopt(sock, level, optname, optval, optlen);
|
||||
}
|
||||
|
||||
int compat_sock_get_timestamp(struct sock *sk, struct timeval __user *userstamp)
|
||||
{
|
||||
struct compat_timeval __user *ctv =
|
||||
(struct compat_timeval __user*) userstamp;
|
||||
int err = -ENOENT;
|
||||
|
||||
if (!sock_flag(sk, SOCK_TIMESTAMP))
|
||||
sock_enable_timestamp(sk);
|
||||
if (sk->sk_stamp.tv_sec == -1)
|
||||
return err;
|
||||
if (sk->sk_stamp.tv_sec == 0)
|
||||
do_gettimeofday(&sk->sk_stamp);
|
||||
if (put_user(sk->sk_stamp.tv_sec, &ctv->tv_sec) ||
|
||||
put_user(sk->sk_stamp.tv_usec, &ctv->tv_usec))
|
||||
err = -EFAULT;
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(compat_sock_get_timestamp);
|
||||
|
||||
asmlinkage long compat_sys_getsockopt(int fd, int level, int optname,
|
||||
char __user *optval, int __user *optlen)
|
||||
{
|
||||
|
21
net/socket.c
21
net/socket.c
@ -107,6 +107,10 @@ static unsigned int sock_poll(struct file *file,
|
||||
struct poll_table_struct *wait);
|
||||
static long sock_ioctl(struct file *file,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
#ifdef CONFIG_COMPAT
|
||||
static long compat_sock_ioctl(struct file *file,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
#endif
|
||||
static int sock_fasync(int fd, struct file *filp, int on);
|
||||
static ssize_t sock_readv(struct file *file, const struct iovec *vector,
|
||||
unsigned long count, loff_t *ppos);
|
||||
@ -128,6 +132,9 @@ static struct file_operations socket_file_ops = {
|
||||
.aio_write = sock_aio_write,
|
||||
.poll = sock_poll,
|
||||
.unlocked_ioctl = sock_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = compat_sock_ioctl,
|
||||
#endif
|
||||
.mmap = sock_mmap,
|
||||
.open = sock_no_open, /* special open code to disallow open via /proc */
|
||||
.release = sock_close,
|
||||
@ -2136,6 +2143,20 @@ void socket_seq_show(struct seq_file *seq)
|
||||
}
|
||||
#endif /* CONFIG_PROC_FS */
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static long compat_sock_ioctl(struct file *file, unsigned cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
struct socket *sock = file->private_data;
|
||||
int ret = -ENOIOCTLCMD;
|
||||
|
||||
if (sock->ops->compat_ioctl)
|
||||
ret = sock->ops->compat_ioctl(sock, cmd, arg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ABI emulation layers need these two */
|
||||
EXPORT_SYMBOL(move_addr_to_kernel);
|
||||
EXPORT_SYMBOL(move_addr_to_user);
|
||||
|
173
net/x25/af_x25.c
173
net/x25/af_x25.c
@ -54,7 +54,10 @@
|
||||
#include <linux/termios.h> /* For TIOCINQ/OUTQ */
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/compat.h>
|
||||
|
||||
#include <net/x25.h>
|
||||
#include <net/compat.h>
|
||||
|
||||
int sysctl_x25_restart_request_timeout = X25_DEFAULT_T20;
|
||||
int sysctl_x25_call_request_timeout = X25_DEFAULT_T21;
|
||||
@ -69,6 +72,14 @@ static const struct proto_ops x25_proto_ops;
|
||||
|
||||
static struct x25_address null_x25_address = {" "};
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
struct compat_x25_subscrip_struct {
|
||||
char device[200-sizeof(compat_ulong_t)];
|
||||
compat_ulong_t global_facil_mask;
|
||||
compat_uint_t extended;
|
||||
};
|
||||
#endif
|
||||
|
||||
int x25_addr_ntoa(unsigned char *p, struct x25_address *called_addr,
|
||||
struct x25_address *calling_addr)
|
||||
{
|
||||
@ -514,6 +525,13 @@ static int x25_create(struct socket *sock, int protocol)
|
||||
x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE;
|
||||
x25->facilities.throughput = X25_DEFAULT_THROUGHPUT;
|
||||
x25->facilities.reverse = X25_DEFAULT_REVERSE;
|
||||
x25->dte_facilities.calling_len = 0;
|
||||
x25->dte_facilities.called_len = 0;
|
||||
memset(x25->dte_facilities.called_ae, '\0',
|
||||
sizeof(x25->dte_facilities.called_ae));
|
||||
memset(x25->dte_facilities.calling_ae, '\0',
|
||||
sizeof(x25->dte_facilities.calling_ae));
|
||||
|
||||
rc = 0;
|
||||
out:
|
||||
return rc;
|
||||
@ -550,6 +568,7 @@ static struct sock *x25_make_new(struct sock *osk)
|
||||
x25->t2 = ox25->t2;
|
||||
x25->facilities = ox25->facilities;
|
||||
x25->qbitincl = ox25->qbitincl;
|
||||
x25->dte_facilities = ox25->dte_facilities;
|
||||
x25->cudmatchlength = ox25->cudmatchlength;
|
||||
x25->accptapprv = ox25->accptapprv;
|
||||
|
||||
@ -733,7 +752,7 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int x25_wait_for_data(struct sock *sk, int timeout)
|
||||
static int x25_wait_for_data(struct sock *sk, long timeout)
|
||||
{
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
int rc = 0;
|
||||
@ -829,6 +848,7 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
|
||||
struct x25_sock *makex25;
|
||||
struct x25_address source_addr, dest_addr;
|
||||
struct x25_facilities facilities;
|
||||
struct x25_dte_facilities dte_facilities;
|
||||
int len, rc;
|
||||
|
||||
/*
|
||||
@ -865,7 +885,8 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
|
||||
/*
|
||||
* Try to reach a compromise on the requested facilities.
|
||||
*/
|
||||
if ((len = x25_negotiate_facilities(skb, sk, &facilities)) == -1)
|
||||
len = x25_negotiate_facilities(skb, sk, &facilities, &dte_facilities);
|
||||
if (len == -1)
|
||||
goto out_sock_put;
|
||||
|
||||
/*
|
||||
@ -896,9 +917,12 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
|
||||
makex25->source_addr = source_addr;
|
||||
makex25->neighbour = nb;
|
||||
makex25->facilities = facilities;
|
||||
makex25->dte_facilities= dte_facilities;
|
||||
makex25->vc_facil_mask = x25_sk(sk)->vc_facil_mask;
|
||||
/* ensure no reverse facil on accept */
|
||||
makex25->vc_facil_mask &= ~X25_MASK_REVERSE;
|
||||
/* ensure no calling address extension on accept */
|
||||
makex25->vc_facil_mask &= ~X25_MASK_CALLING_AE;
|
||||
makex25->cudmatchlength = x25_sk(sk)->cudmatchlength;
|
||||
|
||||
/* Normally all calls are accepted immediatly */
|
||||
@ -1305,6 +1329,36 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
|
||||
break;
|
||||
}
|
||||
|
||||
case SIOCX25GDTEFACILITIES: {
|
||||
rc = copy_to_user(argp, &x25->dte_facilities,
|
||||
sizeof(x25->dte_facilities));
|
||||
if (rc)
|
||||
rc = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
case SIOCX25SDTEFACILITIES: {
|
||||
struct x25_dte_facilities dtefacs;
|
||||
rc = -EFAULT;
|
||||
if (copy_from_user(&dtefacs, argp, sizeof(dtefacs)))
|
||||
break;
|
||||
rc = -EINVAL;
|
||||
if (sk->sk_state != TCP_LISTEN &&
|
||||
sk->sk_state != TCP_CLOSE)
|
||||
break;
|
||||
if (dtefacs.calling_len > X25_MAX_AE_LEN)
|
||||
break;
|
||||
if (dtefacs.calling_ae == NULL)
|
||||
break;
|
||||
if (dtefacs.called_len > X25_MAX_AE_LEN)
|
||||
break;
|
||||
if (dtefacs.called_ae == NULL)
|
||||
break;
|
||||
x25->dte_facilities = dtefacs;
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case SIOCX25GCALLUSERDATA: {
|
||||
struct x25_calluserdata cud = x25->calluserdata;
|
||||
rc = copy_to_user(argp, &cud,
|
||||
@ -1387,6 +1441,118 @@ static struct net_proto_family x25_family_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static int compat_x25_subscr_ioctl(unsigned int cmd,
|
||||
struct compat_x25_subscrip_struct __user *x25_subscr32)
|
||||
{
|
||||
struct compat_x25_subscrip_struct x25_subscr;
|
||||
struct x25_neigh *nb;
|
||||
struct net_device *dev;
|
||||
int rc = -EINVAL;
|
||||
|
||||
rc = -EFAULT;
|
||||
if (copy_from_user(&x25_subscr, x25_subscr32, sizeof(*x25_subscr32)))
|
||||
goto out;
|
||||
|
||||
rc = -EINVAL;
|
||||
dev = x25_dev_get(x25_subscr.device);
|
||||
if (dev == NULL)
|
||||
goto out;
|
||||
|
||||
nb = x25_get_neigh(dev);
|
||||
if (nb == NULL)
|
||||
goto out_dev_put;
|
||||
|
||||
dev_put(dev);
|
||||
|
||||
if (cmd == SIOCX25GSUBSCRIP) {
|
||||
x25_subscr.extended = nb->extended;
|
||||
x25_subscr.global_facil_mask = nb->global_facil_mask;
|
||||
rc = copy_to_user(x25_subscr32, &x25_subscr,
|
||||
sizeof(*x25_subscr32)) ? -EFAULT : 0;
|
||||
} else {
|
||||
rc = -EINVAL;
|
||||
if (x25_subscr.extended == 0 || x25_subscr.extended == 1) {
|
||||
rc = 0;
|
||||
nb->extended = x25_subscr.extended;
|
||||
nb->global_facil_mask = x25_subscr.global_facil_mask;
|
||||
}
|
||||
}
|
||||
x25_neigh_put(nb);
|
||||
out:
|
||||
return rc;
|
||||
out_dev_put:
|
||||
dev_put(dev);
|
||||
goto out;
|
||||
}
|
||||
|
||||
static int compat_x25_ioctl(struct socket *sock, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
void __user *argp = compat_ptr(arg);
|
||||
struct sock *sk = sock->sk;
|
||||
|
||||
int rc = -ENOIOCTLCMD;
|
||||
|
||||
switch(cmd) {
|
||||
case TIOCOUTQ:
|
||||
case TIOCINQ:
|
||||
rc = x25_ioctl(sock, cmd, (unsigned long)argp);
|
||||
break;
|
||||
case SIOCGSTAMP:
|
||||
rc = -EINVAL;
|
||||
if (sk)
|
||||
rc = compat_sock_get_timestamp(sk,
|
||||
(struct timeval __user*)argp);
|
||||
break;
|
||||
case SIOCGIFADDR:
|
||||
case SIOCSIFADDR:
|
||||
case SIOCGIFDSTADDR:
|
||||
case SIOCSIFDSTADDR:
|
||||
case SIOCGIFBRDADDR:
|
||||
case SIOCSIFBRDADDR:
|
||||
case SIOCGIFNETMASK:
|
||||
case SIOCSIFNETMASK:
|
||||
case SIOCGIFMETRIC:
|
||||
case SIOCSIFMETRIC:
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
case SIOCADDRT:
|
||||
case SIOCDELRT:
|
||||
rc = -EPERM;
|
||||
if (!capable(CAP_NET_ADMIN))
|
||||
break;
|
||||
rc = x25_route_ioctl(cmd, argp);
|
||||
break;
|
||||
case SIOCX25GSUBSCRIP:
|
||||
rc = compat_x25_subscr_ioctl(cmd, argp);
|
||||
break;
|
||||
case SIOCX25SSUBSCRIP:
|
||||
rc = -EPERM;
|
||||
if (!capable(CAP_NET_ADMIN))
|
||||
break;
|
||||
rc = compat_x25_subscr_ioctl(cmd, argp);
|
||||
break;
|
||||
case SIOCX25GFACILITIES:
|
||||
case SIOCX25SFACILITIES:
|
||||
case SIOCX25GDTEFACILITIES:
|
||||
case SIOCX25SDTEFACILITIES:
|
||||
case SIOCX25GCALLUSERDATA:
|
||||
case SIOCX25SCALLUSERDATA:
|
||||
case SIOCX25GCAUSEDIAG:
|
||||
case SIOCX25SCUDMATCHLEN:
|
||||
case SIOCX25CALLACCPTAPPRV:
|
||||
case SIOCX25SENDCALLACCPT:
|
||||
rc = x25_ioctl(sock, cmd, (unsigned long)argp);
|
||||
break;
|
||||
default:
|
||||
rc = -ENOIOCTLCMD;
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
|
||||
.family = AF_X25,
|
||||
.owner = THIS_MODULE,
|
||||
@ -1398,6 +1564,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
|
||||
.getname = x25_getname,
|
||||
.poll = datagram_poll,
|
||||
.ioctl = x25_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = compat_x25_ioctl,
|
||||
#endif
|
||||
.listen = x25_listen,
|
||||
.shutdown = sock_no_shutdown,
|
||||
.setsockopt = x25_setsockopt,
|
||||
|
@ -28,18 +28,28 @@
|
||||
#include <net/x25.h>
|
||||
|
||||
/*
|
||||
* Parse a set of facilities into the facilities structure. Unrecognised
|
||||
* Parse a set of facilities into the facilities structures. Unrecognised
|
||||
* facilities are written to the debug log file.
|
||||
*/
|
||||
int x25_parse_facilities(struct sk_buff *skb,
|
||||
struct x25_facilities *facilities,
|
||||
unsigned long *vc_fac_mask)
|
||||
int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities,
|
||||
struct x25_dte_facilities *dte_facs, unsigned long *vc_fac_mask)
|
||||
{
|
||||
unsigned char *p = skb->data;
|
||||
unsigned int len = *p++;
|
||||
|
||||
*vc_fac_mask = 0;
|
||||
|
||||
/*
|
||||
* The kernel knows which facilities were set on an incoming call but
|
||||
* currently this information is not available to userspace. Here we
|
||||
* give userspace who read incoming call facilities 0 length to indicate
|
||||
* it wasn't set.
|
||||
*/
|
||||
dte_facs->calling_len = 0;
|
||||
dte_facs->called_len = 0;
|
||||
memset(dte_facs->called_ae, '\0', sizeof(dte_facs->called_ae));
|
||||
memset(dte_facs->calling_ae, '\0', sizeof(dte_facs->calling_ae));
|
||||
|
||||
while (len > 0) {
|
||||
switch (*p & X25_FAC_CLASS_MASK) {
|
||||
case X25_FAC_CLASS_A:
|
||||
@ -74,6 +84,8 @@ int x25_parse_facilities(struct sk_buff *skb,
|
||||
facilities->throughput = p[1];
|
||||
*vc_fac_mask |= X25_MASK_THROUGHPUT;
|
||||
break;
|
||||
case X25_MARKER:
|
||||
break;
|
||||
default:
|
||||
printk(KERN_DEBUG "X.25: unknown facility "
|
||||
"%02X, value %02X\n",
|
||||
@ -112,11 +124,30 @@ int x25_parse_facilities(struct sk_buff *skb,
|
||||
len -= 4;
|
||||
break;
|
||||
case X25_FAC_CLASS_D:
|
||||
printk(KERN_DEBUG "X.25: unknown facility %02X, "
|
||||
"length %d, values %02X, %02X, %02X, %02X\n",
|
||||
p[0], p[1], p[2], p[3], p[4], p[5]);
|
||||
switch (*p) {
|
||||
case X25_FAC_CALLING_AE:
|
||||
if (p[1] > X25_MAX_DTE_FACIL_LEN)
|
||||
break;
|
||||
dte_facs->calling_len = p[2];
|
||||
memcpy(dte_facs->calling_ae, &p[3], p[1] - 1);
|
||||
*vc_fac_mask |= X25_MASK_CALLING_AE;
|
||||
break;
|
||||
case X25_FAC_CALLED_AE:
|
||||
if (p[1] > X25_MAX_DTE_FACIL_LEN)
|
||||
break;
|
||||
dte_facs->called_len = p[2];
|
||||
memcpy(dte_facs->called_ae, &p[3], p[1] - 1);
|
||||
*vc_fac_mask |= X25_MASK_CALLED_AE;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_DEBUG "X.25: unknown facility %02X,"
|
||||
"length %d, values %02X, %02X, "
|
||||
"%02X, %02X\n",
|
||||
p[0], p[1], p[2], p[3], p[4], p[5]);
|
||||
break;
|
||||
}
|
||||
len -= p[1] + 2;
|
||||
p += p[1] + 2;
|
||||
p += p[1] + 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -128,8 +159,8 @@ int x25_parse_facilities(struct sk_buff *skb,
|
||||
* Create a set of facilities.
|
||||
*/
|
||||
int x25_create_facilities(unsigned char *buffer,
|
||||
struct x25_facilities *facilities,
|
||||
unsigned long facil_mask)
|
||||
struct x25_facilities *facilities,
|
||||
struct x25_dte_facilities *dte_facs, unsigned long facil_mask)
|
||||
{
|
||||
unsigned char *p = buffer + 1;
|
||||
int len;
|
||||
@ -168,6 +199,33 @@ int x25_create_facilities(unsigned char *buffer,
|
||||
*p++ = facilities->winsize_out ? : facilities->winsize_in;
|
||||
}
|
||||
|
||||
if (facil_mask & (X25_MASK_CALLING_AE|X25_MASK_CALLED_AE)) {
|
||||
*p++ = X25_MARKER;
|
||||
*p++ = X25_DTE_SERVICES;
|
||||
}
|
||||
|
||||
if (dte_facs->calling_len && (facil_mask & X25_MASK_CALLING_AE)) {
|
||||
unsigned bytecount = (dte_facs->calling_len % 2) ?
|
||||
dte_facs->calling_len / 2 + 1 :
|
||||
dte_facs->calling_len / 2;
|
||||
*p++ = X25_FAC_CALLING_AE;
|
||||
*p++ = 1 + bytecount;
|
||||
*p++ = dte_facs->calling_len;
|
||||
memcpy(p, dte_facs->calling_ae, bytecount);
|
||||
p += bytecount;
|
||||
}
|
||||
|
||||
if (dte_facs->called_len && (facil_mask & X25_MASK_CALLED_AE)) {
|
||||
unsigned bytecount = (dte_facs->called_len % 2) ?
|
||||
dte_facs->called_len / 2 + 1 :
|
||||
dte_facs->called_len / 2;
|
||||
*p++ = X25_FAC_CALLED_AE;
|
||||
*p++ = 1 + bytecount;
|
||||
*p++ = dte_facs->called_len;
|
||||
memcpy(p, dte_facs->called_ae, bytecount);
|
||||
p+=bytecount;
|
||||
}
|
||||
|
||||
len = p - buffer;
|
||||
buffer[0] = len - 1;
|
||||
|
||||
@ -180,7 +238,7 @@ int x25_create_facilities(unsigned char *buffer,
|
||||
* The only real problem is with reverse charging.
|
||||
*/
|
||||
int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk,
|
||||
struct x25_facilities *new)
|
||||
struct x25_facilities *new, struct x25_dte_facilities *dte)
|
||||
{
|
||||
struct x25_sock *x25 = x25_sk(sk);
|
||||
struct x25_facilities *ours = &x25->facilities;
|
||||
@ -190,7 +248,7 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk,
|
||||
memset(&theirs, 0, sizeof(theirs));
|
||||
memcpy(new, ours, sizeof(*new));
|
||||
|
||||
len = x25_parse_facilities(skb, &theirs, &x25->vc_facil_mask);
|
||||
len = x25_parse_facilities(skb, &theirs, dte, &x25->vc_facil_mask);
|
||||
|
||||
/*
|
||||
* They want reverse charging, we won't accept it.
|
||||
|
@ -106,7 +106,8 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp
|
||||
skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr));
|
||||
skb_pull(skb,
|
||||
x25_parse_facilities(skb, &x25->facilities,
|
||||
&x25->vc_facil_mask));
|
||||
&x25->dte_facilities,
|
||||
&x25->vc_facil_mask));
|
||||
/*
|
||||
* Copy any Call User Data.
|
||||
*/
|
||||
|
@ -190,8 +190,9 @@ void x25_write_internal(struct sock *sk, int frametype)
|
||||
dptr = skb_put(skb, len);
|
||||
memcpy(dptr, addresses, len);
|
||||
len = x25_create_facilities(facilities,
|
||||
&x25->facilities,
|
||||
x25->neighbour->global_facil_mask);
|
||||
&x25->facilities,
|
||||
&x25->dte_facilities,
|
||||
x25->neighbour->global_facil_mask);
|
||||
dptr = skb_put(skb, len);
|
||||
memcpy(dptr, facilities, len);
|
||||
dptr = skb_put(skb, x25->calluserdata.cudlength);
|
||||
@ -206,6 +207,7 @@ void x25_write_internal(struct sock *sk, int frametype)
|
||||
*dptr++ = 0x00; /* Address lengths */
|
||||
len = x25_create_facilities(facilities,
|
||||
&x25->facilities,
|
||||
&x25->dte_facilities,
|
||||
x25->vc_facil_mask);
|
||||
dptr = skb_put(skb, len);
|
||||
memcpy(dptr, facilities, len);
|
||||
|
Loading…
Reference in New Issue
Block a user