Commit 36177ba6 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 2152f853 056755f4
...@@ -69,8 +69,8 @@ ...@@ -69,8 +69,8 @@
#define DRV_MODULE_NAME "tg3" #define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": " #define PFX DRV_MODULE_NAME ": "
#define DRV_MODULE_VERSION "3.52" #define DRV_MODULE_VERSION "3.53"
#define DRV_MODULE_RELDATE "Mar 06, 2006" #define DRV_MODULE_RELDATE "Mar 22, 2006"
#define TG3_DEF_MAC_MODE 0 #define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0 #define TG3_DEF_RX_MODE 0
...@@ -1148,6 +1148,19 @@ static int tg3_halt_cpu(struct tg3 *, u32); ...@@ -1148,6 +1148,19 @@ static int tg3_halt_cpu(struct tg3 *, u32);
static int tg3_nvram_lock(struct tg3 *); static int tg3_nvram_lock(struct tg3 *);
static void tg3_nvram_unlock(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) static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
{ {
u32 misc_host_ctrl; u32 misc_host_ctrl;
...@@ -1327,8 +1340,7 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) ...@@ -1327,8 +1340,7 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
tg3_writephy(tp, MII_TG3_EXT_CTRL, tg3_writephy(tp, MII_TG3_EXT_CTRL,
MII_TG3_EXT_CTRL_FORCE_LED_OFF); MII_TG3_EXT_CTRL_FORCE_LED_OFF);
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x01b2); tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x01b2);
if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) tg3_power_down_phy(tp);
tg3_writephy(tp, MII_BMCR, BMCR_PDOWN);
} }
} }
...@@ -9436,12 +9448,18 @@ static inline struct subsys_tbl_ent *lookup_by_subsys(struct tg3 *tp) ...@@ -9436,12 +9448,18 @@ static inline struct subsys_tbl_ent *lookup_by_subsys(struct tg3 *tp)
return NULL; 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) static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
{ {
u32 val; 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) /* Make sure register accesses (indirect or otherwise)
* will function correctly. * will function correctly.
......
...@@ -143,6 +143,8 @@ struct proto_ops { ...@@ -143,6 +143,8 @@ struct proto_ops {
struct poll_table_struct *wait); struct poll_table_struct *wait);
int (*ioctl) (struct socket *sock, unsigned int cmd, int (*ioctl) (struct socket *sock, unsigned int cmd,
unsigned long arg); unsigned long arg);
int (*compat_ioctl) (struct socket *sock, unsigned int cmd,
unsigned long arg);
int (*listen) (struct socket *sock, int len); int (*listen) (struct socket *sock, int len);
int (*shutdown) (struct socket *sock, int flags); int (*shutdown) (struct socket *sock, int flags);
int (*setsockopt)(struct socket *sock, int level, int (*setsockopt)(struct socket *sock, int level,
...@@ -251,6 +253,8 @@ SOCKCALL_UWRAP(name, poll, (struct file *file, struct socket *sock, struct poll_ ...@@ -251,6 +253,8 @@ SOCKCALL_UWRAP(name, poll, (struct file *file, struct socket *sock, struct poll_
(file, sock, wait)) \ (file, sock, wait)) \
SOCKCALL_WRAP(name, ioctl, (struct socket *sock, unsigned int cmd, \ SOCKCALL_WRAP(name, ioctl, (struct socket *sock, unsigned int cmd, \
unsigned long arg), (sock, cmd, arg)) \ 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, listen, (struct socket *sock, int len), (sock, len)) \
SOCKCALL_WRAP(name, shutdown, (struct socket *sock, int flags), (sock, flags)) \ SOCKCALL_WRAP(name, shutdown, (struct socket *sock, int flags), (sock, flags)) \
SOCKCALL_WRAP(name, setsockopt, (struct socket *sock, int level, int optname, \ SOCKCALL_WRAP(name, setsockopt, (struct socket *sock, int level, int optname, \
...@@ -275,6 +279,7 @@ static const struct proto_ops name##_ops = { \ ...@@ -275,6 +279,7 @@ static const struct proto_ops name##_ops = { \
.getname = __lock_##name##_getname, \ .getname = __lock_##name##_getname, \
.poll = __lock_##name##_poll, \ .poll = __lock_##name##_poll, \
.ioctl = __lock_##name##_ioctl, \ .ioctl = __lock_##name##_ioctl, \
.compat_ioctl = __lock_##name##_compat_ioctl, \
.listen = __lock_##name##_listen, \ .listen = __lock_##name##_listen, \
.shutdown = __lock_##name##_shutdown, \ .shutdown = __lock_##name##_shutdown, \
.setsockopt = __lock_##name##_setsockopt, \ .setsockopt = __lock_##name##_setsockopt, \
...@@ -283,6 +288,7 @@ static const struct proto_ops name##_ops = { \ ...@@ -283,6 +288,7 @@ static const struct proto_ops name##_ops = { \
.recvmsg = __lock_##name##_recvmsg, \ .recvmsg = __lock_##name##_recvmsg, \
.mmap = __lock_##name##_mmap, \ .mmap = __lock_##name##_mmap, \
}; };
#endif #endif
#define MODULE_ALIAS_NETPROTO(proto) \ #define MODULE_ALIAS_NETPROTO(proto) \
......
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#ifndef X25_KERNEL_H #ifndef X25_KERNEL_H
#define X25_KERNEL_H #define X25_KERNEL_H
#include <linux/types.h>
#define SIOCX25GSUBSCRIP (SIOCPROTOPRIVATE + 0) #define SIOCX25GSUBSCRIP (SIOCPROTOPRIVATE + 0)
#define SIOCX25SSUBSCRIP (SIOCPROTOPRIVATE + 1) #define SIOCX25SSUBSCRIP (SIOCPROTOPRIVATE + 1)
#define SIOCX25GFACILITIES (SIOCPROTOPRIVATE + 2) #define SIOCX25GFACILITIES (SIOCPROTOPRIVATE + 2)
...@@ -21,6 +23,8 @@ ...@@ -21,6 +23,8 @@
#define SIOCX25SCUDMATCHLEN (SIOCPROTOPRIVATE + 7) #define SIOCX25SCUDMATCHLEN (SIOCPROTOPRIVATE + 7)
#define SIOCX25CALLACCPTAPPRV (SIOCPROTOPRIVATE + 8) #define SIOCX25CALLACCPTAPPRV (SIOCPROTOPRIVATE + 8)
#define SIOCX25SENDCALLACCPT (SIOCPROTOPRIVATE + 9) #define SIOCX25SENDCALLACCPT (SIOCPROTOPRIVATE + 9)
#define SIOCX25GDTEFACILITIES (SIOCPROTOPRIVATE + 10)
#define SIOCX25SDTEFACILITIES (SIOCPROTOPRIVATE + 11)
/* /*
* Values for {get,set}sockopt. * Values for {get,set}sockopt.
...@@ -77,6 +81,8 @@ struct x25_subscrip_struct { ...@@ -77,6 +81,8 @@ struct x25_subscrip_struct {
#define X25_MASK_PACKET_SIZE 0x04 #define X25_MASK_PACKET_SIZE 0x04
#define X25_MASK_WINDOW_SIZE 0x08 #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 { ...@@ -98,6 +104,26 @@ struct x25_facilities {
unsigned int reverse; 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. * Call User Data structure.
*/ */
......
...@@ -23,6 +23,9 @@ struct compat_cmsghdr { ...@@ -23,6 +23,9 @@ struct compat_cmsghdr {
compat_int_t cmsg_type; compat_int_t cmsg_type;
}; };
struct sock;
extern int compat_sock_get_timestamp(struct sock *, struct timeval __user *);
#else /* defined(CONFIG_COMPAT) */ #else /* defined(CONFIG_COMPAT) */
#define compat_msghdr msghdr /* to avoid compiler warnings */ #define compat_msghdr msghdr /* to avoid compiler warnings */
#endif /* defined(CONFIG_COMPAT) */ #endif /* defined(CONFIG_COMPAT) */
...@@ -34,7 +37,6 @@ extern asmlinkage long compat_sys_recvmsg(int,struct compat_msghdr __user *,unsi ...@@ -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 asmlinkage long compat_sys_getsockopt(int, int, int, char __user *, int __user *);
extern int put_cmsg_compat(struct msghdr*, int, int, int, void *); 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); extern int cmsghdr_from_user_compat_to_kern(struct msghdr *, struct sock *, unsigned char *, int);
#endif /* NET_COMPAT_H */ #endif /* NET_COMPAT_H */
...@@ -101,9 +101,17 @@ enum { ...@@ -101,9 +101,17 @@ enum {
#define X25_FAC_PACKET_SIZE 0x42 #define X25_FAC_PACKET_SIZE 0x42
#define X25_FAC_WINDOW_SIZE 0x43 #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_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 * struct x25_route - x25 routing entry
* @node - entry in x25_list_lock * @node - entry in x25_list_lock
...@@ -148,6 +156,7 @@ struct x25_sock { ...@@ -148,6 +156,7 @@ struct x25_sock {
struct timer_list timer; struct timer_list timer;
struct x25_causediag causediag; struct x25_causediag causediag;
struct x25_facilities facilities; struct x25_facilities facilities;
struct x25_dte_facilities dte_facilities;
struct x25_calluserdata calluserdata; struct x25_calluserdata calluserdata;
unsigned long vc_facil_mask; /* inc_call facilities mask */ unsigned long vc_facil_mask; /* inc_call facilities mask */
}; };
...@@ -180,9 +189,13 @@ extern void x25_establish_link(struct x25_neigh *); ...@@ -180,9 +189,13 @@ extern void x25_establish_link(struct x25_neigh *);
extern void x25_terminate_link(struct x25_neigh *); extern void x25_terminate_link(struct x25_neigh *);
/* x25_facilities.c */ /* x25_facilities.c */
extern int x25_parse_facilities(struct sk_buff *, struct x25_facilities *, unsigned long *); extern int x25_parse_facilities(struct sk_buff *, struct x25_facilities *,
extern int x25_create_facilities(unsigned char *, struct x25_facilities *, unsigned long); struct x25_dte_facilities *, unsigned long *);
extern int x25_negotiate_facilities(struct sk_buff *, struct sock *, struct x25_facilities *); 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 *); extern void x25_limit_facilities(struct x25_facilities *, struct x25_neigh *);
/* x25_in.c */ /* x25_in.c */
......
...@@ -533,7 +533,7 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) ...@@ -533,7 +533,7 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
(*req->device) ? req->device : "bnep%d", (*req->device) ? req->device : "bnep%d",
bnep_net_setup); bnep_net_setup);
if (!dev) if (!dev)
return ENOMEM; return -ENOMEM;
down_write(&bnep_session_sem); down_write(&bnep_session_sem);
......
...@@ -543,6 +543,25 @@ static int compat_sock_getsockopt(struct socket *sock, int level, int optname, ...@@ -543,6 +543,25 @@ static int compat_sock_getsockopt(struct socket *sock, int level, int optname,
return sock_getsockopt(sock, level, optname, optval, optlen); 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, asmlinkage long compat_sys_getsockopt(int fd, int level, int optname,
char __user *optval, int __user *optlen) char __user *optval, int __user *optlen)
{ {
......
...@@ -107,6 +107,10 @@ static unsigned int sock_poll(struct file *file, ...@@ -107,6 +107,10 @@ static unsigned int sock_poll(struct file *file,
struct poll_table_struct *wait); struct poll_table_struct *wait);
static long sock_ioctl(struct file *file, static long sock_ioctl(struct file *file,
unsigned int cmd, unsigned long arg); 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 int sock_fasync(int fd, struct file *filp, int on);
static ssize_t sock_readv(struct file *file, const struct iovec *vector, static ssize_t sock_readv(struct file *file, const struct iovec *vector,
unsigned long count, loff_t *ppos); unsigned long count, loff_t *ppos);
...@@ -128,6 +132,9 @@ static struct file_operations socket_file_ops = { ...@@ -128,6 +132,9 @@ static struct file_operations socket_file_ops = {
.aio_write = sock_aio_write, .aio_write = sock_aio_write,
.poll = sock_poll, .poll = sock_poll,
.unlocked_ioctl = sock_ioctl, .unlocked_ioctl = sock_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = compat_sock_ioctl,
#endif
.mmap = sock_mmap, .mmap = sock_mmap,
.open = sock_no_open, /* special open code to disallow open via /proc */ .open = sock_no_open, /* special open code to disallow open via /proc */
.release = sock_close, .release = sock_close,
...@@ -2136,6 +2143,20 @@ void socket_seq_show(struct seq_file *seq) ...@@ -2136,6 +2143,20 @@ void socket_seq_show(struct seq_file *seq)
} }
#endif /* CONFIG_PROC_FS */ #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 */ /* ABI emulation layers need these two */
EXPORT_SYMBOL(move_addr_to_kernel); EXPORT_SYMBOL(move_addr_to_kernel);
EXPORT_SYMBOL(move_addr_to_user); EXPORT_SYMBOL(move_addr_to_user);
......
...@@ -54,7 +54,10 @@ ...@@ -54,7 +54,10 @@
#include <linux/termios.h> /* For TIOCINQ/OUTQ */ #include <linux/termios.h> /* For TIOCINQ/OUTQ */
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/compat.h>
#include <net/x25.h> #include <net/x25.h>
#include <net/compat.h>
int sysctl_x25_restart_request_timeout = X25_DEFAULT_T20; int sysctl_x25_restart_request_timeout = X25_DEFAULT_T20;
int sysctl_x25_call_request_timeout = X25_DEFAULT_T21; int sysctl_x25_call_request_timeout = X25_DEFAULT_T21;
...@@ -69,6 +72,14 @@ static const struct proto_ops x25_proto_ops; ...@@ -69,6 +72,14 @@ static const struct proto_ops x25_proto_ops;
static struct x25_address null_x25_address = {" "}; 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, int x25_addr_ntoa(unsigned char *p, struct x25_address *called_addr,
struct x25_address *calling_addr) struct x25_address *calling_addr)
{ {
...@@ -514,6 +525,13 @@ static int x25_create(struct socket *sock, int protocol) ...@@ -514,6 +525,13 @@ static int x25_create(struct socket *sock, int protocol)
x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE; x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE;
x25->facilities.throughput = X25_DEFAULT_THROUGHPUT; x25->facilities.throughput = X25_DEFAULT_THROUGHPUT;
x25->facilities.reverse = X25_DEFAULT_REVERSE; 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; rc = 0;
out: out:
return rc; return rc;
...@@ -550,6 +568,7 @@ static struct sock *x25_make_new(struct sock *osk) ...@@ -550,6 +568,7 @@ static struct sock *x25_make_new(struct sock *osk)
x25->t2 = ox25->t2; x25->t2 = ox25->t2;
x25->facilities = ox25->facilities; x25->facilities = ox25->facilities;
x25->qbitincl = ox25->qbitincl; x25->qbitincl = ox25->qbitincl;
x25->dte_facilities = ox25->dte_facilities;
x25->cudmatchlength = ox25->cudmatchlength; x25->cudmatchlength = ox25->cudmatchlength;
x25->accptapprv = ox25->accptapprv; x25->accptapprv = ox25->accptapprv;
...@@ -733,7 +752,7 @@ out: ...@@ -733,7 +752,7 @@ out:
return rc; 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); DECLARE_WAITQUEUE(wait, current);
int rc = 0; int rc = 0;
...@@ -829,6 +848,7 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, ...@@ -829,6 +848,7 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
struct x25_sock *makex25; struct x25_sock *makex25;
struct x25_address source_addr, dest_addr; struct x25_address source_addr, dest_addr;
struct x25_facilities facilities; struct x25_facilities facilities;
struct x25_dte_facilities dte_facilities;
int len, rc; int len, rc;
/* /*
...@@ -865,7 +885,8 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, ...@@ -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. * 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; goto out_sock_put;
/* /*
...@@ -896,9 +917,12 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, ...@@ -896,9 +917,12 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
makex25->source_addr = source_addr; makex25->source_addr = source_addr;
makex25->neighbour = nb; makex25->neighbour = nb;
makex25->facilities = facilities; makex25->facilities = facilities;
makex25->dte_facilities= dte_facilities;
makex25->vc_facil_mask = x25_sk(sk)->vc_facil_mask; makex25->vc_facil_mask = x25_sk(sk)->vc_facil_mask;
/* ensure no reverse facil on accept */ /* ensure no reverse facil on accept */
makex25->vc_facil_mask &= ~X25_MASK_REVERSE; 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; makex25->cudmatchlength = x25_sk(sk)->cudmatchlength;
/* Normally all calls are accepted immediatly */ /* Normally all calls are accepted immediatly */
...@@ -1305,6 +1329,36 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ...@@ -1305,6 +1329,36 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
break; 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: { case SIOCX25GCALLUSERDATA: {
struct x25_calluserdata cud = x25->calluserdata; struct x25_calluserdata cud = x25->calluserdata;
rc = copy_to_user(argp, &cud, rc = copy_to_user(argp, &cud,
...@@ -1387,6 +1441,118 @@ static struct net_proto_family x25_family_ops = { ...@@ -1387,6 +1441,118 @@ static struct net_proto_family x25_family_ops = {
.owner = THIS_MODULE, .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) = { static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
.family = AF_X25, .family = AF_X25,
.owner = THIS_MODULE, .owner = THIS_MODULE,
...@@ -1398,6 +1564,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = { ...@@ -1398,6 +1564,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
.getname = x25_getname, .getname = x25_getname,
.poll = datagram_poll, .poll = datagram_poll,
.ioctl = x25_ioctl, .ioctl = x25_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = compat_x25_ioctl,
#endif
.listen = x25_listen, .listen = x25_listen,
.shutdown = sock_no_shutdown, .shutdown = sock_no_shutdown,
.setsockopt = x25_setsockopt, .setsockopt = x25_setsockopt,
......
...@@ -28,18 +28,28 @@ ...@@ -28,18 +28,28 @@
#include <net/x25.h> #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. * facilities are written to the debug log file.
*/ */
int x25_parse_facilities(struct sk_buff *skb, int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities,
struct x25_facilities *facilities, struct x25_dte_facilities *dte_facs, unsigned long *vc_fac_mask)
unsigned long *vc_fac_mask)
{ {
unsigned char *p = skb->data; unsigned char *p = skb->data;
unsigned int len = *p++; unsigned int len = *p++;
*vc_fac_mask = 0; *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) { while (len > 0) {
switch (*p & X25_FAC_CLASS_MASK) { switch (*p & X25_FAC_CLASS_MASK) {
case X25_FAC_CLASS_A: case X25_FAC_CLASS_A:
...@@ -74,6 +84,8 @@ int x25_parse_facilities(struct sk_buff *skb, ...@@ -74,6 +84,8 @@ int x25_parse_facilities(struct sk_buff *skb,
facilities->throughput = p[1]; facilities->throughput = p[1];
*vc_fac_mask |= X25_MASK_THROUGHPUT; *vc_fac_mask |= X25_MASK_THROUGHPUT;
break; break;
case X25_MARKER:
break;
default: default:
printk(KERN_DEBUG "X.25: unknown facility " printk(KERN_DEBUG "X.25: unknown facility "
"%02X, value %02X\n", "%02X, value %02X\n",
...@@ -112,9 +124,28 @@ int x25_parse_facilities(struct sk_buff *skb, ...@@ -112,9 +124,28 @@ int x25_parse_facilities(struct sk_buff *skb,
len -= 4; len -= 4;
break; break;
case X25_FAC_CLASS_D: case X25_FAC_CLASS_D:
printk(KERN_DEBUG "X.25: unknown facility %02X, " switch (*p) {
"length %d, values %02X, %02X, %02X, %02X\n", 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]); p[0], p[1], p[2], p[3], p[4], p[5]);
break;
}
len -= p[1] + 2; len -= p[1] + 2;
p += p[1] + 2; p += p[1] + 2;
break; break;
...@@ -129,7 +160,7 @@ int x25_parse_facilities(struct sk_buff *skb, ...@@ -129,7 +160,7 @@ int x25_parse_facilities(struct sk_buff *skb,
*/ */
int x25_create_facilities(unsigned char *buffer, int x25_create_facilities(unsigned char *buffer,
struct x25_facilities *facilities, struct x25_facilities *facilities,
unsigned long facil_mask) struct x25_dte_facilities *dte_facs, unsigned long facil_mask)
{ {
unsigned char *p = buffer + 1; unsigned char *p = buffer + 1;
int len; int len;
...@@ -168,6 +199,33 @@ int x25_create_facilities(unsigned char *buffer, ...@@ -168,6 +199,33 @@ int x25_create_facilities(unsigned char *buffer,
*p++ = facilities->winsize_out ? : facilities->winsize_in; *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; len = p - buffer;
buffer[0] = len - 1; buffer[0] = len - 1;
...@@ -180,7 +238,7 @@ int x25_create_facilities(unsigned char *buffer, ...@@ -180,7 +238,7 @@ int x25_create_facilities(unsigned char *buffer,
* The only real problem is with reverse charging. * The only real problem is with reverse charging.
*/ */
int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk, 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_sock *x25 = x25_sk(sk);
struct x25_facilities *ours = &x25->facilities; struct x25_facilities *ours = &x25->facilities;
...@@ -190,7 +248,7 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk, ...@@ -190,7 +248,7 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk,
memset(&theirs, 0, sizeof(theirs)); memset(&theirs, 0, sizeof(theirs));
memcpy(new, ours, sizeof(*new)); 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. * They want reverse charging, we won't accept it.
......
...@@ -106,6 +106,7 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp ...@@ -106,6 +106,7 @@ 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_addr_ntoa(skb->data, &source_addr, &dest_addr));
skb_pull(skb, skb_pull(skb,
x25_parse_facilities(skb, &x25->facilities, x25_parse_facilities(skb, &x25->facilities,
&x25->dte_facilities,
&x25->vc_facil_mask)); &x25->vc_facil_mask));
/* /*
* Copy any Call User Data. * Copy any Call User Data.
......
...@@ -191,6 +191,7 @@ void x25_write_internal(struct sock *sk, int frametype) ...@@ -191,6 +191,7 @@ void x25_write_internal(struct sock *sk, int frametype)
memcpy(dptr, addresses, len); memcpy(dptr, addresses, len);
len = x25_create_facilities(facilities, len = x25_create_facilities(facilities,
&x25->facilities, &x25->facilities,
&x25->dte_facilities,
x25->neighbour->global_facil_mask); x25->neighbour->global_facil_mask);
dptr = skb_put(skb, len); dptr = skb_put(skb, len);
memcpy(dptr, facilities, len); memcpy(dptr, facilities, len);
...@@ -206,6 +207,7 @@ void x25_write_internal(struct sock *sk, int frametype) ...@@ -206,6 +207,7 @@ void x25_write_internal(struct sock *sk, int frametype)
*dptr++ = 0x00; /* Address lengths */ *dptr++ = 0x00; /* Address lengths */
len = x25_create_facilities(facilities, len = x25_create_facilities(facilities,
&x25->facilities, &x25->facilities,
&x25->dte_facilities,
x25->vc_facil_mask); x25->vc_facil_mask);
dptr = skb_put(skb, len); dptr = skb_put(skb, len);
memcpy(dptr, facilities, len); memcpy(dptr, facilities, len);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment