Commit 56e9b263 authored by David S. Miller's avatar David S. Miller

Merge master.kernel.org:/pub/scm/linux/kernel/git/acme/llc-2.6

parents 188bab3a 8420e1b5
...@@ -202,7 +202,8 @@ enum ...@@ -202,7 +202,8 @@ enum
NET_TR=14, NET_TR=14,
NET_DECNET=15, NET_DECNET=15,
NET_ECONET=16, NET_ECONET=16,
NET_SCTP=17, NET_SCTP=17,
NET_LLC=18,
}; };
/* /proc/sys/kernel/random */ /* /proc/sys/kernel/random */
...@@ -522,6 +523,29 @@ enum { ...@@ -522,6 +523,29 @@ enum {
NET_IPX_FORWARDING=2 NET_IPX_FORWARDING=2
}; };
/* /proc/sys/net/llc */
enum {
NET_LLC2=1,
NET_LLC_STATION=2,
};
/* /proc/sys/net/llc/llc2 */
enum {
NET_LLC2_TIMEOUT=1,
};
/* /proc/sys/net/llc/station */
enum {
NET_LLC_STATION_ACK_TIMEOUT=1,
};
/* /proc/sys/net/llc/llc2/timeout */
enum {
NET_LLC2_ACK_TIMEOUT=1,
NET_LLC2_P_TIMEOUT=2,
NET_LLC2_REJ_TIMEOUT=3,
NET_LLC2_BUSY_TIMEOUT=4,
};
/* /proc/sys/net/appletalk */ /* /proc/sys/net/appletalk */
enum { enum {
......
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <asm/atomic.h>
struct net_device; struct net_device;
struct packet_type; struct packet_type;
struct sk_buff; struct sk_buff;
...@@ -44,6 +46,7 @@ struct llc_sap { ...@@ -44,6 +46,7 @@ struct llc_sap {
unsigned char state; unsigned char state;
unsigned char p_bit; unsigned char p_bit;
unsigned char f_bit; unsigned char f_bit;
atomic_t refcnt;
int (*rcv_func)(struct sk_buff *skb, int (*rcv_func)(struct sk_buff *skb,
struct net_device *dev, struct net_device *dev,
struct packet_type *pt, struct packet_type *pt,
...@@ -81,13 +84,27 @@ extern struct llc_sap *llc_sap_open(unsigned char lsap, ...@@ -81,13 +84,27 @@ extern struct llc_sap *llc_sap_open(unsigned char lsap,
struct net_device *dev, struct net_device *dev,
struct packet_type *pt, struct packet_type *pt,
struct net_device *orig_dev)); struct net_device *orig_dev));
static inline void llc_sap_hold(struct llc_sap *sap)
{
atomic_inc(&sap->refcnt);
}
extern void llc_sap_close(struct llc_sap *sap); extern void llc_sap_close(struct llc_sap *sap);
static inline void llc_sap_put(struct llc_sap *sap)
{
if (atomic_dec_and_test(&sap->refcnt))
llc_sap_close(sap);
}
extern struct llc_sap *llc_sap_find(unsigned char sap_value); extern struct llc_sap *llc_sap_find(unsigned char sap_value);
extern int llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb, extern int llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb,
unsigned char *dmac, unsigned char dsap); unsigned char *dmac, unsigned char dsap);
extern void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb);
extern void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb);
extern int llc_station_init(void); extern int llc_station_init(void);
extern void llc_station_exit(void); extern void llc_station_exit(void);
...@@ -98,4 +115,17 @@ extern void llc_proc_exit(void); ...@@ -98,4 +115,17 @@ extern void llc_proc_exit(void);
#define llc_proc_init() (0) #define llc_proc_init() (0)
#define llc_proc_exit() do { } while(0) #define llc_proc_exit() do { } while(0)
#endif /* CONFIG_PROC_FS */ #endif /* CONFIG_PROC_FS */
#ifdef CONFIG_SYSCTL
extern int llc_sysctl_init(void);
extern void llc_sysctl_exit(void);
extern int sysctl_llc2_ack_timeout;
extern int sysctl_llc2_busy_timeout;
extern int sysctl_llc2_p_timeout;
extern int sysctl_llc2_rej_timeout;
extern int sysctl_llc_station_ack_timeout;
#else
#define llc_sysctl_init() (0)
#define llc_sysctl_exit() do { } while(0)
#endif /* CONFIG_SYSCTL */
#endif /* LLC_H */ #endif /* LLC_H */
...@@ -19,14 +19,14 @@ ...@@ -19,14 +19,14 @@
#define LLC_EVENT 1 #define LLC_EVENT 1
#define LLC_PACKET 2 #define LLC_PACKET 2
#define LLC_P_TIME 2 #define LLC2_P_TIME 2
#define LLC_ACK_TIME 1 #define LLC2_ACK_TIME 1
#define LLC_REJ_TIME 3 #define LLC2_REJ_TIME 3
#define LLC_BUSY_TIME 3 #define LLC2_BUSY_TIME 3
struct llc_timer { struct llc_timer {
struct timer_list timer; struct timer_list timer;
u16 expire; /* timer expire time */ unsigned long expire; /* timer expire time */
}; };
struct llc_sock { struct llc_sock {
...@@ -38,6 +38,7 @@ struct llc_sock { ...@@ -38,6 +38,7 @@ struct llc_sock {
struct llc_addr laddr; /* lsap/mac pair */ struct llc_addr laddr; /* lsap/mac pair */
struct llc_addr daddr; /* dsap/mac pair */ struct llc_addr daddr; /* dsap/mac pair */
struct net_device *dev; /* device to send to remote */ struct net_device *dev; /* device to send to remote */
u32 copied_seq; /* head of yet unread data */
u8 retry_count; /* number of retries */ u8 retry_count; /* number of retries */
u8 ack_must_be_send; u8 ack_must_be_send;
u8 first_pdu_Ns; u8 first_pdu_Ns;
...@@ -92,7 +93,8 @@ static __inline__ char llc_backlog_type(struct sk_buff *skb) ...@@ -92,7 +93,8 @@ static __inline__ char llc_backlog_type(struct sk_buff *skb)
return skb->cb[sizeof(skb->cb) - 1]; return skb->cb[sizeof(skb->cb) - 1];
} }
extern struct sock *llc_sk_alloc(int family, int priority, struct proto *prot); extern struct sock *llc_sk_alloc(int family, unsigned int __nocast priority,
struct proto *prot);
extern void llc_sk_free(struct sock *sk); extern void llc_sk_free(struct sock *sk);
extern void llc_sk_reset(struct sock *sk); extern void llc_sk_reset(struct sock *sk);
...@@ -115,5 +117,4 @@ extern void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk); ...@@ -115,5 +117,4 @@ extern void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk);
extern u8 llc_data_accept_state(u8 state); extern u8 llc_data_accept_state(u8 state);
extern void llc_build_offset_table(void); extern void llc_build_offset_table(void);
extern int llc_release_sockets(struct llc_sap *sap);
#endif /* LLC_CONN_H */ #endif /* LLC_CONN_H */
...@@ -12,11 +12,15 @@ ...@@ -12,11 +12,15 @@
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
*/ */
struct llc_sap; struct llc_sap;
struct net_device;
struct sk_buff; struct sk_buff;
struct sock;
extern void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb); extern void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb);
extern void llc_save_primitive(struct sk_buff* skb, unsigned char prim); extern void llc_save_primitive(struct sock *sk, struct sk_buff* skb,
extern struct sk_buff *llc_alloc_frame(void); unsigned char prim);
extern struct sk_buff *llc_alloc_frame(struct sock *sk,
struct net_device *dev);
extern void llc_build_and_send_test_pkt(struct llc_sap *sap, extern void llc_build_and_send_test_pkt(struct llc_sap *sap,
struct sk_buff *skb, struct sk_buff *skb,
......
...@@ -56,7 +56,7 @@ struct datalink_proto *register_8022_client(unsigned char type, ...@@ -56,7 +56,7 @@ struct datalink_proto *register_8022_client(unsigned char type,
void unregister_8022_client(struct datalink_proto *proto) void unregister_8022_client(struct datalink_proto *proto)
{ {
llc_sap_close(proto->sap); llc_sap_put(proto->sap);
kfree(proto); kfree(proto);
} }
......
...@@ -106,7 +106,7 @@ module_init(snap_init); ...@@ -106,7 +106,7 @@ module_init(snap_init);
static void __exit snap_exit(void) static void __exit snap_exit(void)
{ {
llc_sap_close(snap_sap); llc_sap_put(snap_sap);
} }
module_exit(snap_exit); module_exit(snap_exit);
......
...@@ -238,7 +238,7 @@ unsigned short tr_type_trans(struct sk_buff *skb, struct net_device *dev) ...@@ -238,7 +238,7 @@ unsigned short tr_type_trans(struct sk_buff *skb, struct net_device *dev)
return trllc->ethertype; return trllc->ethertype;
} }
return ntohs(ETH_P_802_2); return ntohs(ETH_P_TR_802_2);
} }
/* /*
......
...@@ -574,6 +574,8 @@ struct net_device *dev_getbyhwaddr(unsigned short type, char *ha) ...@@ -574,6 +574,8 @@ struct net_device *dev_getbyhwaddr(unsigned short type, char *ha)
return dev; return dev;
} }
EXPORT_SYMBOL(dev_getbyhwaddr);
struct net_device *dev_getfirstbyhwtype(unsigned short type) struct net_device *dev_getfirstbyhwtype(unsigned short type)
{ {
struct net_device *dev; struct net_device *dev;
......
...@@ -22,3 +22,4 @@ llc2-y := llc_if.o llc_c_ev.o llc_c_ac.o llc_conn.o llc_c_st.o llc_pdu.o \ ...@@ -22,3 +22,4 @@ llc2-y := llc_if.o llc_c_ev.o llc_c_ac.o llc_conn.o llc_c_st.o llc_pdu.o \
llc_sap.o llc_s_ac.o llc_s_ev.o llc_s_st.o af_llc.o llc_station.o llc_sap.o llc_s_ac.o llc_s_ev.o llc_s_st.o af_llc.o llc_station.o
llc2-$(CONFIG_PROC_FS) += llc_proc.o llc2-$(CONFIG_PROC_FS) += llc_proc.o
llc2-$(CONFIG_SYSCTL) += sysctl_net_llc.o
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/compiler.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
...@@ -37,10 +38,9 @@ static u16 llc_ui_sap_link_no_max[256]; ...@@ -37,10 +38,9 @@ static u16 llc_ui_sap_link_no_max[256];
static struct sockaddr_llc llc_ui_addrnull; static struct sockaddr_llc llc_ui_addrnull;
static struct proto_ops llc_ui_ops; static struct proto_ops llc_ui_ops;
static int llc_ui_wait_for_conn(struct sock *sk, int timeout); static int llc_ui_wait_for_conn(struct sock *sk, long timeout);
static int llc_ui_wait_for_disc(struct sock *sk, int timeout); static int llc_ui_wait_for_disc(struct sock *sk, long timeout);
static int llc_ui_wait_for_data(struct sock *sk, int timeout); static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout);
static int llc_ui_wait_for_busy_core(struct sock *sk, int timeout);
#if 0 #if 0
#define dprintk(args...) printk(KERN_DEBUG args) #define dprintk(args...) printk(KERN_DEBUG args)
...@@ -116,12 +116,12 @@ static int llc_ui_send_data(struct sock* sk, struct sk_buff *skb, int noblock) ...@@ -116,12 +116,12 @@ static int llc_ui_send_data(struct sock* sk, struct sk_buff *skb, int noblock)
struct llc_sock* llc = llc_sk(sk); struct llc_sock* llc = llc_sk(sk);
int rc = 0; int rc = 0;
if (llc_data_accept_state(llc->state) || llc->p_flag) { if (unlikely(llc_data_accept_state(llc->state) || llc->p_flag)) {
int timeout = sock_sndtimeo(sk, noblock); long timeout = sock_sndtimeo(sk, noblock);
rc = llc_ui_wait_for_busy_core(sk, timeout); rc = llc_ui_wait_for_busy_core(sk, timeout);
} }
if (!rc) if (unlikely(!rc))
rc = llc_build_and_send_pkt(sk, skb); rc = llc_build_and_send_pkt(sk, skb);
return rc; return rc;
} }
...@@ -155,7 +155,7 @@ static int llc_ui_create(struct socket *sock, int protocol) ...@@ -155,7 +155,7 @@ static int llc_ui_create(struct socket *sock, int protocol)
struct sock *sk; struct sock *sk;
int rc = -ESOCKTNOSUPPORT; int rc = -ESOCKTNOSUPPORT;
if (sock->type == SOCK_DGRAM || sock->type == SOCK_STREAM) { if (likely(sock->type == SOCK_DGRAM || sock->type == SOCK_STREAM)) {
rc = -ENOMEM; rc = -ENOMEM;
sk = llc_sk_alloc(PF_LLC, GFP_KERNEL, &llc_proto); sk = llc_sk_alloc(PF_LLC, GFP_KERNEL, &llc_proto);
if (sk) { if (sk) {
...@@ -177,7 +177,7 @@ static int llc_ui_release(struct socket *sock) ...@@ -177,7 +177,7 @@ static int llc_ui_release(struct socket *sock)
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct llc_sock *llc; struct llc_sock *llc;
if (!sk) if (unlikely(sk == NULL))
goto out; goto out;
sock_hold(sk); sock_hold(sk);
lock_sock(sk); lock_sock(sk);
...@@ -189,10 +189,6 @@ static int llc_ui_release(struct socket *sock) ...@@ -189,10 +189,6 @@ static int llc_ui_release(struct socket *sock)
if (!sock_flag(sk, SOCK_ZAPPED)) if (!sock_flag(sk, SOCK_ZAPPED))
llc_sap_remove_socket(llc->sap, sk); llc_sap_remove_socket(llc->sap, sk);
release_sock(sk); release_sock(sk);
if (llc->sap && hlist_empty(&llc->sap->sk_list.list)) {
llc_release_sockets(llc->sap);
llc_sap_close(llc->sap);
}
if (llc->dev) if (llc->dev)
dev_put(llc->dev); dev_put(llc->dev);
sock_put(sk); sock_put(sk);
...@@ -221,6 +217,7 @@ static int llc_ui_autoport(void) ...@@ -221,6 +217,7 @@ static int llc_ui_autoport(void)
llc_ui_sap_last_autoport = i + 2; llc_ui_sap_last_autoport = i + 2;
goto out; goto out;
} }
llc_sap_put(sap);
} }
llc_ui_sap_last_autoport = LLC_SAP_DYN_START; llc_ui_sap_last_autoport = LLC_SAP_DYN_START;
tries++; tries++;
...@@ -231,20 +228,13 @@ out: ...@@ -231,20 +228,13 @@ out:
} }
/** /**
* llc_ui_autobind - Bind a socket to a specific address. * llc_ui_autobind - automatically bind a socket to a sap
* @sk: Socket to bind an address to. * @sock: socket to bind
* @addr: Address the user wants the socket bound to. * @addr: address to connect to
*
* Used by llc_ui_connect and llc_ui_sendmsg when the user hasn't
* specifically used llc_ui_bind to bind to an specific address/sap
* *
* Bind a socket to a specific address. For llc a user is able to bind to
* a specific sap only or mac + sap. If the user only specifies a sap and
* a null dmac (all zeros) the user is attempting to bind to an entire
* sap. This will stop anyone else on the local system from using that
* sap. If someone else has a mac + sap open the bind to null + sap will
* fail.
* If the user desires to bind to a specific mac + sap, it is possible to
* have multiple sap connections via multiple macs.
* Bind and autobind for that matter must enforce the correct sap usage
* otherwise all hell will break loose.
* Returns: 0 upon success, negative otherwise. * Returns: 0 upon success, negative otherwise.
*/ */
static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr) static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr)
...@@ -285,11 +275,7 @@ out: ...@@ -285,11 +275,7 @@ out:
* @addrlen: Length of the uaddr structure. * @addrlen: Length of the uaddr structure.
* *
* Bind a socket to a specific address. For llc a user is able to bind to * Bind a socket to a specific address. For llc a user is able to bind to
* a specific sap only or mac + sap. If the user only specifies a sap and * a specific sap only or mac + sap.
* a null dmac (all zeros) the user is attempting to bind to an entire
* sap. This will stop anyone else on the local system from using that
* sap. If someone else has a mac + sap open the bind to null + sap will
* fail.
* If the user desires to bind to a specific mac + sap, it is possible to * If the user desires to bind to a specific mac + sap, it is possible to
* have multiple sap connections via multiple macs. * have multiple sap connections via multiple macs.
* Bind and autobind for that matter must enforce the correct sap usage * Bind and autobind for that matter must enforce the correct sap usage
...@@ -305,10 +291,16 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) ...@@ -305,10 +291,16 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
int rc = -EINVAL; int rc = -EINVAL;
dprintk("%s: binding %02X\n", __FUNCTION__, addr->sllc_sap); dprintk("%s: binding %02X\n", __FUNCTION__, addr->sllc_sap);
if (!sock_flag(sk, SOCK_ZAPPED) || addrlen != sizeof(*addr)) if (unlikely(!sock_flag(sk, SOCK_ZAPPED) || addrlen != sizeof(*addr)))
goto out; goto out;
rc = -EAFNOSUPPORT; rc = -EAFNOSUPPORT;
if (addr->sllc_family != AF_LLC) if (unlikely(addr->sllc_family != AF_LLC))
goto out;
rc = -ENODEV;
rtnl_lock();
llc->dev = dev_getbyhwaddr(addr->sllc_arphrd, addr->sllc_mac);
rtnl_unlock();
if (!llc->dev)
goto out; goto out;
if (!addr->sllc_sap) { if (!addr->sllc_sap) {
rc = -EUSERS; rc = -EUSERS;
...@@ -322,6 +314,7 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) ...@@ -322,6 +314,7 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
rc = -EBUSY; /* some other network layer is using the sap */ rc = -EBUSY; /* some other network layer is using the sap */
if (!sap) if (!sap)
goto out; goto out;
llc_sap_hold(sap);
} else { } else {
struct llc_addr laddr, daddr; struct llc_addr laddr, daddr;
struct sock *ask; struct sock *ask;
...@@ -338,7 +331,7 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) ...@@ -338,7 +331,7 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
ask = llc_lookup_established(sap, &daddr, &laddr); ask = llc_lookup_established(sap, &daddr, &laddr);
if (ask) { if (ask) {
sock_put(ask); sock_put(ask);
goto out; goto out_put;
} }
} }
llc->laddr.lsap = addr->sllc_sap; llc->laddr.lsap = addr->sllc_sap;
...@@ -348,6 +341,8 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) ...@@ -348,6 +341,8 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
llc_sap_add_socket(sap, sk); llc_sap_add_socket(sap, sk);
sock_reset_flag(sk, SOCK_ZAPPED); sock_reset_flag(sk, SOCK_ZAPPED);
rc = 0; rc = 0;
out_put:
llc_sap_put(sap);
out: out:
return rc; return rc;
} }
...@@ -369,7 +364,7 @@ static int llc_ui_shutdown(struct socket *sock, int how) ...@@ -369,7 +364,7 @@ static int llc_ui_shutdown(struct socket *sock, int how)
int rc = -ENOTCONN; int rc = -ENOTCONN;
lock_sock(sk); lock_sock(sk);
if (sk->sk_state != TCP_ESTABLISHED) if (unlikely(sk->sk_state != TCP_ESTABLISHED))
goto out; goto out;
rc = -EINVAL; rc = -EINVAL;
if (how != 2) if (how != 2)
...@@ -404,14 +399,18 @@ static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr, ...@@ -404,14 +399,18 @@ static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr,
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct llc_sock *llc = llc_sk(sk); struct llc_sock *llc = llc_sk(sk);
struct sockaddr_llc *addr = (struct sockaddr_llc *)uaddr; struct sockaddr_llc *addr = (struct sockaddr_llc *)uaddr;
struct net_device *dev;
int rc = -EINVAL; int rc = -EINVAL;
lock_sock(sk); lock_sock(sk);
if (addrlen != sizeof(*addr)) if (unlikely(addrlen != sizeof(*addr)))
goto out; goto out;
rc = -EAFNOSUPPORT; rc = -EAFNOSUPPORT;
if (addr->sllc_family != AF_LLC) if (unlikely(addr->sllc_family != AF_LLC))
goto out;
if (unlikely(sk->sk_type != SOCK_STREAM))
goto out;
rc = -EALREADY;
if (unlikely(sock->state == SS_CONNECTING))
goto out; goto out;
/* bind connection to sap if user hasn't done it. */ /* bind connection to sap if user hasn't done it. */
if (sock_flag(sk, SOCK_ZAPPED)) { if (sock_flag(sk, SOCK_ZAPPED)) {
...@@ -419,19 +418,13 @@ static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr, ...@@ -419,19 +418,13 @@ static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr,
rc = llc_ui_autobind(sock, addr); rc = llc_ui_autobind(sock, addr);
if (rc) if (rc)
goto out; goto out;
llc->daddr.lsap = addr->sllc_sap;
memcpy(llc->daddr.mac, addr->sllc_mac, IFHWADDRLEN);
} }
dev = llc->dev; llc->daddr.lsap = addr->sllc_sap;
if (sk->sk_type != SOCK_STREAM) memcpy(llc->daddr.mac, addr->sllc_mac, IFHWADDRLEN);
goto out;
rc = -EALREADY;
if (sock->state == SS_CONNECTING)
goto out;
sock->state = SS_CONNECTING; sock->state = SS_CONNECTING;
sk->sk_state = TCP_SYN_SENT; sk->sk_state = TCP_SYN_SENT;
llc->link = llc_ui_next_link_no(llc->sap->laddr.lsap); llc->link = llc_ui_next_link_no(llc->sap->laddr.lsap);
rc = llc_establish_connection(sk, dev->dev_addr, rc = llc_establish_connection(sk, llc->dev->dev_addr,
addr->sllc_mac, addr->sllc_sap); addr->sllc_mac, addr->sllc_sap);
if (rc) { if (rc) {
dprintk("%s: llc_ui_send_conn failed :-(\n", __FUNCTION__); dprintk("%s: llc_ui_send_conn failed :-(\n", __FUNCTION__);
...@@ -439,12 +432,30 @@ static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr, ...@@ -439,12 +432,30 @@ static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr,
sk->sk_state = TCP_CLOSE; sk->sk_state = TCP_CLOSE;
goto out; goto out;
} }
rc = llc_ui_wait_for_conn(sk, sk->sk_rcvtimeo);
if (rc) if (sk->sk_state == TCP_SYN_SENT) {
dprintk("%s: llc_ui_wait_for_conn failed=%d\n", __FUNCTION__, rc); const long timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
if (!timeo || !llc_ui_wait_for_conn(sk, timeo))
goto out;
rc = sock_intr_errno(timeo);
if (signal_pending(current))
goto out;
}
if (sk->sk_state == TCP_CLOSE)
goto sock_error;
sock->state = SS_CONNECTED;
rc = 0;
out: out:
release_sock(sk); release_sock(sk);
return rc; return rc;
sock_error:
rc = sock_error(sk) ? : -ECONNABORTED;
sock->state = SS_UNCONNECTED;
goto out;
} }
/** /**
...@@ -461,10 +472,10 @@ static int llc_ui_listen(struct socket *sock, int backlog) ...@@ -461,10 +472,10 @@ static int llc_ui_listen(struct socket *sock, int backlog)
int rc = -EINVAL; int rc = -EINVAL;
lock_sock(sk); lock_sock(sk);
if (sock->state != SS_UNCONNECTED) if (unlikely(sock->state != SS_UNCONNECTED))
goto out; goto out;
rc = -EOPNOTSUPP; rc = -EOPNOTSUPP;
if (sk->sk_type != SOCK_STREAM) if (unlikely(sk->sk_type != SOCK_STREAM))
goto out; goto out;
rc = -EAGAIN; rc = -EAGAIN;
if (sock_flag(sk, SOCK_ZAPPED)) if (sock_flag(sk, SOCK_ZAPPED))
...@@ -483,20 +494,14 @@ out: ...@@ -483,20 +494,14 @@ out:
return rc; return rc;
} }
static int llc_ui_wait_for_disc(struct sock *sk, int timeout) static int llc_ui_wait_for_disc(struct sock *sk, long timeout)
{ {
DECLARE_WAITQUEUE(wait, current); DEFINE_WAIT(wait);
int rc; int rc = 0;
add_wait_queue_exclusive(sk->sk_sleep, &wait); while (1) {
for (;;) { prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
__set_current_state(TASK_INTERRUPTIBLE); if (sk_wait_event(sk, &timeout, sk->sk_state == TCP_CLOSE))
rc = 0;
if (sk->sk_state != TCP_CLOSE) {
release_sock(sk);
timeout = schedule_timeout(timeout);
lock_sock(sk);
} else
break; break;
rc = -ERESTARTSYS; rc = -ERESTARTSYS;
if (signal_pending(current)) if (signal_pending(current))
...@@ -504,65 +509,40 @@ static int llc_ui_wait_for_disc(struct sock *sk, int timeout) ...@@ -504,65 +509,40 @@ static int llc_ui_wait_for_disc(struct sock *sk, int timeout)
rc = -EAGAIN; rc = -EAGAIN;
if (!timeout) if (!timeout)
break; break;
rc = 0;
} }
__set_current_state(TASK_RUNNING); finish_wait(sk->sk_sleep, &wait);
remove_wait_queue(sk->sk_sleep, &wait);
return rc; return rc;
} }
static int llc_ui_wait_for_conn(struct sock *sk, int timeout) static int llc_ui_wait_for_conn(struct sock *sk, long timeout)
{ {
DECLARE_WAITQUEUE(wait, current); DEFINE_WAIT(wait);
int rc;
add_wait_queue_exclusive(sk->sk_sleep, &wait); while (1) {
for (;;) { prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
__set_current_state(TASK_INTERRUPTIBLE); if (sk_wait_event(sk, &timeout, sk->sk_state != TCP_SYN_SENT))
rc = -EAGAIN;
if (sk->sk_state == TCP_CLOSE)
break;
rc = 0;
if (sk->sk_state != TCP_ESTABLISHED) {
release_sock(sk);
timeout = schedule_timeout(timeout);
lock_sock(sk);
} else
break; break;
rc = -ERESTARTSYS; if (signal_pending(current) || !timeout)
if (signal_pending(current))
break;
rc = -EAGAIN;
if (!timeout)
break; break;
} }
__set_current_state(TASK_RUNNING); finish_wait(sk->sk_sleep, &wait);
remove_wait_queue(sk->sk_sleep, &wait); return timeout;
return rc;
} }
static int llc_ui_wait_for_data(struct sock *sk, int timeout) static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout)
{ {
DECLARE_WAITQUEUE(wait, current); DEFINE_WAIT(wait);
int rc = 0; struct llc_sock *llc = llc_sk(sk);
int rc;
add_wait_queue_exclusive(sk->sk_sleep, &wait); while (1) {
for (;;) { prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
__set_current_state(TASK_INTERRUPTIBLE);
if (sk->sk_shutdown & RCV_SHUTDOWN)
break;
/*
* Well, if we have backlog, try to process it now.
*/
if (sk->sk_backlog.tail) {
release_sock(sk);
lock_sock(sk);
}
rc = 0; rc = 0;
if (skb_queue_empty(&sk->sk_receive_queue)) { if (sk_wait_event(sk, &timeout,
release_sock(sk); (sk->sk_shutdown & RCV_SHUTDOWN) ||
timeout = schedule_timeout(timeout); (!llc_data_accept_state(llc->state) &&
lock_sock(sk); !llc->p_flag)))
} else
break; break;
rc = -ERESTARTSYS; rc = -ERESTARTSYS;
if (signal_pending(current)) if (signal_pending(current))
...@@ -571,40 +551,35 @@ static int llc_ui_wait_for_data(struct sock *sk, int timeout) ...@@ -571,40 +551,35 @@ static int llc_ui_wait_for_data(struct sock *sk, int timeout)
if (!timeout) if (!timeout)
break; break;
} }
__set_current_state(TASK_RUNNING); finish_wait(sk->sk_sleep, &wait);
remove_wait_queue(sk->sk_sleep, &wait);
return rc; return rc;
} }
static int llc_ui_wait_for_busy_core(struct sock *sk, int timeout) static int llc_wait_data(struct sock *sk, long timeo)
{ {
DECLARE_WAITQUEUE(wait, current);
struct llc_sock *llc = llc_sk(sk);
int rc; int rc;
add_wait_queue_exclusive(sk->sk_sleep, &wait); while (1) {
for (;;) { /*
dprintk("%s: looping...\n", __FUNCTION__); * POSIX 1003.1g mandates this order.
__set_current_state(TASK_INTERRUPTIBLE); */
rc = -ENOTCONN; if (sk->sk_err) {
if (sk->sk_shutdown & RCV_SHUTDOWN) rc = sock_error(sk);
break; break;
}
rc = 0; rc = 0;
if (llc_data_accept_state(llc->state) || llc->p_flag) { if (sk->sk_shutdown & RCV_SHUTDOWN)
release_sock(sk);
timeout = schedule_timeout(timeout);
lock_sock(sk);
} else
break; break;
rc = -ERESTARTSYS; rc = -EAGAIN;
if (!timeo)
break;
rc = sock_intr_errno(timeo);
if (signal_pending(current)) if (signal_pending(current))
break; break;
rc = -EAGAIN; rc = 0;
if (!timeout) if (sk_wait_data(sk, &timeo))
break; break;
} }
__set_current_state(TASK_RUNNING);
remove_wait_queue(sk->sk_sleep, &wait);
return rc; return rc;
} }
...@@ -627,15 +602,18 @@ static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags) ...@@ -627,15 +602,18 @@ static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags)
dprintk("%s: accepting on %02X\n", __FUNCTION__, dprintk("%s: accepting on %02X\n", __FUNCTION__,
llc_sk(sk)->laddr.lsap); llc_sk(sk)->laddr.lsap);
lock_sock(sk); lock_sock(sk);
if (sk->sk_type != SOCK_STREAM) if (unlikely(sk->sk_type != SOCK_STREAM))
goto out; goto out;
rc = -EINVAL; rc = -EINVAL;
if (sock->state != SS_UNCONNECTED || sk->sk_state != TCP_LISTEN) if (unlikely(sock->state != SS_UNCONNECTED ||
sk->sk_state != TCP_LISTEN))
goto out; goto out;
/* wait for a connection to arrive. */ /* wait for a connection to arrive. */
rc = llc_ui_wait_for_data(sk, sk->sk_rcvtimeo); if (skb_queue_empty(&sk->sk_receive_queue)) {
if (rc) rc = llc_wait_data(sk, sk->sk_rcvtimeo);
goto out; if (rc)
goto out;
}
dprintk("%s: got a new connection on %02X\n", __FUNCTION__, dprintk("%s: got a new connection on %02X\n", __FUNCTION__,
llc_sk(sk)->laddr.lsap); llc_sk(sk)->laddr.lsap);
skb = skb_dequeue(&sk->sk_receive_queue); skb = skb_dequeue(&sk->sk_receive_queue);
...@@ -657,7 +635,6 @@ static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags) ...@@ -657,7 +635,6 @@ static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags)
/* put original socket back into a clean listen state. */ /* put original socket back into a clean listen state. */
sk->sk_state = TCP_LISTEN; sk->sk_state = TCP_LISTEN;
sk->sk_ack_backlog--; sk->sk_ack_backlog--;
skb->sk = NULL;
dprintk("%s: ok success on %02X, client on %02X\n", __FUNCTION__, dprintk("%s: ok success on %02X, client on %02X\n", __FUNCTION__,
llc_sk(sk)->addr.sllc_sap, newllc->daddr.lsap); llc_sk(sk)->addr.sllc_sap, newllc->daddr.lsap);
frees: frees:
...@@ -671,56 +648,167 @@ out: ...@@ -671,56 +648,167 @@ out:
* llc_ui_recvmsg - copy received data to the socket user. * llc_ui_recvmsg - copy received data to the socket user.
* @sock: Socket to copy data from. * @sock: Socket to copy data from.
* @msg: Various user space related information. * @msg: Various user space related information.
* @size: Size of user buffer. * @len: Size of user buffer.
* @flags: User specified flags. * @flags: User specified flags.
* *
* Copy received data to the socket user. * Copy received data to the socket user.
* Returns non-negative upon success, negative otherwise. * Returns non-negative upon success, negative otherwise.
*/ */
static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock, static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t size, int flags) struct msghdr *msg, size_t len, int flags)
{ {
struct sock *sk = sock->sk;
struct sockaddr_llc *uaddr = (struct sockaddr_llc *)msg->msg_name; struct sockaddr_llc *uaddr = (struct sockaddr_llc *)msg->msg_name;
struct sk_buff *skb; const int nonblock = flags & MSG_DONTWAIT;
struct sk_buff *skb = NULL;
struct sock *sk = sock->sk;
struct llc_sock *llc = llc_sk(sk);
size_t copied = 0; size_t copied = 0;
int rc = -ENOMEM, timeout; u32 peek_seq = 0;
int noblock = flags & MSG_DONTWAIT; u32 *seq;
unsigned long used;
int target; /* Read at least this many bytes */
long timeo;
dprintk("%s: receiving in %02X from %02X\n", __FUNCTION__,
llc_sk(sk)->laddr.lsap, llc_sk(sk)->daddr.lsap);
lock_sock(sk); lock_sock(sk);
timeout = sock_rcvtimeo(sk, noblock); copied = -ENOTCONN;
rc = llc_ui_wait_for_data(sk, timeout); if (sk->sk_state == TCP_LISTEN)
if (rc) {
dprintk("%s: llc_ui_wait_for_data failed recv "
"in %02X from %02X\n", __FUNCTION__,
llc_sk(sk)->laddr.lsap, llc_sk(sk)->daddr.lsap);
goto out; goto out;
}
skb = skb_dequeue(&sk->sk_receive_queue); timeo = sock_rcvtimeo(sk, nonblock);
if (!skb) /* shutdown */
goto out; seq = &llc->copied_seq;
copied = skb->len; if (flags & MSG_PEEK) {
if (copied > size) peek_seq = llc->copied_seq;
copied = size; seq = &peek_seq;
rc = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); }
if (rc)
goto dgram_free; target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);
if (skb->len > copied) { copied = 0;
skb_pull(skb, copied);
skb_queue_head(&sk->sk_receive_queue, skb); do {
} u32 offset;
if (uaddr)
memcpy(uaddr, llc_ui_skb_cb(skb), sizeof(*uaddr)); /*
msg->msg_namelen = sizeof(*uaddr); * We need to check signals first, to get correct SIGURG
if (!skb->next) { * handling. FIXME: Need to check this doesn't impact 1003.1g
dgram_free: * and move it down to the bottom of the loop
kfree_skb(skb); */
} if (signal_pending(current)) {
if (copied)
break;
copied = timeo ? sock_intr_errno(timeo) : -EAGAIN;
break;
}
/* Next get a buffer. */
skb = skb_peek(&sk->sk_receive_queue);
if (skb) {
offset = *seq;
goto found_ok_skb;
}
/* Well, if we have backlog, try to process it now yet. */
if (copied >= target && !sk->sk_backlog.tail)
break;
if (copied) {
if (sk->sk_err ||
sk->sk_state == TCP_CLOSE ||
(sk->sk_shutdown & RCV_SHUTDOWN) ||
!timeo ||
(flags & MSG_PEEK))
break;
} else {
if (sock_flag(sk, SOCK_DONE))
break;
if (sk->sk_err) {
copied = sock_error(sk);
break;
}
if (sk->sk_shutdown & RCV_SHUTDOWN)
break;
if (sk->sk_state == TCP_CLOSE) {
if (!sock_flag(sk, SOCK_DONE)) {
/*
* This occurs when user tries to read
* from never connected socket.
*/
copied = -ENOTCONN;
break;
}
break;
}
if (!timeo) {
copied = -EAGAIN;
break;
}
}
if (copied >= target) { /* Do not sleep, just process backlog. */
release_sock(sk);
lock_sock(sk);
} else
sk_wait_data(sk, &timeo);
if ((flags & MSG_PEEK) && peek_seq != llc->copied_seq) {
if (net_ratelimit())
printk(KERN_DEBUG "LLC(%s:%d): Application "
"bug, race in MSG_PEEK.\n",
current->comm, current->pid);
peek_seq = llc->copied_seq;
}
continue;
found_ok_skb:
/* Ok so how much can we use? */
used = skb->len - offset;
if (len < used)
used = len;
if (!(flags & MSG_TRUNC)) {
int rc = skb_copy_datagram_iovec(skb, offset,
msg->msg_iov, used);
if (rc) {
/* Exception. Bailout! */
if (!copied)
copied = -EFAULT;
break;
}
}
*seq += used;
copied += used;
len -= used;
if (used + offset < skb->len)
continue;
if (!(flags & MSG_PEEK)) {
sk_eat_skb(sk, skb);
*seq = 0;
}
} while (len > 0);
/*
* According to UNIX98, msg_name/msg_namelen are ignored
* on connected socket. -ANK
* But... af_llc still doesn't have separate sets of methods for
* SOCK_DGRAM and SOCK_STREAM :-( So we have to do this test, will
* eventually fix this tho :-) -acme
*/
if (sk->sk_type == SOCK_DGRAM)
goto copy_uaddr;
out: out:
release_sock(sk); release_sock(sk);
return rc ? : copied; return copied;
copy_uaddr:
if (uaddr != NULL && skb != NULL) {
memcpy(uaddr, llc_ui_skb_cb(skb), sizeof(*uaddr));
msg->msg_namelen = sizeof(*uaddr);
}
goto out;
} }
/** /**
...@@ -740,7 +828,6 @@ static int llc_ui_sendmsg(struct kiocb *iocb, struct socket *sock, ...@@ -740,7 +828,6 @@ static int llc_ui_sendmsg(struct kiocb *iocb, struct socket *sock,
struct sockaddr_llc *addr = (struct sockaddr_llc *)msg->msg_name; struct sockaddr_llc *addr = (struct sockaddr_llc *)msg->msg_name;
int flags = msg->msg_flags; int flags = msg->msg_flags;
int noblock = flags & MSG_DONTWAIT; int noblock = flags & MSG_DONTWAIT;
struct net_device *dev;
struct sk_buff *skb; struct sk_buff *skb;
size_t size = 0; size_t size = 0;
int rc = -EINVAL, copied = 0, hdrlen; int rc = -EINVAL, copied = 0, hdrlen;
...@@ -763,19 +850,17 @@ static int llc_ui_sendmsg(struct kiocb *iocb, struct socket *sock, ...@@ -763,19 +850,17 @@ static int llc_ui_sendmsg(struct kiocb *iocb, struct socket *sock,
if (rc) if (rc)
goto release; goto release;
} }
dev = llc->dev; hdrlen = llc->dev->hard_header_len + llc_ui_header_len(sk, addr);
hdrlen = dev->hard_header_len + llc_ui_header_len(sk, addr);
size = hdrlen + len; size = hdrlen + len;
if (size > dev->mtu) if (size > llc->dev->mtu)
size = dev->mtu; size = llc->dev->mtu;
copied = size - hdrlen; copied = size - hdrlen;
release_sock(sk); release_sock(sk);
skb = sock_alloc_send_skb(sk, size, noblock, &rc); skb = sock_alloc_send_skb(sk, size, noblock, &rc);
lock_sock(sk); lock_sock(sk);
if (!skb) if (!skb)
goto release; goto release;
skb->sk = sk; skb->dev = llc->dev;
skb->dev = dev;
skb->protocol = llc_proto_type(addr->sllc_arphrd); skb->protocol = llc_proto_type(addr->sllc_arphrd);
skb_reserve(skb, hdrlen); skb_reserve(skb, hdrlen);
rc = memcpy_fromiovec(skb_put(skb, copied), msg->msg_iov, copied); rc = memcpy_fromiovec(skb_put(skb, copied), msg->msg_iov, copied);
...@@ -800,15 +885,13 @@ static int llc_ui_sendmsg(struct kiocb *iocb, struct socket *sock, ...@@ -800,15 +885,13 @@ static int llc_ui_sendmsg(struct kiocb *iocb, struct socket *sock,
if (!(sk->sk_type == SOCK_STREAM && !addr->sllc_ua)) if (!(sk->sk_type == SOCK_STREAM && !addr->sllc_ua))
goto out; goto out;
rc = llc_ui_send_data(sk, skb, noblock); rc = llc_ui_send_data(sk, skb, noblock);
if (rc)
dprintk("%s: llc_ui_send_data failed: %d\n", __FUNCTION__, rc);
out: out:
if (rc) if (rc) {
kfree_skb(skb); kfree_skb(skb);
release: release:
if (rc)
dprintk("%s: failed sending from %02X to %02X: %d\n", dprintk("%s: failed sending from %02X to %02X: %d\n",
__FUNCTION__, llc->laddr.lsap, llc->daddr.lsap, rc); __FUNCTION__, llc->laddr.lsap, llc->daddr.lsap, rc);
}
release_sock(sk); release_sock(sk);
return rc ? : copied; return rc ? : copied;
} }
...@@ -895,7 +978,7 @@ static int llc_ui_setsockopt(struct socket *sock, int level, int optname, ...@@ -895,7 +978,7 @@ static int llc_ui_setsockopt(struct socket *sock, int level, int optname,
int rc = -EINVAL, opt; int rc = -EINVAL, opt;
lock_sock(sk); lock_sock(sk);
if (level != SOL_LLC || optlen != sizeof(int)) if (unlikely(level != SOL_LLC || optlen != sizeof(int)))
goto out; goto out;
rc = get_user(opt, (int __user *)optval); rc = get_user(opt, (int __user *)optval);
if (rc) if (rc)
...@@ -915,22 +998,22 @@ static int llc_ui_setsockopt(struct socket *sock, int level, int optname, ...@@ -915,22 +998,22 @@ static int llc_ui_setsockopt(struct socket *sock, int level, int optname,
case LLC_OPT_ACK_TMR_EXP: case LLC_OPT_ACK_TMR_EXP:
if (opt > LLC_OPT_MAX_ACK_TMR_EXP) if (opt > LLC_OPT_MAX_ACK_TMR_EXP)
goto out; goto out;
llc->ack_timer.expire = opt; llc->ack_timer.expire = opt * HZ;
break; break;
case LLC_OPT_P_TMR_EXP: case LLC_OPT_P_TMR_EXP:
if (opt > LLC_OPT_MAX_P_TMR_EXP) if (opt > LLC_OPT_MAX_P_TMR_EXP)
goto out; goto out;
llc->pf_cycle_timer.expire = opt; llc->pf_cycle_timer.expire = opt * HZ;
break; break;
case LLC_OPT_REJ_TMR_EXP: case LLC_OPT_REJ_TMR_EXP:
if (opt > LLC_OPT_MAX_REJ_TMR_EXP) if (opt > LLC_OPT_MAX_REJ_TMR_EXP)
goto out; goto out;
llc->rej_sent_timer.expire = opt; llc->rej_sent_timer.expire = opt * HZ;
break; break;
case LLC_OPT_BUSY_TMR_EXP: case LLC_OPT_BUSY_TMR_EXP:
if (opt > LLC_OPT_MAX_BUSY_TMR_EXP) if (opt > LLC_OPT_MAX_BUSY_TMR_EXP)
goto out; goto out;
llc->busy_state_timer.expire = opt; llc->busy_state_timer.expire = opt * HZ;
break; break;
case LLC_OPT_TX_WIN: case LLC_OPT_TX_WIN:
if (opt > LLC_OPT_MAX_WIN) if (opt > LLC_OPT_MAX_WIN)
...@@ -970,7 +1053,7 @@ static int llc_ui_getsockopt(struct socket *sock, int level, int optname, ...@@ -970,7 +1053,7 @@ static int llc_ui_getsockopt(struct socket *sock, int level, int optname,
int val = 0, len = 0, rc = -EINVAL; int val = 0, len = 0, rc = -EINVAL;
lock_sock(sk); lock_sock(sk);
if (level != SOL_LLC) if (unlikely(level != SOL_LLC))
goto out; goto out;
rc = get_user(len, optlen); rc = get_user(len, optlen);
if (rc) if (rc)
...@@ -980,17 +1063,17 @@ static int llc_ui_getsockopt(struct socket *sock, int level, int optname, ...@@ -980,17 +1063,17 @@ static int llc_ui_getsockopt(struct socket *sock, int level, int optname,
goto out; goto out;
switch (optname) { switch (optname) {
case LLC_OPT_RETRY: case LLC_OPT_RETRY:
val = llc->n2; break; val = llc->n2; break;
case LLC_OPT_SIZE: case LLC_OPT_SIZE:
val = llc->n1; break; val = llc->n1; break;
case LLC_OPT_ACK_TMR_EXP: case LLC_OPT_ACK_TMR_EXP:
val = llc->ack_timer.expire; break; val = llc->ack_timer.expire / HZ; break;
case LLC_OPT_P_TMR_EXP: case LLC_OPT_P_TMR_EXP:
val = llc->pf_cycle_timer.expire; break; val = llc->pf_cycle_timer.expire / HZ; break;
case LLC_OPT_REJ_TMR_EXP: case LLC_OPT_REJ_TMR_EXP:
val = llc->rej_sent_timer.expire; break; val = llc->rej_sent_timer.expire / HZ; break;
case LLC_OPT_BUSY_TMR_EXP: case LLC_OPT_BUSY_TMR_EXP:
val = llc->busy_state_timer.expire; break; val = llc->busy_state_timer.expire / HZ; break;
case LLC_OPT_TX_WIN: case LLC_OPT_TX_WIN:
val = llc->k; break; val = llc->k; break;
case LLC_OPT_RX_WIN: case LLC_OPT_RX_WIN:
...@@ -1034,8 +1117,12 @@ static struct proto_ops llc_ui_ops = { ...@@ -1034,8 +1117,12 @@ static struct proto_ops llc_ui_ops = {
.sendpage = sock_no_sendpage, .sendpage = sock_no_sendpage,
}; };
extern void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb); static char llc_proc_err_msg[] __initdata =
extern void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb); KERN_CRIT "LLC: Unable to register the proc_fs entries\n";
static char llc_sysctl_err_msg[] __initdata =
KERN_CRIT "LLC: Unable to register the sysctl entries\n";
static char llc_sock_err_msg[] __initdata =
KERN_CRIT "LLC: Unable to register the network family\n";
static int __init llc2_init(void) static int __init llc2_init(void)
{ {
...@@ -1048,13 +1135,28 @@ static int __init llc2_init(void) ...@@ -1048,13 +1135,28 @@ static int __init llc2_init(void)
llc_station_init(); llc_station_init();
llc_ui_sap_last_autoport = LLC_SAP_DYN_START; llc_ui_sap_last_autoport = LLC_SAP_DYN_START;
rc = llc_proc_init(); rc = llc_proc_init();
if (rc != 0) if (rc != 0) {
printk(llc_proc_err_msg);
goto out_unregister_llc_proto; goto out_unregister_llc_proto;
sock_register(&llc_ui_family_ops); }
rc = llc_sysctl_init();
if (rc) {
printk(llc_sysctl_err_msg);
goto out_proc;
}
rc = sock_register(&llc_ui_family_ops);
if (rc) {
printk(llc_sock_err_msg);
goto out_sysctl;
}
llc_add_pack(LLC_DEST_SAP, llc_sap_handler); llc_add_pack(LLC_DEST_SAP, llc_sap_handler);
llc_add_pack(LLC_DEST_CONN, llc_conn_handler); llc_add_pack(LLC_DEST_CONN, llc_conn_handler);
out: out:
return rc; return rc;
out_sysctl:
llc_sysctl_exit();
out_proc:
llc_proc_exit();
out_unregister_llc_proto: out_unregister_llc_proto:
proto_unregister(&llc_proto); proto_unregister(&llc_proto);
goto out; goto out;
...@@ -1067,6 +1169,7 @@ static void __exit llc2_exit(void) ...@@ -1067,6 +1169,7 @@ static void __exit llc2_exit(void)
llc_remove_pack(LLC_DEST_CONN); llc_remove_pack(LLC_DEST_CONN);
sock_unregister(PF_LLC); sock_unregister(PF_LLC);
llc_proc_exit(); llc_proc_exit();
llc_sysctl_exit();
proto_unregister(&llc_proto); proto_unregister(&llc_proto);
} }
......
...@@ -60,23 +60,10 @@ int llc_conn_ac_clear_remote_busy(struct sock *sk, struct sk_buff *skb) ...@@ -60,23 +60,10 @@ int llc_conn_ac_clear_remote_busy(struct sock *sk, struct sk_buff *skb)
int llc_conn_ac_conn_ind(struct sock *sk, struct sk_buff *skb) int llc_conn_ac_conn_ind(struct sock *sk, struct sk_buff *skb)
{ {
int rc = -ENOTCONN; struct llc_conn_state_ev *ev = llc_conn_ev(skb);
u8 dsap;
struct llc_sap *sap;
llc_pdu_decode_dsap(skb, &dsap);
sap = llc_sap_find(dsap);
if (sap) {
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
struct llc_sock *llc = llc_sk(sk);
llc_pdu_decode_sa(skb, llc->daddr.mac); ev->ind_prim = LLC_CONN_PRIM;
llc_pdu_decode_da(skb, llc->laddr.mac); return 0;
llc->dev = skb->dev;
ev->ind_prim = LLC_CONN_PRIM;
rc = 0;
}
return rc;
} }
int llc_conn_ac_conn_confirm(struct sock *sk, struct sk_buff *skb) int llc_conn_ac_conn_confirm(struct sock *sk, struct sk_buff *skb)
...@@ -120,10 +107,8 @@ int llc_conn_ac_disc_ind(struct sock *sk, struct sk_buff *skb) ...@@ -120,10 +107,8 @@ int llc_conn_ac_disc_ind(struct sock *sk, struct sk_buff *skb)
reason = LLC_DISC_REASON_RX_DISC_CMD_PDU; reason = LLC_DISC_REASON_RX_DISC_CMD_PDU;
} else if (ev->type == LLC_CONN_EV_TYPE_ACK_TMR) } else if (ev->type == LLC_CONN_EV_TYPE_ACK_TMR)
reason = LLC_DISC_REASON_ACK_TMR_EXP; reason = LLC_DISC_REASON_ACK_TMR_EXP;
else { else
reason = 0;
rc = -EINVAL; rc = -EINVAL;
}
if (!rc) { if (!rc) {
ev->reason = reason; ev->reason = reason;
ev->ind_prim = LLC_DISC_PRIM; ev->ind_prim = LLC_DISC_PRIM;
...@@ -160,9 +145,6 @@ int llc_conn_ac_rst_ind(struct sock *sk, struct sk_buff *skb) ...@@ -160,9 +145,6 @@ int llc_conn_ac_rst_ind(struct sock *sk, struct sk_buff *skb)
LLC_U_PDU_CMD(pdu) == LLC_2_PDU_CMD_SABME) { LLC_U_PDU_CMD(pdu) == LLC_2_PDU_CMD_SABME) {
reason = LLC_RESET_REASON_REMOTE; reason = LLC_RESET_REASON_REMOTE;
rc = 0; rc = 0;
} else {
reason = 0;
rc = 1;
} }
break; break;
case LLC_CONN_EV_TYPE_ACK_TMR: case LLC_CONN_EV_TYPE_ACK_TMR:
...@@ -172,8 +154,7 @@ int llc_conn_ac_rst_ind(struct sock *sk, struct sk_buff *skb) ...@@ -172,8 +154,7 @@ int llc_conn_ac_rst_ind(struct sock *sk, struct sk_buff *skb)
if (llc->retry_count > llc->n2) { if (llc->retry_count > llc->n2) {
reason = LLC_RESET_REASON_LOCAL; reason = LLC_RESET_REASON_LOCAL;
rc = 0; rc = 0;
} else }
rc = 1;
break; break;
} }
if (!rc) { if (!rc) {
...@@ -217,18 +198,17 @@ int llc_conn_ac_stop_rej_tmr_if_data_flag_eq_2(struct sock *sk, ...@@ -217,18 +198,17 @@ int llc_conn_ac_stop_rej_tmr_if_data_flag_eq_2(struct sock *sk,
int llc_conn_ac_send_disc_cmd_p_set_x(struct sock *sk, struct sk_buff *skb) int llc_conn_ac_send_disc_cmd_p_set_x(struct sock *sk, struct sk_buff *skb)
{ {
int rc = -ENOBUFS; int rc = -ENOBUFS;
struct sk_buff *nskb = llc_alloc_frame(); struct llc_sock *llc = llc_sk(sk);
struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
if (nskb) { if (nskb) {
struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap; struct llc_sap *sap = llc->sap;
nskb->dev = llc->dev;
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap,
llc->daddr.lsap, LLC_PDU_CMD); llc->daddr.lsap, LLC_PDU_CMD);
llc_pdu_init_as_disc_cmd(nskb, 1); llc_pdu_init_as_disc_cmd(nskb, 1);
rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
if (rc) if (unlikely(rc))
goto free; goto free;
llc_conn_send_pdu(sk, nskb); llc_conn_send_pdu(sk, nskb);
llc_conn_ac_set_p_flag_1(sk, skb); llc_conn_ac_set_p_flag_1(sk, skb);
...@@ -243,20 +223,19 @@ free: ...@@ -243,20 +223,19 @@ free:
int llc_conn_ac_send_dm_rsp_f_set_p(struct sock *sk, struct sk_buff *skb) int llc_conn_ac_send_dm_rsp_f_set_p(struct sock *sk, struct sk_buff *skb)
{ {
int rc = -ENOBUFS; int rc = -ENOBUFS;
struct sk_buff *nskb = llc_alloc_frame(); struct llc_sock *llc = llc_sk(sk);
struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
if (nskb) { if (nskb) {
struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap; struct llc_sap *sap = llc->sap;
u8 f_bit; u8 f_bit;
nskb->dev = llc->dev;
llc_pdu_decode_pf_bit(skb, &f_bit); llc_pdu_decode_pf_bit(skb, &f_bit);
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap,
llc->daddr.lsap, LLC_PDU_RSP); llc->daddr.lsap, LLC_PDU_RSP);
llc_pdu_init_as_dm_rsp(nskb, f_bit); llc_pdu_init_as_dm_rsp(nskb, f_bit);
rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
if (rc) if (unlikely(rc))
goto free; goto free;
llc_conn_send_pdu(sk, nskb); llc_conn_send_pdu(sk, nskb);
} }
...@@ -270,19 +249,17 @@ free: ...@@ -270,19 +249,17 @@ free:
int llc_conn_ac_send_dm_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) int llc_conn_ac_send_dm_rsp_f_set_1(struct sock *sk, struct sk_buff *skb)
{ {
int rc = -ENOBUFS; int rc = -ENOBUFS;
struct sk_buff *nskb = llc_alloc_frame(); struct llc_sock *llc = llc_sk(sk);
struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
if (nskb) { if (nskb) {
struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap; struct llc_sap *sap = llc->sap;
u8 f_bit = 1;
nskb->dev = llc->dev;
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap,
llc->daddr.lsap, LLC_PDU_RSP); llc->daddr.lsap, LLC_PDU_RSP);
llc_pdu_init_as_dm_rsp(nskb, f_bit); llc_pdu_init_as_dm_rsp(nskb, 1);
rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
if (rc) if (unlikely(rc))
goto free; goto free;
llc_conn_send_pdu(sk, nskb); llc_conn_send_pdu(sk, nskb);
} }
...@@ -306,17 +283,16 @@ int llc_conn_ac_send_frmr_rsp_f_set_x(struct sock *sk, struct sk_buff *skb) ...@@ -306,17 +283,16 @@ int llc_conn_ac_send_frmr_rsp_f_set_x(struct sock *sk, struct sk_buff *skb)
llc_pdu_decode_pf_bit(skb, &f_bit); llc_pdu_decode_pf_bit(skb, &f_bit);
else else
f_bit = 0; f_bit = 0;
nskb = llc_alloc_frame(); nskb = llc_alloc_frame(sk, llc->dev);
if (nskb) { if (nskb) {
struct llc_sap *sap = llc->sap; struct llc_sap *sap = llc->sap;
nskb->dev = llc->dev;
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap,
llc->daddr.lsap, LLC_PDU_RSP); llc->daddr.lsap, LLC_PDU_RSP);
llc_pdu_init_as_frmr_rsp(nskb, pdu, f_bit, llc->vS, llc_pdu_init_as_frmr_rsp(nskb, pdu, f_bit, llc->vS,
llc->vR, INCORRECT); llc->vR, INCORRECT);
rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
if (rc) if (unlikely(rc))
goto free; goto free;
llc_conn_send_pdu(sk, nskb); llc_conn_send_pdu(sk, nskb);
} }
...@@ -330,21 +306,19 @@ free: ...@@ -330,21 +306,19 @@ free:
int llc_conn_ac_resend_frmr_rsp_f_set_0(struct sock *sk, struct sk_buff *skb) int llc_conn_ac_resend_frmr_rsp_f_set_0(struct sock *sk, struct sk_buff *skb)
{ {
int rc = -ENOBUFS; int rc = -ENOBUFS;
struct sk_buff *nskb = llc_alloc_frame(); struct llc_sock *llc = llc_sk(sk);
struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
if (nskb) { if (nskb) {
u8 f_bit = 0;
struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap; struct llc_sap *sap = llc->sap;
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)&llc->rx_pdu_hdr; struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)&llc->rx_pdu_hdr;
nskb->dev = llc->dev;
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap,
llc->daddr.lsap, LLC_PDU_RSP); llc->daddr.lsap, LLC_PDU_RSP);
llc_pdu_init_as_frmr_rsp(nskb, pdu, f_bit, llc->vS, llc_pdu_init_as_frmr_rsp(nskb, pdu, 0, llc->vS,
llc->vR, INCORRECT); llc->vR, INCORRECT);
rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
if (rc) if (unlikely(rc))
goto free; goto free;
llc_conn_send_pdu(sk, nskb); llc_conn_send_pdu(sk, nskb);
} }
...@@ -360,21 +334,20 @@ int llc_conn_ac_resend_frmr_rsp_f_set_p(struct sock *sk, struct sk_buff *skb) ...@@ -360,21 +334,20 @@ int llc_conn_ac_resend_frmr_rsp_f_set_p(struct sock *sk, struct sk_buff *skb)
u8 f_bit; u8 f_bit;
int rc = -ENOBUFS; int rc = -ENOBUFS;
struct sk_buff *nskb; struct sk_buff *nskb;
struct llc_sock *llc = llc_sk(sk);
llc_pdu_decode_pf_bit(skb, &f_bit); llc_pdu_decode_pf_bit(skb, &f_bit);
nskb = llc_alloc_frame(); nskb = llc_alloc_frame(sk, llc->dev);
if (nskb) { if (nskb) {
struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap; struct llc_sap *sap = llc->sap;
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
nskb->dev = llc->dev;
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap,
llc->daddr.lsap, LLC_PDU_RSP); llc->daddr.lsap, LLC_PDU_RSP);
llc_pdu_init_as_frmr_rsp(nskb, pdu, f_bit, llc->vS, llc_pdu_init_as_frmr_rsp(nskb, pdu, f_bit, llc->vS,
llc->vR, INCORRECT); llc->vR, INCORRECT);
rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
if (rc) if (unlikely(rc))
goto free; goto free;
llc_conn_send_pdu(sk, nskb); llc_conn_send_pdu(sk, nskb);
} }
...@@ -395,7 +368,7 @@ int llc_conn_ac_send_i_cmd_p_set_1(struct sock *sk, struct sk_buff *skb) ...@@ -395,7 +368,7 @@ int llc_conn_ac_send_i_cmd_p_set_1(struct sock *sk, struct sk_buff *skb)
llc->daddr.lsap, LLC_PDU_CMD); llc->daddr.lsap, LLC_PDU_CMD);
llc_pdu_init_as_i_cmd(skb, 1, llc->vS, llc->vR); llc_pdu_init_as_i_cmd(skb, 1, llc->vS, llc->vR);
rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac); rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac);
if (!rc) { if (likely(!rc)) {
llc_conn_send_pdu(sk, skb); llc_conn_send_pdu(sk, skb);
llc_conn_ac_inc_vs_by_1(sk, skb); llc_conn_ac_inc_vs_by_1(sk, skb);
} }
...@@ -412,7 +385,7 @@ static int llc_conn_ac_send_i_cmd_p_set_0(struct sock *sk, struct sk_buff *skb) ...@@ -412,7 +385,7 @@ static int llc_conn_ac_send_i_cmd_p_set_0(struct sock *sk, struct sk_buff *skb)
llc->daddr.lsap, LLC_PDU_CMD); llc->daddr.lsap, LLC_PDU_CMD);
llc_pdu_init_as_i_cmd(skb, 0, llc->vS, llc->vR); llc_pdu_init_as_i_cmd(skb, 0, llc->vS, llc->vR);
rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac); rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac);
if (!rc) { if (likely(!rc)) {
llc_conn_send_pdu(sk, skb); llc_conn_send_pdu(sk, skb);
llc_conn_ac_inc_vs_by_1(sk, skb); llc_conn_ac_inc_vs_by_1(sk, skb);
} }
...@@ -429,7 +402,7 @@ int llc_conn_ac_send_i_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) ...@@ -429,7 +402,7 @@ int llc_conn_ac_send_i_xxx_x_set_0(struct sock *sk, struct sk_buff *skb)
llc->daddr.lsap, LLC_PDU_CMD); llc->daddr.lsap, LLC_PDU_CMD);
llc_pdu_init_as_i_cmd(skb, 0, llc->vS, llc->vR); llc_pdu_init_as_i_cmd(skb, 0, llc->vS, llc->vR);
rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac); rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac);
if (!rc) { if (likely(!rc)) {
llc_conn_send_pdu(sk, skb); llc_conn_send_pdu(sk, skb);
llc_conn_ac_inc_vs_by_1(sk, skb); llc_conn_ac_inc_vs_by_1(sk, skb);
} }
...@@ -451,18 +424,17 @@ int llc_conn_ac_resend_i_xxx_x_set_0_or_send_rr(struct sock *sk, ...@@ -451,18 +424,17 @@ int llc_conn_ac_resend_i_xxx_x_set_0_or_send_rr(struct sock *sk,
u8 nr; u8 nr;
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
int rc = -ENOBUFS; int rc = -ENOBUFS;
struct sk_buff *nskb = llc_alloc_frame(); struct llc_sock *llc = llc_sk(sk);
struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
if (nskb) { if (nskb) {
struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap; struct llc_sap *sap = llc->sap;
nskb->dev = llc->dev;
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap,
llc->daddr.lsap, LLC_PDU_RSP); llc->daddr.lsap, LLC_PDU_RSP);
llc_pdu_init_as_rr_rsp(nskb, 0, llc->vR); llc_pdu_init_as_rr_rsp(nskb, 0, llc->vR);
rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
if (!rc) if (likely(!rc))
llc_conn_send_pdu(sk, nskb); llc_conn_send_pdu(sk, nskb);
else else
kfree_skb(skb); kfree_skb(skb);
...@@ -487,18 +459,17 @@ int llc_conn_ac_resend_i_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) ...@@ -487,18 +459,17 @@ int llc_conn_ac_resend_i_rsp_f_set_1(struct sock *sk, struct sk_buff *skb)
int llc_conn_ac_send_rej_cmd_p_set_1(struct sock *sk, struct sk_buff *skb) int llc_conn_ac_send_rej_cmd_p_set_1(struct sock *sk, struct sk_buff *skb)
{ {
int rc = -ENOBUFS; int rc = -ENOBUFS;
struct sk_buff *nskb = llc_alloc_frame(); struct llc_sock *llc = llc_sk(sk);
struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
if (nskb) { if (nskb) {
struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap; struct llc_sap *sap = llc->sap;
nskb->dev = llc->dev;
llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
llc->daddr.lsap, LLC_PDU_CMD); llc->daddr.lsap, LLC_PDU_CMD);
llc_pdu_init_as_rej_cmd(nskb, 1, llc->vR); llc_pdu_init_as_rej_cmd(nskb, 1, llc->vR);
rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
if (rc) if (unlikely(rc))
goto free; goto free;
llc_conn_send_pdu(sk, nskb); llc_conn_send_pdu(sk, nskb);
} }
...@@ -512,19 +483,17 @@ free: ...@@ -512,19 +483,17 @@ free:
int llc_conn_ac_send_rej_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) int llc_conn_ac_send_rej_rsp_f_set_1(struct sock *sk, struct sk_buff *skb)
{ {
int rc = -ENOBUFS; int rc = -ENOBUFS;
struct sk_buff *nskb = llc_alloc_frame(); struct llc_sock *llc = llc_sk(sk);
struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
if (nskb) { if (nskb) {
u8 f_bit = 1;
struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap; struct llc_sap *sap = llc->sap;
nskb->dev = llc->dev;
llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
llc->daddr.lsap, LLC_PDU_RSP); llc->daddr.lsap, LLC_PDU_RSP);
llc_pdu_init_as_rej_rsp(nskb, f_bit, llc->vR); llc_pdu_init_as_rej_rsp(nskb, 1, llc->vR);
rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
if (rc) if (unlikely(rc))
goto free; goto free;
llc_conn_send_pdu(sk, nskb); llc_conn_send_pdu(sk, nskb);
} }
...@@ -538,19 +507,17 @@ free: ...@@ -538,19 +507,17 @@ free:
int llc_conn_ac_send_rej_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) int llc_conn_ac_send_rej_xxx_x_set_0(struct sock *sk, struct sk_buff *skb)
{ {
int rc = -ENOBUFS; int rc = -ENOBUFS;
struct sk_buff *nskb = llc_alloc_frame(); struct llc_sock *llc = llc_sk(sk);
struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
if (nskb) { if (nskb) {
struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap; struct llc_sap *sap = llc->sap;
u8 f_bit = 0;
nskb->dev = llc->dev;
llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
llc->daddr.lsap, LLC_PDU_RSP); llc->daddr.lsap, LLC_PDU_RSP);
llc_pdu_init_as_rej_rsp(nskb, f_bit, llc->vR); llc_pdu_init_as_rej_rsp(nskb, 0, llc->vR);
rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
if (rc) if (unlikely(rc))
goto free; goto free;
llc_conn_send_pdu(sk, nskb); llc_conn_send_pdu(sk, nskb);
} }
...@@ -564,18 +531,17 @@ free: ...@@ -564,18 +531,17 @@ free:
int llc_conn_ac_send_rnr_cmd_p_set_1(struct sock *sk, struct sk_buff *skb) int llc_conn_ac_send_rnr_cmd_p_set_1(struct sock *sk, struct sk_buff *skb)
{ {
int rc = -ENOBUFS; int rc = -ENOBUFS;
struct sk_buff *nskb = llc_alloc_frame(); struct llc_sock *llc = llc_sk(sk);
struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
if (nskb) { if (nskb) {
struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap; struct llc_sap *sap = llc->sap;
nskb->dev = llc->dev;
llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
llc->daddr.lsap, LLC_PDU_CMD); llc->daddr.lsap, LLC_PDU_CMD);
llc_pdu_init_as_rnr_cmd(nskb, 1, llc->vR); llc_pdu_init_as_rnr_cmd(nskb, 1, llc->vR);
rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
if (rc) if (unlikely(rc))
goto free; goto free;
llc_conn_send_pdu(sk, nskb); llc_conn_send_pdu(sk, nskb);
} }
...@@ -589,19 +555,17 @@ free: ...@@ -589,19 +555,17 @@ free:
int llc_conn_ac_send_rnr_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) int llc_conn_ac_send_rnr_rsp_f_set_1(struct sock *sk, struct sk_buff *skb)
{ {
int rc = -ENOBUFS; int rc = -ENOBUFS;
struct sk_buff *nskb = llc_alloc_frame(); struct llc_sock *llc = llc_sk(sk);
struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
if (nskb) { if (nskb) {
struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap; struct llc_sap *sap = llc->sap;
u8 f_bit = 1;
nskb->dev = llc->dev;
llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
llc->daddr.lsap, LLC_PDU_RSP); llc->daddr.lsap, LLC_PDU_RSP);
llc_pdu_init_as_rnr_rsp(nskb, f_bit, llc->vR); llc_pdu_init_as_rnr_rsp(nskb, 1, llc->vR);
rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
if (rc) if (unlikely(rc))
goto free; goto free;
llc_conn_send_pdu(sk, nskb); llc_conn_send_pdu(sk, nskb);
} }
...@@ -615,19 +579,17 @@ free: ...@@ -615,19 +579,17 @@ free:
int llc_conn_ac_send_rnr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) int llc_conn_ac_send_rnr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb)
{ {
int rc = -ENOBUFS; int rc = -ENOBUFS;
struct sk_buff *nskb = llc_alloc_frame(); struct llc_sock *llc = llc_sk(sk);
struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
if (nskb) { if (nskb) {
u8 f_bit = 0;
struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap; struct llc_sap *sap = llc->sap;
nskb->dev = llc->dev;
llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
llc->daddr.lsap, LLC_PDU_RSP); llc->daddr.lsap, LLC_PDU_RSP);
llc_pdu_init_as_rnr_rsp(nskb, f_bit, llc->vR); llc_pdu_init_as_rnr_rsp(nskb, 0, llc->vR);
rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
if (rc) if (unlikely(rc))
goto free; goto free;
llc_conn_send_pdu(sk, nskb); llc_conn_send_pdu(sk, nskb);
} }
...@@ -645,7 +607,7 @@ int llc_conn_ac_set_remote_busy(struct sock *sk, struct sk_buff *skb) ...@@ -645,7 +607,7 @@ int llc_conn_ac_set_remote_busy(struct sock *sk, struct sk_buff *skb)
if (!llc->remote_busy_flag) { if (!llc->remote_busy_flag) {
llc->remote_busy_flag = 1; llc->remote_busy_flag = 1;
mod_timer(&llc->busy_state_timer.timer, mod_timer(&llc->busy_state_timer.timer,
jiffies + llc->busy_state_timer.expire * HZ); jiffies + llc->busy_state_timer.expire);
} }
return 0; return 0;
} }
...@@ -653,18 +615,17 @@ int llc_conn_ac_set_remote_busy(struct sock *sk, struct sk_buff *skb) ...@@ -653,18 +615,17 @@ int llc_conn_ac_set_remote_busy(struct sock *sk, struct sk_buff *skb)
int llc_conn_ac_opt_send_rnr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) int llc_conn_ac_opt_send_rnr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb)
{ {
int rc = -ENOBUFS; int rc = -ENOBUFS;
struct sk_buff *nskb = llc_alloc_frame(); struct llc_sock *llc = llc_sk(sk);
struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
if (nskb) { if (nskb) {
struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap; struct llc_sap *sap = llc->sap;
nskb->dev = llc->dev;
llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
llc->daddr.lsap, LLC_PDU_RSP); llc->daddr.lsap, LLC_PDU_RSP);
llc_pdu_init_as_rnr_rsp(nskb, 0, llc->vR); llc_pdu_init_as_rnr_rsp(nskb, 0, llc->vR);
rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
if (rc) if (unlikely(rc))
goto free; goto free;
llc_conn_send_pdu(sk, nskb); llc_conn_send_pdu(sk, nskb);
} }
...@@ -678,18 +639,17 @@ free: ...@@ -678,18 +639,17 @@ free:
int llc_conn_ac_send_rr_cmd_p_set_1(struct sock *sk, struct sk_buff *skb) int llc_conn_ac_send_rr_cmd_p_set_1(struct sock *sk, struct sk_buff *skb)
{ {
int rc = -ENOBUFS; int rc = -ENOBUFS;
struct sk_buff *nskb = llc_alloc_frame(); struct llc_sock *llc = llc_sk(sk);
struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
if (nskb) { if (nskb) {
struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap; struct llc_sap *sap = llc->sap;
nskb->dev = llc->dev;
llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
llc->daddr.lsap, LLC_PDU_CMD); llc->daddr.lsap, LLC_PDU_CMD);
llc_pdu_init_as_rr_cmd(nskb, 1, llc->vR); llc_pdu_init_as_rr_cmd(nskb, 1, llc->vR);
rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
if (rc) if (unlikely(rc))
goto free; goto free;
llc_conn_send_pdu(sk, nskb); llc_conn_send_pdu(sk, nskb);
} }
...@@ -703,19 +663,18 @@ free: ...@@ -703,19 +663,18 @@ free:
int llc_conn_ac_send_rr_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) int llc_conn_ac_send_rr_rsp_f_set_1(struct sock *sk, struct sk_buff *skb)
{ {
int rc = -ENOBUFS; int rc = -ENOBUFS;
struct sk_buff *nskb = llc_alloc_frame(); struct llc_sock *llc = llc_sk(sk);
struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
if (nskb) { if (nskb) {
struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap; struct llc_sap *sap = llc->sap;
u8 f_bit = 1; u8 f_bit = 1;
nskb->dev = llc->dev;
llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
llc->daddr.lsap, LLC_PDU_RSP); llc->daddr.lsap, LLC_PDU_RSP);
llc_pdu_init_as_rr_rsp(nskb, f_bit, llc->vR); llc_pdu_init_as_rr_rsp(nskb, f_bit, llc->vR);
rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
if (rc) if (unlikely(rc))
goto free; goto free;
llc_conn_send_pdu(sk, nskb); llc_conn_send_pdu(sk, nskb);
} }
...@@ -729,19 +688,17 @@ free: ...@@ -729,19 +688,17 @@ free:
int llc_conn_ac_send_ack_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) int llc_conn_ac_send_ack_rsp_f_set_1(struct sock *sk, struct sk_buff *skb)
{ {
int rc = -ENOBUFS; int rc = -ENOBUFS;
struct sk_buff *nskb = llc_alloc_frame(); struct llc_sock *llc = llc_sk(sk);
struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
if (nskb) { if (nskb) {
struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap; struct llc_sap *sap = llc->sap;
u8 f_bit = 1;
nskb->dev = llc->dev;
llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
llc->daddr.lsap, LLC_PDU_RSP); llc->daddr.lsap, LLC_PDU_RSP);
llc_pdu_init_as_rr_rsp(nskb, f_bit, llc->vR); llc_pdu_init_as_rr_rsp(nskb, 1, llc->vR);
rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
if (rc) if (unlikely(rc))
goto free; goto free;
llc_conn_send_pdu(sk, nskb); llc_conn_send_pdu(sk, nskb);
} }
...@@ -755,18 +712,17 @@ free: ...@@ -755,18 +712,17 @@ free:
int llc_conn_ac_send_rr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) int llc_conn_ac_send_rr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb)
{ {
int rc = -ENOBUFS; int rc = -ENOBUFS;
struct sk_buff *nskb = llc_alloc_frame(); struct llc_sock *llc = llc_sk(sk);
struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
if (nskb) { if (nskb) {
struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap; struct llc_sap *sap = llc->sap;
nskb->dev = llc->dev;
llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
llc->daddr.lsap, LLC_PDU_RSP); llc->daddr.lsap, LLC_PDU_RSP);
llc_pdu_init_as_rr_rsp(nskb, 0, llc->vR); llc_pdu_init_as_rr_rsp(nskb, 0, llc->vR);
rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
if (rc) if (unlikely(rc))
goto free; goto free;
llc_conn_send_pdu(sk, nskb); llc_conn_send_pdu(sk, nskb);
} }
...@@ -780,18 +736,17 @@ free: ...@@ -780,18 +736,17 @@ free:
int llc_conn_ac_send_ack_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) int llc_conn_ac_send_ack_xxx_x_set_0(struct sock *sk, struct sk_buff *skb)
{ {
int rc = -ENOBUFS; int rc = -ENOBUFS;
struct sk_buff *nskb = llc_alloc_frame(); struct llc_sock *llc = llc_sk(sk);
struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
if (nskb) { if (nskb) {
struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap; struct llc_sap *sap = llc->sap;
nskb->dev = llc->dev;
llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
llc->daddr.lsap, LLC_PDU_RSP); llc->daddr.lsap, LLC_PDU_RSP);
llc_pdu_init_as_rr_rsp(nskb, 0, llc->vR); llc_pdu_init_as_rr_rsp(nskb, 0, llc->vR);
rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
if (rc) if (unlikely(rc))
goto free; goto free;
llc_conn_send_pdu(sk, nskb); llc_conn_send_pdu(sk, nskb);
} }
...@@ -815,8 +770,8 @@ void llc_conn_set_p_flag(struct sock *sk, u8 value) ...@@ -815,8 +770,8 @@ void llc_conn_set_p_flag(struct sock *sk, u8 value)
int llc_conn_ac_send_sabme_cmd_p_set_x(struct sock *sk, struct sk_buff *skb) int llc_conn_ac_send_sabme_cmd_p_set_x(struct sock *sk, struct sk_buff *skb)
{ {
int rc = -ENOBUFS; int rc = -ENOBUFS;
struct sk_buff *nskb = llc_alloc_frame();
struct llc_sock *llc = llc_sk(sk); struct llc_sock *llc = llc_sk(sk);
struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
if (nskb) { if (nskb) {
struct llc_sap *sap = llc->sap; struct llc_sap *sap = llc->sap;
...@@ -824,12 +779,11 @@ int llc_conn_ac_send_sabme_cmd_p_set_x(struct sock *sk, struct sk_buff *skb) ...@@ -824,12 +779,11 @@ int llc_conn_ac_send_sabme_cmd_p_set_x(struct sock *sk, struct sk_buff *skb)
if (llc->dev->flags & IFF_LOOPBACK) if (llc->dev->flags & IFF_LOOPBACK)
dmac = llc->dev->dev_addr; dmac = llc->dev->dev_addr;
nskb->dev = llc->dev;
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap,
llc->daddr.lsap, LLC_PDU_CMD); llc->daddr.lsap, LLC_PDU_CMD);
llc_pdu_init_as_sabme_cmd(nskb, 1); llc_pdu_init_as_sabme_cmd(nskb, 1);
rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, dmac); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, dmac);
if (rc) if (unlikely(rc))
goto free; goto free;
llc_conn_send_pdu(sk, nskb); llc_conn_send_pdu(sk, nskb);
llc_conn_set_p_flag(sk, 1); llc_conn_set_p_flag(sk, 1);
...@@ -845,11 +799,11 @@ int llc_conn_ac_send_ua_rsp_f_set_p(struct sock *sk, struct sk_buff *skb) ...@@ -845,11 +799,11 @@ int llc_conn_ac_send_ua_rsp_f_set_p(struct sock *sk, struct sk_buff *skb)
{ {
u8 f_bit; u8 f_bit;
int rc = -ENOBUFS; int rc = -ENOBUFS;
struct sk_buff *nskb = llc_alloc_frame(); struct llc_sock *llc = llc_sk(sk);
struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
llc_pdu_decode_pf_bit(skb, &f_bit); llc_pdu_decode_pf_bit(skb, &f_bit);
if (nskb) { if (nskb) {
struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap; struct llc_sap *sap = llc->sap;
nskb->dev = llc->dev; nskb->dev = llc->dev;
...@@ -857,7 +811,7 @@ int llc_conn_ac_send_ua_rsp_f_set_p(struct sock *sk, struct sk_buff *skb) ...@@ -857,7 +811,7 @@ int llc_conn_ac_send_ua_rsp_f_set_p(struct sock *sk, struct sk_buff *skb)
llc->daddr.lsap, LLC_PDU_RSP); llc->daddr.lsap, LLC_PDU_RSP);
llc_pdu_init_as_ua_rsp(nskb, f_bit); llc_pdu_init_as_ua_rsp(nskb, f_bit);
rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
if (rc) if (unlikely(rc))
goto free; goto free;
llc_conn_send_pdu(sk, nskb); llc_conn_send_pdu(sk, nskb);
} }
...@@ -886,7 +840,7 @@ int llc_conn_ac_start_p_timer(struct sock *sk, struct sk_buff *skb) ...@@ -886,7 +840,7 @@ int llc_conn_ac_start_p_timer(struct sock *sk, struct sk_buff *skb)
llc_conn_set_p_flag(sk, 1); llc_conn_set_p_flag(sk, 1);
mod_timer(&llc->pf_cycle_timer.timer, mod_timer(&llc->pf_cycle_timer.timer,
jiffies + llc->pf_cycle_timer.expire * HZ); jiffies + llc->pf_cycle_timer.expire);
return 0; return 0;
} }
...@@ -957,7 +911,7 @@ static int llc_conn_ac_send_i_rsp_f_set_ackpf(struct sock *sk, ...@@ -957,7 +911,7 @@ static int llc_conn_ac_send_i_rsp_f_set_ackpf(struct sock *sk,
llc->daddr.lsap, LLC_PDU_RSP); llc->daddr.lsap, LLC_PDU_RSP);
llc_pdu_init_as_i_cmd(skb, llc->ack_pf, llc->vS, llc->vR); llc_pdu_init_as_i_cmd(skb, llc->ack_pf, llc->vS, llc->vR);
rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac); rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac);
if (!rc) { if (likely(!rc)) {
llc_conn_send_pdu(sk, skb); llc_conn_send_pdu(sk, skb);
llc_conn_ac_inc_vs_by_1(sk, skb); llc_conn_ac_inc_vs_by_1(sk, skb);
} }
...@@ -1001,18 +955,17 @@ static int llc_conn_ac_send_rr_rsp_f_set_ackpf(struct sock *sk, ...@@ -1001,18 +955,17 @@ static int llc_conn_ac_send_rr_rsp_f_set_ackpf(struct sock *sk,
struct sk_buff *skb) struct sk_buff *skb)
{ {
int rc = -ENOBUFS; int rc = -ENOBUFS;
struct sk_buff *nskb = llc_alloc_frame(); struct llc_sock *llc = llc_sk(sk);
struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
if (nskb) { if (nskb) {
struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap; struct llc_sap *sap = llc->sap;
nskb->dev = llc->dev;
llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
llc->daddr.lsap, LLC_PDU_RSP); llc->daddr.lsap, LLC_PDU_RSP);
llc_pdu_init_as_rr_rsp(nskb, llc->ack_pf, llc->vR); llc_pdu_init_as_rr_rsp(nskb, llc->ack_pf, llc->vR);
rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
if (rc) if (unlikely(rc))
goto free; goto free;
llc_conn_send_pdu(sk, nskb); llc_conn_send_pdu(sk, nskb);
} }
...@@ -1165,7 +1118,7 @@ int llc_conn_ac_start_ack_timer(struct sock *sk, struct sk_buff *skb) ...@@ -1165,7 +1118,7 @@ int llc_conn_ac_start_ack_timer(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_sock *llc = llc_sk(sk); struct llc_sock *llc = llc_sk(sk);
mod_timer(&llc->ack_timer.timer, jiffies + llc->ack_timer.expire * HZ); mod_timer(&llc->ack_timer.timer, jiffies + llc->ack_timer.expire);
return 0; return 0;
} }
...@@ -1174,7 +1127,7 @@ int llc_conn_ac_start_rej_timer(struct sock *sk, struct sk_buff *skb) ...@@ -1174,7 +1127,7 @@ int llc_conn_ac_start_rej_timer(struct sock *sk, struct sk_buff *skb)
struct llc_sock *llc = llc_sk(sk); struct llc_sock *llc = llc_sk(sk);
mod_timer(&llc->rej_sent_timer.timer, mod_timer(&llc->rej_sent_timer.timer,
jiffies + llc->rej_sent_timer.expire * HZ); jiffies + llc->rej_sent_timer.expire);
return 0; return 0;
} }
...@@ -1185,7 +1138,7 @@ int llc_conn_ac_start_ack_tmr_if_not_running(struct sock *sk, ...@@ -1185,7 +1138,7 @@ int llc_conn_ac_start_ack_tmr_if_not_running(struct sock *sk,
if (!timer_pending(&llc->ack_timer.timer)) if (!timer_pending(&llc->ack_timer.timer))
mod_timer(&llc->ack_timer.timer, mod_timer(&llc->ack_timer.timer,
jiffies + llc->ack_timer.expire * HZ); jiffies + llc->ack_timer.expire);
return 0; return 0;
} }
...@@ -1233,7 +1186,7 @@ int llc_conn_ac_upd_nr_received(struct sock *sk, struct sk_buff *skb) ...@@ -1233,7 +1186,7 @@ int llc_conn_ac_upd_nr_received(struct sock *sk, struct sk_buff *skb)
} }
if (unacked) if (unacked)
mod_timer(&llc->ack_timer.timer, mod_timer(&llc->ack_timer.timer,
jiffies + llc->ack_timer.expire * HZ); jiffies + llc->ack_timer.expire);
} else if (llc->failed_data_req) { } else if (llc->failed_data_req) {
u8 f_bit; u8 f_bit;
...@@ -1354,13 +1307,13 @@ int llc_conn_ac_set_vs_nr(struct sock *sk, struct sk_buff *skb) ...@@ -1354,13 +1307,13 @@ int llc_conn_ac_set_vs_nr(struct sock *sk, struct sk_buff *skb)
return 0; return 0;
} }
int llc_conn_ac_inc_vs_by_1(struct sock *sk, struct sk_buff *skb) static int llc_conn_ac_inc_vs_by_1(struct sock *sk, struct sk_buff *skb)
{ {
llc_sk(sk)->vS = (llc_sk(sk)->vS + 1) % 128; llc_sk(sk)->vS = (llc_sk(sk)->vS + 1) % 128;
return 0; return 0;
} }
void llc_conn_pf_cycle_tmr_cb(unsigned long timeout_data) static void llc_conn_tmr_common_cb(unsigned long timeout_data, u8 type)
{ {
struct sock *sk = (struct sock *)timeout_data; struct sock *sk = (struct sock *)timeout_data;
struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC); struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC);
...@@ -1369,59 +1322,31 @@ void llc_conn_pf_cycle_tmr_cb(unsigned long timeout_data) ...@@ -1369,59 +1322,31 @@ void llc_conn_pf_cycle_tmr_cb(unsigned long timeout_data)
if (skb) { if (skb) {
struct llc_conn_state_ev *ev = llc_conn_ev(skb); struct llc_conn_state_ev *ev = llc_conn_ev(skb);
skb->sk = sk; skb_set_owner_r(skb, sk);
ev->type = LLC_CONN_EV_TYPE_P_TMR; ev->type = type;
llc_process_tmr_ev(sk, skb); llc_process_tmr_ev(sk, skb);
} }
bh_unlock_sock(sk); bh_unlock_sock(sk);
} }
void llc_conn_busy_tmr_cb(unsigned long timeout_data) void llc_conn_pf_cycle_tmr_cb(unsigned long timeout_data)
{ {
struct sock *sk = (struct sock *)timeout_data; llc_conn_tmr_common_cb(timeout_data, LLC_CONN_EV_TYPE_P_TMR);
struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC); }
bh_lock_sock(sk);
if (skb) {
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
skb->sk = sk; void llc_conn_busy_tmr_cb(unsigned long timeout_data)
ev->type = LLC_CONN_EV_TYPE_BUSY_TMR; {
llc_process_tmr_ev(sk, skb); llc_conn_tmr_common_cb(timeout_data, LLC_CONN_EV_TYPE_BUSY_TMR);
}
bh_unlock_sock(sk);
} }
void llc_conn_ack_tmr_cb(unsigned long timeout_data) void llc_conn_ack_tmr_cb(unsigned long timeout_data)
{ {
struct sock* sk = (struct sock *)timeout_data; llc_conn_tmr_common_cb(timeout_data, LLC_CONN_EV_TYPE_ACK_TMR);
struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC);
bh_lock_sock(sk);
if (skb) {
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
skb->sk = sk;
ev->type = LLC_CONN_EV_TYPE_ACK_TMR;
llc_process_tmr_ev(sk, skb);
}
bh_unlock_sock(sk);
} }
void llc_conn_rej_tmr_cb(unsigned long timeout_data) void llc_conn_rej_tmr_cb(unsigned long timeout_data)
{ {
struct sock *sk = (struct sock *)timeout_data; llc_conn_tmr_common_cb(timeout_data, LLC_CONN_EV_TYPE_REJ_TMR);
struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC);
bh_lock_sock(sk);
if (skb) {
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
skb->sk = sk;
ev->type = LLC_CONN_EV_TYPE_REJ_TMR;
llc_process_tmr_ev(sk, skb);
}
bh_unlock_sock(sk);
} }
int llc_conn_ac_rst_vs(struct sock *sk, struct sk_buff *skb) int llc_conn_ac_rst_vs(struct sock *sk, struct sk_buff *skb)
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <net/llc_conn.h> #include <net/llc_conn.h>
#include <net/llc_sap.h> #include <net/llc_sap.h>
#include <net/sock.h> #include <net/sock.h>
#include <net/llc_c_ac.h>
#include <net/llc_c_ev.h> #include <net/llc_c_ev.h>
#include <net/llc_pdu.h> #include <net/llc_pdu.h>
...@@ -46,8 +47,6 @@ ...@@ -46,8 +47,6 @@
#define dprintk(args...) #define dprintk(args...)
#endif #endif
extern u16 llc_circular_between(u8 a, u8 b, u8 c);
/** /**
* llc_util_ns_inside_rx_window - check if sequence number is in rx window * llc_util_ns_inside_rx_window - check if sequence number is in rx window
* @ns: sequence number of received pdu. * @ns: sequence number of received pdu.
...@@ -99,7 +98,7 @@ out: ...@@ -99,7 +98,7 @@ out:
int llc_conn_ev_conn_req(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_conn_req(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_conn_state_ev *ev = llc_conn_ev(skb); const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
return ev->prim == LLC_CONN_PRIM && return ev->prim == LLC_CONN_PRIM &&
ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1; ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
...@@ -107,7 +106,7 @@ int llc_conn_ev_conn_req(struct sock *sk, struct sk_buff *skb) ...@@ -107,7 +106,7 @@ int llc_conn_ev_conn_req(struct sock *sk, struct sk_buff *skb)
int llc_conn_ev_data_req(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_data_req(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_conn_state_ev *ev = llc_conn_ev(skb); const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
return ev->prim == LLC_DATA_PRIM && return ev->prim == LLC_DATA_PRIM &&
ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1; ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
...@@ -115,7 +114,7 @@ int llc_conn_ev_data_req(struct sock *sk, struct sk_buff *skb) ...@@ -115,7 +114,7 @@ int llc_conn_ev_data_req(struct sock *sk, struct sk_buff *skb)
int llc_conn_ev_disc_req(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_disc_req(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_conn_state_ev *ev = llc_conn_ev(skb); const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
return ev->prim == LLC_DISC_PRIM && return ev->prim == LLC_DISC_PRIM &&
ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1; ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
...@@ -123,7 +122,7 @@ int llc_conn_ev_disc_req(struct sock *sk, struct sk_buff *skb) ...@@ -123,7 +122,7 @@ int llc_conn_ev_disc_req(struct sock *sk, struct sk_buff *skb)
int llc_conn_ev_rst_req(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rst_req(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_conn_state_ev *ev = llc_conn_ev(skb); const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
return ev->prim == LLC_RESET_PRIM && return ev->prim == LLC_RESET_PRIM &&
ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1; ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
...@@ -131,7 +130,7 @@ int llc_conn_ev_rst_req(struct sock *sk, struct sk_buff *skb) ...@@ -131,7 +130,7 @@ int llc_conn_ev_rst_req(struct sock *sk, struct sk_buff *skb)
int llc_conn_ev_local_busy_detected(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_local_busy_detected(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_conn_state_ev *ev = llc_conn_ev(skb); const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
return ev->type == LLC_CONN_EV_TYPE_SIMPLE && return ev->type == LLC_CONN_EV_TYPE_SIMPLE &&
ev->prim_type == LLC_CONN_EV_LOCAL_BUSY_DETECTED ? 0 : 1; ev->prim_type == LLC_CONN_EV_LOCAL_BUSY_DETECTED ? 0 : 1;
...@@ -139,7 +138,7 @@ int llc_conn_ev_local_busy_detected(struct sock *sk, struct sk_buff *skb) ...@@ -139,7 +138,7 @@ int llc_conn_ev_local_busy_detected(struct sock *sk, struct sk_buff *skb)
int llc_conn_ev_local_busy_cleared(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_local_busy_cleared(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_conn_state_ev *ev = llc_conn_ev(skb); const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
return ev->type == LLC_CONN_EV_TYPE_SIMPLE && return ev->type == LLC_CONN_EV_TYPE_SIMPLE &&
ev->prim_type == LLC_CONN_EV_LOCAL_BUSY_CLEARED ? 0 : 1; ev->prim_type == LLC_CONN_EV_LOCAL_BUSY_CLEARED ? 0 : 1;
...@@ -152,7 +151,7 @@ int llc_conn_ev_rx_bad_pdu(struct sock *sk, struct sk_buff *skb) ...@@ -152,7 +151,7 @@ int llc_conn_ev_rx_bad_pdu(struct sock *sk, struct sk_buff *skb)
int llc_conn_ev_rx_disc_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_disc_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_U(pdu) && return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_U(pdu) &&
LLC_U_PDU_CMD(pdu) == LLC_2_PDU_CMD_DISC ? 0 : 1; LLC_U_PDU_CMD(pdu) == LLC_2_PDU_CMD_DISC ? 0 : 1;
...@@ -160,7 +159,7 @@ int llc_conn_ev_rx_disc_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb) ...@@ -160,7 +159,7 @@ int llc_conn_ev_rx_disc_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb)
int llc_conn_ev_rx_dm_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_dm_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_U(pdu) && return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_U(pdu) &&
LLC_U_PDU_RSP(pdu) == LLC_2_PDU_RSP_DM ? 0 : 1; LLC_U_PDU_RSP(pdu) == LLC_2_PDU_RSP_DM ? 0 : 1;
...@@ -168,7 +167,7 @@ int llc_conn_ev_rx_dm_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb) ...@@ -168,7 +167,7 @@ int llc_conn_ev_rx_dm_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
int llc_conn_ev_rx_frmr_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_frmr_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_U(pdu) && return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_U(pdu) &&
LLC_U_PDU_RSP(pdu) == LLC_2_PDU_RSP_FRMR ? 0 : 1; LLC_U_PDU_RSP(pdu) == LLC_2_PDU_RSP_FRMR ? 0 : 1;
...@@ -176,7 +175,7 @@ int llc_conn_ev_rx_frmr_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb) ...@@ -176,7 +175,7 @@ int llc_conn_ev_rx_frmr_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
int llc_conn_ev_rx_i_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_i_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return llc_conn_space(sk, skb) && return llc_conn_space(sk, skb) &&
LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) && LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
...@@ -186,7 +185,7 @@ int llc_conn_ev_rx_i_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb) ...@@ -186,7 +185,7 @@ int llc_conn_ev_rx_i_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb)
int llc_conn_ev_rx_i_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_i_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return llc_conn_space(sk, skb) && return llc_conn_space(sk, skb) &&
LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) && LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
...@@ -197,9 +196,9 @@ int llc_conn_ev_rx_i_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb) ...@@ -197,9 +196,9 @@ int llc_conn_ev_rx_i_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
int llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns(struct sock *sk, int llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns(struct sock *sk,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
u8 vr = llc_sk(sk)->vR; const u8 vr = llc_sk(sk)->vR;
u8 ns = LLC_I_GET_NS(pdu); const u8 ns = LLC_I_GET_NS(pdu);
return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) && return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
LLC_I_PF_IS_0(pdu) && ns != vr && LLC_I_PF_IS_0(pdu) && ns != vr &&
...@@ -209,9 +208,9 @@ int llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns(struct sock *sk, ...@@ -209,9 +208,9 @@ int llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns(struct sock *sk,
int llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns(struct sock *sk, int llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns(struct sock *sk,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
u8 vr = llc_sk(sk)->vR; const u8 vr = llc_sk(sk)->vR;
u8 ns = LLC_I_GET_NS(pdu); const u8 ns = LLC_I_GET_NS(pdu);
return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) && return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
LLC_I_PF_IS_1(pdu) && ns != vr && LLC_I_PF_IS_1(pdu) && ns != vr &&
...@@ -221,10 +220,11 @@ int llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns(struct sock *sk, ...@@ -221,10 +220,11 @@ int llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns(struct sock *sk,
int llc_conn_ev_rx_i_cmd_pbit_set_x_inval_ns(struct sock *sk, int llc_conn_ev_rx_i_cmd_pbit_set_x_inval_ns(struct sock *sk,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct llc_pdu_sn * pdu = llc_pdu_sn_hdr(skb); const struct llc_pdu_sn * pdu = llc_pdu_sn_hdr(skb);
u8 vr = llc_sk(sk)->vR; const u8 vr = llc_sk(sk)->vR;
u8 ns = LLC_I_GET_NS(pdu); const u8 ns = LLC_I_GET_NS(pdu);
u16 rc = LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) && ns != vr && const u16 rc = LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
ns != vr &&
llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1; llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
if (!rc) if (!rc)
dprintk("%s: matched, state=%d, ns=%d, vr=%d\n", dprintk("%s: matched, state=%d, ns=%d, vr=%d\n",
...@@ -234,7 +234,7 @@ int llc_conn_ev_rx_i_cmd_pbit_set_x_inval_ns(struct sock *sk, ...@@ -234,7 +234,7 @@ int llc_conn_ev_rx_i_cmd_pbit_set_x_inval_ns(struct sock *sk,
int llc_conn_ev_rx_i_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_i_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return llc_conn_space(sk, skb) && return llc_conn_space(sk, skb) &&
LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) && LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
...@@ -244,7 +244,7 @@ int llc_conn_ev_rx_i_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb) ...@@ -244,7 +244,7 @@ int llc_conn_ev_rx_i_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb)
int llc_conn_ev_rx_i_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_i_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) && return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
LLC_I_PF_IS_1(pdu) && LLC_I_PF_IS_1(pdu) &&
...@@ -253,7 +253,7 @@ int llc_conn_ev_rx_i_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb) ...@@ -253,7 +253,7 @@ int llc_conn_ev_rx_i_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb)
int llc_conn_ev_rx_i_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_i_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return llc_conn_space(sk, skb) && return llc_conn_space(sk, skb) &&
LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) && LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
...@@ -263,9 +263,9 @@ int llc_conn_ev_rx_i_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb) ...@@ -263,9 +263,9 @@ int llc_conn_ev_rx_i_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
int llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns(struct sock *sk, int llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns(struct sock *sk,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
u8 vr = llc_sk(sk)->vR; const u8 vr = llc_sk(sk)->vR;
u8 ns = LLC_I_GET_NS(pdu); const u8 ns = LLC_I_GET_NS(pdu);
return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) && return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
LLC_I_PF_IS_0(pdu) && ns != vr && LLC_I_PF_IS_0(pdu) && ns != vr &&
...@@ -275,9 +275,9 @@ int llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns(struct sock *sk, ...@@ -275,9 +275,9 @@ int llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns(struct sock *sk,
int llc_conn_ev_rx_i_rsp_fbit_set_1_unexpd_ns(struct sock *sk, int llc_conn_ev_rx_i_rsp_fbit_set_1_unexpd_ns(struct sock *sk,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
u8 vr = llc_sk(sk)->vR; const u8 vr = llc_sk(sk)->vR;
u8 ns = LLC_I_GET_NS(pdu); const u8 ns = LLC_I_GET_NS(pdu);
return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) && return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
LLC_I_PF_IS_1(pdu) && ns != vr && LLC_I_PF_IS_1(pdu) && ns != vr &&
...@@ -287,9 +287,9 @@ int llc_conn_ev_rx_i_rsp_fbit_set_1_unexpd_ns(struct sock *sk, ...@@ -287,9 +287,9 @@ int llc_conn_ev_rx_i_rsp_fbit_set_1_unexpd_ns(struct sock *sk,
int llc_conn_ev_rx_i_rsp_fbit_set_x_unexpd_ns(struct sock *sk, int llc_conn_ev_rx_i_rsp_fbit_set_x_unexpd_ns(struct sock *sk,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
u8 vr = llc_sk(sk)->vR; const u8 vr = llc_sk(sk)->vR;
u8 ns = LLC_I_GET_NS(pdu); const u8 ns = LLC_I_GET_NS(pdu);
return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) && ns != vr && return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) && ns != vr &&
!llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1; !llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
...@@ -298,10 +298,11 @@ int llc_conn_ev_rx_i_rsp_fbit_set_x_unexpd_ns(struct sock *sk, ...@@ -298,10 +298,11 @@ int llc_conn_ev_rx_i_rsp_fbit_set_x_unexpd_ns(struct sock *sk,
int llc_conn_ev_rx_i_rsp_fbit_set_x_inval_ns(struct sock *sk, int llc_conn_ev_rx_i_rsp_fbit_set_x_inval_ns(struct sock *sk,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
u8 vr = llc_sk(sk)->vR; const u8 vr = llc_sk(sk)->vR;
u8 ns = LLC_I_GET_NS(pdu); const u8 ns = LLC_I_GET_NS(pdu);
u16 rc = LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) && ns != vr && const u16 rc = LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
ns != vr &&
llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1; llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
if (!rc) if (!rc)
dprintk("%s: matched, state=%d, ns=%d, vr=%d\n", dprintk("%s: matched, state=%d, ns=%d, vr=%d\n",
...@@ -311,7 +312,7 @@ int llc_conn_ev_rx_i_rsp_fbit_set_x_inval_ns(struct sock *sk, ...@@ -311,7 +312,7 @@ int llc_conn_ev_rx_i_rsp_fbit_set_x_inval_ns(struct sock *sk,
int llc_conn_ev_rx_rej_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_rej_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) && return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
LLC_S_PF_IS_0(pdu) && LLC_S_PF_IS_0(pdu) &&
...@@ -320,7 +321,7 @@ int llc_conn_ev_rx_rej_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb) ...@@ -320,7 +321,7 @@ int llc_conn_ev_rx_rej_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb)
int llc_conn_ev_rx_rej_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_rej_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) && return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
LLC_S_PF_IS_1(pdu) && LLC_S_PF_IS_1(pdu) &&
...@@ -329,7 +330,7 @@ int llc_conn_ev_rx_rej_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb) ...@@ -329,7 +330,7 @@ int llc_conn_ev_rx_rej_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
int llc_conn_ev_rx_rej_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_rej_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) && return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
LLC_S_PF_IS_0(pdu) && LLC_S_PF_IS_0(pdu) &&
...@@ -338,7 +339,7 @@ int llc_conn_ev_rx_rej_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb) ...@@ -338,7 +339,7 @@ int llc_conn_ev_rx_rej_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb)
int llc_conn_ev_rx_rej_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_rej_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) && return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
LLC_S_PF_IS_1(pdu) && LLC_S_PF_IS_1(pdu) &&
...@@ -347,7 +348,7 @@ int llc_conn_ev_rx_rej_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb) ...@@ -347,7 +348,7 @@ int llc_conn_ev_rx_rej_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb)
int llc_conn_ev_rx_rej_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_rej_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) && return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_REJ ? 0 : 1; LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_REJ ? 0 : 1;
...@@ -355,7 +356,7 @@ int llc_conn_ev_rx_rej_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb) ...@@ -355,7 +356,7 @@ int llc_conn_ev_rx_rej_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
int llc_conn_ev_rx_rnr_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_rnr_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) && return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
LLC_S_PF_IS_0(pdu) && LLC_S_PF_IS_0(pdu) &&
...@@ -364,7 +365,7 @@ int llc_conn_ev_rx_rnr_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb) ...@@ -364,7 +365,7 @@ int llc_conn_ev_rx_rnr_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb)
int llc_conn_ev_rx_rnr_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_rnr_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) && return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
LLC_S_PF_IS_1(pdu) && LLC_S_PF_IS_1(pdu) &&
...@@ -373,7 +374,7 @@ int llc_conn_ev_rx_rnr_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb) ...@@ -373,7 +374,7 @@ int llc_conn_ev_rx_rnr_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
int llc_conn_ev_rx_rnr_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_rnr_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) && return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
LLC_S_PF_IS_0(pdu) && LLC_S_PF_IS_0(pdu) &&
...@@ -382,7 +383,7 @@ int llc_conn_ev_rx_rnr_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb) ...@@ -382,7 +383,7 @@ int llc_conn_ev_rx_rnr_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb)
int llc_conn_ev_rx_rnr_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_rnr_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) && return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
LLC_S_PF_IS_1(pdu) && LLC_S_PF_IS_1(pdu) &&
...@@ -391,7 +392,7 @@ int llc_conn_ev_rx_rnr_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb) ...@@ -391,7 +392,7 @@ int llc_conn_ev_rx_rnr_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb)
int llc_conn_ev_rx_rr_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_rr_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) && return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
LLC_S_PF_IS_0(pdu) && LLC_S_PF_IS_0(pdu) &&
...@@ -400,7 +401,7 @@ int llc_conn_ev_rx_rr_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb) ...@@ -400,7 +401,7 @@ int llc_conn_ev_rx_rr_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb)
int llc_conn_ev_rx_rr_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_rr_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) && return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
LLC_S_PF_IS_1(pdu) && LLC_S_PF_IS_1(pdu) &&
...@@ -409,7 +410,7 @@ int llc_conn_ev_rx_rr_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb) ...@@ -409,7 +410,7 @@ int llc_conn_ev_rx_rr_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
int llc_conn_ev_rx_rr_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_rr_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return llc_conn_space(sk, skb) && return llc_conn_space(sk, skb) &&
LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) && LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
...@@ -419,7 +420,7 @@ int llc_conn_ev_rx_rr_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb) ...@@ -419,7 +420,7 @@ int llc_conn_ev_rx_rr_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb)
int llc_conn_ev_rx_rr_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_rr_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return llc_conn_space(sk, skb) && return llc_conn_space(sk, skb) &&
LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) && LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
...@@ -429,7 +430,7 @@ int llc_conn_ev_rx_rr_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb) ...@@ -429,7 +430,7 @@ int llc_conn_ev_rx_rr_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb)
int llc_conn_ev_rx_sabme_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_sabme_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_U(pdu) && return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_U(pdu) &&
LLC_U_PDU_CMD(pdu) == LLC_2_PDU_CMD_SABME ? 0 : 1; LLC_U_PDU_CMD(pdu) == LLC_2_PDU_CMD_SABME ? 0 : 1;
...@@ -446,7 +447,7 @@ int llc_conn_ev_rx_ua_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb) ...@@ -446,7 +447,7 @@ int llc_conn_ev_rx_ua_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
int llc_conn_ev_rx_xxx_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_xxx_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
{ {
u16 rc = 1; u16 rc = 1;
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
if (LLC_PDU_IS_CMD(pdu)) { if (LLC_PDU_IS_CMD(pdu)) {
if (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) { if (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) {
...@@ -461,7 +462,7 @@ int llc_conn_ev_rx_xxx_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb) ...@@ -461,7 +462,7 @@ int llc_conn_ev_rx_xxx_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
int llc_conn_ev_rx_xxx_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_xxx_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb)
{ {
u16 rc = 1; u16 rc = 1;
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
if (LLC_PDU_IS_CMD(pdu)) { if (LLC_PDU_IS_CMD(pdu)) {
if (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) if (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu))
...@@ -477,32 +478,10 @@ int llc_conn_ev_rx_xxx_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb) ...@@ -477,32 +478,10 @@ int llc_conn_ev_rx_xxx_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb)
return rc; return rc;
} }
int llc_conn_ev_rx_xxx_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb)
{
u16 rc = 1;
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
if (LLC_PDU_IS_RSP(pdu)) {
if (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) {
if (LLC_I_PF_IS_1(pdu))
rc = 0;
} else if (LLC_PDU_TYPE_IS_U(pdu))
switch (LLC_U_PDU_RSP(pdu)) {
case LLC_2_PDU_RSP_UA:
case LLC_2_PDU_RSP_DM:
case LLC_2_PDU_RSP_FRMR:
if (LLC_U_PF_IS_1(pdu))
rc = 0;
break;
}
}
return rc;
}
int llc_conn_ev_rx_xxx_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_xxx_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
{ {
u16 rc = 1; u16 rc = 1;
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
if (LLC_PDU_IS_RSP(pdu)) { if (LLC_PDU_IS_RSP(pdu)) {
if (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) if (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu))
...@@ -524,9 +503,9 @@ int llc_conn_ev_rx_zzz_cmd_pbit_set_x_inval_nr(struct sock *sk, ...@@ -524,9 +503,9 @@ int llc_conn_ev_rx_zzz_cmd_pbit_set_x_inval_nr(struct sock *sk,
struct sk_buff *skb) struct sk_buff *skb)
{ {
u16 rc = 1; u16 rc = 1;
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
u8 vs = llc_sk(sk)->vS; const u8 vs = llc_sk(sk)->vS;
u8 nr = LLC_I_GET_NR(pdu); const u8 nr = LLC_I_GET_NR(pdu);
if (LLC_PDU_IS_CMD(pdu) && if (LLC_PDU_IS_CMD(pdu) &&
(LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) && (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) &&
...@@ -542,9 +521,9 @@ int llc_conn_ev_rx_zzz_rsp_fbit_set_x_inval_nr(struct sock *sk, ...@@ -542,9 +521,9 @@ int llc_conn_ev_rx_zzz_rsp_fbit_set_x_inval_nr(struct sock *sk,
struct sk_buff *skb) struct sk_buff *skb)
{ {
u16 rc = 1; u16 rc = 1;
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
u8 vs = llc_sk(sk)->vS; const u8 vs = llc_sk(sk)->vS;
u8 nr = LLC_I_GET_NR(pdu); const u8 nr = LLC_I_GET_NR(pdu);
if (LLC_PDU_IS_RSP(pdu) && if (LLC_PDU_IS_RSP(pdu) &&
(LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) && (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) &&
...@@ -563,28 +542,28 @@ int llc_conn_ev_rx_any_frame(struct sock *sk, struct sk_buff *skb) ...@@ -563,28 +542,28 @@ int llc_conn_ev_rx_any_frame(struct sock *sk, struct sk_buff *skb)
int llc_conn_ev_p_tmr_exp(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_p_tmr_exp(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_conn_state_ev *ev = llc_conn_ev(skb); const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
return ev->type != LLC_CONN_EV_TYPE_P_TMR; return ev->type != LLC_CONN_EV_TYPE_P_TMR;
} }
int llc_conn_ev_ack_tmr_exp(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_ack_tmr_exp(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_conn_state_ev *ev = llc_conn_ev(skb); const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
return ev->type != LLC_CONN_EV_TYPE_ACK_TMR; return ev->type != LLC_CONN_EV_TYPE_ACK_TMR;
} }
int llc_conn_ev_rej_tmr_exp(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rej_tmr_exp(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_conn_state_ev *ev = llc_conn_ev(skb); const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
return ev->type != LLC_CONN_EV_TYPE_REJ_TMR; return ev->type != LLC_CONN_EV_TYPE_REJ_TMR;
} }
int llc_conn_ev_busy_tmr_exp(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_busy_tmr_exp(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_conn_state_ev *ev = llc_conn_ev(skb); const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
return ev->type != LLC_CONN_EV_TYPE_BUSY_TMR; return ev->type != LLC_CONN_EV_TYPE_BUSY_TMR;
} }
...@@ -596,7 +575,7 @@ int llc_conn_ev_init_p_f_cycle(struct sock *sk, struct sk_buff *skb) ...@@ -596,7 +575,7 @@ int llc_conn_ev_init_p_f_cycle(struct sock *sk, struct sk_buff *skb)
int llc_conn_ev_tx_buffer_full(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_tx_buffer_full(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_conn_state_ev *ev = llc_conn_ev(skb); const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
return ev->type == LLC_CONN_EV_TYPE_SIMPLE && return ev->type == LLC_CONN_EV_TYPE_SIMPLE &&
ev->prim_type == LLC_CONN_EV_TX_BUFF_FULL ? 0 : 1; ev->prim_type == LLC_CONN_EV_TX_BUFF_FULL ? 0 : 1;
......
...@@ -40,6 +40,11 @@ static struct llc_conn_state_trans *llc_qualify_conn_ev(struct sock *sk, ...@@ -40,6 +40,11 @@ static struct llc_conn_state_trans *llc_qualify_conn_ev(struct sock *sk,
/* Offset table on connection states transition diagram */ /* Offset table on connection states transition diagram */
static int llc_offset_table[NBR_CONN_STATES][NBR_CONN_EV]; static int llc_offset_table[NBR_CONN_STATES][NBR_CONN_EV];
int sysctl_llc2_ack_timeout = LLC2_ACK_TIME * HZ;
int sysctl_llc2_p_timeout = LLC2_P_TIME * HZ;
int sysctl_llc2_rej_timeout = LLC2_REJ_TIME * HZ;
int sysctl_llc2_busy_timeout = LLC2_BUSY_TIME * HZ;
/** /**
* llc_conn_state_process - sends event to connection state machine * llc_conn_state_process - sends event to connection state machine
* @sk: connection * @sk: connection
...@@ -53,7 +58,7 @@ static int llc_offset_table[NBR_CONN_STATES][NBR_CONN_EV]; ...@@ -53,7 +58,7 @@ static int llc_offset_table[NBR_CONN_STATES][NBR_CONN_EV];
int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
{ {
int rc; int rc;
struct llc_sock *llc = llc_sk(sk); struct llc_sock *llc = llc_sk(skb->sk);
struct llc_conn_state_ev *ev = llc_conn_ev(skb); struct llc_conn_state_ev *ev = llc_conn_ev(skb);
/* /*
...@@ -63,13 +68,16 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) ...@@ -63,13 +68,16 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
*/ */
skb_get(skb); skb_get(skb);
ev->ind_prim = ev->cfm_prim = 0; ev->ind_prim = ev->cfm_prim = 0;
rc = llc_conn_service(sk, skb); /* sending event to state machine */ /*
if (rc) { * Send event to state machine
*/
rc = llc_conn_service(skb->sk, skb);
if (unlikely(rc != 0)) {
printk(KERN_ERR "%s: llc_conn_service failed\n", __FUNCTION__); printk(KERN_ERR "%s: llc_conn_service failed\n", __FUNCTION__);
goto out_kfree_skb; goto out_kfree_skb;
} }
if (!ev->ind_prim && !ev->cfm_prim) { if (unlikely(!ev->ind_prim && !ev->cfm_prim)) {
/* indicate or confirm not required */ /* indicate or confirm not required */
/* XXX this is not very pretty, perhaps we should store /* XXX this is not very pretty, perhaps we should store
* XXX indicate/confirm-needed state in the llc_conn_state_ev * XXX indicate/confirm-needed state in the llc_conn_state_ev
...@@ -80,13 +88,13 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) ...@@ -80,13 +88,13 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
goto out_skb_put; goto out_skb_put;
} }
if (ev->ind_prim && ev->cfm_prim) /* Paranoia */ if (unlikely(ev->ind_prim && ev->cfm_prim)) /* Paranoia */
skb_get(skb); skb_get(skb);
switch (ev->ind_prim) { switch (ev->ind_prim) {
case LLC_DATA_PRIM: case LLC_DATA_PRIM:
llc_save_primitive(skb, LLC_DATA_PRIM); llc_save_primitive(sk, skb, LLC_DATA_PRIM);
if (sock_queue_rcv_skb(sk, skb)) { if (unlikely(sock_queue_rcv_skb(sk, skb))) {
/* /*
* shouldn't happen * shouldn't happen
*/ */
...@@ -95,13 +103,14 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) ...@@ -95,13 +103,14 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
kfree_skb(skb); kfree_skb(skb);
} }
break; break;
case LLC_CONN_PRIM: { case LLC_CONN_PRIM:
struct sock *parent = skb->sk; /*
* Can't be sock_queue_rcv_skb, because we have to leave the
skb->sk = sk; * skb->sk pointing to the newly created struct sock in
skb_queue_tail(&parent->sk_receive_queue, skb); * llc_conn_handler. -acme
sk->sk_state_change(parent); */
} skb_queue_tail(&sk->sk_receive_queue, skb);
sk->sk_state_change(sk);
break; break;
case LLC_DISC_PRIM: case LLC_DISC_PRIM:
sock_hold(sk); sock_hold(sk);
...@@ -111,8 +120,8 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) ...@@ -111,8 +120,8 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
sk->sk_socket->state = SS_UNCONNECTED; sk->sk_socket->state = SS_UNCONNECTED;
sk->sk_state = TCP_CLOSE; sk->sk_state = TCP_CLOSE;
if (!sock_flag(sk, SOCK_DEAD)) { if (!sock_flag(sk, SOCK_DEAD)) {
sk->sk_state_change(sk);
sock_set_flag(sk, SOCK_DEAD); sock_set_flag(sk, SOCK_DEAD);
sk->sk_state_change(sk);
} }
} }
kfree_skb(skb); kfree_skb(skb);
...@@ -465,7 +474,7 @@ static int llc_exec_conn_trans_actions(struct sock *sk, ...@@ -465,7 +474,7 @@ static int llc_exec_conn_trans_actions(struct sock *sk,
} }
/** /**
* llc_lookup_established - Finds connection for the remote/local sap/mac * __llc_lookup_established - Finds connection for the remote/local sap/mac
* @sap: SAP * @sap: SAP
* @daddr: address of remote LLC (MAC + SAP) * @daddr: address of remote LLC (MAC + SAP)
* @laddr: address of local LLC (MAC + SAP) * @laddr: address of local LLC (MAC + SAP)
...@@ -473,14 +482,16 @@ static int llc_exec_conn_trans_actions(struct sock *sk, ...@@ -473,14 +482,16 @@ static int llc_exec_conn_trans_actions(struct sock *sk,
* Search connection list of the SAP and finds connection using the remote * Search connection list of the SAP and finds connection using the remote
* mac, remote sap, local mac, and local sap. Returns pointer for * mac, remote sap, local mac, and local sap. Returns pointer for
* connection found, %NULL otherwise. * connection found, %NULL otherwise.
* Caller has to make sure local_bh is disabled.
*/ */
struct sock *llc_lookup_established(struct llc_sap *sap, struct llc_addr *daddr, static struct sock *__llc_lookup_established(struct llc_sap *sap,
struct llc_addr *laddr) struct llc_addr *daddr,
struct llc_addr *laddr)
{ {
struct sock *rc; struct sock *rc;
struct hlist_node *node; struct hlist_node *node;
read_lock_bh(&sap->sk_list.lock); read_lock(&sap->sk_list.lock);
sk_for_each(rc, node, &sap->sk_list.list) { sk_for_each(rc, node, &sap->sk_list.list) {
struct llc_sock *llc = llc_sk(rc); struct llc_sock *llc = llc_sk(rc);
...@@ -494,10 +505,22 @@ struct sock *llc_lookup_established(struct llc_sap *sap, struct llc_addr *daddr, ...@@ -494,10 +505,22 @@ struct sock *llc_lookup_established(struct llc_sap *sap, struct llc_addr *daddr,
} }
rc = NULL; rc = NULL;
found: found:
read_unlock_bh(&sap->sk_list.lock); read_unlock(&sap->sk_list.lock);
return rc; return rc;
} }
struct sock *llc_lookup_established(struct llc_sap *sap,
struct llc_addr *daddr,
struct llc_addr *laddr)
{
struct sock *sk;
local_bh_disable();
sk = __llc_lookup_established(sap, daddr, laddr);
local_bh_enable();
return sk;
}
/** /**
* llc_lookup_listener - Finds listener for local MAC + SAP * llc_lookup_listener - Finds listener for local MAC + SAP
* @sap: SAP * @sap: SAP
...@@ -506,6 +529,7 @@ found: ...@@ -506,6 +529,7 @@ found:
* Search connection list of the SAP and finds connection listening on * Search connection list of the SAP and finds connection listening on
* local mac, and local sap. Returns pointer for parent socket found, * local mac, and local sap. Returns pointer for parent socket found,
* %NULL otherwise. * %NULL otherwise.
* Caller has to make sure local_bh is disabled.
*/ */
static struct sock *llc_lookup_listener(struct llc_sap *sap, static struct sock *llc_lookup_listener(struct llc_sap *sap,
struct llc_addr *laddr) struct llc_addr *laddr)
...@@ -513,7 +537,7 @@ static struct sock *llc_lookup_listener(struct llc_sap *sap, ...@@ -513,7 +537,7 @@ static struct sock *llc_lookup_listener(struct llc_sap *sap,
struct sock *rc; struct sock *rc;
struct hlist_node *node; struct hlist_node *node;
read_lock_bh(&sap->sk_list.lock); read_lock(&sap->sk_list.lock);
sk_for_each(rc, node, &sap->sk_list.list) { sk_for_each(rc, node, &sap->sk_list.list) {
struct llc_sock *llc = llc_sk(rc); struct llc_sock *llc = llc_sk(rc);
...@@ -527,10 +551,19 @@ static struct sock *llc_lookup_listener(struct llc_sap *sap, ...@@ -527,10 +551,19 @@ static struct sock *llc_lookup_listener(struct llc_sap *sap,
} }
rc = NULL; rc = NULL;
found: found:
read_unlock_bh(&sap->sk_list.lock); read_unlock(&sap->sk_list.lock);
return rc; return rc;
} }
static struct sock *__llc_lookup(struct llc_sap *sap,
struct llc_addr *daddr,
struct llc_addr *laddr)
{
struct sock *sk = __llc_lookup_established(sap, daddr, laddr);
return sk ? : llc_lookup_listener(sap, laddr);
}
/** /**
* llc_data_accept_state - designates if in this state data can be sent. * llc_data_accept_state - designates if in this state data can be sent.
* @state: state of connection. * @state: state of connection.
...@@ -544,14 +577,14 @@ u8 llc_data_accept_state(u8 state) ...@@ -544,14 +577,14 @@ u8 llc_data_accept_state(u8 state)
} }
/** /**
* find_next_offset - finds offset for next category of transitions * llc_find_next_offset - finds offset for next category of transitions
* @state: state table. * @state: state table.
* @offset: start offset. * @offset: start offset.
* *
* Finds offset of next category of transitions in transition table. * Finds offset of next category of transitions in transition table.
* Returns the start index of next category. * Returns the start index of next category.
*/ */
static u16 find_next_offset(struct llc_conn_state *state, u16 offset) static u16 __init llc_find_next_offset(struct llc_conn_state *state, u16 offset)
{ {
u16 cnt = 0; u16 cnt = 0;
struct llc_conn_state_trans **next_trans; struct llc_conn_state_trans **next_trans;
...@@ -578,8 +611,8 @@ void __init llc_build_offset_table(void) ...@@ -578,8 +611,8 @@ void __init llc_build_offset_table(void)
next_offset = 0; next_offset = 0;
for (ev_type = 0; ev_type < NBR_CONN_EV; ev_type++) { for (ev_type = 0; ev_type < NBR_CONN_EV; ev_type++) {
llc_offset_table[state][ev_type] = next_offset; llc_offset_table[state][ev_type] = next_offset;
next_offset += find_next_offset(curr_state, next_offset += llc_find_next_offset(curr_state,
next_offset) + 1; next_offset) + 1;
} }
} }
} }
...@@ -623,6 +656,7 @@ static int llc_find_offset(int state, int ev_type) ...@@ -623,6 +656,7 @@ static int llc_find_offset(int state, int ev_type)
*/ */
void llc_sap_add_socket(struct llc_sap *sap, struct sock *sk) void llc_sap_add_socket(struct llc_sap *sap, struct sock *sk)
{ {
llc_sap_hold(sap);
write_lock_bh(&sap->sk_list.lock); write_lock_bh(&sap->sk_list.lock);
llc_sk(sk)->sap = sap; llc_sk(sk)->sap = sap;
sk_add_node(sk, &sap->sk_list.list); sk_add_node(sk, &sap->sk_list.list);
...@@ -642,6 +676,7 @@ void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk) ...@@ -642,6 +676,7 @@ void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk)
write_lock_bh(&sap->sk_list.lock); write_lock_bh(&sap->sk_list.lock);
sk_del_node_init(sk); sk_del_node_init(sk);
write_unlock_bh(&sap->sk_list.lock); write_unlock_bh(&sap->sk_list.lock);
llc_sap_put(sap);
} }
/** /**
...@@ -654,15 +689,34 @@ void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk) ...@@ -654,15 +689,34 @@ void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk)
static int llc_conn_rcv(struct sock* sk, struct sk_buff *skb) static int llc_conn_rcv(struct sock* sk, struct sk_buff *skb)
{ {
struct llc_conn_state_ev *ev = llc_conn_ev(skb); struct llc_conn_state_ev *ev = llc_conn_ev(skb);
struct llc_sock *llc = llc_sk(sk);
if (!llc->dev)
llc->dev = skb->dev;
ev->type = LLC_CONN_EV_TYPE_PDU; ev->type = LLC_CONN_EV_TYPE_PDU;
ev->reason = 0; ev->reason = 0;
return llc_conn_state_process(sk, skb); return llc_conn_state_process(sk, skb);
} }
static struct sock *llc_create_incoming_sock(struct sock *sk,
struct net_device *dev,
struct llc_addr *saddr,
struct llc_addr *daddr)
{
struct sock *newsk = llc_sk_alloc(sk->sk_family, GFP_ATOMIC,
sk->sk_prot);
struct llc_sock *newllc, *llc = llc_sk(sk);
if (!newsk)
goto out;
newllc = llc_sk(newsk);
memcpy(&newllc->laddr, daddr, sizeof(newllc->laddr));
memcpy(&newllc->daddr, saddr, sizeof(newllc->daddr));
newllc->dev = dev;
dev_hold(dev);
llc_sap_add_socket(llc->sap, newsk);
llc_sap_hold(llc->sap);
out:
return newsk;
}
void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb) void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb)
{ {
struct llc_addr saddr, daddr; struct llc_addr saddr, daddr;
...@@ -673,35 +727,35 @@ void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb) ...@@ -673,35 +727,35 @@ void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb)
llc_pdu_decode_da(skb, daddr.mac); llc_pdu_decode_da(skb, daddr.mac);
llc_pdu_decode_dsap(skb, &daddr.lsap); llc_pdu_decode_dsap(skb, &daddr.lsap);
sk = llc_lookup_established(sap, &saddr, &daddr); sk = __llc_lookup(sap, &saddr, &daddr);
if (!sk) { if (!sk)
goto drop;
bh_lock_sock(sk);
/*
* This has to be done here and not at the upper layer ->accept
* method because of the way the PROCOM state machine works:
* it needs to set several state variables (see, for instance,
* llc_adm_actions_2 in net/llc/llc_c_st.c) and send a packet to
* the originator of the new connection, and this state has to be
* in the newly created struct sock private area. -acme
*/
if (unlikely(sk->sk_state == TCP_LISTEN)) {
struct sock *newsk = llc_create_incoming_sock(sk, skb->dev,
&saddr, &daddr);
if (!newsk)
goto drop_unlock;
skb_set_owner_r(skb, newsk);
} else {
/* /*
* Didn't find an active connection; verify if there * Can't be skb_set_owner_r, this will be done at the
* is a listening socket for this llc addr * llc_conn_state_process function, later on, when we will use
* skb_queue_rcv_skb to send it to upper layers, this is
* another trick required to cope with how the PROCOM state
* machine works. -acme
*/ */
struct llc_sock *llc;
struct sock *parent = llc_lookup_listener(sap, &daddr);
if (!parent) {
dprintk("llc_lookup_listener failed!\n");
goto drop;
}
sk = llc_sk_alloc(parent->sk_family, GFP_ATOMIC, parent->sk_prot);
if (!sk) {
sock_put(parent);
goto drop;
}
llc = llc_sk(sk);
memcpy(&llc->laddr, &daddr, sizeof(llc->laddr));
memcpy(&llc->daddr, &saddr, sizeof(llc->daddr));
llc_sap_add_socket(sap, sk);
sock_hold(sk);
sock_put(parent);
skb->sk = parent;
} else
skb->sk = sk; skb->sk = sk;
bh_lock_sock(sk); }
if (!sock_owned_by_user(sk)) if (!sock_owned_by_user(sk))
llc_conn_rcv(sk, skb); llc_conn_rcv(sk, skb);
else { else {
...@@ -709,11 +763,16 @@ void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb) ...@@ -709,11 +763,16 @@ void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb)
llc_set_backlog_type(skb, LLC_PACKET); llc_set_backlog_type(skb, LLC_PACKET);
sk_add_backlog(sk, skb); sk_add_backlog(sk, skb);
} }
out:
bh_unlock_sock(sk); bh_unlock_sock(sk);
sock_put(sk); sock_put(sk);
return; return;
drop: drop:
kfree_skb(skb); kfree_skb(skb);
return;
drop_unlock:
kfree_skb(skb);
goto out;
} }
#undef LLC_REFCNT_DEBUG #undef LLC_REFCNT_DEBUG
...@@ -721,32 +780,6 @@ drop: ...@@ -721,32 +780,6 @@ drop:
static atomic_t llc_sock_nr; static atomic_t llc_sock_nr;
#endif #endif
/**
* llc_release_sockets - releases all sockets in a sap
* @sap: sap to release its sockets
*
* Releases all connections of a sap. Returns 0 if all actions complete
* successfully, nonzero otherwise
*/
int llc_release_sockets(struct llc_sap *sap)
{
int rc = 0;
struct sock *sk;
struct hlist_node *node;
write_lock_bh(&sap->sk_list.lock);
sk_for_each(sk, node, &sap->sk_list.list) {
llc_sk(sk)->state = LLC_CONN_STATE_TEMP;
if (llc_send_disc(sk))
rc = 1;
}
write_unlock_bh(&sap->sk_list.lock);
return rc;
}
/** /**
* llc_backlog_rcv - Processes rx frames and expired timers. * llc_backlog_rcv - Processes rx frames and expired timers.
* @sk: LLC sock (p8022 connection) * @sk: LLC sock (p8022 connection)
...@@ -762,14 +795,14 @@ static int llc_backlog_rcv(struct sock *sk, struct sk_buff *skb) ...@@ -762,14 +795,14 @@ static int llc_backlog_rcv(struct sock *sk, struct sk_buff *skb)
int rc = 0; int rc = 0;
struct llc_sock *llc = llc_sk(sk); struct llc_sock *llc = llc_sk(sk);
if (llc_backlog_type(skb) == LLC_PACKET) { if (likely(llc_backlog_type(skb) == LLC_PACKET)) {
if (llc->state > 1) /* not closed */ if (likely(llc->state > 1)) /* not closed */
rc = llc_conn_rcv(sk, skb); rc = llc_conn_rcv(sk, skb);
else else
goto out_kfree_skb; goto out_kfree_skb;
} else if (llc_backlog_type(skb) == LLC_EVENT) { } else if (llc_backlog_type(skb) == LLC_EVENT) {
/* timer expiration event */ /* timer expiration event */
if (llc->state > 1) /* not closed */ if (likely(llc->state > 1)) /* not closed */
rc = llc_conn_state_process(sk, skb); rc = llc_conn_state_process(sk, skb);
else else
goto out_kfree_skb; goto out_kfree_skb;
...@@ -799,22 +832,22 @@ static void llc_sk_init(struct sock* sk) ...@@ -799,22 +832,22 @@ static void llc_sk_init(struct sock* sk)
llc->dec_step = llc->connect_step = 1; llc->dec_step = llc->connect_step = 1;
init_timer(&llc->ack_timer.timer); init_timer(&llc->ack_timer.timer);
llc->ack_timer.expire = LLC_ACK_TIME; llc->ack_timer.expire = sysctl_llc2_ack_timeout;
llc->ack_timer.timer.data = (unsigned long)sk; llc->ack_timer.timer.data = (unsigned long)sk;
llc->ack_timer.timer.function = llc_conn_ack_tmr_cb; llc->ack_timer.timer.function = llc_conn_ack_tmr_cb;
init_timer(&llc->pf_cycle_timer.timer); init_timer(&llc->pf_cycle_timer.timer);
llc->pf_cycle_timer.expire = LLC_P_TIME; llc->pf_cycle_timer.expire = sysctl_llc2_p_timeout;
llc->pf_cycle_timer.timer.data = (unsigned long)sk; llc->pf_cycle_timer.timer.data = (unsigned long)sk;
llc->pf_cycle_timer.timer.function = llc_conn_pf_cycle_tmr_cb; llc->pf_cycle_timer.timer.function = llc_conn_pf_cycle_tmr_cb;
init_timer(&llc->rej_sent_timer.timer); init_timer(&llc->rej_sent_timer.timer);
llc->rej_sent_timer.expire = LLC_REJ_TIME; llc->rej_sent_timer.expire = sysctl_llc2_rej_timeout;
llc->rej_sent_timer.timer.data = (unsigned long)sk; llc->rej_sent_timer.timer.data = (unsigned long)sk;
llc->rej_sent_timer.timer.function = llc_conn_rej_tmr_cb; llc->rej_sent_timer.timer.function = llc_conn_rej_tmr_cb;
init_timer(&llc->busy_state_timer.timer); init_timer(&llc->busy_state_timer.timer);
llc->busy_state_timer.expire = LLC_BUSY_TIME; llc->busy_state_timer.expire = sysctl_llc2_busy_timeout;
llc->busy_state_timer.timer.data = (unsigned long)sk; llc->busy_state_timer.timer.data = (unsigned long)sk;
llc->busy_state_timer.timer.function = llc_conn_busy_tmr_cb; llc->busy_state_timer.timer.function = llc_conn_busy_tmr_cb;
...@@ -834,7 +867,8 @@ static void llc_sk_init(struct sock* sk) ...@@ -834,7 +867,8 @@ static void llc_sk_init(struct sock* sk)
* Allocates a LLC sock and initializes it. Returns the new LLC sock * Allocates a LLC sock and initializes it. Returns the new LLC sock
* or %NULL if there's no memory available for one * or %NULL if there's no memory available for one
*/ */
struct sock *llc_sk_alloc(int family, int priority, struct proto *prot) struct sock *llc_sk_alloc(int family, unsigned int __nocast priority,
struct proto *prot)
{ {
struct sock *sk = sk_alloc(family, priority, prot, 1); struct sock *sk = sk_alloc(family, priority, prot, 1);
......
...@@ -40,6 +40,7 @@ static struct llc_sap *llc_sap_alloc(void) ...@@ -40,6 +40,7 @@ static struct llc_sap *llc_sap_alloc(void)
sap->state = LLC_SAP_STATE_ACTIVE; sap->state = LLC_SAP_STATE_ACTIVE;
memcpy(sap->laddr.mac, llc_station_mac_sa, ETH_ALEN); memcpy(sap->laddr.mac, llc_station_mac_sa, ETH_ALEN);
rwlock_init(&sap->sk_list.lock); rwlock_init(&sap->sk_list.lock);
atomic_set(&sap->refcnt, 1);
} }
return sap; return sap;
} }
...@@ -52,9 +53,7 @@ static struct llc_sap *llc_sap_alloc(void) ...@@ -52,9 +53,7 @@ static struct llc_sap *llc_sap_alloc(void)
*/ */
static void llc_add_sap(struct llc_sap *sap) static void llc_add_sap(struct llc_sap *sap)
{ {
write_lock_bh(&llc_sap_list_lock);
list_add_tail(&sap->node, &llc_sap_list); list_add_tail(&sap->node, &llc_sap_list);
write_unlock_bh(&llc_sap_list_lock);
} }
/** /**
...@@ -70,11 +69,25 @@ static void llc_del_sap(struct llc_sap *sap) ...@@ -70,11 +69,25 @@ static void llc_del_sap(struct llc_sap *sap)
write_unlock_bh(&llc_sap_list_lock); write_unlock_bh(&llc_sap_list_lock);
} }
static struct llc_sap *__llc_sap_find(unsigned char sap_value)
{
struct llc_sap* sap;
list_for_each_entry(sap, &llc_sap_list, node)
if (sap->laddr.lsap == sap_value)
goto out;
sap = NULL;
out:
return sap;
}
/** /**
* llc_sap_find - searchs a SAP in station * llc_sap_find - searchs a SAP in station
* @sap_value: sap to be found * @sap_value: sap to be found
* *
* Searchs for a sap in the sap list of the LLC's station upon the sap ID. * Searchs for a sap in the sap list of the LLC's station upon the sap ID.
* If the sap is found it will be refcounted and the user will have to do
* a llc_sap_put after use.
* Returns the sap or %NULL if not found. * Returns the sap or %NULL if not found.
*/ */
struct llc_sap *llc_sap_find(unsigned char sap_value) struct llc_sap *llc_sap_find(unsigned char sap_value)
...@@ -82,11 +95,9 @@ struct llc_sap *llc_sap_find(unsigned char sap_value) ...@@ -82,11 +95,9 @@ struct llc_sap *llc_sap_find(unsigned char sap_value)
struct llc_sap* sap; struct llc_sap* sap;
read_lock_bh(&llc_sap_list_lock); read_lock_bh(&llc_sap_list_lock);
list_for_each_entry(sap, &llc_sap_list, node) sap = __llc_sap_find(sap_value);
if (sap->laddr.lsap == sap_value) if (sap)
goto out; llc_sap_hold(sap);
sap = NULL;
out:
read_unlock_bh(&llc_sap_list_lock); read_unlock_bh(&llc_sap_list_lock);
return sap; return sap;
} }
...@@ -106,19 +117,20 @@ struct llc_sap *llc_sap_open(unsigned char lsap, ...@@ -106,19 +117,20 @@ struct llc_sap *llc_sap_open(unsigned char lsap,
struct packet_type *pt, struct packet_type *pt,
struct net_device *orig_dev)) struct net_device *orig_dev))
{ {
struct llc_sap *sap = llc_sap_find(lsap); struct llc_sap *sap = NULL;
if (sap) { /* SAP already exists */ write_lock_bh(&llc_sap_list_lock);
sap = NULL; if (__llc_sap_find(lsap)) /* SAP already exists */
goto out; goto out;
}
sap = llc_sap_alloc(); sap = llc_sap_alloc();
if (!sap) if (!sap)
goto out; goto out;
sap->laddr.lsap = lsap; sap->laddr.lsap = lsap;
sap->rcv_func = func; sap->rcv_func = func;
llc_sap_hold(sap);
llc_add_sap(sap); llc_add_sap(sap);
out: out:
write_unlock_bh(&llc_sap_list_lock);
return sap; return sap;
} }
......
...@@ -47,14 +47,11 @@ int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb) ...@@ -47,14 +47,11 @@ int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb)
int rc = -ECONNABORTED; int rc = -ECONNABORTED;
struct llc_sock *llc = llc_sk(sk); struct llc_sock *llc = llc_sk(sk);
if (llc->state == LLC_CONN_STATE_ADM) if (unlikely(llc->state == LLC_CONN_STATE_ADM))
goto out; goto out;
rc = -EBUSY; rc = -EBUSY;
if (llc_data_accept_state(llc->state)) { /* data_conn_refuse */ if (unlikely(llc_data_accept_state(llc->state) || /* data_conn_refuse */
llc->failed_data_req = 1; llc->p_flag)) {
goto out;
}
if (llc->p_flag) {
llc->failed_data_req = 1; llc->failed_data_req = 1;
goto out; goto out;
} }
...@@ -110,6 +107,7 @@ int llc_establish_connection(struct sock *sk, u8 *lmac, u8 *dmac, u8 dsap) ...@@ -110,6 +107,7 @@ int llc_establish_connection(struct sock *sk, u8 *lmac, u8 *dmac, u8 dsap)
ev->type = LLC_CONN_EV_TYPE_PRIM; ev->type = LLC_CONN_EV_TYPE_PRIM;
ev->prim = LLC_CONN_PRIM; ev->prim = LLC_CONN_PRIM;
ev->prim_type = LLC_PRIM_TYPE_REQ; ev->prim_type = LLC_PRIM_TYPE_REQ;
skb_set_owner_w(skb, sk);
rc = llc_conn_state_process(sk, skb); rc = llc_conn_state_process(sk, skb);
} }
out_put: out_put:
...@@ -144,6 +142,7 @@ int llc_send_disc(struct sock *sk) ...@@ -144,6 +142,7 @@ int llc_send_disc(struct sock *sk)
skb = alloc_skb(0, GFP_ATOMIC); skb = alloc_skb(0, GFP_ATOMIC);
if (!skb) if (!skb)
goto out; goto out;
skb_set_owner_w(skb, sk);
sk->sk_state = TCP_CLOSING; sk->sk_state = TCP_CLOSING;
ev = llc_conn_ev(skb); ev = llc_conn_ev(skb);
ev->type = LLC_CONN_EV_TYPE_PRIM; ev->type = LLC_CONN_EV_TYPE_PRIM;
......
...@@ -99,15 +99,19 @@ out: ...@@ -99,15 +99,19 @@ out:
static inline int llc_fixup_skb(struct sk_buff *skb) static inline int llc_fixup_skb(struct sk_buff *skb)
{ {
u8 llc_len = 2; u8 llc_len = 2;
struct llc_pdu_sn *pdu; struct llc_pdu_un *pdu;
if (!pskb_may_pull(skb, sizeof(*pdu))) if (unlikely(!pskb_may_pull(skb, sizeof(*pdu))))
return 0; return 0;
pdu = (struct llc_pdu_sn *)skb->data; pdu = (struct llc_pdu_un *)skb->data;
if ((pdu->ctrl_1 & LLC_PDU_TYPE_MASK) == LLC_PDU_TYPE_U) if ((pdu->ctrl_1 & LLC_PDU_TYPE_MASK) == LLC_PDU_TYPE_U)
llc_len = 1; llc_len = 1;
llc_len += 2; llc_len += 2;
if (unlikely(!pskb_may_pull(skb, llc_len)))
return 0;
skb->h.raw += llc_len; skb->h.raw += llc_len;
skb_pull(skb, llc_len); skb_pull(skb, llc_len);
if (skb->protocol == htons(ETH_P_802_2)) { if (skb->protocol == htons(ETH_P_802_2)) {
...@@ -166,17 +170,22 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -166,17 +170,22 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev,
*/ */
if (sap->rcv_func) { if (sap->rcv_func) {
sap->rcv_func(skb, dev, pt, orig_dev); sap->rcv_func(skb, dev, pt, orig_dev);
goto out; goto out_put;
} }
dest = llc_pdu_type(skb); dest = llc_pdu_type(skb);
if (unlikely(!dest || !llc_type_handlers[dest - 1])) if (unlikely(!dest || !llc_type_handlers[dest - 1]))
goto drop; goto drop_put;
llc_type_handlers[dest - 1](sap, skb); llc_type_handlers[dest - 1](sap, skb);
out_put:
llc_sap_put(sap);
out: out:
return 0; return 0;
drop: drop:
kfree_skb(skb); kfree_skb(skb);
goto out; goto out;
drop_put:
kfree_skb(skb);
goto out_put;
handle_station: handle_station:
if (!llc_station_handler) if (!llc_station_handler)
goto drop; goto drop;
......
...@@ -98,7 +98,7 @@ int llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb, ...@@ -98,7 +98,7 @@ int llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb,
dsap, LLC_PDU_CMD); dsap, LLC_PDU_CMD);
llc_pdu_init_as_ui_cmd(skb); llc_pdu_init_as_ui_cmd(skb);
rc = llc_mac_hdr_init(skb, skb->dev->dev_addr, dmac); rc = llc_mac_hdr_init(skb, skb->dev->dev_addr, dmac);
if (!rc) if (likely(!rc))
rc = dev_queue_xmit(skb); rc = dev_queue_xmit(skb);
return rc; return rc;
} }
......
...@@ -134,7 +134,7 @@ static int llc_seq_socket_show(struct seq_file *seq, void *v) ...@@ -134,7 +134,7 @@ static int llc_seq_socket_show(struct seq_file *seq, void *v)
llc_ui_format_mac(seq, llc->daddr.mac); llc_ui_format_mac(seq, llc->daddr.mac);
seq_printf(seq, "@%02X %8d %8d %2d %3d %4d\n", llc->daddr.lsap, seq_printf(seq, "@%02X %8d %8d %2d %3d %4d\n", llc->daddr.lsap,
atomic_read(&sk->sk_wmem_alloc), atomic_read(&sk->sk_wmem_alloc),
atomic_read(&sk->sk_rmem_alloc), atomic_read(&sk->sk_rmem_alloc) - llc->copied_seq,
sk->sk_state, sk->sk_state,
sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_uid : -1, sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_uid : -1,
llc->link); llc->link);
......
...@@ -58,7 +58,7 @@ int llc_sap_action_send_ui(struct llc_sap *sap, struct sk_buff *skb) ...@@ -58,7 +58,7 @@ int llc_sap_action_send_ui(struct llc_sap *sap, struct sk_buff *skb)
ev->daddr.lsap, LLC_PDU_CMD); ev->daddr.lsap, LLC_PDU_CMD);
llc_pdu_init_as_ui_cmd(skb); llc_pdu_init_as_ui_cmd(skb);
rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac); rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac);
if (!rc) if (likely(!rc))
rc = dev_queue_xmit(skb); rc = dev_queue_xmit(skb);
return rc; return rc;
} }
...@@ -81,7 +81,7 @@ int llc_sap_action_send_xid_c(struct llc_sap *sap, struct sk_buff *skb) ...@@ -81,7 +81,7 @@ int llc_sap_action_send_xid_c(struct llc_sap *sap, struct sk_buff *skb)
ev->daddr.lsap, LLC_PDU_CMD); ev->daddr.lsap, LLC_PDU_CMD);
llc_pdu_init_as_xid_cmd(skb, LLC_XID_NULL_CLASS_2, 0); llc_pdu_init_as_xid_cmd(skb, LLC_XID_NULL_CLASS_2, 0);
rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac); rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac);
if (!rc) if (likely(!rc))
rc = dev_queue_xmit(skb); rc = dev_queue_xmit(skb);
return rc; return rc;
} }
...@@ -103,15 +103,14 @@ int llc_sap_action_send_xid_r(struct llc_sap *sap, struct sk_buff *skb) ...@@ -103,15 +103,14 @@ int llc_sap_action_send_xid_r(struct llc_sap *sap, struct sk_buff *skb)
llc_pdu_decode_sa(skb, mac_da); llc_pdu_decode_sa(skb, mac_da);
llc_pdu_decode_da(skb, mac_sa); llc_pdu_decode_da(skb, mac_sa);
llc_pdu_decode_ssap(skb, &dsap); llc_pdu_decode_ssap(skb, &dsap);
nskb = llc_alloc_frame(); nskb = llc_alloc_frame(NULL, skb->dev);
if (!nskb) if (!nskb)
goto out; goto out;
nskb->dev = skb->dev;
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap, llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap,
LLC_PDU_RSP); LLC_PDU_RSP);
llc_pdu_init_as_xid_rsp(nskb, LLC_XID_NULL_CLASS_2, 0); llc_pdu_init_as_xid_rsp(nskb, LLC_XID_NULL_CLASS_2, 0);
rc = llc_mac_hdr_init(nskb, mac_sa, mac_da); rc = llc_mac_hdr_init(nskb, mac_sa, mac_da);
if (!rc) if (likely(!rc))
rc = dev_queue_xmit(nskb); rc = dev_queue_xmit(nskb);
out: out:
return rc; return rc;
...@@ -135,7 +134,7 @@ int llc_sap_action_send_test_c(struct llc_sap *sap, struct sk_buff *skb) ...@@ -135,7 +134,7 @@ int llc_sap_action_send_test_c(struct llc_sap *sap, struct sk_buff *skb)
ev->daddr.lsap, LLC_PDU_CMD); ev->daddr.lsap, LLC_PDU_CMD);
llc_pdu_init_as_test_cmd(skb); llc_pdu_init_as_test_cmd(skb);
rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac); rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac);
if (!rc) if (likely(!rc))
rc = dev_queue_xmit(skb); rc = dev_queue_xmit(skb);
return rc; return rc;
} }
...@@ -149,15 +148,14 @@ int llc_sap_action_send_test_r(struct llc_sap *sap, struct sk_buff *skb) ...@@ -149,15 +148,14 @@ int llc_sap_action_send_test_r(struct llc_sap *sap, struct sk_buff *skb)
llc_pdu_decode_sa(skb, mac_da); llc_pdu_decode_sa(skb, mac_da);
llc_pdu_decode_da(skb, mac_sa); llc_pdu_decode_da(skb, mac_sa);
llc_pdu_decode_ssap(skb, &dsap); llc_pdu_decode_ssap(skb, &dsap);
nskb = llc_alloc_frame(); nskb = llc_alloc_frame(NULL, skb->dev);
if (!nskb) if (!nskb)
goto out; goto out;
nskb->dev = skb->dev;
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap, llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap,
LLC_PDU_RSP); LLC_PDU_RSP);
llc_pdu_init_as_test_rsp(nskb, skb); llc_pdu_init_as_test_rsp(nskb, skb);
rc = llc_mac_hdr_init(nskb, mac_sa, mac_da); rc = llc_mac_hdr_init(nskb, mac_sa, mac_da);
if (!rc) if (likely(!rc))
rc = dev_queue_xmit(nskb); rc = dev_queue_xmit(nskb);
out: out:
return rc; return rc;
......
...@@ -26,11 +26,12 @@ ...@@ -26,11 +26,12 @@
/** /**
* llc_alloc_frame - allocates sk_buff for frame * llc_alloc_frame - allocates sk_buff for frame
* @dev: network device this skb will be sent over
* *
* Allocates an sk_buff for frame and initializes sk_buff fields. * Allocates an sk_buff for frame and initializes sk_buff fields.
* Returns allocated skb or %NULL when out of memory. * Returns allocated skb or %NULL when out of memory.
*/ */
struct sk_buff *llc_alloc_frame(void) struct sk_buff *llc_alloc_frame(struct sock *sk, struct net_device *dev)
{ {
struct sk_buff *skb = alloc_skb(128, GFP_ATOMIC); struct sk_buff *skb = alloc_skb(128, GFP_ATOMIC);
...@@ -38,18 +39,23 @@ struct sk_buff *llc_alloc_frame(void) ...@@ -38,18 +39,23 @@ struct sk_buff *llc_alloc_frame(void)
skb_reserve(skb, 50); skb_reserve(skb, 50);
skb->nh.raw = skb->h.raw = skb->data; skb->nh.raw = skb->h.raw = skb->data;
skb->protocol = htons(ETH_P_802_2); skb->protocol = htons(ETH_P_802_2);
skb->dev = dev_base->next; skb->dev = dev;
skb->mac.raw = skb->head; skb->mac.raw = skb->head;
if (sk != NULL)
skb_set_owner_w(skb, sk);
} }
return skb; return skb;
} }
void llc_save_primitive(struct sk_buff* skb, u8 prim) void llc_save_primitive(struct sock *sk, struct sk_buff* skb, u8 prim)
{ {
struct sockaddr_llc *addr = llc_ui_skb_cb(skb); struct sockaddr_llc *addr;
if (skb->sk->sk_type == SOCK_STREAM) /* See UNIX98 */
return;
/* save primitive for use by the user. */ /* save primitive for use by the user. */
addr->sllc_family = skb->sk->sk_family; addr = llc_ui_skb_cb(skb);
addr->sllc_family = sk->sk_family;
addr->sllc_arphrd = skb->dev->type; addr->sllc_arphrd = skb->dev->type;
addr->sllc_test = prim == LLC_TEST_PRIM; addr->sllc_test = prim == LLC_TEST_PRIM;
addr->sllc_xid = prim == LLC_XID_PRIM; addr->sllc_xid = prim == LLC_XID_PRIM;
...@@ -189,7 +195,7 @@ static void llc_sap_state_process(struct llc_sap *sap, struct sk_buff *skb) ...@@ -189,7 +195,7 @@ static void llc_sap_state_process(struct llc_sap *sap, struct sk_buff *skb)
if (skb->sk->sk_state == TCP_LISTEN) if (skb->sk->sk_state == TCP_LISTEN)
kfree_skb(skb); kfree_skb(skb);
else { else {
llc_save_primitive(skb, ev->prim); llc_save_primitive(skb->sk, skb, ev->prim);
/* queue skb to the user. */ /* queue skb to the user. */
if (sock_queue_rcv_skb(skb->sk, skb)) if (sock_queue_rcv_skb(skb->sk, skb))
...@@ -308,7 +314,7 @@ void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb) ...@@ -308,7 +314,7 @@ void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb)
sk = llc_lookup_dgram(sap, &laddr); sk = llc_lookup_dgram(sap, &laddr);
if (sk) { if (sk) {
skb->sk = sk; skb_set_owner_r(skb, sk);
llc_sap_rcv(sap, skb); llc_sap_rcv(sap, skb);
sock_put(sk); sock_put(sk);
} else } else
......
...@@ -50,6 +50,10 @@ struct llc_station { ...@@ -50,6 +50,10 @@ struct llc_station {
struct sk_buff_head mac_pdu_q; struct sk_buff_head mac_pdu_q;
}; };
#define LLC_STATION_ACK_TIME (3 * HZ)
int sysctl_llc_station_ack_timeout = LLC_STATION_ACK_TIME;
/* Types of events (possible values in 'ev->type') */ /* Types of events (possible values in 'ev->type') */
#define LLC_STATION_EV_TYPE_SIMPLE 1 #define LLC_STATION_EV_TYPE_SIMPLE 1
#define LLC_STATION_EV_TYPE_CONDITION 2 #define LLC_STATION_EV_TYPE_CONDITION 2
...@@ -218,7 +222,8 @@ static void llc_station_send_pdu(struct sk_buff *skb) ...@@ -218,7 +222,8 @@ static void llc_station_send_pdu(struct sk_buff *skb)
static int llc_station_ac_start_ack_timer(struct sk_buff *skb) static int llc_station_ac_start_ack_timer(struct sk_buff *skb)
{ {
mod_timer(&llc_main_station.ack_timer, jiffies + LLC_ACK_TIME * HZ); mod_timer(&llc_main_station.ack_timer,
jiffies + sysctl_llc_station_ack_timeout);
return 0; return 0;
} }
...@@ -249,14 +254,14 @@ static int llc_station_ac_inc_xid_r_cnt_by_1(struct sk_buff *skb) ...@@ -249,14 +254,14 @@ static int llc_station_ac_inc_xid_r_cnt_by_1(struct sk_buff *skb)
static int llc_station_ac_send_null_dsap_xid_c(struct sk_buff *skb) static int llc_station_ac_send_null_dsap_xid_c(struct sk_buff *skb)
{ {
int rc = 1; int rc = 1;
struct sk_buff *nskb = llc_alloc_frame(); struct sk_buff *nskb = llc_alloc_frame(NULL, skb->dev);
if (!nskb) if (!nskb)
goto out; goto out;
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, 0, LLC_PDU_CMD); llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, 0, LLC_PDU_CMD);
llc_pdu_init_as_xid_cmd(nskb, LLC_XID_NULL_CLASS_2, 127); llc_pdu_init_as_xid_cmd(nskb, LLC_XID_NULL_CLASS_2, 127);
rc = llc_mac_hdr_init(nskb, llc_station_mac_sa, llc_station_mac_sa); rc = llc_mac_hdr_init(nskb, llc_station_mac_sa, llc_station_mac_sa);
if (rc) if (unlikely(rc))
goto free; goto free;
llc_station_send_pdu(nskb); llc_station_send_pdu(nskb);
out: out:
...@@ -270,18 +275,17 @@ static int llc_station_ac_send_xid_r(struct sk_buff *skb) ...@@ -270,18 +275,17 @@ static int llc_station_ac_send_xid_r(struct sk_buff *skb)
{ {
u8 mac_da[ETH_ALEN], dsap; u8 mac_da[ETH_ALEN], dsap;
int rc = 1; int rc = 1;
struct sk_buff* nskb = llc_alloc_frame(); struct sk_buff* nskb = llc_alloc_frame(NULL, skb->dev);
if (!nskb) if (!nskb)
goto out; goto out;
rc = 0; rc = 0;
nskb->dev = skb->dev;
llc_pdu_decode_sa(skb, mac_da); llc_pdu_decode_sa(skb, mac_da);
llc_pdu_decode_ssap(skb, &dsap); llc_pdu_decode_ssap(skb, &dsap);
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP); llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP);
llc_pdu_init_as_xid_rsp(nskb, LLC_XID_NULL_CLASS_2, 127); llc_pdu_init_as_xid_rsp(nskb, LLC_XID_NULL_CLASS_2, 127);
rc = llc_mac_hdr_init(nskb, llc_station_mac_sa, mac_da); rc = llc_mac_hdr_init(nskb, llc_station_mac_sa, mac_da);
if (rc) if (unlikely(rc))
goto free; goto free;
llc_station_send_pdu(nskb); llc_station_send_pdu(nskb);
out: out:
...@@ -295,18 +299,17 @@ static int llc_station_ac_send_test_r(struct sk_buff *skb) ...@@ -295,18 +299,17 @@ static int llc_station_ac_send_test_r(struct sk_buff *skb)
{ {
u8 mac_da[ETH_ALEN], dsap; u8 mac_da[ETH_ALEN], dsap;
int rc = 1; int rc = 1;
struct sk_buff *nskb = llc_alloc_frame(); struct sk_buff *nskb = llc_alloc_frame(NULL, skb->dev);
if (!nskb) if (!nskb)
goto out; goto out;
rc = 0; rc = 0;
nskb->dev = skb->dev;
llc_pdu_decode_sa(skb, mac_da); llc_pdu_decode_sa(skb, mac_da);
llc_pdu_decode_ssap(skb, &dsap); llc_pdu_decode_ssap(skb, &dsap);
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP); llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP);
llc_pdu_init_as_test_rsp(nskb, skb); llc_pdu_init_as_test_rsp(nskb, skb);
rc = llc_mac_hdr_init(nskb, llc_station_mac_sa, mac_da); rc = llc_mac_hdr_init(nskb, llc_station_mac_sa, mac_da);
if (rc) if (unlikely(rc))
goto free; goto free;
llc_station_send_pdu(nskb); llc_station_send_pdu(nskb);
out: out:
...@@ -689,7 +692,8 @@ int __init llc_station_init(void) ...@@ -689,7 +692,8 @@ int __init llc_station_init(void)
init_timer(&llc_main_station.ack_timer); init_timer(&llc_main_station.ack_timer);
llc_main_station.ack_timer.data = (unsigned long)&llc_main_station; llc_main_station.ack_timer.data = (unsigned long)&llc_main_station;
llc_main_station.ack_timer.function = llc_station_ack_tmr_cb; llc_main_station.ack_timer.function = llc_station_ack_tmr_cb;
llc_main_station.ack_timer.expires = jiffies +
sysctl_llc_station_ack_timeout;
skb = alloc_skb(0, GFP_ATOMIC); skb = alloc_skb(0, GFP_ATOMIC);
if (!skb) if (!skb)
goto out; goto out;
...@@ -697,7 +701,6 @@ int __init llc_station_init(void) ...@@ -697,7 +701,6 @@ int __init llc_station_init(void)
llc_set_station_handler(llc_station_rcv); llc_set_station_handler(llc_station_rcv);
ev = llc_station_ev(skb); ev = llc_station_ev(skb);
memset(ev, 0, sizeof(*ev)); memset(ev, 0, sizeof(*ev));
llc_main_station.ack_timer.expires = jiffies + 3 * HZ;
llc_main_station.maximum_retry = 1; llc_main_station.maximum_retry = 1;
llc_main_station.state = LLC_STATION_STATE_DOWN; llc_main_station.state = LLC_STATION_STATE_DOWN;
ev->type = LLC_STATION_EV_TYPE_SIMPLE; ev->type = LLC_STATION_EV_TYPE_SIMPLE;
......
/*
* sysctl_net_llc.c: sysctl interface to LLC net subsystem.
*
* Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*/
#include <linux/config.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/sysctl.h>
#include <net/llc.h>
#ifndef CONFIG_SYSCTL
#error This file should not be compiled without CONFIG_SYSCTL defined
#endif
static struct ctl_table llc2_timeout_table[] = {
{
.ctl_name = NET_LLC2_ACK_TIMEOUT,
.procname = "ack",
.data = &sysctl_llc2_ack_timeout,
.maxlen = sizeof(long),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
.strategy = &sysctl_jiffies,
},
{
.ctl_name = NET_LLC2_BUSY_TIMEOUT,
.procname = "busy",
.data = &sysctl_llc2_busy_timeout,
.maxlen = sizeof(long),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
.strategy = &sysctl_jiffies,
},
{
.ctl_name = NET_LLC2_P_TIMEOUT,
.procname = "p",
.data = &sysctl_llc2_p_timeout,
.maxlen = sizeof(long),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
.strategy = &sysctl_jiffies,
},
{
.ctl_name = NET_LLC2_REJ_TIMEOUT,
.procname = "rej",
.data = &sysctl_llc2_rej_timeout,
.maxlen = sizeof(long),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
.strategy = &sysctl_jiffies,
},
{ 0 },
};
static struct ctl_table llc_station_table[] = {
{
.ctl_name = NET_LLC_STATION_ACK_TIMEOUT,
.procname = "ack_timeout",
.data = &sysctl_llc_station_ack_timeout,
.maxlen = sizeof(long),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies,
.strategy = &sysctl_jiffies,
},
{ 0 },
};
static struct ctl_table llc2_dir_timeout_table[] = {
{
.ctl_name = NET_LLC2,
.procname = "timeout",
.mode = 0555,
.child = llc2_timeout_table,
},
{ 0 },
};
static struct ctl_table llc_table[] = {
{
.ctl_name = NET_LLC2,
.procname = "llc2",
.mode = 0555,
.child = llc2_dir_timeout_table,
},
{
.ctl_name = NET_LLC_STATION,
.procname = "station",
.mode = 0555,
.child = llc_station_table,
},
{ 0 },
};
static struct ctl_table llc_dir_table[] = {
{
.ctl_name = NET_LLC,
.procname = "llc",
.mode = 0555,
.child = llc_table,
},
{ 0 },
};
static struct ctl_table llc_root_table[] = {
{
.ctl_name = CTL_NET,
.procname = "net",
.mode = 0555,
.child = llc_dir_table,
},
{ 0 },
};
static struct ctl_table_header *llc_table_header;
int __init llc_sysctl_init(void)
{
llc_table_header = register_sysctl_table(llc_root_table, 1);
return llc_table_header ? 0 : -ENOMEM;
}
void llc_sysctl_exit(void)
{
if (llc_table_header) {
unregister_sysctl_table(llc_table_header);
llc_table_header = NULL;
}
}
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