Commit 54c8c5d8 authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/home/davem/BK/net-2.5

into penguin.transmeta.com:/home/penguin/torvalds/repositories/kernel/linux
parents b85e4ca0 a5ea51da
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
# #
mainmenu_option next_comment mainmenu_option next_comment
comment 'Appletalk devices'
dep_mbool 'Appletalk interfaces support' CONFIG_DEV_APPLETALK $CONFIG_ATALK dep_mbool 'Appletalk interfaces support' CONFIG_DEV_APPLETALK $CONFIG_ATALK
if [ "$CONFIG_DEV_APPLETALK" = "y" ]; then if [ "$CONFIG_DEV_APPLETALK" = "y" ]; then
tristate ' Apple/Farallon LocalTalk PC support' CONFIG_LTPC tristate ' Apple/Farallon LocalTalk PC support' CONFIG_LTPC
...@@ -18,4 +17,3 @@ if [ "$CONFIG_DEV_APPLETALK" = "y" ]; then ...@@ -18,4 +17,3 @@ if [ "$CONFIG_DEV_APPLETALK" = "y" ]; then
bool ' Appletalk-IP to IP Decapsulation support' CONFIG_IPDDP_DECAP bool ' Appletalk-IP to IP Decapsulation support' CONFIG_IPDDP_DECAP
fi fi
fi fi
endmenu
...@@ -181,7 +181,7 @@ struct cops_local ...@@ -181,7 +181,7 @@ struct cops_local
int board; /* Holds what board type is. */ int board; /* Holds what board type is. */
int nodeid; /* Set to 1 once have nodeid. */ int nodeid; /* Set to 1 once have nodeid. */
unsigned char node_acquire; /* Node ID when acquired. */ unsigned char node_acquire; /* Node ID when acquired. */
struct at_addr node_addr; /* Full node address */ struct atalk_addr node_addr; /* Full node address */
}; };
/* Index to functions, as function prototypes. */ /* Index to functions, as function prototypes. */
...@@ -955,8 +955,8 @@ static int cops_hard_header(struct sk_buff *skb, struct net_device *dev, ...@@ -955,8 +955,8 @@ static int cops_hard_header(struct sk_buff *skb, struct net_device *dev,
static int cops_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) static int cops_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{ {
struct cops_local *lp = (struct cops_local *)dev->priv; struct cops_local *lp = (struct cops_local *)dev->priv;
struct sockaddr_at *sa=(struct sockaddr_at *)&ifr->ifr_addr; struct sockaddr_at *sa = (struct sockaddr_at *)&ifr->ifr_addr;
struct at_addr *aa=(struct at_addr *)&lp->node_addr; struct atalk_addr *aa = (struct atalk_addr *)&lp->node_addr;
switch(cmd) switch(cmd)
{ {
......
...@@ -116,7 +116,7 @@ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -116,7 +116,7 @@ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev)
u32 paddr = ((struct rtable*)skb->dst)->rt_gateway; u32 paddr = ((struct rtable*)skb->dst)->rt_gateway;
struct ddpehdr *ddp; struct ddpehdr *ddp;
struct ipddp_route *rt; struct ipddp_route *rt;
struct at_addr *our_addr; struct atalk_addr *our_addr;
/* /*
* Find appropriate route to use, based only on IP number. * Find appropriate route to use, based only on IP number.
......
...@@ -15,7 +15,7 @@ struct ipddp_route ...@@ -15,7 +15,7 @@ struct ipddp_route
{ {
struct net_device *dev; /* Carrier device */ struct net_device *dev; /* Carrier device */
__u32 ip; /* IP address */ __u32 ip; /* IP address */
struct at_addr at; /* Gateway appletalk address */ struct atalk_addr at; /* Gateway appletalk address */
int flags; int flags;
struct ipddp_route *next; struct ipddp_route *next;
}; };
......
...@@ -262,7 +262,7 @@ static unsigned char *ltdmacbuf; ...@@ -262,7 +262,7 @@ static unsigned char *ltdmacbuf;
struct ltpc_private struct ltpc_private
{ {
struct net_device_stats stats; struct net_device_stats stats;
struct at_addr my_addr; struct atalk_addr my_addr;
}; };
/* transmit queue element struct */ /* transmit queue element struct */
...@@ -826,7 +826,7 @@ static int ltpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -826,7 +826,7 @@ static int ltpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{ {
struct sockaddr_at *sa = (struct sockaddr_at *) &ifr->ifr_addr; struct sockaddr_at *sa = (struct sockaddr_at *) &ifr->ifr_addr;
/* we'll keep the localtalk node address in dev->pa_addr */ /* we'll keep the localtalk node address in dev->pa_addr */
struct at_addr *aa = &((struct ltpc_private *)dev->priv)->my_addr; struct atalk_addr *aa = &((struct ltpc_private *)dev->priv)->my_addr;
struct lt_init c; struct lt_init c;
int ltflags; int ltflags;
......
...@@ -399,7 +399,7 @@ static u16 bond_check_dev_link(struct net_device *dev) ...@@ -399,7 +399,7 @@ static u16 bond_check_dev_link(struct net_device *dev)
{ {
static int (* ioctl)(struct net_device *, struct ifreq *, int); static int (* ioctl)(struct net_device *, struct ifreq *, int);
struct ifreq ifr; struct ifreq ifr;
struct mii_ioctl_data mii; struct mii_ioctl_data *mii;
struct ethtool_value etool; struct ethtool_value etool;
if ((ioctl = dev->do_ioctl) != NULL) { /* ioctl to access MII */ if ((ioctl = dev->do_ioctl) != NULL) { /* ioctl to access MII */
...@@ -425,21 +425,24 @@ static u16 bond_check_dev_link(struct net_device *dev) ...@@ -425,21 +425,24 @@ static u16 bond_check_dev_link(struct net_device *dev)
} }
} }
ifr.ifr_data = (char*)&mii; /*
/* try MIIPHY first then, if that doesn't work, try MIIREG */ * We cannot assume that SIOCGMIIPHY will also read a
if (ioctl(dev, &ifr, SIOCGMIIPHY) == 0) { * register; not all network drivers support that.
/* now, mii.phy_id contains info about link status : */
- mii.phy_id & 0x04 means link up
- mii.phy_id & 0x20 means end of auto-negociation /* Yes, the mii is overlaid on the ifreq.ifr_ifru */
*/ mii = (struct mii_ioctl_data *)&ifr.ifr_data;
return mii.phy_id; if (ioctl(dev, &ifr, SIOCGMIIPHY) != 0) {
return MII_LINK_READY; /* can't tell */
} }
mii.reg_num = 1; /* the MII register we want to read */ mii->reg_num = 1;
if (ioctl(dev, &ifr, SIOCGMIIREG) == 0) { if (ioctl(dev, &ifr, SIOCGMIIREG) == 0) {
/* mii.val_out contians the same link info as phy_id */ /*
/* above */ * mii->val_out contains MII reg 1, BMSR
return mii.val_out; * 0x0004 means link established
*/
return mii->val_out;
} }
} }
...@@ -641,12 +644,6 @@ static void set_multicast_list(struct net_device *master) ...@@ -641,12 +644,6 @@ static void set_multicast_list(struct net_device *master)
*/ */
write_lock_irqsave(&bond->lock, flags); write_lock_irqsave(&bond->lock, flags);
/*
* Lock the master device so that noone trys to transmit
* while we're changing things
*/
spin_lock_bh(&master->xmit_lock);
/* set promiscuity flag to slaves */ /* set promiscuity flag to slaves */
if ( (master->flags & IFF_PROMISC) && !(bond->flags & IFF_PROMISC) ) if ( (master->flags & IFF_PROMISC) && !(bond->flags & IFF_PROMISC) )
bond_set_promiscuity(bond, 1); bond_set_promiscuity(bond, 1);
...@@ -680,7 +677,6 @@ static void set_multicast_list(struct net_device *master) ...@@ -680,7 +677,6 @@ static void set_multicast_list(struct net_device *master)
bond_mc_list_destroy (bond); bond_mc_list_destroy (bond);
bond_mc_list_copy (master->mc_list, bond, GFP_KERNEL); bond_mc_list_copy (master->mc_list, bond, GFP_KERNEL);
spin_unlock_bh(&master->xmit_lock);
write_unlock_irqrestore(&bond->lock, flags); write_unlock_irqrestore(&bond->lock, flags);
} }
......
...@@ -29,13 +29,11 @@ ...@@ -29,13 +29,11 @@
* compare-and-swap cpus (Sparc64). So we control which * compare-and-swap cpus (Sparc64). So we control which
* implementation to use with a __BRLOCK_USE_ATOMICS define. -DaveM * implementation to use with a __BRLOCK_USE_ATOMICS define. -DaveM
* *
* Added BR_LLC_LOCK for use in net/core/ext8022.c -acme
*/ */
/* Register bigreader lock indices here. */ /* Register bigreader lock indices here. */
enum brlock_indices { enum brlock_indices {
BR_NETPROTO_LOCK, BR_NETPROTO_LOCK,
BR_LLC_LOCK,
__BR_END __BR_END
}; };
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/compiler.h> #include <linux/compiler.h>
#include <asm/byteorder.h>
/* Optimization barrier */ /* Optimization barrier */
/* The "volatile" is due to gcc bugs */ /* The "volatile" is due to gcc bugs */
...@@ -116,11 +117,17 @@ extern const char *print_tainted(void); ...@@ -116,11 +117,17 @@ extern const char *print_tainted(void);
((unsigned char *)&addr)[2], \ ((unsigned char *)&addr)[2], \
((unsigned char *)&addr)[3] ((unsigned char *)&addr)[3]
#if defined(__LITTLE_ENDIAN)
#define HIPQUAD(addr) \ #define HIPQUAD(addr) \
((unsigned char *)&addr)[3], \ ((unsigned char *)&addr)[3], \
((unsigned char *)&addr)[2], \ ((unsigned char *)&addr)[2], \
((unsigned char *)&addr)[1], \ ((unsigned char *)&addr)[1], \
((unsigned char *)&addr)[0] ((unsigned char *)&addr)[0]
#elif defined(__BIG_ENDIAN)
#define HIPQUAD NIPQUAD
#else
#error "Please fix asm/byteorder.h"
#endif /* __LITTLE_ENDIAN */
/* /*
* min()/max() macros that also do * min()/max() macros that also do
......
...@@ -162,7 +162,7 @@ struct netif_rx_stats ...@@ -162,7 +162,7 @@ struct netif_rx_stats
unsigned fastroute_deferred_out; unsigned fastroute_deferred_out;
unsigned fastroute_latency_reduction; unsigned fastroute_latency_reduction;
unsigned cpu_collision; unsigned cpu_collision;
} __attribute__ ((__aligned__(SMP_CACHE_BYTES))); } ____cacheline_aligned;
extern struct netif_rx_stats netdev_rx_stat[]; extern struct netif_rx_stats netdev_rx_stat[];
...@@ -376,6 +376,7 @@ struct net_device ...@@ -376,6 +376,7 @@ struct net_device
int (*stop)(struct net_device *dev); int (*stop)(struct net_device *dev);
int (*hard_start_xmit) (struct sk_buff *skb, int (*hard_start_xmit) (struct sk_buff *skb,
struct net_device *dev); struct net_device *dev);
#define HAVE_NETDEV_POLL
int (*poll) (struct net_device *dev, int *quota); int (*poll) (struct net_device *dev, int *quota);
int (*hard_header) (struct sk_buff *skb, int (*hard_header) (struct sk_buff *skb,
struct net_device *dev, struct net_device *dev,
...@@ -501,7 +502,7 @@ struct softnet_data ...@@ -501,7 +502,7 @@ struct softnet_data
struct sk_buff *completion_queue; struct sk_buff *completion_queue;
struct net_device backlog_dev; /* Sorry. 8) */ struct net_device backlog_dev; /* Sorry. 8) */
} __attribute__((__aligned__(SMP_CACHE_BYTES))); } ____cacheline_aligned;
extern struct softnet_data softnet_data[NR_CPUS]; extern struct softnet_data softnet_data[NR_CPUS];
......
...@@ -2,24 +2,17 @@ ...@@ -2,24 +2,17 @@
#define _NET_INET_DATALINK_H_ #define _NET_INET_DATALINK_H_
struct datalink_proto { struct datalink_proto {
unsigned short type_len;
unsigned char type[8]; unsigned char type[8];
const char *string_name;
union { struct llc_sap *sap;
struct llc_pinfo *llc;
} ll_pinfo;
struct llc_sc_info *llc_sc;
struct sock *sock;
unsigned short header_length; unsigned short header_length;
int (*rcvfunc)(struct sk_buff *, struct net_device *, int (*rcvfunc)(struct sk_buff *, struct net_device *,
struct packet_type *); struct packet_type *);
void (*datalink_header)(struct datalink_proto *, struct sk_buff *, int (*request)(struct datalink_proto *, struct sk_buff *,
unsigned char *); unsigned char *);
struct datalink_proto *next; struct list_head node;
}; };
#endif #endif
...@@ -29,8 +29,6 @@ ...@@ -29,8 +29,6 @@
#define LLC_GLOBAL_DEFAULT_MAX_NBR_SAPS 4 #define LLC_GLOBAL_DEFAULT_MAX_NBR_SAPS 4
#define LLC_GLOBAL_DEFAULT_MAX_NBR_CONNS 64 #define LLC_GLOBAL_DEFAULT_MAX_NBR_CONNS 64
extern struct llc_prim_if_block llc_ind_prim, llc_cfm_prim;
/* LLC station component (SAP and connection resource manager) */ /* LLC station component (SAP and connection resource manager) */
/* Station component; one per adapter */ /* Station component; one per adapter */
struct llc_station { struct llc_station {
......
...@@ -198,6 +198,11 @@ struct llc_pdu_sn { ...@@ -198,6 +198,11 @@ struct llc_pdu_sn {
u8 ctrl_2; u8 ctrl_2;
}; };
static __inline__ struct llc_pdu_sn *llc_pdu_sn_hdr(struct sk_buff *skb)
{
return (struct llc_pdu_sn *)skb->nh.raw;
}
/* Un-numbered PDU format (3 bytes in length) */ /* Un-numbered PDU format (3 bytes in length) */
struct llc_pdu_un { struct llc_pdu_un {
u8 dsap; u8 dsap;
...@@ -205,6 +210,16 @@ struct llc_pdu_un { ...@@ -205,6 +210,16 @@ struct llc_pdu_un {
u8 ctrl_1; u8 ctrl_1;
}; };
static __inline__ struct llc_pdu_un *llc_pdu_un_hdr(struct sk_buff *skb)
{
return (struct llc_pdu_un *)skb->nh.raw;
}
static __inline__ void *llc_set_pdu_hdr(struct sk_buff *skb, void *ptr)
{
return skb->nh.raw = ptr;
}
/* LLC Type 1 XID command/response information fields format */ /* LLC Type 1 XID command/response information fields format */
struct llc_xid_info { struct llc_xid_info {
u8 fmt_id; /* always 0x18 for LLC */ u8 fmt_id; /* always 0x18 for LLC */
......
...@@ -12,23 +12,38 @@ ...@@ -12,23 +12,38 @@
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
*/ */
#include <linux/skbuff.h> #include <linux/skbuff.h>
/* Defines the SAP component */ /**
* struct llc_sap - Defines the SAP component
*
* @p_bit - only lowest-order bit used
* @f_bit - only lowest-order bit used
* @req - provided by LLC layer
* @resp - provided by LLC layer
* @ind - provided by network layer
* @conf - provided by network layer
* @laddr - SAP value in this 'lsap'
* @node - entry in station sap_list
* @sk_list - LLC sockets this one manages
* @mac_pdu_q - PDUs ready to send to MAC
*/
struct llc_sap { struct llc_sap {
u8 state; struct llc_station *parent_station;
struct llc_station *parent_station; u8 state;
u8 p_bit; /* only lowest-order bit used */ u8 p_bit;
u8 f_bit; /* only lowest-order bit used */ u8 f_bit;
llc_prim_call_t req; /* provided by LLC layer */ llc_prim_call_t req;
llc_prim_call_t resp; /* provided by LLC layer */ llc_prim_call_t resp;
llc_prim_call_t ind; /* provided by network layer */ llc_prim_call_t ind;
llc_prim_call_t conf; /* provided by network layer */ llc_prim_call_t conf;
struct llc_addr laddr; /* SAP value in this 'lsap' */ struct llc_prim_if_block llc_ind_prim, llc_cfm_prim;
struct list_head node; /* entry in station sap_list */ union llc_u_prim_data llc_ind_data_prim, llc_cfm_data_prim;
struct llc_addr laddr;
struct list_head node;
struct { struct {
spinlock_t lock; spinlock_t lock;
struct list_head list; struct list_head list;
} sk_list; /* LLC sockets this one manages */ } sk_list;
struct sk_buff_head mac_pdu_q; /* PDUs ready to send to MAC */ struct sk_buff_head mac_pdu_q;
}; };
struct llc_sap_state_ev; struct llc_sap_state_ev;
......
#ifndef _NET_P8022_H #ifndef _NET_P8022_H
#define _NET_P8022_H #define _NET_P8022_H
#include <net/llc_if.h>
extern struct datalink_proto *register_8022_client(unsigned char type, extern struct datalink_proto *register_8022_client(unsigned char type,
int (*rcvfunc) int (*indicate)(struct llc_prim_if_block *prim));
(struct sk_buff *, extern void unregister_8022_client(struct datalink_proto *proto);
struct net_device *,
struct packet_type *));
extern void unregister_8022_client(unsigned char type);
#endif #endif
...@@ -2,6 +2,6 @@ ...@@ -2,6 +2,6 @@
#define _NET_PSNAP_H #define _NET_PSNAP_H
extern struct datalink_proto *register_snap_client(unsigned char *desc, int (*rcvfunc)(struct sk_buff *, struct net_device *, struct packet_type *)); extern struct datalink_proto *register_snap_client(unsigned char *desc, int (*rcvfunc)(struct sk_buff *, struct net_device *, struct packet_type *));
extern void unregister_snap_client(unsigned char *desc); extern void unregister_snap_client(struct datalink_proto *proto);
#endif #endif
...@@ -23,103 +23,48 @@ ...@@ -23,103 +23,48 @@
#include <linux/in.h> #include <linux/in.h>
#include <linux/init.h> #include <linux/init.h>
#include <net/p8022.h> #include <net/p8022.h>
#include <net/llc_sap.h>
extern void llc_register_sap(unsigned char sap, static int p8022_request(struct datalink_proto *dl, struct sk_buff *skb,
int (*rcvfunc)(struct sk_buff *, unsigned char *dest)
struct net_device *,
struct packet_type *));
extern void llc_unregister_sap(unsigned char sap);
static struct datalink_proto *p8022_list;
/*
* We don't handle the loopback SAP stuff, the extended
* 802.2 command set, multicast SAP identifiers and non UI
* frames. We have the absolute minimum needed for IPX,
* IP and Appletalk phase 2. See the llc_* routines for
* support libraries if your protocol needs these.
*/
static struct datalink_proto *find_8022_client(unsigned char type)
{
struct datalink_proto *proto = p8022_list;
while (proto && *(proto->type) != type)
proto = proto->next;
return proto;
}
int p8022_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt)
{
struct datalink_proto *proto;
int rc = 0;
proto = find_8022_client(*(skb->h.raw));
if (!proto) {
skb->sk = NULL;
kfree_skb(skb);
goto out;
}
skb->h.raw += 3;
skb->nh.raw += 3;
skb_pull(skb, 3);
rc = proto->rcvfunc(skb, dev, pt);
out: return rc;
}
static void p8022_datalink_header(struct datalink_proto *dl,
struct sk_buff *skb, unsigned char *dest_node)
{ {
struct net_device *dev = skb->dev; union llc_u_prim_data prim_data;
unsigned char *rawp = skb_push(skb, 3); struct llc_prim_if_block prim;
*rawp++ = dl->type[0]; prim.data = &prim_data;
*rawp++ = dl->type[0]; prim.sap = dl->sap;
*rawp = 0x03; /* UI */ prim.prim = LLC_DATAUNIT_PRIM;
dev->hard_header(skb, dev, ETH_P_802_3, dest_node, NULL, skb->len); prim_data.test.skb = skb;
prim_data.test.saddr.lsap = dl->sap->laddr.lsap;
prim_data.test.daddr.lsap = dl->sap->laddr.lsap;
memcpy(prim_data.test.saddr.mac, skb->dev->dev_addr, IFHWADDRLEN);
memcpy(prim_data.test.daddr.mac, dest, IFHWADDRLEN);
return dl->sap->req(&prim);
} }
struct datalink_proto *register_8022_client(unsigned char type, struct datalink_proto *register_8022_client(unsigned char type,
int (*rcvfunc)(struct sk_buff *, int (*indicate)(struct llc_prim_if_block *prim))
struct net_device *,
struct packet_type *))
{ {
struct datalink_proto *proto = NULL; struct datalink_proto *proto;
if (find_8022_client(type))
goto out;
proto = kmalloc(sizeof(*proto), GFP_ATOMIC); proto = kmalloc(sizeof(*proto), GFP_ATOMIC);
if (proto) { if (proto) {
proto->type[0] = type; proto->type[0] = type;
proto->type_len = 1;
proto->rcvfunc = rcvfunc;
proto->header_length = 3; proto->header_length = 3;
proto->datalink_header = p8022_datalink_header; proto->request = p8022_request;
proto->string_name = "802.2"; proto->sap = llc_sap_open(indicate, NULL, type);
proto->next = p8022_list; if (!proto->sap) {
p8022_list = proto; kfree(proto);
llc_register_sap(type, p8022_rcv); proto = NULL;
}
} }
out: return proto; return proto;
} }
void unregister_8022_client(unsigned char type) void unregister_8022_client(struct datalink_proto *proto)
{ {
struct datalink_proto *tmp, **clients = &p8022_list; llc_sap_close(proto->sap);
unsigned long flags; kfree(proto);
save_flags(flags);
cli();
while (*clients) {
tmp = *clients;
if (tmp->type[0] == type) {
*clients = tmp->next;
kfree(tmp);
llc_unregister_sap(type);
break;
}
clients = &tmp->next;
}
restore_flags(flags);
} }
EXPORT_SYMBOL(register_8022_client); EXPORT_SYMBOL(register_8022_client);
......
...@@ -24,11 +24,12 @@ ...@@ -24,11 +24,12 @@
* addresses, we just need to give it the buffer length. * addresses, we just need to give it the buffer length.
*/ */
static void p8023_datalink_header(struct datalink_proto *dl, static int p8023_request(struct datalink_proto *dl,
struct sk_buff *skb, unsigned char *dest_node) struct sk_buff *skb, unsigned char *dest_node)
{ {
struct net_device *dev = skb->dev; struct net_device *dev = skb->dev;
dev->hard_header(skb, dev, ETH_P_802_3, dest_node, NULL, skb->len); dev->hard_header(skb, dev, ETH_P_802_3, dest_node, NULL, skb->len);
return dev_queue_xmit(skb);
} }
/* /*
...@@ -42,10 +43,8 @@ struct datalink_proto *make_8023_client(void) ...@@ -42,10 +43,8 @@ struct datalink_proto *make_8023_client(void)
proto = (struct datalink_proto *) kmalloc(sizeof(*proto), GFP_ATOMIC); proto = (struct datalink_proto *) kmalloc(sizeof(*proto), GFP_ATOMIC);
if (proto != NULL) if (proto != NULL)
{ {
proto->type_len = 0;
proto->header_length = 0; proto->header_length = 0;
proto->datalink_header = p8023_datalink_header; proto->request = p8023_request;
proto->string_name = "802.3";
} }
return proto; return proto;
} }
......
...@@ -15,61 +15,90 @@ ...@@ -15,61 +15,90 @@
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <net/datalink.h> #include <net/datalink.h>
#include <net/p8022.h>
#include <net/psnap.h> #include <net/psnap.h>
#include <net/llc_if.h>
#include <net/llc_sap.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/in.h> #include <linux/in.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/brlock.h>
static struct datalink_proto *snap_list; LIST_HEAD(snap_list);
static struct datalink_proto *snap_dl; /* 802.2 DL for SNAP */ static struct llc_sap *snap_sap;
/* /*
* Find a snap client by matching the 5 bytes. * Find a snap client by matching the 5 bytes.
*/ */
static struct datalink_proto *find_snap_client(unsigned char *desc) static struct datalink_proto *find_snap_client(unsigned char *desc)
{ {
struct datalink_proto *proto = snap_list; struct list_head *entry;
struct datalink_proto *proto = NULL, *p;
for (; proto && memcmp(proto->type, desc, 5); proto = proto->next); if (list_empty(&snap_list))
goto out;
list_for_each(entry, &snap_list) {
p = list_entry(entry, struct datalink_proto, node);
if (!memcmp(p->type, desc, 5)) {
proto = p;
break;
}
}
out:
return proto; return proto;
} }
/* /*
* A SNAP packet has arrived * A SNAP packet has arrived
*/ */
int snap_rcv(struct sk_buff *skb, struct net_device *dev, static int snap_indicate(struct llc_prim_if_block *prim)
struct packet_type *pt)
{ {
struct sk_buff *skb;
struct datalink_proto *proto;
int rc = 1;
static struct packet_type psnap_packet_type = { static struct packet_type psnap_packet_type = {
.type = __constant_htons(ETH_P_SNAP), .type = __constant_htons(ETH_P_SNAP),
.func = snap_rcv,
}; };
struct datalink_proto *proto = find_snap_client(skb->h.raw); if (prim->prim != LLC_DATAUNIT_PRIM)
goto out;
skb = prim->data->udata.skb;
proto = find_snap_client(skb->h.raw);
if (proto) { if (proto) {
/* Pass the frame on. */ /* Pass the frame on. */
skb->h.raw += 5; skb->h.raw += 5;
skb->nh.raw += 5;
skb_pull(skb, 5); skb_pull(skb, 5);
rc = proto->rcvfunc(skb, skb->dev, &psnap_packet_type);
return proto->rcvfunc(skb, dev, &psnap_packet_type); } else {
skb->sk = NULL;
kfree_skb(skb);
rc = 1;
} }
skb->sk = NULL; out:
kfree_skb(skb); return rc;
return 0;
} }
/* /*
* Put a SNAP header on a frame and pass to 802.2 * Put a SNAP header on a frame and pass to 802.2
*/ */
static void snap_datalink_header(struct datalink_proto *dl, static int snap_request(struct datalink_proto *dl,
struct sk_buff *skb, unsigned char *dest_node) struct sk_buff *skb, u8 *dest)
{ {
union llc_u_prim_data prim_data;
struct llc_prim_if_block prim;
memcpy(skb_push(skb, 5), dl->type, 5); memcpy(skb_push(skb, 5), dl->type, 5);
snap_dl->datalink_header(snap_dl, skb, dest_node); prim.data = &prim_data;
prim.sap = snap_sap;
prim.prim = LLC_DATAUNIT_PRIM;
prim_data.test.skb = skb;
prim_data.test.saddr.lsap = snap_sap->laddr.lsap;
prim_data.test.daddr.lsap = snap_sap->laddr.lsap;
memcpy(prim_data.test.saddr.mac, skb->dev->dev_addr, IFHWADDRLEN);
memcpy(prim_data.test.daddr.mac, dest, IFHWADDRLEN);
return snap_sap->req(&prim);
} }
/* /*
...@@ -80,9 +109,9 @@ EXPORT_SYMBOL(unregister_snap_client); ...@@ -80,9 +109,9 @@ EXPORT_SYMBOL(unregister_snap_client);
static int __init snap_init(void) static int __init snap_init(void)
{ {
snap_dl = register_8022_client(0xAA, snap_rcv); snap_sap = llc_sap_open(snap_indicate, NULL, 0xAA);
if (!snap_dl) if (!snap_sap)
printk(KERN_CRIT "SNAP - unable to register with 802.2\n"); printk(KERN_CRIT "SNAP - unable to register with 802.2\n");
return 0; return 0;
...@@ -90,6 +119,14 @@ static int __init snap_init(void) ...@@ -90,6 +119,14 @@ static int __init snap_init(void)
module_init(snap_init); module_init(snap_init);
static void __exit snap_exit(void)
{
llc_sap_close(snap_sap);
}
module_exit(snap_exit);
/* /*
* Register SNAP clients. We don't yet use this for IP. * Register SNAP clients. We don't yet use this for IP.
*/ */
...@@ -100,46 +137,35 @@ struct datalink_proto *register_snap_client(unsigned char *desc, ...@@ -100,46 +137,35 @@ struct datalink_proto *register_snap_client(unsigned char *desc,
{ {
struct datalink_proto *proto = NULL; struct datalink_proto *proto = NULL;
br_write_lock_bh(BR_NETPROTO_LOCK);
if (find_snap_client(desc)) if (find_snap_client(desc))
goto out; goto out;
proto = kmalloc(sizeof(*proto), GFP_ATOMIC); proto = kmalloc(sizeof(*proto), GFP_ATOMIC);
if (proto) { if (proto) {
memcpy(proto->type, desc,5); memcpy(proto->type, desc,5);
proto->type_len = 5;
proto->rcvfunc = rcvfunc; proto->rcvfunc = rcvfunc;
proto->header_length = 5 + snap_dl->header_length; proto->header_length = 5 + 3; /* snap + 802.2 */
proto->datalink_header = snap_datalink_header; proto->request = snap_request;
proto->string_name = "SNAP"; list_add(&proto->node, &snap_list);
proto->next = snap_list;
snap_list = proto;
} }
out: out:
br_write_unlock_bh(BR_NETPROTO_LOCK);
return proto; return proto;
} }
/* /*
* Unregister SNAP clients. Protocols no longer want to play with us ... * Unregister SNAP clients. Protocols no longer want to play with us ...
*/ */
void unregister_snap_client(unsigned char *desc) void unregister_snap_client(struct datalink_proto *proto)
{ {
struct datalink_proto **clients = &snap_list; br_write_lock_bh(BR_NETPROTO_LOCK);
struct datalink_proto *tmp;
unsigned long flags;
save_flags(flags);
cli();
while ((tmp = *clients) != NULL) { list_del(&proto->node);
if (!memcmp(tmp->type, desc, 5)) { kfree(proto);
*clients = tmp->next;
kfree(tmp);
break;
} else
clients = &tmp->next;
}
restore_flags(flags); br_write_unlock_bh(BR_NETPROTO_LOCK);
} }
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -44,13 +44,17 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then ...@@ -44,13 +44,17 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
fi fi
tristate '802.1Q VLAN Support' CONFIG_VLAN_8021Q tristate '802.1Q VLAN Support' CONFIG_VLAN_8021Q
comment ' ' tristate 'ANSI/IEEE 802.2 Data link layer protocol' CONFIG_LLC
tristate 'The IPX protocol' CONFIG_IPX if [ "$CONFIG_LLC" != "n" ]; then
tristate ' LLC sockets interface' CONFIG_LLC_UI
fi
dep_tristate 'The IPX protocol' CONFIG_IPX $CONFIG_LLC
if [ "$CONFIG_IPX" != "n" ]; then if [ "$CONFIG_IPX" != "n" ]; then
source net/ipx/Config.in source net/ipx/Config.in
fi fi
tristate 'Appletalk protocol support' CONFIG_ATALK dep_tristate 'Appletalk protocol support' CONFIG_ATALK $CONFIG_LLC
source drivers/net/appletalk/Config.in source drivers/net/appletalk/Config.in
tristate 'DECnet Support' CONFIG_DECNET tristate 'DECnet Support' CONFIG_DECNET
...@@ -61,11 +65,6 @@ dep_tristate '802.1d Ethernet Bridging' CONFIG_BRIDGE $CONFIG_INET ...@@ -61,11 +65,6 @@ dep_tristate '802.1d Ethernet Bridging' CONFIG_BRIDGE $CONFIG_INET
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
tristate 'CCITT X.25 Packet Layer (EXPERIMENTAL)' CONFIG_X25 tristate 'CCITT X.25 Packet Layer (EXPERIMENTAL)' CONFIG_X25
tristate 'LAPB Data Link Driver (EXPERIMENTAL)' CONFIG_LAPB tristate 'LAPB Data Link Driver (EXPERIMENTAL)' CONFIG_LAPB
tristate 'ANSI/IEEE 802.2 Data link layer protocol' CONFIG_LLC
if [ "$CONFIG_LLC" != "n" ]; then
# When NETBEUI is added the following line will be a tristate
define_bool CONFIG_LLC_UI y
fi
bool 'Frame Diverter (EXPERIMENTAL)' CONFIG_NET_DIVERT bool 'Frame Diverter (EXPERIMENTAL)' CONFIG_NET_DIVERT
if [ "$CONFIG_INET" = "y" ]; then if [ "$CONFIG_INET" = "y" ]; then
tristate 'Acorn Econet/AUN protocols (EXPERIMENTAL)' CONFIG_ECONET tristate 'Acorn Econet/AUN protocols (EXPERIMENTAL)' CONFIG_ECONET
......
...@@ -163,11 +163,8 @@ static void __aarp_send_query(struct aarp_entry *a) ...@@ -163,11 +163,8 @@ static void __aarp_send_query(struct aarp_entry *a)
eah->pa_dst_net = a->target_addr.s_net; eah->pa_dst_net = a->target_addr.s_net;
eah->pa_dst_node = a->target_addr.s_node; eah->pa_dst_node = a->target_addr.s_node;
/* Add ELAP headers and set target to the AARP multicast */
aarp_dl->datalink_header(aarp_dl, skb, aarp_eth_multicast);
/* Send it */ /* Send it */
dev_queue_xmit(skb); aarp_dl->request(aarp_dl, skb, aarp_eth_multicast);
/* Update the sending count */ /* Update the sending count */
a->xmit_count++; a->xmit_count++;
} }
...@@ -213,10 +210,8 @@ static void aarp_send_reply(struct net_device *dev, struct atalk_addr *us, ...@@ -213,10 +210,8 @@ static void aarp_send_reply(struct net_device *dev, struct atalk_addr *us,
eah->pa_dst_net = them->s_net; eah->pa_dst_net = them->s_net;
eah->pa_dst_node = them->s_node; eah->pa_dst_node = them->s_node;
/* Add ELAP headers and set target to the AARP multicast */
aarp_dl->datalink_header(aarp_dl, skb, sha);
/* Send it */ /* Send it */
dev_queue_xmit(skb); aarp_dl->request(aarp_dl, skb, sha);
} }
/* /*
...@@ -261,10 +256,8 @@ void aarp_send_probe(struct net_device *dev, struct atalk_addr *us) ...@@ -261,10 +256,8 @@ void aarp_send_probe(struct net_device *dev, struct atalk_addr *us)
eah->pa_dst_net = us->s_net; eah->pa_dst_net = us->s_net;
eah->pa_dst_node = us->s_node; eah->pa_dst_node = us->s_node;
/* Add ELAP headers and set target to the AARP multicast */
aarp_dl->datalink_header(aarp_dl, skb, aarp_eth_multicast);
/* Send it */ /* Send it */
dev_queue_xmit(skb); aarp_dl->request(aarp_dl, skb, aarp_eth_multicast);
} }
/* /*
...@@ -602,8 +595,9 @@ int aarp_send_ddp(struct net_device *dev,struct sk_buff *skb, ...@@ -602,8 +595,9 @@ int aarp_send_ddp(struct net_device *dev,struct sk_buff *skb,
/* Do we have a resolved entry? */ /* Do we have a resolved entry? */
if (sa->s_node == ATADDR_BCAST) { if (sa->s_node == ATADDR_BCAST) {
ddp_dl->datalink_header(ddp_dl, skb, ddp_eth_multicast); /* Send it */
goto sendit; ddp_dl->request(ddp_dl, skb, ddp_eth_multicast);
goto sent;
} }
spin_lock_bh(&aarp_lock); spin_lock_bh(&aarp_lock);
...@@ -611,9 +605,9 @@ int aarp_send_ddp(struct net_device *dev,struct sk_buff *skb, ...@@ -611,9 +605,9 @@ int aarp_send_ddp(struct net_device *dev,struct sk_buff *skb,
if (a) { /* Return 1 and fill in the address */ if (a) { /* Return 1 and fill in the address */
a->expires_at = jiffies + (sysctl_aarp_expiry_time * 10); a->expires_at = jiffies + (sysctl_aarp_expiry_time * 10);
ddp_dl->datalink_header(ddp_dl, skb, a->hwaddr); ddp_dl->request(ddp_dl, skb, a->hwaddr);
spin_unlock_bh(&aarp_lock); spin_unlock_bh(&aarp_lock);
goto sendit; goto sent;
} }
/* Do we have an unresolved entry: This is the less common path */ /* Do we have an unresolved entry: This is the less common path */
...@@ -663,6 +657,7 @@ int aarp_send_ddp(struct net_device *dev,struct sk_buff *skb, ...@@ -663,6 +657,7 @@ int aarp_send_ddp(struct net_device *dev,struct sk_buff *skb,
if (skb->sk) if (skb->sk)
skb->priority = skb->sk->priority; skb->priority = skb->sk->priority;
dev_queue_xmit(skb); dev_queue_xmit(skb);
sent:
return 1; return 1;
} }
...@@ -690,10 +685,7 @@ static void __aarp_resolved(struct aarp_entry **list, struct aarp_entry *a, ...@@ -690,10 +685,7 @@ static void __aarp_resolved(struct aarp_entry **list, struct aarp_entry *a,
while ((skb = skb_dequeue(&a->packet_queue)) != NULL) { while ((skb = skb_dequeue(&a->packet_queue)) != NULL) {
a->expires_at = jiffies + a->expires_at = jiffies +
sysctl_aarp_expiry_time * 10; sysctl_aarp_expiry_time * 10;
ddp_dl->datalink_header(ddp_dl, skb, a->hwaddr); ddp_dl->request(ddp_dl, skb, a->hwaddr);
if (skb->sk)
skb->priority = skb->sk->priority;
dev_queue_xmit(skb);
} }
} else } else
list = &((*list)->next); list = &((*list)->next);
...@@ -989,7 +981,7 @@ void aarp_cleanup_module(void) ...@@ -989,7 +981,7 @@ void aarp_cleanup_module(void)
{ {
del_timer(&aarp_timer); del_timer(&aarp_timer);
unregister_netdevice_notifier(&aarp_notifier); unregister_netdevice_notifier(&aarp_notifier);
unregister_snap_client(aarp_snap_id); unregister_snap_client(aarp_dl);
} }
#endif /* MODULE */ #endif /* MODULE */
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
......
...@@ -1782,13 +1782,7 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, int len, ...@@ -1782,13 +1782,7 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, int len,
SOCK_DEBUG(sk, "SK %p: Loop back.\n", sk); SOCK_DEBUG(sk, "SK %p: Loop back.\n", sk);
/* loop back */ /* loop back */
skb_orphan(skb); skb_orphan(skb);
ddp_dl->datalink_header(ddp_dl, skb, dev->dev_addr); ddp_dl->request(ddp_dl, skb, dev->dev_addr);
skb->mac.raw = skb->data;
skb->h.raw = skb->data + ddp_dl->header_length +
dev->hard_header_len;
skb_pull(skb, dev->hard_header_len);
skb_pull(skb, ddp_dl->header_length);
atalk_rcv(skb, dev, NULL);
} else { } else {
SOCK_DEBUG(sk, "SK %p: send out.\n", sk); SOCK_DEBUG(sk, "SK %p: send out.\n", sk);
if (rt->flags & RTF_GATEWAY) { if (rt->flags & RTF_GATEWAY) {
...@@ -2040,7 +2034,7 @@ static void __exit atalk_exit(void) ...@@ -2040,7 +2034,7 @@ static void __exit atalk_exit(void)
unregister_netdevice_notifier(&ddp_notifier); unregister_netdevice_notifier(&ddp_notifier);
dev_remove_pack(&ltalk_packet_type); dev_remove_pack(&ltalk_packet_type);
dev_remove_pack(&ppptalk_packet_type); dev_remove_pack(&ppptalk_packet_type);
unregister_snap_client(ddp_snap_id); unregister_snap_client(ddp_dl);
sock_unregister(PF_APPLETALK); sock_unregister(PF_APPLETALK);
} }
module_exit(atalk_exit); module_exit(atalk_exit);
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
# Makefile for the Linux networking core. # Makefile for the Linux networking core.
# #
export-objs := ext8022.o
obj-y := sock.o skbuff.o iovec.o datagram.o scm.o obj-y := sock.o skbuff.o iovec.o datagram.o scm.o
ifeq ($(CONFIG_SYSCTL),y) ifeq ($(CONFIG_SYSCTL),y)
...@@ -16,11 +14,6 @@ obj-$(CONFIG_FILTER) += filter.o ...@@ -16,11 +14,6 @@ obj-$(CONFIG_FILTER) += filter.o
obj-$(CONFIG_NET) += dev.o dev_mcast.o dst.o neighbour.o rtnetlink.o utils.o obj-$(CONFIG_NET) += dev.o dev_mcast.o dst.o neighbour.o rtnetlink.o utils.o
# See p8022 in net/802/Makefile for config options to check
ifneq ($(CONFIG_LLC)$(CONFIG_TR)$(CONFIG_IPX)$(CONFIG_ATALK),)
obj-y += ext8022.o
endif
obj-$(CONFIG_NETFILTER) += netfilter.o obj-$(CONFIG_NETFILTER) += netfilter.o
obj-$(CONFIG_NET_DIVERT) += dv.o obj-$(CONFIG_NET_DIVERT) += dv.o
obj-$(CONFIG_NET_PROFILE) += profile.o obj-$(CONFIG_NET_PROFILE) += profile.o
......
/*
* (ext8022.c)
*
* Copyright (c) 1997 by Procom Technology, Inc.
* 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*
* This program can be redistributed or modified under the terms of the
* GNU General Public License as published by the Free Software Foundation.
* This program is distributed without any warranty or implied warranty
* of merchantability or fitness for a particular purpose.
*
* See the GNU General Public License for more details.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/brlock.h>
typedef int (*func_type)(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt);
static int llc_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *);
static func_type llc_sap_table[128];
static int llc_users;
static struct packet_type llc_packet_type = {
.type = __constant_htons(ETH_P_802_2),
.func = llc_rcv,
};
static struct packet_type llc_tr_packet_type = {
.type = __constant_htons(ETH_P_TR_802_2),
.func = llc_rcv,
};
static int llc_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt)
{
unsigned char n = (*(skb->h.raw)) >> 1;
br_read_lock(BR_LLC_LOCK);
if (llc_sap_table[n])
llc_sap_table[n](skb, dev, pt);
else
kfree_skb(skb);
br_read_unlock(BR_LLC_LOCK);
return 0;
}
void llc_register_sap(unsigned char sap, func_type rcvfunc)
{
sap >>= 1;
br_write_lock_bh(BR_LLC_LOCK);
llc_sap_table[sap] = rcvfunc;
if (!llc_users) {
dev_add_pack(&llc_packet_type);
dev_add_pack(&llc_tr_packet_type);
}
llc_users++;
br_write_unlock_bh(BR_LLC_LOCK);
}
void llc_unregister_sap(unsigned char sap)
{
sap >>= 1;
br_write_lock_bh(BR_LLC_LOCK);
llc_sap_table[sap] = NULL;
if (!--llc_users) {
dev_remove_pack(&llc_packet_type);
dev_remove_pack(&llc_tr_packet_type);
}
br_write_unlock_bh(BR_LLC_LOCK);
}
EXPORT_SYMBOL(llc_register_sap);
EXPORT_SYMBOL(llc_unregister_sap);
...@@ -2238,7 +2238,7 @@ MODULE_PARM(addr, "2i"); ...@@ -2238,7 +2238,7 @@ MODULE_PARM(addr, "2i");
MODULE_PARM_DESC(addr, "The DECnet address of this machine: area,node"); MODULE_PARM_DESC(addr, "The DECnet address of this machine: area,node");
#endif #endif
static char banner[] __initdata = KERN_INFO "NET4: DECnet for Linux: V.2.4.15-pre5s (C) 1995-2001 Linux DECnet Project Team\n"; static char banner[] __initdata = KERN_INFO "NET4: DECnet for Linux: V.2.4.20-pre1s (C) 1995-2002 Linux DECnet Project Team\n";
static int __init decnet_init(void) static int __init decnet_init(void)
{ {
......
...@@ -35,6 +35,8 @@ ...@@ -35,6 +35,8 @@
* are numbered! * are numbered!
* Steve Whitehouse : Added return-to-sender functions. Added * Steve Whitehouse : Added return-to-sender functions. Added
* backlog congestion level return codes. * backlog congestion level return codes.
* Steve Whitehouse : Fixed bug where routes were set up with
* no ref count on net devices.
* *
*/ */
...@@ -801,6 +803,8 @@ static int dn_route_output_slow(struct dst_entry **pprt, dn_address dst, dn_addr ...@@ -801,6 +803,8 @@ static int dn_route_output_slow(struct dst_entry **pprt, dn_address dst, dn_addr
rt->u.dst.neighbour = neigh; rt->u.dst.neighbour = neigh;
rt->u.dst.dev = neigh ? neigh->dev : NULL; rt->u.dst.dev = neigh ? neigh->dev : NULL;
if (rt->u.dst.dev)
dev_hold(rt->u.dst.dev);
rt->u.dst.lastuse = jiffies; rt->u.dst.lastuse = jiffies;
rt->u.dst.output = dn_output; rt->u.dst.output = dn_output;
rt->u.dst.input = dn_rt_bug; rt->u.dst.input = dn_rt_bug;
...@@ -978,6 +982,8 @@ static int dn_route_input_slow(struct sk_buff *skb) ...@@ -978,6 +982,8 @@ static int dn_route_input_slow(struct sk_buff *skb)
rt->u.dst.neighbour = neigh; rt->u.dst.neighbour = neigh;
rt->u.dst.dev = neigh ? neigh->dev : NULL; rt->u.dst.dev = neigh ? neigh->dev : NULL;
if (rt->u.dst.dev)
dev_hold(rt->u.dst.dev);
rt->u.dst.lastuse = jiffies; rt->u.dst.lastuse = jiffies;
rt->u.dst.output = dnrt_output; rt->u.dst.output = dnrt_output;
rt->u.dst.input = dnrt_input; rt->u.dst.input = dnrt_input;
......
...@@ -4,8 +4,7 @@ ...@@ -4,8 +4,7 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/in.h> #include <linux/in.h>
static void static int pEII_request(struct datalink_proto *dl,
pEII_datalink_header(struct datalink_proto *dl,
struct sk_buff *skb, unsigned char *dest_node) struct sk_buff *skb, unsigned char *dest_node)
{ {
struct net_device *dev = skb->dev; struct net_device *dev = skb->dev;
...@@ -13,6 +12,7 @@ pEII_datalink_header(struct datalink_proto *dl, ...@@ -13,6 +12,7 @@ pEII_datalink_header(struct datalink_proto *dl,
skb->protocol = htons (ETH_P_IPX); skb->protocol = htons (ETH_P_IPX);
if(dev->hard_header) if(dev->hard_header)
dev->hard_header(skb, dev, ETH_P_IPX, dest_node, NULL, skb->len); dev->hard_header(skb, dev, ETH_P_IPX, dest_node, NULL, skb->len);
return dev_queue_xmit(skb);
} }
struct datalink_proto * struct datalink_proto *
...@@ -22,10 +22,8 @@ make_EII_client(void) ...@@ -22,10 +22,8 @@ make_EII_client(void)
proto = (struct datalink_proto *) kmalloc(sizeof(*proto), GFP_ATOMIC); proto = (struct datalink_proto *) kmalloc(sizeof(*proto), GFP_ATOMIC);
if (proto != NULL) { if (proto != NULL) {
proto->type_len = 0;
proto->header_length = 0; proto->header_length = 0;
proto->datalink_header = pEII_datalink_header; proto->request = pEII_request;
proto->string_name = "EtherII";
} }
return proto; return proto;
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* real coder of this. * real coder of this.
* Few changes needed, mainly the hard_routing code and * Few changes needed, mainly the hard_routing code and
* the netlink socket protocol (we're NETLINK_IP6_FW). * the netlink socket protocol (we're NETLINK_IP6_FW).
* * 2002-06-25: Code cleanup. [JM: ported cleanup over from ip_queue.c]
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
...@@ -26,18 +26,12 @@ ...@@ -26,18 +26,12 @@
#include <linux/netfilter.h> #include <linux/netfilter.h>
#include <linux/netlink.h> #include <linux/netlink.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/rtnetlink.h> #include <linux/brlock.h>
#include <linux/sysctl.h> #include <linux/sysctl.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <net/sock.h> #include <net/sock.h>
#include <net/ipv6.h> #include <net/ipv6.h>
#include <net/ip6_route.h> #include <net/ip6_route.h>
/* We're still usign the following structs. No need to change them: */
/* ipq_packet_msg */
/* ipq_mode_msg */
/* ipq_verdict_msg */
/* ipq_peer_msg */
#include <linux/netfilter_ipv4/ip_queue.h> #include <linux/netfilter_ipv4/ip_queue.h>
#include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv6/ip6_tables.h> #include <linux/netfilter_ipv6/ip6_tables.h>
...@@ -47,184 +41,289 @@ ...@@ -47,184 +41,289 @@
#define NET_IPQ_QMAX 2088 #define NET_IPQ_QMAX 2088
#define NET_IPQ_QMAX_NAME "ip6_queue_maxlen" #define NET_IPQ_QMAX_NAME "ip6_queue_maxlen"
typedef struct ip6q_rt_info { struct ipq_rt_info {
struct in6_addr daddr; struct in6_addr daddr;
struct in6_addr saddr; struct in6_addr saddr;
} ip6q_rt_info_t; };
typedef struct ip6q_queue_element { struct ipq_queue_entry {
struct list_head list; /* Links element into queue */ struct list_head list;
int verdict; /* Current verdict */ struct nf_info *info;
struct nf_info *info; /* Extra info from netfilter */ struct sk_buff *skb;
struct sk_buff *skb; /* Packet inside */ struct ipq_rt_info rt_info;
ip6q_rt_info_t rt_info; /* May need post-mangle routing */ };
} ip6q_queue_element_t;
typedef int (*ipq_cmpfn)(struct ipq_queue_entry *, unsigned long);
typedef int (*ip6q_send_cb_t)(ip6q_queue_element_t *e);
static unsigned char copy_mode = IPQ_COPY_NONE;
typedef struct ip6q_peer { static unsigned int queue_maxlen = IPQ_QMAX_DEFAULT;
pid_t pid; /* PID of userland peer */ static rwlock_t queue_lock = RW_LOCK_UNLOCKED;
unsigned char died; /* We think the peer died */ static int peer_pid;
unsigned char copy_mode; /* Copy packet as well as metadata? */ static unsigned int copy_range;
size_t copy_range; /* Range past metadata to copy */ static unsigned int queue_total;
ip6q_send_cb_t send; /* Callback for sending data to peer */ static struct sock *ipqnl;
} ip6q_peer_t; static LIST_HEAD(queue_list);
static DECLARE_MUTEX(ipqnl_sem);
typedef struct ip6q_queue {
int len; /* Current queue len */ static void
int *maxlen; /* Maximum queue len, via sysctl */ ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict)
unsigned char flushing; /* If queue is being flushed */
unsigned char terminate; /* If the queue is being terminated */
struct list_head list; /* Head of packet queue */
spinlock_t lock; /* Queue spinlock */
ip6q_peer_t peer; /* Userland peer */
} ip6q_queue_t;
/****************************************************************************
*
* Packet queue
*
****************************************************************************/
/* Dequeue a packet if matched by cmp, or the next available if cmp is NULL */
static ip6q_queue_element_t *
ip6q_dequeue(ip6q_queue_t *q,
int (*cmp)(ip6q_queue_element_t *, unsigned long),
unsigned long data)
{ {
struct list_head *i; nf_reinject(entry->skb, entry->info, verdict);
kfree(entry);
}
static inline int
__ipq_enqueue_entry(struct ipq_queue_entry *entry)
{
if (queue_total >= queue_maxlen) {
if (net_ratelimit())
printk(KERN_WARNING "ip6_queue: full at %d entries, "
"dropping packet(s).\n", queue_total);
return -ENOSPC;
}
list_add(&entry->list, &queue_list);
queue_total++;
return 0;
}
spin_lock_bh(&q->lock); /*
for (i = q->list.prev; i != &q->list; i = i->prev) { * Find and return a queued entry matched by cmpfn, or return the last
ip6q_queue_element_t *e = (ip6q_queue_element_t *)i; * entry if cmpfn is NULL.
*/
static inline struct ipq_queue_entry *
__ipq_find_entry(ipq_cmpfn cmpfn, unsigned long data)
{
struct list_head *p;
list_for_each_prev(p, &queue_list) {
struct ipq_queue_entry *entry = (struct ipq_queue_entry *)p;
if (!cmp || cmp(e, data)) { if (!cmpfn || cmpfn(entry, data))
list_del(&e->list); return entry;
q->len--;
spin_unlock_bh(&q->lock);
return e;
}
} }
spin_unlock_bh(&q->lock);
return NULL; return NULL;
} }
/* Flush all packets */ static inline void
static void ip6q_flush(ip6q_queue_t *q) __ipq_dequeue_entry(struct ipq_queue_entry *entry)
{
list_del(&entry->list);
queue_total--;
}
static inline struct ipq_queue_entry *
__ipq_find_dequeue_entry(ipq_cmpfn cmpfn, unsigned long data)
{ {
ip6q_queue_element_t *e; struct ipq_queue_entry *entry;
entry = __ipq_find_entry(cmpfn, data);
if (entry == NULL)
return NULL;
__ipq_dequeue_entry(entry);
return entry;
}
static inline void
__ipq_flush(int verdict)
{
struct ipq_queue_entry *entry;
spin_lock_bh(&q->lock); while ((entry = __ipq_find_dequeue_entry(NULL, 0)))
q->flushing = 1; ipq_issue_verdict(entry, verdict);
spin_unlock_bh(&q->lock); }
while ((e = ip6q_dequeue(q, NULL, 0))) {
e->verdict = NF_DROP; static inline int
nf_reinject(e->skb, e->info, e->verdict); __ipq_set_mode(unsigned char mode, unsigned int range)
kfree(e); {
int status = 0;
switch(mode) {
case IPQ_COPY_NONE:
case IPQ_COPY_META:
copy_mode = mode;
copy_range = 0;
break;
case IPQ_COPY_PACKET:
copy_mode = mode;
copy_range = range;
if (copy_range > 0xFFFF)
copy_range = 0xFFFF;
break;
default:
status = -EINVAL;
} }
spin_lock_bh(&q->lock); return status;
q->flushing = 0;
spin_unlock_bh(&q->lock);
} }
static ip6q_queue_t *ip6q_create_queue(nf_queue_outfn_t outfn, static inline void
ip6q_send_cb_t send_cb, __ipq_reset(void)
int *errp, int *sysctl_qmax)
{ {
int status; peer_pid = 0;
ip6q_queue_t *q; __ipq_set_mode(IPQ_COPY_NONE, 0);
__ipq_flush(NF_DROP);
}
static struct ipq_queue_entry *
ipq_find_dequeue_entry(ipq_cmpfn cmpfn, unsigned long data)
{
struct ipq_queue_entry *entry;
write_lock_bh(&queue_lock);
entry = __ipq_find_dequeue_entry(cmpfn, data);
write_unlock_bh(&queue_lock);
return entry;
}
static void
ipq_flush(int verdict)
{
write_lock_bh(&queue_lock);
__ipq_flush(verdict);
write_unlock_bh(&queue_lock);
}
static struct sk_buff *
ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp)
{
unsigned char *old_tail;
size_t size = 0;
size_t data_len = 0;
struct sk_buff *skb;
struct ipq_packet_msg *pmsg;
struct nlmsghdr *nlh;
*errp = 0; read_lock_bh(&queue_lock);
q = kmalloc(sizeof(ip6q_queue_t), GFP_KERNEL);
if (q == NULL) { switch (copy_mode) {
*errp = -ENOMEM; case IPQ_COPY_META:
case IPQ_COPY_NONE:
size = NLMSG_SPACE(sizeof(*pmsg));
data_len = 0;
break;
case IPQ_COPY_PACKET:
if (copy_range == 0 || copy_range > entry->skb->len)
data_len = entry->skb->len;
else
data_len = copy_range;
size = NLMSG_SPACE(sizeof(*pmsg) + data_len);
break;
default:
*errp = -EINVAL;
read_unlock_bh(&queue_lock);
return NULL; return NULL;
} }
q->peer.pid = 0;
q->peer.died = 0; read_unlock_bh(&queue_lock);
q->peer.copy_mode = IPQ_COPY_NONE;
q->peer.copy_range = 0; skb = alloc_skb(size, GFP_ATOMIC);
q->peer.send = send_cb; if (!skb)
q->len = 0; goto nlmsg_failure;
q->maxlen = sysctl_qmax;
q->flushing = 0; old_tail= skb->tail;
q->terminate = 0; nlh = NLMSG_PUT(skb, 0, 0, IPQM_PACKET, size - sizeof(*nlh));
INIT_LIST_HEAD(&q->list); pmsg = NLMSG_DATA(nlh);
spin_lock_init(&q->lock); memset(pmsg, 0, sizeof(*pmsg));
status = nf_register_queue_handler(PF_INET6, outfn, q);
if (status < 0) { pmsg->packet_id = (unsigned long )entry;
*errp = -EBUSY; pmsg->data_len = data_len;
kfree(q); pmsg->timestamp_sec = entry->skb->stamp.tv_sec;
return NULL; pmsg->timestamp_usec = entry->skb->stamp.tv_usec;
pmsg->mark = entry->skb->nfmark;
pmsg->hook = entry->info->hook;
pmsg->hw_protocol = entry->skb->protocol;
if (entry->info->indev)
strcpy(pmsg->indev_name, entry->info->indev->name);
else
pmsg->indev_name[0] = '\0';
if (entry->info->outdev)
strcpy(pmsg->outdev_name, entry->info->outdev->name);
else
pmsg->outdev_name[0] = '\0';
if (entry->info->indev && entry->skb->dev) {
pmsg->hw_type = entry->skb->dev->type;
if (entry->skb->dev->hard_header_parse)
pmsg->hw_addrlen =
entry->skb->dev->hard_header_parse(entry->skb,
pmsg->hw_addr);
} }
return q;
if (data_len)
memcpy(pmsg->payload, entry->skb->data, data_len);
nlh->nlmsg_len = skb->tail - old_tail;
return skb;
nlmsg_failure:
if (skb)
kfree_skb(skb);
*errp = -EINVAL;
printk(KERN_ERR "ip6_queue: error creating packet message\n");
return NULL;
} }
static int ip6q_enqueue(ip6q_queue_t *q, static int
struct sk_buff *skb, struct nf_info *info) ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info, void *data)
{ {
ip6q_queue_element_t *e; int status = -EINVAL;
int status; struct sk_buff *nskb;
struct ipq_queue_entry *entry;
e = kmalloc(sizeof(*e), GFP_ATOMIC);
if (e == NULL) { if (copy_mode == IPQ_COPY_NONE)
printk(KERN_ERR "ip6_queue: OOM in enqueue\n"); return -EAGAIN;
entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
if (entry == NULL) {
printk(KERN_ERR "ip6_queue: OOM in ipq_enqueue_packet()\n");
return -ENOMEM; return -ENOMEM;
} }
e->verdict = NF_DROP; entry->info = info;
e->info = info; entry->skb = skb;
e->skb = skb;
if (e->info->hook == NF_IP_LOCAL_OUT) { if (entry->info->hook == NF_IP_LOCAL_OUT) {
struct ipv6hdr *iph = skb->nh.ipv6h; struct ipv6hdr *iph = skb->nh.ipv6h;
e->rt_info.daddr = iph->daddr; entry->rt_info.daddr = iph->daddr;
e->rt_info.saddr = iph->saddr; entry->rt_info.saddr = iph->saddr;
} }
spin_lock_bh(&q->lock); nskb = ipq_build_packet_message(entry, &status);
if (q->len >= *q->maxlen) { if (nskb == NULL)
spin_unlock_bh(&q->lock); goto err_out_free;
if (net_ratelimit())
printk(KERN_WARNING "ip6_queue: full at %d entries, " write_lock_bh(&queue_lock);
"dropping packet(s).\n", q->len);
goto free_drop; if (!peer_pid)
} goto err_out_unlock;
if (q->flushing || q->peer.copy_mode == IPQ_COPY_NONE
|| q->peer.pid == 0 || q->peer.died || q->terminate) {
spin_unlock_bh(&q->lock);
goto free_drop;
}
status = q->peer.send(e);
if (status > 0) {
list_add(&e->list, &q->list);
q->len++;
spin_unlock_bh(&q->lock);
return status;
}
spin_unlock_bh(&q->lock);
if (status == -ECONNREFUSED) {
printk(KERN_INFO "ip6_queue: peer %d died, "
"resetting state and flushing queue\n", q->peer.pid);
q->peer.died = 1;
q->peer.pid = 0;
q->peer.copy_mode = IPQ_COPY_NONE;
q->peer.copy_range = 0;
ip6q_flush(q);
}
free_drop:
kfree(e);
return -EBUSY;
}
static void ip6q_destroy_queue(ip6q_queue_t *q) status = netlink_unicast(ipqnl, nskb, peer_pid, MSG_DONTWAIT);
{ if (status < 0)
nf_unregister_queue_handler(PF_INET6); goto err_out_unlock;
spin_lock_bh(&q->lock);
q->terminate = 1; status = __ipq_enqueue_entry(entry);
spin_unlock_bh(&q->lock); if (status < 0)
ip6q_flush(q); goto err_out_unlock;
kfree(q);
write_unlock_bh(&queue_lock);
return status;
err_out_unlock:
write_unlock_bh(&queue_lock);
err_out_free:
kfree(entry);
return status;
} }
/* /*
...@@ -236,7 +335,8 @@ static void ip6q_destroy_queue(ip6q_queue_t *q) ...@@ -236,7 +335,8 @@ static void ip6q_destroy_queue(ip6q_queue_t *q)
* *
* If that one is modified, this one should be modified too. * If that one is modified, this one should be modified too.
*/ */
static int route6_me_harder(struct sk_buff *skb) static int
route6_me_harder(struct sk_buff *skb)
{ {
struct ipv6hdr *iph = skb->nh.ipv6h; struct ipv6hdr *iph = skb->nh.ipv6h;
struct dst_entry *dst; struct dst_entry *dst;
...@@ -264,7 +364,9 @@ static int route6_me_harder(struct sk_buff *skb) ...@@ -264,7 +364,9 @@ static int route6_me_harder(struct sk_buff *skb)
skb->dst = dst; skb->dst = dst;
return 0; return 0;
} }
static int ip6q_mangle_ipv6(ipq_verdict_msg_t *v, ip6q_queue_element_t *e)
static int
ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
{ {
int diff; int diff;
struct ipv6hdr *user_iph = (struct ipv6hdr *)v->payload; struct ipv6hdr *user_iph = (struct ipv6hdr *)v->payload;
...@@ -319,344 +421,255 @@ static int ip6q_mangle_ipv6(ipq_verdict_msg_t *v, ip6q_queue_element_t *e) ...@@ -319,344 +421,255 @@ static int ip6q_mangle_ipv6(ipq_verdict_msg_t *v, ip6q_queue_element_t *e)
return 0; return 0;
} }
static inline int id_cmp(ip6q_queue_element_t *e, unsigned long id) static inline int
id_cmp(struct ipq_queue_entry *e, unsigned long id)
{ {
return (id == (unsigned long )e); return (id == (unsigned long )e);
} }
static int ip6q_set_verdict(ip6q_queue_t *q, static int
ipq_verdict_msg_t *v, unsigned int len) ipq_set_verdict(struct ipq_verdict_msg *vmsg, unsigned int len)
{ {
ip6q_queue_element_t *e; struct ipq_queue_entry *entry;
if (v->value > NF_MAX_VERDICT) if (vmsg->value > NF_MAX_VERDICT)
return -EINVAL; return -EINVAL;
e = ip6q_dequeue(q, id_cmp, v->id);
if (e == NULL) entry = ipq_find_dequeue_entry(id_cmp, vmsg->id);
if (entry == NULL)
return -ENOENT; return -ENOENT;
else { else {
e->verdict = v->value; int verdict = vmsg->value;
if (v->data_len && v->data_len == len)
if (ip6q_mangle_ipv6(v, e) < 0) if (vmsg->data_len && vmsg->data_len == len)
e->verdict = NF_DROP; if (ipq_mangle_ipv6(vmsg, entry) < 0)
nf_reinject(e->skb, e->info, e->verdict); verdict = NF_DROP;
kfree(e);
ipq_issue_verdict(entry, verdict);
return 0; return 0;
} }
} }
static int ip6q_receive_peer(ip6q_queue_t* q, ipq_peer_msg_t *m, static int
unsigned char type, unsigned int len) ipq_set_mode(unsigned char mode, unsigned int range)
{ {
int status;
write_lock_bh(&queue_lock);
status = __ipq_set_mode(mode, range);
write_unlock_bh(&queue_lock);
return status;
}
static int
ipq_receive_peer(struct ipq_peer_msg *pmsg,
unsigned char type, unsigned int len)
{
int status = 0; int status = 0;
int busy;
if (len < sizeof(*pmsg))
spin_lock_bh(&q->lock);
busy = (q->terminate || q->flushing);
spin_unlock_bh(&q->lock);
if (busy)
return -EBUSY;
if (len < sizeof(ipq_peer_msg_t))
return -EINVAL; return -EINVAL;
switch (type) { switch (type) {
case IPQM_MODE: case IPQM_MODE:
switch (m->msg.mode.value) { status = ipq_set_mode(pmsg->msg.mode.value,
case IPQ_COPY_META: pmsg->msg.mode.range);
q->peer.copy_mode = IPQ_COPY_META; break;
q->peer.copy_range = 0;
break; case IPQM_VERDICT:
case IPQ_COPY_PACKET: if (pmsg->msg.verdict.value > NF_MAX_VERDICT)
q->peer.copy_mode = IPQ_COPY_PACKET; status = -EINVAL;
q->peer.copy_range = m->msg.mode.range; else
if (q->peer.copy_range > 0xFFFF) status = ipq_set_verdict(&pmsg->msg.verdict,
q->peer.copy_range = 0xFFFF; len - sizeof(*pmsg));
break;
default:
status = -EINVAL;
}
break;
case IPQM_VERDICT:
if (m->msg.verdict.value > NF_MAX_VERDICT)
status = -EINVAL;
else
status = ip6q_set_verdict(q,
&m->msg.verdict,
len - sizeof(*m));
break; break;
default: default:
status = -EINVAL; status = -EINVAL;
} }
return status; return status;
} }
static inline int dev_cmp(ip6q_queue_element_t *e, unsigned long ifindex) static int
dev_cmp(struct ipq_queue_entry *entry, unsigned long ifindex)
{ {
if (e->info->indev) if (entry->info->indev)
if (e->info->indev->ifindex == ifindex) if (entry->info->indev->ifindex == ifindex)
return 1; return 1;
if (e->info->outdev)
if (e->info->outdev->ifindex == ifindex) if (entry->info->outdev)
if (entry->info->outdev->ifindex == ifindex)
return 1; return 1;
return 0; return 0;
} }
/* Drop any queued packets associated with device ifindex */ static void
static void ip6q_dev_drop(ip6q_queue_t *q, int ifindex) ipq_dev_drop(int ifindex)
{ {
ip6q_queue_element_t *e; struct ipq_queue_entry *entry;
while ((e = ip6q_dequeue(q, dev_cmp, ifindex))) { while ((entry = ipq_find_dequeue_entry(dev_cmp, ifindex)) != NULL)
e->verdict = NF_DROP; ipq_issue_verdict(entry, NF_DROP);
nf_reinject(e->skb, e->info, e->verdict);
kfree(e);
}
}
/****************************************************************************
*
* Netfilter interface
*
****************************************************************************/
/*
* Packets arrive here from netfilter for queuing to userspace.
* All of them must be fed back via nf_reinject() or Alexey will kill Rusty.
*/
static int netfilter6_receive(struct sk_buff *skb,
struct nf_info *info, void *data)
{
return ip6q_enqueue((ip6q_queue_t *)data, skb, info);
}
/****************************************************************************
*
* Netlink interface.
*
****************************************************************************/
static struct sock *nfnl = NULL;
/* This is not a static one, so we should not repeat its name */
ip6q_queue_t *nlq6 = NULL;
static struct sk_buff *netlink_build_message(ip6q_queue_element_t *e, int *errp)
{
unsigned char *old_tail;
size_t size = 0;
size_t data_len = 0;
struct sk_buff *skb;
ipq_packet_msg_t *pm;
struct nlmsghdr *nlh;
switch (nlq6->peer.copy_mode) {
size_t copy_range;
case IPQ_COPY_META:
size = NLMSG_SPACE(sizeof(*pm));
data_len = 0;
break;
case IPQ_COPY_PACKET:
copy_range = nlq6->peer.copy_range;
if (copy_range == 0 || copy_range > e->skb->len)
data_len = e->skb->len;
else
data_len = copy_range;
size = NLMSG_SPACE(sizeof(*pm) + data_len);
break;
case IPQ_COPY_NONE:
default:
*errp = -EINVAL;
return NULL;
}
skb = alloc_skb(size, GFP_ATOMIC);
if (!skb)
goto nlmsg_failure;
old_tail = skb->tail;
nlh = NLMSG_PUT(skb, 0, 0, IPQM_PACKET, size - sizeof(*nlh));
pm = NLMSG_DATA(nlh);
memset(pm, 0, sizeof(*pm));
pm->packet_id = (unsigned long )e;
pm->data_len = data_len;
pm->timestamp_sec = e->skb->stamp.tv_sec;
pm->timestamp_usec = e->skb->stamp.tv_usec;
pm->mark = e->skb->nfmark;
pm->hook = e->info->hook;
if (e->info->indev) strcpy(pm->indev_name, e->info->indev->name);
else pm->indev_name[0] = '\0';
if (e->info->outdev) strcpy(pm->outdev_name, e->info->outdev->name);
else pm->outdev_name[0] = '\0';
pm->hw_protocol = e->skb->protocol;
if (e->info->indev && e->skb->dev) {
pm->hw_type = e->skb->dev->type;
if (e->skb->dev->hard_header_parse)
pm->hw_addrlen =
e->skb->dev->hard_header_parse(e->skb,
pm->hw_addr);
}
if (data_len)
memcpy(pm->payload, e->skb->data, data_len);
nlh->nlmsg_len = skb->tail - old_tail;
NETLINK_CB(skb).dst_groups = 0;
return skb;
nlmsg_failure:
if (skb)
kfree_skb(skb);
*errp = 0;
printk(KERN_ERR "ip6_queue: error creating netlink message\n");
return NULL;
}
static int netlink_send_peer(ip6q_queue_element_t *e)
{
int status = 0;
struct sk_buff *skb;
skb = netlink_build_message(e, &status);
if (skb == NULL)
return status;
return netlink_unicast(nfnl, skb, nlq6->peer.pid, MSG_DONTWAIT);
} }
#define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0) #define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0)
static __inline__ void netlink_receive_user_skb(struct sk_buff *skb) static inline void
ipq_rcv_skb(struct sk_buff *skb)
{ {
int status, type; int status, type, pid, flags, nlmsglen, skblen;
struct nlmsghdr *nlh; struct nlmsghdr *nlh;
if (skb->len < sizeof(struct nlmsghdr)) skblen = skb->len;
if (skblen < sizeof(*nlh))
return; return;
nlh = (struct nlmsghdr *)skb->data; nlh = (struct nlmsghdr *)skb->data;
if (nlh->nlmsg_len < sizeof(struct nlmsghdr) nlmsglen = nlh->nlmsg_len;
|| skb->len < nlh->nlmsg_len) if (nlmsglen < sizeof(*nlh) || skblen < nlmsglen)
return; return;
if(nlh->nlmsg_pid <= 0 pid = nlh->nlmsg_pid;
|| !(nlh->nlmsg_flags & NLM_F_REQUEST) flags = nlh->nlmsg_flags;
|| nlh->nlmsg_flags & NLM_F_MULTI)
if(pid <= 0 || !(flags & NLM_F_REQUEST) || flags & NLM_F_MULTI)
RCV_SKB_FAIL(-EINVAL); RCV_SKB_FAIL(-EINVAL);
if (nlh->nlmsg_flags & MSG_TRUNC)
if (flags & MSG_TRUNC)
RCV_SKB_FAIL(-ECOMM); RCV_SKB_FAIL(-ECOMM);
type = nlh->nlmsg_type; type = nlh->nlmsg_type;
if (type < NLMSG_NOOP || type >= IPQM_MAX) if (type < NLMSG_NOOP || type >= IPQM_MAX)
RCV_SKB_FAIL(-EINVAL); RCV_SKB_FAIL(-EINVAL);
if (type <= IPQM_BASE) if (type <= IPQM_BASE)
return; return;
if(!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN)) if(!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN))
RCV_SKB_FAIL(-EPERM); RCV_SKB_FAIL(-EPERM);
if (nlq6->peer.pid && !nlq6->peer.died
&& (nlq6->peer.pid != nlh->nlmsg_pid)) { write_lock_bh(&queue_lock);
printk(KERN_WARNING "ip6_queue: peer pid changed from %d to "
"%d, flushing queue\n", nlq6->peer.pid, nlh->nlmsg_pid); if (peer_pid) {
ip6q_flush(nlq6); if (peer_pid != pid) {
} write_unlock_bh(&queue_lock);
nlq6->peer.pid = nlh->nlmsg_pid; RCV_SKB_FAIL(-EBUSY);
nlq6->peer.died = 0; }
status = ip6q_receive_peer(nlq6, NLMSG_DATA(nlh), }
type, skb->len - NLMSG_LENGTH(0)); else
peer_pid = pid;
write_unlock_bh(&queue_lock);
status = ipq_receive_peer(NLMSG_DATA(nlh), type,
skblen - NLMSG_LENGTH(0));
if (status < 0) if (status < 0)
RCV_SKB_FAIL(status); RCV_SKB_FAIL(status);
if (nlh->nlmsg_flags & NLM_F_ACK)
if (flags & NLM_F_ACK)
netlink_ack(skb, nlh, 0); netlink_ack(skb, nlh, 0);
return; return;
} }
/* Note: we are only dealing with single part messages at the moment. */ static void
static void netlink_receive_user_sk(struct sock *sk, int len) ipq_rcv_sk(struct sock *sk, int len)
{ {
do { do {
struct sk_buff *skb; struct sk_buff *skb;
if (rtnl_shlock_nowait()) if (down_trylock(&ipqnl_sem))
return; return;
while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) { while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) {
netlink_receive_user_skb(skb); ipq_rcv_skb(skb);
kfree_skb(skb); kfree_skb(skb);
} }
up(&rtnl_sem);
} while (nfnl && nfnl->receive_queue.qlen); up(&ipqnl_sem);
}
/**************************************************************************** } while (ipqnl && ipqnl->receive_queue.qlen);
* }
* System events
*
****************************************************************************/
static int receive_event(struct notifier_block *this, static int
unsigned long event, void *ptr) ipq_rcv_dev_event(struct notifier_block *this,
unsigned long event, void *ptr)
{ {
struct net_device *dev = ptr; struct net_device *dev = ptr;
/* Drop any packets associated with the downed device */ /* Drop any packets associated with the downed device */
if (event == NETDEV_DOWN) if (event == NETDEV_DOWN)
ip6q_dev_drop(nlq6, dev->ifindex); ipq_dev_drop(dev->ifindex);
return NOTIFY_DONE; return NOTIFY_DONE;
} }
struct notifier_block ip6q_dev_notifier = { static struct notifier_block ipq_dev_notifier = {
receive_event, ipq_rcv_dev_event,
NULL, NULL,
0 0
}; };
/**************************************************************************** static int
* ipq_rcv_nl_event(struct notifier_block *this,
* Sysctl - queue tuning. unsigned long event, void *ptr)
* {
****************************************************************************/ struct netlink_notify *n = ptr;
if (event == NETLINK_URELEASE &&
n->protocol == NETLINK_IP6_FW && n->pid) {
write_lock_bh(&queue_lock);
if (n->pid == peer_pid)
__ipq_reset();
write_unlock_bh(&queue_lock);
}
return NOTIFY_DONE;
}
static int sysctl_maxlen = IPQ_QMAX_DEFAULT; static struct notifier_block ipq_nl_notifier = {
ipq_rcv_nl_event,
NULL,
0
};
static struct ctl_table_header *ip6q_sysctl_header; static int sysctl_maxlen = IPQ_QMAX_DEFAULT;
static struct ctl_table_header *ipq_sysctl_header;
static ctl_table ip6q_table[] = { static ctl_table ipq_table[] = {
{ NET_IPQ_QMAX, NET_IPQ_QMAX_NAME, &sysctl_maxlen, { NET_IPQ_QMAX, NET_IPQ_QMAX_NAME, &sysctl_maxlen,
sizeof(sysctl_maxlen), 0644, NULL, proc_dointvec }, sizeof(sysctl_maxlen), 0644, NULL, proc_dointvec },
{ 0 } { 0 }
}; };
static ctl_table ip6q_dir_table[] = { static ctl_table ipq_dir_table[] = {
{NET_IPV6, "ipv6", NULL, 0, 0555, ip6q_table, 0, 0, 0, 0, 0}, {NET_IPV6, "ipv6", NULL, 0, 0555, ipq_table, 0, 0, 0, 0, 0},
{ 0 } { 0 }
}; };
static ctl_table ip6q_root_table[] = { static ctl_table ipq_root_table[] = {
{CTL_NET, "net", NULL, 0, 0555, ip6q_dir_table, 0, 0, 0, 0, 0}, {CTL_NET, "net", NULL, 0, 0555, ipq_dir_table, 0, 0, 0, 0, 0},
{ 0 } { 0 }
}; };
/**************************************************************************** static int
* ipq_get_info(char *buffer, char **start, off_t offset, int length)
* Procfs - debugging info.
*
****************************************************************************/
static int ip6q_get_info(char *buffer, char **start, off_t offset, int length)
{ {
int len; int len;
spin_lock_bh(&nlq6->lock); read_lock_bh(&queue_lock);
len = sprintf(buffer, len = sprintf(buffer,
"Peer pid : %d\n" "Peer PID : %d\n"
"Peer died : %d\n" "Copy mode : %hu\n"
"Peer copy mode : %d\n" "Copy range : %u\n"
"Peer copy range : %Zu\n" "Queue length : %u\n"
"Queue length : %d\n" "Queue max. length : %u\n",
"Queue max. length : %d\n" peer_pid,
"Queue flushing : %d\n" copy_mode,
"Queue terminate : %d\n", copy_range,
nlq6->peer.pid, queue_total,
nlq6->peer.died, queue_maxlen);
nlq6->peer.copy_mode,
nlq6->peer.copy_range, read_unlock_bh(&queue_lock);
nlq6->len,
*nlq6->maxlen,
nlq6->flushing,
nlq6->terminate);
spin_unlock_bh(&nlq6->lock);
*start = buffer + offset; *start = buffer + offset;
len -= offset; len -= offset;
if (len > length) if (len > length)
...@@ -666,52 +679,70 @@ static int ip6q_get_info(char *buffer, char **start, off_t offset, int length) ...@@ -666,52 +679,70 @@ static int ip6q_get_info(char *buffer, char **start, off_t offset, int length)
return len; return len;
} }
/**************************************************************************** static int
* init_or_cleanup(int init)
* Module stuff.
*
****************************************************************************/
static int __init init(void)
{ {
int status = 0; int status = -ENOMEM;
struct proc_dir_entry *proc; struct proc_dir_entry *proc;
/* We must create the NETLINK_IP6_FW protocol service */ if (!init)
nfnl = netlink_kernel_create(NETLINK_IP6_FW, netlink_receive_user_sk); goto cleanup;
if (nfnl == NULL) {
printk(KERN_ERR "ip6_queue: initialisation failed: unable to " netlink_register_notifier(&ipq_nl_notifier);
"create kernel netlink socket\n"); ipqnl = netlink_kernel_create(NETLINK_IP6_FW, ipq_rcv_sk);
return -ENOMEM; if (ipqnl == NULL) {
} printk(KERN_ERR "ip6_queue: failed to create netlink socket\n");
nlq6 = ip6q_create_queue(netfilter6_receive, goto cleanup_netlink_notifier;
netlink_send_peer, &status, &sysctl_maxlen);
if (nlq6 == NULL) {
printk(KERN_ERR "ip6_queue: initialisation failed: unable to "
"create queue\n");
sock_release(nfnl->socket);
return status;
} }
/* The file will be /proc/net/ip6_queue */
proc = proc_net_create(IPQ_PROC_FS_NAME, 0, ip6q_get_info); proc = proc_net_create(IPQ_PROC_FS_NAME, 0, ipq_get_info);
if (proc) proc->owner = THIS_MODULE; if (proc)
proc->owner = THIS_MODULE;
else { else {
ip6q_destroy_queue(nlq6); printk(KERN_ERR "ip6_queue: failed to create proc entry\n");
sock_release(nfnl->socket); goto cleanup_ipqnl;
return -ENOMEM; }
register_netdevice_notifier(&ipq_dev_notifier);
ipq_sysctl_header = register_sysctl_table(ipq_root_table, 0);
status = nf_register_queue_handler(PF_INET6, ipq_enqueue_packet, NULL);
if (status < 0) {
printk(KERN_ERR "ip6_queue: failed to register queue handler\n");
goto cleanup_sysctl;
} }
register_netdevice_notifier(&ip6q_dev_notifier); return status;
ip6q_sysctl_header = register_sysctl_table(ip6q_root_table, 0);
cleanup:
nf_unregister_queue_handler(PF_INET6);
br_write_lock_bh(BR_NETPROTO_LOCK);
br_write_unlock_bh(BR_NETPROTO_LOCK);
ipq_flush(NF_DROP);
cleanup_sysctl:
unregister_sysctl_table(ipq_sysctl_header);
unregister_netdevice_notifier(&ipq_dev_notifier);
proc_net_remove(IPQ_PROC_FS_NAME);
cleanup_ipqnl:
sock_release(ipqnl->socket);
down(&ipqnl_sem);
up(&ipqnl_sem);
cleanup_netlink_notifier:
netlink_unregister_notifier(&ipq_nl_notifier);
return status; return status;
} }
static int __init init(void)
{
return init_or_cleanup(1);
}
static void __exit fini(void) static void __exit fini(void)
{ {
unregister_sysctl_table(ip6q_sysctl_header); init_or_cleanup(0);
proc_net_remove(IPQ_PROC_FS_NAME);
unregister_netdevice_notifier(&ip6q_dev_notifier);
ip6q_destroy_queue(nlq6);
sock_release(nfnl->socket);
} }
MODULE_DESCRIPTION("IPv6 packet queue handler"); MODULE_DESCRIPTION("IPv6 packet queue handler");
......
...@@ -777,10 +777,9 @@ static int ipxitf_send(struct ipx_interface *intrfc, struct sk_buff *skb, ...@@ -777,10 +777,9 @@ static int ipxitf_send(struct ipx_interface *intrfc, struct sk_buff *skb,
/* set up data link and physical headers */ /* set up data link and physical headers */
skb->dev = dev; skb->dev = dev;
skb->protocol = htons(ETH_P_IPX); skb->protocol = htons(ETH_P_IPX);
dl->datalink_header(dl, skb, dest_node);
/* Send it out */ /* Send it out */
dev_queue_xmit(skb); dl->request(dl, skb, dest_node);
out: return 0; out: return 0;
} }
...@@ -2253,6 +2252,22 @@ drop: kfree_skb(skb); ...@@ -2253,6 +2252,22 @@ drop: kfree_skb(skb);
out: return ret; out: return ret;
} }
static int ipx_8022_indicate(struct llc_prim_if_block *prim)
{
int rc = 1;
static struct packet_type p8022_packet_type = {
.type = __constant_htons(ETH_P_802_2),
};
if (prim->prim == LLC_DATAUNIT_PRIM) {
struct sk_buff *skb = prim->data->udata.skb;
rc = ipx_rcv(skb, skb->dev, &p8022_packet_type);
}
return rc;
}
static int ipx_sendmsg(struct socket *sock, struct msghdr *msg, int len, static int ipx_sendmsg(struct socket *sock, struct msghdr *msg, int len,
struct scm_cookie *scm) struct scm_cookie *scm)
{ {
...@@ -2545,7 +2560,7 @@ static int __init ipx_init(void) ...@@ -2545,7 +2560,7 @@ static int __init ipx_init(void)
else else
printk(ipx_8023_err_msg); printk(ipx_8023_err_msg);
p8022_datalink = register_8022_client(ipx_8022_type, ipx_rcv); p8022_datalink = register_8022_client(ipx_8022_type, ipx_8022_indicate);
if (!p8022_datalink) if (!p8022_datalink)
printk(ipx_llc_err_msg); printk(ipx_llc_err_msg);
...@@ -2593,10 +2608,10 @@ static void __exit ipx_proto_finito(void) ...@@ -2593,10 +2608,10 @@ static void __exit ipx_proto_finito(void)
unregister_netdevice_notifier(&ipx_dev_notifier); unregister_netdevice_notifier(&ipx_dev_notifier);
unregister_snap_client(ipx_snap_id); unregister_snap_client(pSNAP_datalink);
pSNAP_datalink = NULL; pSNAP_datalink = NULL;
unregister_8022_client(ipx_8022_type); unregister_8022_client(p8022_datalink);
p8022_datalink = NULL; p8022_datalink = NULL;
dev_remove_pack(&ipx_8023_packet_type); dev_remove_pack(&ipx_8023_packet_type);
......
...@@ -61,15 +61,18 @@ int llc_conn_ac_clear_remote_busy(struct sock *sk, struct llc_conn_state_ev *ev) ...@@ -61,15 +61,18 @@ int llc_conn_ac_clear_remote_busy(struct sock *sk, struct llc_conn_state_ev *ev)
int llc_conn_ac_conn_ind(struct sock *sk, struct llc_conn_state_ev *ev) int llc_conn_ac_conn_ind(struct sock *sk, struct llc_conn_state_ev *ev)
{ {
int rc = 1; int rc = 1;
u8 dsap;
struct sk_buff *skb = ev->data.pdu.skb; struct sk_buff *skb = ev->data.pdu.skb;
union llc_u_prim_data *prim_data = llc_ind_prim.data;
struct llc_prim_if_block *prim = &llc_ind_prim;
struct llc_sap *sap; struct llc_sap *sap;
struct llc_opt *llc = llc_sk(sk);
llc_pdu_decode_dsap(skb, &prim_data->conn.daddr.lsap); llc_pdu_decode_dsap(skb, &dsap);
sap = llc_sap_find(prim_data->conn.daddr.lsap); sap = llc_sap_find(dsap);
if (sap) { if (sap) {
struct llc_prim_if_block *prim = &sap->llc_ind_prim;
union llc_u_prim_data *prim_data = prim->data;
struct llc_opt *llc = llc_sk(sk);
prim_data->conn.daddr.lsap = dsap;
llc_pdu_decode_sa(skb, llc->daddr.mac); llc_pdu_decode_sa(skb, llc->daddr.mac);
llc_pdu_decode_da(skb, llc->laddr.mac); llc_pdu_decode_da(skb, llc->laddr.mac);
llc->dev = skb->dev; llc->dev = skb->dev;
...@@ -90,14 +93,11 @@ int llc_conn_ac_conn_ind(struct sock *sk, struct llc_conn_state_ev *ev) ...@@ -90,14 +93,11 @@ int llc_conn_ac_conn_ind(struct sock *sk, struct llc_conn_state_ev *ev)
int llc_conn_ac_conn_confirm(struct sock *sk, struct llc_conn_state_ev *ev) int llc_conn_ac_conn_confirm(struct sock *sk, struct llc_conn_state_ev *ev)
{ {
union llc_u_prim_data *prim_data = llc_cfm_prim.data;
struct sk_buff *skb = ev->data.pdu.skb; struct sk_buff *skb = ev->data.pdu.skb;
/* FIXME: wtf, this is global, so the whole thing is really
* non reentrant...
*/
struct llc_prim_if_block *prim = &llc_cfm_prim;
struct llc_opt *llc = llc_sk(sk); struct llc_opt *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap; struct llc_sap *sap = llc->sap;
struct llc_prim_if_block *prim = &sap->llc_cfm_prim;
union llc_u_prim_data *prim_data = prim->data;
prim_data->conn.sk = sk; prim_data->conn.sk = sk;
prim_data->conn.pri = 0; prim_data->conn.pri = 0;
...@@ -106,7 +106,7 @@ int llc_conn_ac_conn_confirm(struct sock *sk, struct llc_conn_state_ev *ev) ...@@ -106,7 +106,7 @@ int llc_conn_ac_conn_confirm(struct sock *sk, struct llc_conn_state_ev *ev)
if (skb) if (skb)
prim_data->conn.dev = skb->dev; prim_data->conn.dev = skb->dev;
else else
printk(KERN_ERR __FUNCTION__ "ev->data.pdu.skb == NULL\n"); printk(KERN_ERR "%s: ev->data.pdu.skb == NULL\n", __FUNCTION__);
prim->data = prim_data; prim->data = prim_data;
prim->prim = LLC_CONN_PRIM; prim->prim = LLC_CONN_PRIM;
prim->sap = sap; prim->sap = sap;
...@@ -118,17 +118,19 @@ int llc_conn_ac_conn_confirm(struct sock *sk, struct llc_conn_state_ev *ev) ...@@ -118,17 +118,19 @@ int llc_conn_ac_conn_confirm(struct sock *sk, struct llc_conn_state_ev *ev)
static int llc_conn_ac_data_confirm(struct sock *sk, static int llc_conn_ac_data_confirm(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_prim_if_block *prim = &llc_cfm_prim; struct llc_opt *llc = llc_sk(sk);
union llc_u_prim_data *prim_data = llc_cfm_prim.data; struct llc_sap *sap = llc->sap;
struct llc_prim_if_block *prim = &sap->llc_cfm_prim;
union llc_u_prim_data *prim_data = prim->data;
prim_data->data.sk = sk; prim_data->data.sk = sk;
prim_data->data.pri = 0; prim_data->data.pri = 0;
prim_data->data.link = llc_sk(sk)->link; prim_data->data.link = llc->link;
prim_data->data.status = LLC_STATUS_RECEIVED; prim_data->data.status = LLC_STATUS_RECEIVED;
prim_data->data.skb = NULL; prim_data->data.skb = NULL;
prim->data = prim_data; prim->data = prim_data;
prim->prim = LLC_DATA_PRIM; prim->prim = LLC_DATA_PRIM;
prim->sap = llc_sk(sk)->sap; prim->sap = sap;
ev->flag = 1; ev->flag = 1;
ev->cfm_prim = prim; ev->cfm_prim = prim;
return 0; return 0;
...@@ -144,12 +146,9 @@ int llc_conn_ac_disc_ind(struct sock *sk, struct llc_conn_state_ev *ev) ...@@ -144,12 +146,9 @@ int llc_conn_ac_disc_ind(struct sock *sk, struct llc_conn_state_ev *ev)
{ {
u8 reason = 0; u8 reason = 0;
int rc = 1; int rc = 1;
union llc_u_prim_data *prim_data = llc_ind_prim.data;
struct llc_prim_if_block *prim = &llc_ind_prim;
if (ev->type == LLC_CONN_EV_TYPE_PDU) { if (ev->type == LLC_CONN_EV_TYPE_PDU) {
struct llc_pdu_un *pdu = struct llc_pdu_un *pdu = llc_pdu_un_hdr(ev->data.pdu.skb);
(struct llc_pdu_un *)ev->data.pdu.skb->nh.raw;
if (!LLC_PDU_IS_RSP(pdu) && if (!LLC_PDU_IS_RSP(pdu) &&
!LLC_PDU_TYPE_IS_U(pdu) && !LLC_PDU_TYPE_IS_U(pdu) &&
...@@ -170,12 +169,17 @@ int llc_conn_ac_disc_ind(struct sock *sk, struct llc_conn_state_ev *ev) ...@@ -170,12 +169,17 @@ int llc_conn_ac_disc_ind(struct sock *sk, struct llc_conn_state_ev *ev)
rc = 1; rc = 1;
} }
if (!rc) { if (!rc) {
struct llc_opt *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap;
struct llc_prim_if_block *prim = &sap->llc_ind_prim;
union llc_u_prim_data *prim_data = prim->data;
prim_data->disc.sk = sk; prim_data->disc.sk = sk;
prim_data->disc.reason = reason; prim_data->disc.reason = reason;
prim_data->disc.link = llc_sk(sk)->link; prim_data->disc.link = llc->link;
prim->data = prim_data; prim->data = prim_data;
prim->prim = LLC_DISC_PRIM; prim->prim = LLC_DISC_PRIM;
prim->sap = llc_sk(sk)->sap; prim->sap = llc->sap;
ev->flag = 1; ev->flag = 1;
ev->ind_prim = prim; ev->ind_prim = prim;
} }
...@@ -184,15 +188,17 @@ int llc_conn_ac_disc_ind(struct sock *sk, struct llc_conn_state_ev *ev) ...@@ -184,15 +188,17 @@ int llc_conn_ac_disc_ind(struct sock *sk, struct llc_conn_state_ev *ev)
int llc_conn_ac_disc_confirm(struct sock *sk, struct llc_conn_state_ev *ev) int llc_conn_ac_disc_confirm(struct sock *sk, struct llc_conn_state_ev *ev)
{ {
union llc_u_prim_data *prim_data = llc_cfm_prim.data; struct llc_opt *llc = llc_sk(sk);
struct llc_prim_if_block *prim = &llc_cfm_prim; struct llc_sap *sap = llc->sap;
struct llc_prim_if_block *prim = &sap->llc_cfm_prim;
union llc_u_prim_data *prim_data = prim->data;
prim_data->disc.sk = sk; prim_data->disc.sk = sk;
prim_data->disc.reason = ev->status; prim_data->disc.reason = ev->status;
prim_data->disc.link = llc_sk(sk)->link; prim_data->disc.link = llc->link;
prim->data = prim_data; prim->data = prim_data;
prim->prim = LLC_DISC_PRIM; prim->prim = LLC_DISC_PRIM;
prim->sap = llc_sk(sk)->sap; prim->sap = sap;
ev->flag = 1; ev->flag = 1;
ev->cfm_prim = prim; ev->cfm_prim = prim;
return 0; return 0;
...@@ -202,9 +208,7 @@ int llc_conn_ac_rst_ind(struct sock *sk, struct llc_conn_state_ev *ev) ...@@ -202,9 +208,7 @@ int llc_conn_ac_rst_ind(struct sock *sk, struct llc_conn_state_ev *ev)
{ {
u8 reason = 0; u8 reason = 0;
int rc = 1; int rc = 1;
struct llc_pdu_un *pdu = (struct llc_pdu_un *)ev->data.pdu.skb->nh.raw; struct llc_pdu_un *pdu = llc_pdu_un_hdr(ev->data.pdu.skb);
union llc_u_prim_data *prim_data = llc_ind_prim.data;
struct llc_prim_if_block *prim = &llc_ind_prim;
struct llc_opt *llc = llc_sk(sk); struct llc_opt *llc = llc_sk(sk);
switch (ev->type) { switch (ev->type) {
...@@ -237,12 +241,16 @@ int llc_conn_ac_rst_ind(struct sock *sk, struct llc_conn_state_ev *ev) ...@@ -237,12 +241,16 @@ int llc_conn_ac_rst_ind(struct sock *sk, struct llc_conn_state_ev *ev)
break; break;
} }
if (!rc) { if (!rc) {
struct llc_sap *sap = llc->sap;
struct llc_prim_if_block *prim = &sap->llc_ind_prim;
union llc_u_prim_data *prim_data = prim->data;
prim_data->res.sk = sk; prim_data->res.sk = sk;
prim_data->res.reason = reason; prim_data->res.reason = reason;
prim_data->res.link = llc->link; prim_data->res.link = llc->link;
prim->data = prim_data; prim->data = prim_data;
prim->prim = LLC_RESET_PRIM; prim->prim = LLC_RESET_PRIM;
prim->sap = llc->sap; prim->sap = sap;
ev->flag = 1; ev->flag = 1;
ev->ind_prim = prim; ev->ind_prim = prim;
} }
...@@ -251,14 +259,16 @@ int llc_conn_ac_rst_ind(struct sock *sk, struct llc_conn_state_ev *ev) ...@@ -251,14 +259,16 @@ int llc_conn_ac_rst_ind(struct sock *sk, struct llc_conn_state_ev *ev)
int llc_conn_ac_rst_confirm(struct sock *sk, struct llc_conn_state_ev *ev) int llc_conn_ac_rst_confirm(struct sock *sk, struct llc_conn_state_ev *ev)
{ {
union llc_u_prim_data *prim_data = llc_cfm_prim.data; struct llc_opt *llc = llc_sk(sk);
struct llc_prim_if_block *prim = &llc_cfm_prim; struct llc_sap *sap = llc->sap;
struct llc_prim_if_block *prim = &sap->llc_cfm_prim;
union llc_u_prim_data *prim_data = prim->data;
prim_data->res.sk = sk; prim_data->res.sk = sk;
prim_data->res.link = llc_sk(sk)->link; prim_data->res.link = llc->link;
prim->data = prim_data; prim->data = prim_data;
prim->prim = LLC_RESET_PRIM; prim->prim = LLC_RESET_PRIM;
prim->sap = llc_sk(sk)->sap; prim->sap = sap;
ev->flag = 1; ev->flag = 1;
ev->cfm_prim = prim; ev->cfm_prim = prim;
return 0; return 0;
......
...@@ -87,10 +87,10 @@ static u16 llc_util_nr_inside_tx_window(struct sock *sk, u8 nr) ...@@ -87,10 +87,10 @@ static u16 llc_util_nr_inside_tx_window(struct sock *sk, u8 nr)
if (!skb_queue_len(&llc->pdu_unack_q)) if (!skb_queue_len(&llc->pdu_unack_q))
goto out; goto out;
skb = skb_peek(&llc->pdu_unack_q); skb = skb_peek(&llc->pdu_unack_q);
pdu = (struct llc_pdu_sn *)skb->nh.raw; pdu = llc_pdu_sn_hdr(skb);
nr1 = LLC_I_GET_NS(pdu); nr1 = LLC_I_GET_NS(pdu);
skb = skb_peek_tail(&llc->pdu_unack_q); skb = skb_peek_tail(&llc->pdu_unack_q);
pdu = (struct llc_pdu_sn *)skb->nh.raw; pdu = llc_pdu_sn_hdr(skb);
nr2 = LLC_I_GET_NS(pdu); nr2 = LLC_I_GET_NS(pdu);
rc = !llc_circular_between(nr1, nr, (nr2 + 1) % LLC_2_SEQ_NBR_MODULO); rc = !llc_circular_between(nr1, nr, (nr2 + 1) % LLC_2_SEQ_NBR_MODULO);
out: out:
...@@ -155,7 +155,7 @@ int llc_conn_ev_rx_bad_pdu(struct sock *sk, struct llc_conn_state_ev *ev) ...@@ -155,7 +155,7 @@ int llc_conn_ev_rx_bad_pdu(struct sock *sk, struct llc_conn_state_ev *ev)
int llc_conn_ev_rx_disc_cmd_pbit_set_x(struct sock *sk, int llc_conn_ev_rx_disc_cmd_pbit_set_x(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_pdu_un *pdu = (struct llc_pdu_un *)ev->data.pdu.skb->nh.raw; struct llc_pdu_un *pdu = llc_pdu_un_hdr(ev->data.pdu.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;
...@@ -164,7 +164,7 @@ int llc_conn_ev_rx_disc_cmd_pbit_set_x(struct sock *sk, ...@@ -164,7 +164,7 @@ int llc_conn_ev_rx_disc_cmd_pbit_set_x(struct sock *sk,
int llc_conn_ev_rx_dm_rsp_fbit_set_x(struct sock *sk, int llc_conn_ev_rx_dm_rsp_fbit_set_x(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_pdu_un *pdu = (struct llc_pdu_un *)ev->data.pdu.skb->nh.raw; struct llc_pdu_un *pdu = llc_pdu_un_hdr(ev->data.pdu.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;
...@@ -173,7 +173,7 @@ int llc_conn_ev_rx_dm_rsp_fbit_set_x(struct sock *sk, ...@@ -173,7 +173,7 @@ int llc_conn_ev_rx_dm_rsp_fbit_set_x(struct sock *sk,
int llc_conn_ev_rx_frmr_rsp_fbit_set_x(struct sock *sk, int llc_conn_ev_rx_frmr_rsp_fbit_set_x(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_pdu_un *pdu = (struct llc_pdu_un *)ev->data.pdu.skb->nh.raw; struct llc_pdu_un *pdu = llc_pdu_un_hdr(ev->data.pdu.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;
...@@ -182,7 +182,7 @@ int llc_conn_ev_rx_frmr_rsp_fbit_set_x(struct sock *sk, ...@@ -182,7 +182,7 @@ int llc_conn_ev_rx_frmr_rsp_fbit_set_x(struct sock *sk,
int llc_conn_ev_rx_i_cmd_pbit_set_0(struct sock *sk, int llc_conn_ev_rx_i_cmd_pbit_set_0(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(ev->data.pdu.skb);
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) && !LLC_I_PF_IS_0(pdu) &&
...@@ -192,7 +192,7 @@ int llc_conn_ev_rx_i_cmd_pbit_set_0(struct sock *sk, ...@@ -192,7 +192,7 @@ int llc_conn_ev_rx_i_cmd_pbit_set_0(struct sock *sk,
int llc_conn_ev_rx_i_cmd_pbit_set_1(struct sock *sk, int llc_conn_ev_rx_i_cmd_pbit_set_1(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(ev->data.pdu.skb);
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) && !LLC_I_PF_IS_1(pdu) &&
...@@ -202,7 +202,7 @@ int llc_conn_ev_rx_i_cmd_pbit_set_1(struct sock *sk, ...@@ -202,7 +202,7 @@ int llc_conn_ev_rx_i_cmd_pbit_set_1(struct sock *sk,
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 llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(ev->data.pdu.skb);
u8 vr = llc_sk(sk)->vR; u8 vr = llc_sk(sk)->vR;
u8 ns = LLC_I_GET_NS(pdu); u8 ns = LLC_I_GET_NS(pdu);
...@@ -214,7 +214,7 @@ int llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns(struct sock *sk, ...@@ -214,7 +214,7 @@ 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 llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(ev->data.pdu.skb);
u8 vr = llc_sk(sk)->vR; u8 vr = llc_sk(sk)->vR;
u8 ns = LLC_I_GET_NS(pdu); u8 ns = LLC_I_GET_NS(pdu);
...@@ -226,7 +226,7 @@ int llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns(struct sock *sk, ...@@ -226,7 +226,7 @@ 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 llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_pdu_sn * pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn * pdu = llc_pdu_sn_hdr(ev->data.pdu.skb);
u8 vr = llc_sk(sk)->vR; u8 vr = llc_sk(sk)->vR;
u8 ns = LLC_I_GET_NS(pdu); u8 ns = LLC_I_GET_NS(pdu);
u16 rc = !LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_I(pdu) && ns != vr && u16 rc = !LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_I(pdu) && ns != vr &&
...@@ -241,7 +241,7 @@ int llc_conn_ev_rx_i_cmd_pbit_set_x_inval_ns(struct sock *sk, ...@@ -241,7 +241,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, int llc_conn_ev_rx_i_rsp_fbit_set_0(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(ev->data.pdu.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_0(pdu) && !LLC_I_PF_IS_0(pdu) &&
...@@ -251,7 +251,7 @@ int llc_conn_ev_rx_i_rsp_fbit_set_0(struct sock *sk, ...@@ -251,7 +251,7 @@ int llc_conn_ev_rx_i_rsp_fbit_set_0(struct sock *sk,
int llc_conn_ev_rx_i_rsp_fbit_set_1(struct sock *sk, int llc_conn_ev_rx_i_rsp_fbit_set_1(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(ev->data.pdu.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) &&
...@@ -261,7 +261,7 @@ int llc_conn_ev_rx_i_rsp_fbit_set_1(struct sock *sk, ...@@ -261,7 +261,7 @@ int llc_conn_ev_rx_i_rsp_fbit_set_1(struct sock *sk,
int llc_conn_ev_rx_i_rsp_fbit_set_x(struct sock *sk, int llc_conn_ev_rx_i_rsp_fbit_set_x(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(ev->data.pdu.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_GET_NS(pdu) == llc_sk(sk)->vR ? 0 : 1; LLC_I_GET_NS(pdu) == llc_sk(sk)->vR ? 0 : 1;
...@@ -270,7 +270,7 @@ int llc_conn_ev_rx_i_rsp_fbit_set_x(struct sock *sk, ...@@ -270,7 +270,7 @@ int llc_conn_ev_rx_i_rsp_fbit_set_x(struct sock *sk,
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 llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(ev->data.pdu.skb);
u8 vr = llc_sk(sk)->vR; u8 vr = llc_sk(sk)->vR;
u8 ns = LLC_I_GET_NS(pdu); u8 ns = LLC_I_GET_NS(pdu);
...@@ -282,7 +282,7 @@ int llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns(struct sock *sk, ...@@ -282,7 +282,7 @@ 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 llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(ev->data.pdu.skb);
u8 vr = llc_sk(sk)->vR; u8 vr = llc_sk(sk)->vR;
u8 ns = LLC_I_GET_NS(pdu); u8 ns = LLC_I_GET_NS(pdu);
...@@ -294,7 +294,7 @@ int llc_conn_ev_rx_i_rsp_fbit_set_1_unexpd_ns(struct sock *sk, ...@@ -294,7 +294,7 @@ 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 llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(ev->data.pdu.skb);
u8 vr = llc_sk(sk)->vR; u8 vr = llc_sk(sk)->vR;
u8 ns = LLC_I_GET_NS(pdu); u8 ns = LLC_I_GET_NS(pdu);
...@@ -305,7 +305,7 @@ int llc_conn_ev_rx_i_rsp_fbit_set_x_unexpd_ns(struct sock *sk, ...@@ -305,7 +305,7 @@ 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 llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(ev->data.pdu.skb);
u8 vr = llc_sk(sk)->vR; u8 vr = llc_sk(sk)->vR;
u8 ns = LLC_I_GET_NS(pdu); u8 ns = LLC_I_GET_NS(pdu);
u16 rc = !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_I(pdu) && ns != vr && u16 rc = !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_I(pdu) && ns != vr &&
...@@ -320,7 +320,7 @@ int llc_conn_ev_rx_i_rsp_fbit_set_x_inval_ns(struct sock *sk, ...@@ -320,7 +320,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, int llc_conn_ev_rx_rej_cmd_pbit_set_0(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(ev->data.pdu.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) &&
...@@ -330,7 +330,7 @@ int llc_conn_ev_rx_rej_cmd_pbit_set_0(struct sock *sk, ...@@ -330,7 +330,7 @@ int llc_conn_ev_rx_rej_cmd_pbit_set_0(struct sock *sk,
int llc_conn_ev_rx_rej_cmd_pbit_set_1(struct sock *sk, int llc_conn_ev_rx_rej_cmd_pbit_set_1(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(ev->data.pdu.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) &&
...@@ -340,7 +340,7 @@ int llc_conn_ev_rx_rej_cmd_pbit_set_1(struct sock *sk, ...@@ -340,7 +340,7 @@ int llc_conn_ev_rx_rej_cmd_pbit_set_1(struct sock *sk,
int llc_conn_ev_rx_rej_rsp_fbit_set_0(struct sock *sk, int llc_conn_ev_rx_rej_rsp_fbit_set_0(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(ev->data.pdu.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) &&
...@@ -350,7 +350,7 @@ int llc_conn_ev_rx_rej_rsp_fbit_set_0(struct sock *sk, ...@@ -350,7 +350,7 @@ int llc_conn_ev_rx_rej_rsp_fbit_set_0(struct sock *sk,
int llc_conn_ev_rx_rej_rsp_fbit_set_1(struct sock *sk, int llc_conn_ev_rx_rej_rsp_fbit_set_1(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(ev->data.pdu.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) &&
...@@ -360,7 +360,7 @@ int llc_conn_ev_rx_rej_rsp_fbit_set_1(struct sock *sk, ...@@ -360,7 +360,7 @@ int llc_conn_ev_rx_rej_rsp_fbit_set_1(struct sock *sk,
int llc_conn_ev_rx_rej_rsp_fbit_set_x(struct sock *sk, int llc_conn_ev_rx_rej_rsp_fbit_set_x(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_pdu_un *pdu = (struct llc_pdu_un *)ev->data.pdu.skb->nh.raw; struct llc_pdu_un *pdu = llc_pdu_un_hdr(ev->data.pdu.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;
...@@ -369,7 +369,7 @@ int llc_conn_ev_rx_rej_rsp_fbit_set_x(struct sock *sk, ...@@ -369,7 +369,7 @@ int llc_conn_ev_rx_rej_rsp_fbit_set_x(struct sock *sk,
int llc_conn_ev_rx_rnr_cmd_pbit_set_0(struct sock *sk, int llc_conn_ev_rx_rnr_cmd_pbit_set_0(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(ev->data.pdu.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) &&
...@@ -379,7 +379,7 @@ int llc_conn_ev_rx_rnr_cmd_pbit_set_0(struct sock *sk, ...@@ -379,7 +379,7 @@ int llc_conn_ev_rx_rnr_cmd_pbit_set_0(struct sock *sk,
int llc_conn_ev_rx_rnr_cmd_pbit_set_1(struct sock *sk, int llc_conn_ev_rx_rnr_cmd_pbit_set_1(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(ev->data.pdu.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) &&
...@@ -389,7 +389,7 @@ int llc_conn_ev_rx_rnr_cmd_pbit_set_1(struct sock *sk, ...@@ -389,7 +389,7 @@ int llc_conn_ev_rx_rnr_cmd_pbit_set_1(struct sock *sk,
int llc_conn_ev_rx_rnr_rsp_fbit_set_0(struct sock *sk, int llc_conn_ev_rx_rnr_rsp_fbit_set_0(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(ev->data.pdu.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) &&
...@@ -399,7 +399,7 @@ int llc_conn_ev_rx_rnr_rsp_fbit_set_0(struct sock *sk, ...@@ -399,7 +399,7 @@ int llc_conn_ev_rx_rnr_rsp_fbit_set_0(struct sock *sk,
int llc_conn_ev_rx_rnr_rsp_fbit_set_1(struct sock *sk, int llc_conn_ev_rx_rnr_rsp_fbit_set_1(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(ev->data.pdu.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) &&
...@@ -409,7 +409,7 @@ int llc_conn_ev_rx_rnr_rsp_fbit_set_1(struct sock *sk, ...@@ -409,7 +409,7 @@ int llc_conn_ev_rx_rnr_rsp_fbit_set_1(struct sock *sk,
int llc_conn_ev_rx_rr_cmd_pbit_set_0(struct sock *sk, int llc_conn_ev_rx_rr_cmd_pbit_set_0(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(ev->data.pdu.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) &&
...@@ -419,7 +419,7 @@ int llc_conn_ev_rx_rr_cmd_pbit_set_0(struct sock *sk, ...@@ -419,7 +419,7 @@ int llc_conn_ev_rx_rr_cmd_pbit_set_0(struct sock *sk,
int llc_conn_ev_rx_rr_cmd_pbit_set_1(struct sock *sk, int llc_conn_ev_rx_rr_cmd_pbit_set_1(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(ev->data.pdu.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) &&
...@@ -429,7 +429,7 @@ int llc_conn_ev_rx_rr_cmd_pbit_set_1(struct sock *sk, ...@@ -429,7 +429,7 @@ int llc_conn_ev_rx_rr_cmd_pbit_set_1(struct sock *sk,
int llc_conn_ev_rx_rr_rsp_fbit_set_0(struct sock *sk, int llc_conn_ev_rx_rr_rsp_fbit_set_0(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(ev->data.pdu.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) &&
...@@ -439,7 +439,7 @@ int llc_conn_ev_rx_rr_rsp_fbit_set_0(struct sock *sk, ...@@ -439,7 +439,7 @@ int llc_conn_ev_rx_rr_rsp_fbit_set_0(struct sock *sk,
int llc_conn_ev_rx_rr_rsp_fbit_set_1(struct sock *sk, int llc_conn_ev_rx_rr_rsp_fbit_set_1(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(ev->data.pdu.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) &&
...@@ -449,7 +449,7 @@ int llc_conn_ev_rx_rr_rsp_fbit_set_1(struct sock *sk, ...@@ -449,7 +449,7 @@ int llc_conn_ev_rx_rr_rsp_fbit_set_1(struct sock *sk,
int llc_conn_ev_rx_sabme_cmd_pbit_set_x(struct sock *sk, int llc_conn_ev_rx_sabme_cmd_pbit_set_x(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_pdu_un *pdu = (struct llc_pdu_un *)ev->data.pdu.skb->nh.raw; struct llc_pdu_un *pdu = llc_pdu_un_hdr(ev->data.pdu.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;
...@@ -458,7 +458,7 @@ int llc_conn_ev_rx_sabme_cmd_pbit_set_x(struct sock *sk, ...@@ -458,7 +458,7 @@ int llc_conn_ev_rx_sabme_cmd_pbit_set_x(struct sock *sk,
int llc_conn_ev_rx_ua_rsp_fbit_set_x(struct sock *sk, int llc_conn_ev_rx_ua_rsp_fbit_set_x(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_pdu_un *pdu = (struct llc_pdu_un *)ev->data.pdu.skb->nh.raw; struct llc_pdu_un *pdu = llc_pdu_un_hdr(ev->data.pdu.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_UA ? 0 : 1; LLC_U_PDU_RSP(pdu) == LLC_2_PDU_RSP_UA ? 0 : 1;
...@@ -468,7 +468,7 @@ int llc_conn_ev_rx_xxx_cmd_pbit_set_1(struct sock *sk, ...@@ -468,7 +468,7 @@ int llc_conn_ev_rx_xxx_cmd_pbit_set_1(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
u16 rc = 1; u16 rc = 1;
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(ev->data.pdu.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)) {
...@@ -484,7 +484,7 @@ int llc_conn_ev_rx_xxx_cmd_pbit_set_0(struct sock *sk, ...@@ -484,7 +484,7 @@ int llc_conn_ev_rx_xxx_cmd_pbit_set_0(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
u16 rc = 1; u16 rc = 1;
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(ev->data.pdu.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)) {
...@@ -506,7 +506,7 @@ int llc_conn_ev_rx_xxx_cmd_pbit_set_x(struct sock *sk, ...@@ -506,7 +506,7 @@ int llc_conn_ev_rx_xxx_cmd_pbit_set_x(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
u16 rc = 1; u16 rc = 1;
struct llc_pdu_un *pdu = (struct llc_pdu_un *)ev->data.pdu.skb->nh.raw; struct llc_pdu_un *pdu = llc_pdu_un_hdr(ev->data.pdu.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))
...@@ -526,7 +526,7 @@ int llc_conn_ev_rx_xxx_rsp_fbit_set_1(struct sock *sk, ...@@ -526,7 +526,7 @@ int llc_conn_ev_rx_xxx_rsp_fbit_set_1(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
u16 rc = 1; u16 rc = 1;
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(ev->data.pdu.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)) {
...@@ -549,7 +549,7 @@ int llc_conn_ev_rx_xxx_rsp_fbit_set_x(struct sock *sk, ...@@ -549,7 +549,7 @@ int llc_conn_ev_rx_xxx_rsp_fbit_set_x(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
u16 rc = 1; u16 rc = 1;
struct llc_pdu_un *pdu = (struct llc_pdu_un *)ev->data.pdu.skb->nh.raw; struct llc_pdu_un *pdu = llc_pdu_un_hdr(ev->data.pdu.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))
...@@ -570,7 +570,7 @@ int llc_conn_ev_rx_xxx_rsp_fbit_set_x(struct sock *sk, ...@@ -570,7 +570,7 @@ int llc_conn_ev_rx_xxx_rsp_fbit_set_x(struct sock *sk,
int llc_conn_ev_rx_xxx_yyy(struct sock *sk, struct llc_conn_state_ev *ev) int llc_conn_ev_rx_xxx_yyy(struct sock *sk, struct llc_conn_state_ev *ev)
{ {
u16 rc = 1; u16 rc = 1;
struct llc_pdu_un *pdu = (struct llc_pdu_un *)ev->data.pdu.skb->nh.raw; struct llc_pdu_un *pdu = llc_pdu_un_hdr(ev->data.pdu.skb);
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))
rc = 0; rc = 0;
...@@ -591,7 +591,7 @@ int llc_conn_ev_rx_zzz_cmd_pbit_set_x_inval_nr(struct sock *sk, ...@@ -591,7 +591,7 @@ int llc_conn_ev_rx_zzz_cmd_pbit_set_x_inval_nr(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
u16 rc = 1; u16 rc = 1;
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(ev->data.pdu.skb);
u8 vs = llc_sk(sk)->vS; u8 vs = llc_sk(sk)->vS;
u8 nr = LLC_I_GET_NR(pdu); u8 nr = LLC_I_GET_NR(pdu);
...@@ -613,7 +613,7 @@ int llc_conn_ev_rx_zzz_rsp_fbit_set_x_inval_nr(struct sock *sk, ...@@ -613,7 +613,7 @@ int llc_conn_ev_rx_zzz_rsp_fbit_set_x_inval_nr(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
u16 rc = 1; u16 rc = 1;
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(ev->data.pdu.skb);
u8 vs = llc_sk(sk)->vS; u8 vs = llc_sk(sk)->vS;
u8 nr = LLC_I_GET_NR(pdu); u8 nr = LLC_I_GET_NR(pdu);
......
...@@ -82,7 +82,7 @@ int llc_conn_send_ev(struct sock *sk, struct llc_conn_state_ev *ev) ...@@ -82,7 +82,7 @@ int llc_conn_send_ev(struct sock *sk, struct llc_conn_state_ev *ev)
/* check if the connection was freed by the state machine by /* check if the connection was freed by the state machine by
* means of llc_conn_disc */ * means of llc_conn_disc */
if (rc == 2) { if (rc == 2) {
printk(KERN_INFO __FUNCTION__ ": rc == 2\n"); printk(KERN_INFO "%s: rc == 2\n", __FUNCTION__);
rc = -ECONNABORTED; rc = -ECONNABORTED;
goto out; goto out;
} }
...@@ -134,16 +134,18 @@ void llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb) ...@@ -134,16 +134,18 @@ void llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb)
void llc_conn_rtn_pdu(struct sock *sk, struct sk_buff *skb, void llc_conn_rtn_pdu(struct sock *sk, struct sk_buff *skb,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
struct llc_prim_if_block *prim = &llc_ind_prim; struct llc_opt *llc = llc_sk(sk);
union llc_u_prim_data *prim_data = llc_ind_prim.data; struct llc_sap *sap = llc->sap;
struct llc_prim_if_block *prim = &sap->llc_ind_prim;
union llc_u_prim_data *prim_data = prim->data;
prim_data->data.sk = sk; prim_data->data.sk = sk;
prim_data->data.pri = 0; prim_data->data.pri = 0;
prim_data->data.skb = skb; prim_data->data.skb = skb;
prim_data->data.link = llc_sk(sk)->link; prim_data->data.link = llc->link;
prim->data = prim_data; prim->data = prim_data;
prim->prim = LLC_DATA_PRIM; prim->prim = LLC_DATA_PRIM;
prim->sap = llc_sk(sk)->sap; prim->sap = sap;
ev->flag = 1; ev->flag = 1;
/* saving prepd prim in event for future use in llc_conn_send_ev */ /* saving prepd prim in event for future use in llc_conn_send_ev */
ev->ind_prim = prim; ev->ind_prim = prim;
......
...@@ -56,7 +56,7 @@ int llc_stat_ev_ack_tmr_exp_eq_retry_cnt_max_retry(struct llc_station *station, ...@@ -56,7 +56,7 @@ int llc_stat_ev_ack_tmr_exp_eq_retry_cnt_max_retry(struct llc_station *station,
int llc_stat_ev_rx_null_dsap_xid_c(struct llc_station *station, int llc_stat_ev_rx_null_dsap_xid_c(struct llc_station *station,
struct llc_station_state_ev *ev) struct llc_station_state_ev *ev)
{ {
struct llc_pdu_un *pdu = (struct llc_pdu_un *)ev->data.pdu.skb->nh.raw; struct llc_pdu_un *pdu = llc_pdu_un_hdr(ev->data.pdu.skb);
return ev->type == LLC_STATION_EV_TYPE_PDU && return ev->type == LLC_STATION_EV_TYPE_PDU &&
!LLC_PDU_IS_CMD(pdu) && /* command PDU */ !LLC_PDU_IS_CMD(pdu) && /* command PDU */
...@@ -68,7 +68,7 @@ int llc_stat_ev_rx_null_dsap_xid_c(struct llc_station *station, ...@@ -68,7 +68,7 @@ int llc_stat_ev_rx_null_dsap_xid_c(struct llc_station *station,
int llc_stat_ev_rx_null_dsap_0_xid_r_xid_r_cnt_eq(struct llc_station *station, int llc_stat_ev_rx_null_dsap_0_xid_r_xid_r_cnt_eq(struct llc_station *station,
struct llc_station_state_ev *ev) struct llc_station_state_ev *ev)
{ {
struct llc_pdu_un *pdu = (struct llc_pdu_un *)ev->data.pdu.skb->nh.raw; struct llc_pdu_un *pdu = llc_pdu_un_hdr(ev->data.pdu.skb);
return ev->type == LLC_STATION_EV_TYPE_PDU && return ev->type == LLC_STATION_EV_TYPE_PDU &&
!LLC_PDU_IS_RSP(pdu) && /* response PDU */ !LLC_PDU_IS_RSP(pdu) && /* response PDU */
...@@ -81,7 +81,7 @@ int llc_stat_ev_rx_null_dsap_0_xid_r_xid_r_cnt_eq(struct llc_station *station, ...@@ -81,7 +81,7 @@ int llc_stat_ev_rx_null_dsap_0_xid_r_xid_r_cnt_eq(struct llc_station *station,
int llc_stat_ev_rx_null_dsap_1_xid_r_xid_r_cnt_eq(struct llc_station *station, int llc_stat_ev_rx_null_dsap_1_xid_r_xid_r_cnt_eq(struct llc_station *station,
struct llc_station_state_ev *ev) struct llc_station_state_ev *ev)
{ {
struct llc_pdu_un *pdu = (struct llc_pdu_un *)ev->data.pdu.skb->nh.raw; struct llc_pdu_un *pdu = llc_pdu_un_hdr(ev->data.pdu.skb);
return ev->type == LLC_STATION_EV_TYPE_PDU && return ev->type == LLC_STATION_EV_TYPE_PDU &&
!LLC_PDU_IS_RSP(pdu) && /* response PDU */ !LLC_PDU_IS_RSP(pdu) && /* response PDU */
...@@ -94,7 +94,7 @@ int llc_stat_ev_rx_null_dsap_1_xid_r_xid_r_cnt_eq(struct llc_station *station, ...@@ -94,7 +94,7 @@ int llc_stat_ev_rx_null_dsap_1_xid_r_xid_r_cnt_eq(struct llc_station *station,
int llc_stat_ev_rx_null_dsap_test_c(struct llc_station *station, int llc_stat_ev_rx_null_dsap_test_c(struct llc_station *station,
struct llc_station_state_ev *ev) struct llc_station_state_ev *ev)
{ {
struct llc_pdu_un *pdu = (struct llc_pdu_un *)ev->data.pdu.skb->nh.raw; struct llc_pdu_un *pdu = llc_pdu_un_hdr(ev->data.pdu.skb);
return ev->type == LLC_STATION_EV_TYPE_PDU && return ev->type == LLC_STATION_EV_TYPE_PDU &&
!LLC_PDU_IS_CMD(pdu) && /* command PDU */ !LLC_PDU_IS_CMD(pdu) && /* command PDU */
......
...@@ -41,12 +41,6 @@ static int llc_conn_rsp_handler(struct llc_prim_if_block *prim); ...@@ -41,12 +41,6 @@ static int llc_conn_rsp_handler(struct llc_prim_if_block *prim);
static int llc_rst_rsp_handler(struct llc_prim_if_block *prim); static int llc_rst_rsp_handler(struct llc_prim_if_block *prim);
static int llc_no_rsp_handler(struct llc_prim_if_block *prim); static int llc_no_rsp_handler(struct llc_prim_if_block *prim);
extern void llc_register_sap(unsigned char sap,
int (*rcvfunc)(struct sk_buff *skb,
struct net_device *dev,
struct packet_type *pt));
extern void llc_unregister_sap(unsigned char sap);
/* table of request handler functions */ /* table of request handler functions */
static llc_prim_call_t llc_req_prim[LLC_NBR_PRIMITIVES] = { static llc_prim_call_t llc_req_prim[LLC_NBR_PRIMITIVES] = {
[LLC_DATAUNIT_PRIM] = llc_unitdata_req_handler, [LLC_DATAUNIT_PRIM] = llc_unitdata_req_handler,
...@@ -105,7 +99,6 @@ struct llc_sap *llc_sap_open(llc_prim_call_t nw_indicate, ...@@ -105,7 +99,6 @@ struct llc_sap *llc_sap_open(llc_prim_call_t nw_indicate,
sap->parent_station = llc_station_get(); sap->parent_station = llc_station_get();
/* initialized SAP; add it to list of SAPs this station manages */ /* initialized SAP; add it to list of SAPs this station manages */
llc_sap_save(sap); llc_sap_save(sap);
llc_register_sap(lsap, mac_indicate);
out: out:
return sap; return sap;
err: err:
...@@ -122,7 +115,6 @@ struct llc_sap *llc_sap_open(llc_prim_call_t nw_indicate, ...@@ -122,7 +115,6 @@ struct llc_sap *llc_sap_open(llc_prim_call_t nw_indicate,
*/ */
void llc_sap_close(struct llc_sap *sap) void llc_sap_close(struct llc_sap *sap)
{ {
llc_unregister_sap(sap->laddr.lsap);
llc_free_sap(sap); llc_free_sap(sap);
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
} }
...@@ -141,7 +133,7 @@ static int llc_sap_req(struct llc_prim_if_block *prim) ...@@ -141,7 +133,7 @@ static int llc_sap_req(struct llc_prim_if_block *prim)
int rc = 1; int rc = 1;
if (prim->prim > 8 || prim->prim == 6) { if (prim->prim > 8 || prim->prim == 6) {
printk(KERN_ERR __FUNCTION__ ": invalid primitive %d\n", printk(KERN_ERR "%s: invalid primitive %d\n", __FUNCTION__,
prim->prim); prim->prim);
goto out; goto out;
} }
...@@ -338,7 +330,7 @@ static int llc_conn_req_handler(struct llc_prim_if_block *prim) ...@@ -338,7 +330,7 @@ static int llc_conn_req_handler(struct llc_prim_if_block *prim)
memcpy(laddr.mac, sdev->dev_addr, sizeof(laddr.mac)); memcpy(laddr.mac, sdev->dev_addr, sizeof(laddr.mac));
laddr.lsap = prim->data->conn.saddr.lsap; laddr.lsap = prim->data->conn.saddr.lsap;
memcpy(daddr.mac, ddev->dev_addr, sizeof(daddr.mac)); memcpy(daddr.mac, prim->data->conn.daddr.mac, sizeof(daddr.mac));
daddr.lsap = prim->data->conn.daddr.lsap; daddr.lsap = prim->data->conn.daddr.lsap;
sk = llc_find_sock(sap, &daddr, &laddr); sk = llc_find_sock(sap, &daddr, &laddr);
if (sk) { if (sk) {
......
...@@ -46,7 +46,7 @@ int mac_send_pdu(struct sk_buff *skb) ...@@ -46,7 +46,7 @@ int mac_send_pdu(struct sk_buff *skb)
int pri = GFP_ATOMIC, rc = -1; int pri = GFP_ATOMIC, rc = -1;
if (!skb->dev) { if (!skb->dev) {
printk(KERN_ERR __FUNCTION__ ": skb->dev == NULL!"); printk(KERN_ERR "%s: skb->dev == NULL!", __FUNCTION__);
goto out; goto out;
} }
if (skb->sk) if (skb->sk)
...@@ -83,27 +83,30 @@ int mac_indicate(struct sk_buff *skb, struct net_device *dev, ...@@ -83,27 +83,30 @@ int mac_indicate(struct sk_buff *skb, struct net_device *dev,
* receives, do not try to analyse it. * receives, do not try to analyse it.
*/ */
if (skb->pkt_type == PACKET_OTHERHOST) { if (skb->pkt_type == PACKET_OTHERHOST) {
printk(KERN_INFO __FUNCTION__ ": PACKET_OTHERHOST\n"); printk(KERN_INFO "%s: PACKET_OTHERHOST\n", __FUNCTION__);
goto drop; goto drop;
} }
skb = skb_share_check(skb, GFP_ATOMIC); skb = skb_share_check(skb, GFP_ATOMIC);
if (!skb) if (!skb)
goto out; goto out;
fix_up_incoming_skb(skb); fix_up_incoming_skb(skb);
pdu = (struct llc_pdu_sn *)skb->nh.raw; pdu = llc_pdu_sn_hdr(skb);
if (!pdu->dsap) { /* NULL DSAP, refer to station */ if (!pdu->dsap) { /* NULL DSAP, refer to station */
llc_pdu_router(NULL, NULL, skb, 0); if (llc_pdu_router(NULL, NULL, skb, 0))
goto drop;
goto out; goto out;
} }
sap = llc_sap_find(pdu->dsap); sap = llc_sap_find(pdu->dsap);
if (!sap) /* unknown SAP */ if (!sap) /* unknown SAP */
goto drop; goto drop;
llc_decode_pdu_type(skb, &dest); llc_decode_pdu_type(skb, &dest);
if (dest == LLC_DEST_SAP) /* type 1 services */ if (dest == LLC_DEST_SAP) { /* type 1 services */
llc_pdu_router(sap, NULL, skb, LLC_TYPE_1); if (llc_pdu_router(sap, NULL, skb, LLC_TYPE_1))
else if (dest == LLC_DEST_CONN) { goto drop;
} else if (dest == LLC_DEST_CONN) {
struct llc_addr saddr, daddr; struct llc_addr saddr, daddr;
struct sock *sk; struct sock *sk;
int rc;
llc_pdu_decode_sa(skb, saddr.mac); llc_pdu_decode_sa(skb, saddr.mac);
llc_pdu_decode_ssap(skb, &saddr.lsap); llc_pdu_decode_ssap(skb, &saddr.lsap);
...@@ -134,14 +137,17 @@ int mac_indicate(struct sk_buff *skb, struct net_device *dev, ...@@ -134,14 +137,17 @@ int mac_indicate(struct sk_buff *skb, struct net_device *dev,
* in the llc_req_prim (llc_data_req_handler, etc) and * in the llc_req_prim (llc_data_req_handler, etc) and
* add the request to the backlog, well see... * add the request to the backlog, well see...
*/ */
llc_pdu_router(llc_sk(sk)->sap, sk, skb, LLC_TYPE_2); rc = llc_pdu_router(llc_sk(sk)->sap, sk, skb,
bh_unlock_sock(sk); LLC_TYPE_2);
} else { } else {
skb->cb[0] = LLC_PACKET; skb->cb[0] = LLC_PACKET;
sk_add_backlog(sk, skb); sk_add_backlog(sk, skb);
bh_unlock_sock(sk); rc = 0;
} }
bh_unlock_sock(sk);
sock_put(sk); sock_put(sk);
if (rc)
goto drop;
} else /* unknown or not supported pdu */ } else /* unknown or not supported pdu */
goto drop; goto drop;
out: out:
...@@ -196,7 +202,7 @@ static void fix_up_incoming_skb(struct sk_buff *skb) ...@@ -196,7 +202,7 @@ static void fix_up_incoming_skb(struct sk_buff *skb)
int llc_pdu_router(struct llc_sap *sap, struct sock* sk, int llc_pdu_router(struct llc_sap *sap, struct sock* sk,
struct sk_buff *skb, u8 type) struct sk_buff *skb, u8 type)
{ {
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
int rc = 0; int rc = 0;
if (!pdu->dsap) { if (!pdu->dsap) {
...@@ -208,7 +214,8 @@ int llc_pdu_router(struct llc_sap *sap, struct sock* sk, ...@@ -208,7 +214,8 @@ int llc_pdu_router(struct llc_sap *sap, struct sock* sk,
stat_ev->data.pdu.skb = skb; stat_ev->data.pdu.skb = skb;
stat_ev->data.pdu.reason = 0; stat_ev->data.pdu.reason = 0;
llc_station_send_ev(station, stat_ev); llc_station_send_ev(station, stat_ev);
} } else
rc = -ENOMEM;
} else if (type == LLC_TYPE_1) { } else if (type == LLC_TYPE_1) {
struct llc_sap_state_ev *sap_ev = llc_sap_alloc_ev(sap); struct llc_sap_state_ev *sap_ev = llc_sap_alloc_ev(sap);
...@@ -217,7 +224,8 @@ int llc_pdu_router(struct llc_sap *sap, struct sock* sk, ...@@ -217,7 +224,8 @@ int llc_pdu_router(struct llc_sap *sap, struct sock* sk,
sap_ev->data.pdu.skb = skb; sap_ev->data.pdu.skb = skb;
sap_ev->data.pdu.reason = 0; sap_ev->data.pdu.reason = 0;
llc_sap_send_ev(sap, sap_ev); llc_sap_send_ev(sap, sap_ev);
} } else
rc = -ENOMEM;
} else if (type == LLC_TYPE_2) { } else if (type == LLC_TYPE_2) {
struct llc_conn_state_ev *conn_ev = llc_conn_alloc_ev(sk); struct llc_conn_state_ev *conn_ev = llc_conn_alloc_ev(sk);
struct llc_opt *llc = llc_sk(sk); struct llc_opt *llc = llc_sk(sk);
...@@ -229,8 +237,10 @@ int llc_pdu_router(struct llc_sap *sap, struct sock* sk, ...@@ -229,8 +237,10 @@ int llc_pdu_router(struct llc_sap *sap, struct sock* sk,
conn_ev->data.pdu.skb = skb; conn_ev->data.pdu.skb = skb;
conn_ev->data.pdu.reason = 0; conn_ev->data.pdu.reason = 0;
rc = llc_conn_send_ev(sk, conn_ev); rc = llc_conn_send_ev(sk, conn_ev);
} } else
} rc = -ENOMEM;
} else
rc = -EINVAL;
return rc; return rc;
} }
......
...@@ -50,15 +50,7 @@ static struct llc_station_state_trans * ...@@ -50,15 +50,7 @@ static struct llc_station_state_trans *
struct llc_station_state_ev *ev); struct llc_station_state_ev *ev);
static int llc_rtn_all_conns(struct llc_sap *sap); static int llc_rtn_all_conns(struct llc_sap *sap);
extern void llc_register_sap(unsigned char sap,
int (*rcvfunc)(struct sk_buff *skb,
struct net_device *dev,
struct packet_type *pt));
extern void llc_unregister_sap(unsigned char sap);
static struct llc_station llc_main_station; /* only one of its kind */ static struct llc_station llc_main_station; /* only one of its kind */
struct llc_prim_if_block llc_ind_prim, llc_cfm_prim;
static union llc_u_prim_data llc_ind_data_prim, llc_cfm_data_prim;
/** /**
* llc_sap_alloc - allocates and initializes sap. * llc_sap_alloc - allocates and initializes sap.
...@@ -76,6 +68,8 @@ struct llc_sap *llc_sap_alloc(void) ...@@ -76,6 +68,8 @@ struct llc_sap *llc_sap_alloc(void)
spin_lock_init(&sap->sk_list.lock); spin_lock_init(&sap->sk_list.lock);
INIT_LIST_HEAD(&sap->sk_list.list); INIT_LIST_HEAD(&sap->sk_list.list);
skb_queue_head_init(&sap->mac_pdu_q); skb_queue_head_init(&sap->mac_pdu_q);
sap->llc_ind_prim.data = &sap->llc_ind_data_prim;
sap->llc_cfm_prim.data = &sap->llc_cfm_data_prim;
} }
return sap; return sap;
} }
...@@ -238,7 +232,7 @@ void __llc_sock_free(struct sock *sk, u8 free) ...@@ -238,7 +232,7 @@ void __llc_sock_free(struct sock *sk, u8 free)
/* stop all (possibly) running timers */ /* stop all (possibly) running timers */
llc_conn_ac_stop_all_timers(sk, NULL); llc_conn_ac_stop_all_timers(sk, NULL);
/* handle return of frames on lists */ /* handle return of frames on lists */
printk(KERN_INFO __FUNCTION__ ": unackq=%d, txq=%d\n", printk(KERN_INFO "%s: unackq=%d, txq=%d\n", __FUNCTION__,
skb_queue_len(&llc->pdu_unack_q), skb_queue_len(&llc->pdu_unack_q),
skb_queue_len(&sk->write_queue)); skb_queue_len(&sk->write_queue));
skb_queue_purge(&sk->write_queue); skb_queue_purge(&sk->write_queue);
...@@ -580,6 +574,18 @@ static int llc_proc_get_info(char *bf, char **start, off_t offset, int length) ...@@ -580,6 +574,18 @@ static int llc_proc_get_info(char *bf, char **start, off_t offset, int length)
return len; return len;
} }
static struct packet_type llc_packet_type = {
.type = __constant_htons(ETH_P_802_2),
.func = mac_indicate,
.data = (void *)1,
};
static struct packet_type llc_tr_packet_type = {
.type = __constant_htons(ETH_P_TR_802_2),
.func = mac_indicate,
.data = (void *)1,
};
static char llc_banner[] __initdata = static char llc_banner[] __initdata =
KERN_INFO "LLC 2.0 by Procom, 1997, Arnaldo C. Melo, 2001\n" KERN_INFO "LLC 2.0 by Procom, 1997, Arnaldo C. Melo, 2001\n"
KERN_INFO "NET4.0 IEEE 802.2 extended support\n"; KERN_INFO "NET4.0 IEEE 802.2 extended support\n";
...@@ -612,12 +618,10 @@ static int __init llc_init(void) ...@@ -612,12 +618,10 @@ static int __init llc_init(void)
ev->type = LLC_STATION_EV_TYPE_SIMPLE; ev->type = LLC_STATION_EV_TYPE_SIMPLE;
ev->data.a.ev = LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK; ev->data.a.ev = LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK;
rc = llc_station_next_state(&llc_main_station, ev); rc = llc_station_next_state(&llc_main_station, ev);
llc_ind_prim.data = &llc_ind_data_prim;
llc_cfm_prim.data = &llc_cfm_data_prim;
proc_net_create("802.2", 0, llc_proc_get_info); proc_net_create("802.2", 0, llc_proc_get_info);
/* initialize the station component */
llc_register_sap(0, mac_indicate);
llc_ui_init(); llc_ui_init();
dev_add_pack(&llc_packet_type);
dev_add_pack(&llc_tr_packet_type);
out: out:
return rc; return rc;
err: err:
...@@ -629,7 +633,8 @@ static int __init llc_init(void) ...@@ -629,7 +633,8 @@ static int __init llc_init(void)
static void __exit llc_exit(void) static void __exit llc_exit(void)
{ {
llc_ui_exit(); llc_ui_exit();
llc_unregister_sap(0); dev_remove_pack(&llc_packet_type);
dev_remove_pack(&llc_tr_packet_type);
proc_net_remove("802.2"); proc_net_remove("802.2");
} }
......
...@@ -19,26 +19,23 @@ ...@@ -19,26 +19,23 @@
#include <net/llc_main.h> #include <net/llc_main.h>
static int llc_pdu_decode_pdu_type(struct sk_buff *skb, u8 *type); static int llc_pdu_decode_pdu_type(struct sk_buff *skb, u8 *type);
static int llc_get_llc_hdr_length(u8 pdu_type); static __inline__ int llc_get_hdr_len(u8 pdu_type);
static u8 llc_pdu_get_pf_bit(struct llc_pdu_sn *pdu); static u8 llc_pdu_get_pf_bit(struct llc_pdu_sn *pdu);
/** /**
* llc_pdu_header_init - initializes pdu header * llc_pdu_header_init - initializes pdu header
* @skb: input skb that header must be set into it. * @skb: input skb that header must be set into it.
* @pdu_type: type of PDU (U, I or S). * @type: type of PDU (U, I or S).
* @ssap: source sap. * @ssap: source sap.
* @dsap: destination sap. * @dsap: destination sap.
* @cr: command/response bit (0 or 1). * @cr: command/response bit (0 or 1).
* *
* This function sets DSAP, SSAP and command/Response bit in LLC header. * This function sets DSAP, SSAP and command/Response bit in LLC header.
*/ */
void llc_pdu_header_init(struct sk_buff *skb, u8 pdu_type, u8 ssap, void llc_pdu_header_init(struct sk_buff *skb, u8 type, u8 ssap, u8 dsap, u8 cr)
u8 dsap, u8 cr)
{ {
struct llc_pdu_un *pdu; struct llc_pdu_un *pdu =
llc_set_pdu_hdr(skb, skb_push(skb, llc_get_hdr_len(type)));
skb->nh.raw = skb_push(skb, llc_get_llc_hdr_length(pdu_type));
pdu = (struct llc_pdu_un *)skb->nh.raw;
pdu->dsap = dsap; pdu->dsap = dsap;
pdu->ssap = ssap; pdu->ssap = ssap;
pdu->ssap |= cr; pdu->ssap |= cr;
...@@ -46,7 +43,7 @@ void llc_pdu_header_init(struct sk_buff *skb, u8 pdu_type, u8 ssap, ...@@ -46,7 +43,7 @@ void llc_pdu_header_init(struct sk_buff *skb, u8 pdu_type, u8 ssap,
void llc_pdu_set_cmd_rsp(struct sk_buff *skb, u8 pdu_type) void llc_pdu_set_cmd_rsp(struct sk_buff *skb, u8 pdu_type)
{ {
((struct llc_pdu_un *)skb->nh.raw)->ssap |= pdu_type; llc_pdu_un_hdr(skb)->ssap |= pdu_type;
} }
/** /**
...@@ -66,7 +63,7 @@ void llc_pdu_set_pf_bit(struct sk_buff *skb, u8 bit_value) ...@@ -66,7 +63,7 @@ void llc_pdu_set_pf_bit(struct sk_buff *skb, u8 bit_value)
if (llc_pdu_decode_pdu_type(skb, &pdu_type)) if (llc_pdu_decode_pdu_type(skb, &pdu_type))
goto out; goto out;
pdu = (struct llc_pdu_sn *)skb->nh.raw; pdu = llc_pdu_sn_hdr(skb);
switch (pdu_type) { switch (pdu_type) {
case LLC_PDU_TYPE_I: case LLC_PDU_TYPE_I:
...@@ -98,7 +95,7 @@ int llc_pdu_decode_pf_bit(struct sk_buff *skb, u8 *pf_bit) ...@@ -98,7 +95,7 @@ int llc_pdu_decode_pf_bit(struct sk_buff *skb, u8 *pf_bit)
if (rc) if (rc)
goto out; goto out;
pdu = (struct llc_pdu_sn *)skb->nh.raw; pdu = llc_pdu_sn_hdr(skb);
switch (pdu_type) { switch (pdu_type) {
case LLC_PDU_TYPE_I: case LLC_PDU_TYPE_I:
...@@ -123,8 +120,7 @@ int llc_pdu_decode_pf_bit(struct sk_buff *skb, u8 *pf_bit) ...@@ -123,8 +120,7 @@ int llc_pdu_decode_pf_bit(struct sk_buff *skb, u8 *pf_bit)
*/ */
int llc_pdu_decode_cr_bit(struct sk_buff *skb, u8 *cr_bit) int llc_pdu_decode_cr_bit(struct sk_buff *skb, u8 *cr_bit)
{ {
*cr_bit = ((struct llc_pdu_un *)skb->nh.raw)->ssap & *cr_bit = llc_pdu_un_hdr(skb)->ssap & LLC_PDU_CMD_RSP_MASK;
LLC_PDU_CMD_RSP_MASK;
return 0; return 0;
} }
...@@ -170,7 +166,7 @@ int llc_pdu_decode_da(struct sk_buff *skb, u8 *da) ...@@ -170,7 +166,7 @@ int llc_pdu_decode_da(struct sk_buff *skb, u8 *da)
*/ */
int llc_pdu_decode_dsap(struct sk_buff *skb, u8 *dsap) int llc_pdu_decode_dsap(struct sk_buff *skb, u8 *dsap)
{ {
*dsap = ((struct llc_pdu_un *)skb->nh.raw)->dsap & 0xFE; *dsap = llc_pdu_un_hdr(skb)->dsap & 0xFE;
return 0; return 0;
} }
...@@ -184,7 +180,7 @@ int llc_pdu_decode_dsap(struct sk_buff *skb, u8 *dsap) ...@@ -184,7 +180,7 @@ int llc_pdu_decode_dsap(struct sk_buff *skb, u8 *dsap)
*/ */
int llc_pdu_decode_ssap(struct sk_buff *skb, u8 *ssap) int llc_pdu_decode_ssap(struct sk_buff *skb, u8 *ssap)
{ {
*ssap = ((struct llc_pdu_un *)skb->nh.raw)->ssap & 0xFE; *ssap = llc_pdu_un_hdr(skb)->ssap & 0xFE;
return 0; return 0;
} }
...@@ -196,7 +192,7 @@ int llc_pdu_decode_ssap(struct sk_buff *skb, u8 *ssap) ...@@ -196,7 +192,7 @@ int llc_pdu_decode_ssap(struct sk_buff *skb, u8 *ssap)
*/ */
int llc_pdu_init_as_ui_cmd(struct sk_buff *skb) int llc_pdu_init_as_ui_cmd(struct sk_buff *skb)
{ {
struct llc_pdu_un *pdu = (struct llc_pdu_un *)skb->nh.raw; struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
pdu->ctrl_1 = LLC_PDU_TYPE_U; pdu->ctrl_1 = LLC_PDU_TYPE_U;
pdu->ctrl_1 |= LLC_1_PDU_CMD_UI; pdu->ctrl_1 |= LLC_1_PDU_CMD_UI;
...@@ -214,7 +210,7 @@ int llc_pdu_init_as_xid_cmd(struct sk_buff *skb, u8 svcs_supported, ...@@ -214,7 +210,7 @@ int llc_pdu_init_as_xid_cmd(struct sk_buff *skb, u8 svcs_supported,
u8 rx_window) u8 rx_window)
{ {
struct llc_xid_info *xid_info; struct llc_xid_info *xid_info;
struct llc_pdu_un *pdu = (struct llc_pdu_un *)skb->nh.raw; struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
pdu->ctrl_1 = LLC_PDU_TYPE_U; pdu->ctrl_1 = LLC_PDU_TYPE_U;
pdu->ctrl_1 |= LLC_1_PDU_CMD_XID; pdu->ctrl_1 |= LLC_1_PDU_CMD_XID;
...@@ -235,7 +231,7 @@ int llc_pdu_init_as_xid_cmd(struct sk_buff *skb, u8 svcs_supported, ...@@ -235,7 +231,7 @@ int llc_pdu_init_as_xid_cmd(struct sk_buff *skb, u8 svcs_supported,
*/ */
int llc_pdu_init_as_test_cmd(struct sk_buff *skb) int llc_pdu_init_as_test_cmd(struct sk_buff *skb)
{ {
struct llc_pdu_un *pdu = (struct llc_pdu_un *)skb->nh.raw; struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
pdu->ctrl_1 = LLC_PDU_TYPE_U; pdu->ctrl_1 = LLC_PDU_TYPE_U;
pdu->ctrl_1 |= LLC_1_PDU_CMD_TEST; pdu->ctrl_1 |= LLC_1_PDU_CMD_TEST;
...@@ -252,7 +248,7 @@ int llc_pdu_init_as_test_cmd(struct sk_buff *skb) ...@@ -252,7 +248,7 @@ int llc_pdu_init_as_test_cmd(struct sk_buff *skb)
*/ */
int llc_pdu_init_as_disc_cmd(struct sk_buff *skb, u8 p_bit) int llc_pdu_init_as_disc_cmd(struct sk_buff *skb, u8 p_bit)
{ {
struct llc_pdu_un *pdu = (struct llc_pdu_un *)skb->nh.raw; struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
pdu->ctrl_1 = LLC_PDU_TYPE_U; pdu->ctrl_1 = LLC_PDU_TYPE_U;
pdu->ctrl_1 |= LLC_2_PDU_CMD_DISC; pdu->ctrl_1 |= LLC_2_PDU_CMD_DISC;
...@@ -271,7 +267,7 @@ int llc_pdu_init_as_disc_cmd(struct sk_buff *skb, u8 p_bit) ...@@ -271,7 +267,7 @@ int llc_pdu_init_as_disc_cmd(struct sk_buff *skb, u8 p_bit)
*/ */
int llc_pdu_init_as_i_cmd(struct sk_buff *skb, u8 p_bit, u8 ns, u8 nr) int llc_pdu_init_as_i_cmd(struct sk_buff *skb, u8 p_bit, u8 ns, u8 nr)
{ {
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
pdu->ctrl_1 = LLC_PDU_TYPE_I; pdu->ctrl_1 = LLC_PDU_TYPE_I;
pdu->ctrl_2 = 0; pdu->ctrl_2 = 0;
...@@ -291,7 +287,7 @@ int llc_pdu_init_as_i_cmd(struct sk_buff *skb, u8 p_bit, u8 ns, u8 nr) ...@@ -291,7 +287,7 @@ int llc_pdu_init_as_i_cmd(struct sk_buff *skb, u8 p_bit, u8 ns, u8 nr)
*/ */
int llc_pdu_init_as_rej_cmd(struct sk_buff *skb, u8 p_bit, u8 nr) int llc_pdu_init_as_rej_cmd(struct sk_buff *skb, u8 p_bit, u8 nr)
{ {
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
pdu->ctrl_1 = LLC_PDU_TYPE_S; pdu->ctrl_1 = LLC_PDU_TYPE_S;
pdu->ctrl_1 |= LLC_2_PDU_CMD_REJ; pdu->ctrl_1 |= LLC_2_PDU_CMD_REJ;
...@@ -312,7 +308,7 @@ int llc_pdu_init_as_rej_cmd(struct sk_buff *skb, u8 p_bit, u8 nr) ...@@ -312,7 +308,7 @@ int llc_pdu_init_as_rej_cmd(struct sk_buff *skb, u8 p_bit, u8 nr)
*/ */
int llc_pdu_init_as_rnr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr) int llc_pdu_init_as_rnr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr)
{ {
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
pdu->ctrl_1 = LLC_PDU_TYPE_S; pdu->ctrl_1 = LLC_PDU_TYPE_S;
pdu->ctrl_1 |= LLC_2_PDU_CMD_RNR; pdu->ctrl_1 |= LLC_2_PDU_CMD_RNR;
...@@ -333,7 +329,7 @@ int llc_pdu_init_as_rnr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr) ...@@ -333,7 +329,7 @@ int llc_pdu_init_as_rnr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr)
*/ */
int llc_pdu_init_as_rr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr) int llc_pdu_init_as_rr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr)
{ {
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
pdu->ctrl_1 = LLC_PDU_TYPE_S; pdu->ctrl_1 = LLC_PDU_TYPE_S;
pdu->ctrl_1 |= LLC_2_PDU_CMD_RR; pdu->ctrl_1 |= LLC_2_PDU_CMD_RR;
...@@ -352,7 +348,7 @@ int llc_pdu_init_as_rr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr) ...@@ -352,7 +348,7 @@ int llc_pdu_init_as_rr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr)
*/ */
int llc_pdu_init_as_sabme_cmd(struct sk_buff *skb, u8 p_bit) int llc_pdu_init_as_sabme_cmd(struct sk_buff *skb, u8 p_bit)
{ {
struct llc_pdu_un *pdu = (struct llc_pdu_un *)skb->nh.raw; struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
pdu->ctrl_1 = LLC_PDU_TYPE_U; pdu->ctrl_1 = LLC_PDU_TYPE_U;
pdu->ctrl_1 |= LLC_2_PDU_CMD_SABME; pdu->ctrl_1 |= LLC_2_PDU_CMD_SABME;
...@@ -369,7 +365,7 @@ int llc_pdu_init_as_sabme_cmd(struct sk_buff *skb, u8 p_bit) ...@@ -369,7 +365,7 @@ int llc_pdu_init_as_sabme_cmd(struct sk_buff *skb, u8 p_bit)
*/ */
int llc_pdu_init_as_dm_rsp(struct sk_buff *skb, u8 f_bit) int llc_pdu_init_as_dm_rsp(struct sk_buff *skb, u8 f_bit)
{ {
struct llc_pdu_un *pdu = (struct llc_pdu_un *)skb->nh.raw; struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
pdu->ctrl_1 = LLC_PDU_TYPE_U; pdu->ctrl_1 = LLC_PDU_TYPE_U;
pdu->ctrl_1 |= LLC_2_PDU_RSP_DM; pdu->ctrl_1 |= LLC_2_PDU_RSP_DM;
...@@ -389,7 +385,7 @@ int llc_pdu_init_as_xid_rsp(struct sk_buff *skb, u8 svcs_supported, ...@@ -389,7 +385,7 @@ int llc_pdu_init_as_xid_rsp(struct sk_buff *skb, u8 svcs_supported,
u8 rx_window) u8 rx_window)
{ {
struct llc_xid_info *xid_info; struct llc_xid_info *xid_info;
struct llc_pdu_un *pdu = (struct llc_pdu_un *)skb->nh.raw; struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
pdu->ctrl_1 = LLC_PDU_TYPE_U; pdu->ctrl_1 = LLC_PDU_TYPE_U;
pdu->ctrl_1 |= LLC_1_PDU_CMD_XID; pdu->ctrl_1 |= LLC_1_PDU_CMD_XID;
...@@ -413,15 +409,16 @@ int llc_pdu_init_as_xid_rsp(struct sk_buff *skb, u8 svcs_supported, ...@@ -413,15 +409,16 @@ int llc_pdu_init_as_xid_rsp(struct sk_buff *skb, u8 svcs_supported,
int llc_pdu_init_as_test_rsp(struct sk_buff *skb, struct sk_buff *ev_skb) int llc_pdu_init_as_test_rsp(struct sk_buff *skb, struct sk_buff *ev_skb)
{ {
int dsize; int dsize;
struct llc_pdu_un *pdu = (struct llc_pdu_un *)skb->nh.raw; struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
pdu->ctrl_1 = LLC_PDU_TYPE_U; pdu->ctrl_1 = LLC_PDU_TYPE_U;
pdu->ctrl_1 |= LLC_1_PDU_CMD_TEST; pdu->ctrl_1 |= LLC_1_PDU_CMD_TEST;
pdu->ctrl_1 |= LLC_U_PF_BIT_MASK; pdu->ctrl_1 |= LLC_U_PF_BIT_MASK;
if (ev_skb->protocol == ntohs(ETH_P_802_2)) { if (ev_skb->protocol == ntohs(ETH_P_802_2)) {
struct llc_pdu_un *ev_pdu = llc_pdu_un_hdr(ev_skb);
dsize = ntohs(((struct ethhdr *)ev_skb->mac.raw)->h_proto) - 3; dsize = ntohs(((struct ethhdr *)ev_skb->mac.raw)->h_proto) - 3;
memcpy(((u8 *)skb->nh.raw) + 3, memcpy(((u8 *)pdu) + 3, ((u8 *)ev_pdu) + 3, dsize);
((u8 *)ev_skb->nh.raw) + 3, dsize);
skb_put(skb, dsize); skb_put(skb, dsize);
} }
return 0; return 0;
...@@ -444,7 +441,7 @@ int llc_pdu_init_as_frmr_rsp(struct sk_buff *skb, struct llc_pdu_sn *prev_pdu, ...@@ -444,7 +441,7 @@ int llc_pdu_init_as_frmr_rsp(struct sk_buff *skb, struct llc_pdu_sn *prev_pdu,
struct llc_frmr_info *frmr_info; struct llc_frmr_info *frmr_info;
u8 prev_pf = 0; u8 prev_pf = 0;
u8 *ctrl; u8 *ctrl;
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
pdu->ctrl_1 = LLC_PDU_TYPE_U; pdu->ctrl_1 = LLC_PDU_TYPE_U;
pdu->ctrl_1 |= LLC_2_PDU_RSP_FRMR; pdu->ctrl_1 |= LLC_2_PDU_RSP_FRMR;
...@@ -476,7 +473,7 @@ int llc_pdu_init_as_frmr_rsp(struct sk_buff *skb, struct llc_pdu_sn *prev_pdu, ...@@ -476,7 +473,7 @@ int llc_pdu_init_as_frmr_rsp(struct sk_buff *skb, struct llc_pdu_sn *prev_pdu,
*/ */
int llc_pdu_init_as_rr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr) int llc_pdu_init_as_rr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr)
{ {
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
pdu->ctrl_1 = LLC_PDU_TYPE_S; pdu->ctrl_1 = LLC_PDU_TYPE_S;
pdu->ctrl_1 |= LLC_2_PDU_RSP_RR; pdu->ctrl_1 |= LLC_2_PDU_RSP_RR;
...@@ -497,7 +494,7 @@ int llc_pdu_init_as_rr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr) ...@@ -497,7 +494,7 @@ int llc_pdu_init_as_rr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr)
*/ */
int llc_pdu_init_as_rej_rsp(struct sk_buff *skb, u8 f_bit, u8 nr) int llc_pdu_init_as_rej_rsp(struct sk_buff *skb, u8 f_bit, u8 nr)
{ {
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
pdu->ctrl_1 = LLC_PDU_TYPE_S; pdu->ctrl_1 = LLC_PDU_TYPE_S;
pdu->ctrl_1 |= LLC_2_PDU_RSP_REJ; pdu->ctrl_1 |= LLC_2_PDU_RSP_REJ;
...@@ -518,7 +515,7 @@ int llc_pdu_init_as_rej_rsp(struct sk_buff *skb, u8 f_bit, u8 nr) ...@@ -518,7 +515,7 @@ int llc_pdu_init_as_rej_rsp(struct sk_buff *skb, u8 f_bit, u8 nr)
*/ */
int llc_pdu_init_as_rnr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr) int llc_pdu_init_as_rnr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr)
{ {
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
pdu->ctrl_1 = LLC_PDU_TYPE_S; pdu->ctrl_1 = LLC_PDU_TYPE_S;
pdu->ctrl_1 |= LLC_2_PDU_RSP_RNR; pdu->ctrl_1 |= LLC_2_PDU_RSP_RNR;
...@@ -538,7 +535,7 @@ int llc_pdu_init_as_rnr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr) ...@@ -538,7 +535,7 @@ int llc_pdu_init_as_rnr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr)
*/ */
int llc_pdu_init_as_ua_rsp(struct sk_buff *skb, u8 f_bit) int llc_pdu_init_as_ua_rsp(struct sk_buff *skb, u8 f_bit)
{ {
struct llc_pdu_un *pdu = (struct llc_pdu_un *)skb->nh.raw; struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
pdu->ctrl_1 = LLC_PDU_TYPE_U; pdu->ctrl_1 = LLC_PDU_TYPE_U;
pdu->ctrl_1 |= LLC_2_PDU_RSP_UA; pdu->ctrl_1 |= LLC_2_PDU_RSP_UA;
...@@ -555,7 +552,7 @@ int llc_pdu_init_as_ua_rsp(struct sk_buff *skb, u8 f_bit) ...@@ -555,7 +552,7 @@ int llc_pdu_init_as_ua_rsp(struct sk_buff *skb, u8 f_bit)
*/ */
static int llc_pdu_decode_pdu_type(struct sk_buff *skb, u8 *type) static int llc_pdu_decode_pdu_type(struct sk_buff *skb, u8 *type)
{ {
struct llc_pdu_un *pdu = (struct llc_pdu_un *)skb->nh.raw; struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
if (pdu->ctrl_1 & 1) { if (pdu->ctrl_1 & 1) {
if ((pdu->ctrl_1 & LLC_PDU_TYPE_U) == LLC_PDU_TYPE_U) if ((pdu->ctrl_1 & LLC_PDU_TYPE_U) == LLC_PDU_TYPE_U)
...@@ -577,7 +574,7 @@ static int llc_pdu_decode_pdu_type(struct sk_buff *skb, u8 *type) ...@@ -577,7 +574,7 @@ static int llc_pdu_decode_pdu_type(struct sk_buff *skb, u8 *type)
int llc_decode_pdu_type(struct sk_buff *skb, u8 *dest) int llc_decode_pdu_type(struct sk_buff *skb, u8 *dest)
{ {
u8 type = LLC_DEST_CONN; /* I-PDU or S-PDU type */ u8 type = LLC_DEST_CONN; /* I-PDU or S-PDU type */
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)skb->nh.raw; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
if ((pdu->ctrl_1 & LLC_PDU_TYPE_MASK) != LLC_PDU_TYPE_U) if ((pdu->ctrl_1 & LLC_PDU_TYPE_MASK) != LLC_PDU_TYPE_U)
goto out; goto out;
...@@ -603,26 +600,21 @@ int llc_decode_pdu_type(struct sk_buff *skb, u8 *dest) ...@@ -603,26 +600,21 @@ int llc_decode_pdu_type(struct sk_buff *skb, u8 *dest)
} }
/** /**
* get_llc_hdr_len - designates LLC header length * llc_get_hdr_len - designates LLC header length
* @pdu_type: type of PDU. * @type: type of PDU.
* *
* This function designates LLC header length of PDU. header length for I * This function designates LLC header length of PDU. header length for I
* and S PDU is 4 and for U is 3 bytes. Returns the length of header. * and S PDU is 4 and for U is 3 bytes. Returns the length of header.
*/ */
static int llc_get_llc_hdr_length(u8 pdu_type) static __inline__ int llc_get_hdr_len(u8 type)
{ {
int rtn_val = 0; static int hdr_len[] = {
[LLC_PDU_TYPE_U] = 3,
[LLC_PDU_TYPE_I] = 4,
[LLC_PDU_TYPE_S] = 4,
};
switch (pdu_type) { return hdr_len[type];
case LLC_PDU_TYPE_I:
case LLC_PDU_TYPE_S:
rtn_val = 4;
break;
case LLC_PDU_TYPE_U:
rtn_val = 3;
break;
}
return rtn_val;
} }
/** /**
......
...@@ -28,7 +28,7 @@ int llc_sap_ev_activation_req(struct llc_sap *sap, struct llc_sap_state_ev *ev) ...@@ -28,7 +28,7 @@ int llc_sap_ev_activation_req(struct llc_sap *sap, struct llc_sap_state_ev *ev)
int llc_sap_ev_rx_ui(struct llc_sap *sap, struct llc_sap_state_ev *ev) int llc_sap_ev_rx_ui(struct llc_sap *sap, struct llc_sap_state_ev *ev)
{ {
struct llc_pdu_un *pdu = (struct llc_pdu_un *)ev->data.pdu.skb->nh.raw; struct llc_pdu_un *pdu = llc_pdu_un_hdr(ev->data.pdu.skb);
return ev->type == LLC_SAP_EV_TYPE_PDU && !LLC_PDU_IS_CMD(pdu) && return ev->type == LLC_SAP_EV_TYPE_PDU && !LLC_PDU_IS_CMD(pdu) &&
!LLC_PDU_TYPE_IS_U(pdu) && !LLC_PDU_TYPE_IS_U(pdu) &&
...@@ -52,7 +52,7 @@ int llc_sap_ev_xid_req(struct llc_sap *sap, struct llc_sap_state_ev *ev) ...@@ -52,7 +52,7 @@ int llc_sap_ev_xid_req(struct llc_sap *sap, struct llc_sap_state_ev *ev)
int llc_sap_ev_rx_xid_c(struct llc_sap *sap, struct llc_sap_state_ev *ev) int llc_sap_ev_rx_xid_c(struct llc_sap *sap, struct llc_sap_state_ev *ev)
{ {
struct llc_pdu_un *pdu = (struct llc_pdu_un *)ev->data.pdu.skb->nh.raw; struct llc_pdu_un *pdu = llc_pdu_un_hdr(ev->data.pdu.skb);
return ev->type == LLC_SAP_EV_TYPE_PDU && !LLC_PDU_IS_CMD(pdu) && return ev->type == LLC_SAP_EV_TYPE_PDU && !LLC_PDU_IS_CMD(pdu) &&
!LLC_PDU_TYPE_IS_U(pdu) && !LLC_PDU_TYPE_IS_U(pdu) &&
...@@ -61,7 +61,7 @@ int llc_sap_ev_rx_xid_c(struct llc_sap *sap, struct llc_sap_state_ev *ev) ...@@ -61,7 +61,7 @@ int llc_sap_ev_rx_xid_c(struct llc_sap *sap, struct llc_sap_state_ev *ev)
int llc_sap_ev_rx_xid_r(struct llc_sap *sap, struct llc_sap_state_ev *ev) int llc_sap_ev_rx_xid_r(struct llc_sap *sap, struct llc_sap_state_ev *ev)
{ {
struct llc_pdu_un *pdu = (struct llc_pdu_un *)ev->data.pdu.skb->nh.raw; struct llc_pdu_un *pdu = llc_pdu_un_hdr(ev->data.pdu.skb);
return ev->type == LLC_SAP_EV_TYPE_PDU && !LLC_PDU_IS_RSP(pdu) && return ev->type == LLC_SAP_EV_TYPE_PDU && !LLC_PDU_IS_RSP(pdu) &&
!LLC_PDU_TYPE_IS_U(pdu) && !LLC_PDU_TYPE_IS_U(pdu) &&
...@@ -77,7 +77,7 @@ int llc_sap_ev_test_req(struct llc_sap *sap, struct llc_sap_state_ev *ev) ...@@ -77,7 +77,7 @@ int llc_sap_ev_test_req(struct llc_sap *sap, struct llc_sap_state_ev *ev)
int llc_sap_ev_rx_test_c(struct llc_sap *sap, struct llc_sap_state_ev *ev) int llc_sap_ev_rx_test_c(struct llc_sap *sap, struct llc_sap_state_ev *ev)
{ {
struct llc_pdu_un *pdu = (struct llc_pdu_un *)ev->data.pdu.skb->nh.raw; struct llc_pdu_un *pdu = llc_pdu_un_hdr(ev->data.pdu.skb);
return ev->type == LLC_SAP_EV_TYPE_PDU && !LLC_PDU_IS_CMD(pdu) && return ev->type == LLC_SAP_EV_TYPE_PDU && !LLC_PDU_IS_CMD(pdu) &&
!LLC_PDU_TYPE_IS_U(pdu) && !LLC_PDU_TYPE_IS_U(pdu) &&
...@@ -86,7 +86,7 @@ int llc_sap_ev_rx_test_c(struct llc_sap *sap, struct llc_sap_state_ev *ev) ...@@ -86,7 +86,7 @@ int llc_sap_ev_rx_test_c(struct llc_sap *sap, struct llc_sap_state_ev *ev)
int llc_sap_ev_rx_test_r(struct llc_sap *sap, struct llc_sap_state_ev *ev) int llc_sap_ev_rx_test_r(struct llc_sap *sap, struct llc_sap_state_ev *ev)
{ {
struct llc_pdu_un *pdu = (struct llc_pdu_un *)ev->data.pdu.skb->nh.raw; struct llc_pdu_un *pdu = llc_pdu_un_hdr(ev->data.pdu.skb);
return ev->type == LLC_SAP_EV_TYPE_PDU && !LLC_PDU_IS_RSP(pdu) && return ev->type == LLC_SAP_EV_TYPE_PDU && !LLC_PDU_IS_RSP(pdu) &&
!LLC_PDU_TYPE_IS_U(pdu) && !LLC_PDU_TYPE_IS_U(pdu) &&
......
...@@ -89,15 +89,10 @@ struct llc_sap_state_ev *llc_sap_alloc_ev(struct llc_sap *sap) ...@@ -89,15 +89,10 @@ struct llc_sap_state_ev *llc_sap_alloc_ev(struct llc_sap *sap)
*/ */
void llc_sap_send_ev(struct llc_sap *sap, struct llc_sap_state_ev *ev) void llc_sap_send_ev(struct llc_sap *sap, struct llc_sap_state_ev *ev)
{ {
struct llc_prim_if_block *prim;
u8 flag;
llc_sap_next_state(sap, ev); llc_sap_next_state(sap, ev);
flag = ev->ind_cfm_flag; if (ev->ind_cfm_flag == LLC_IND) {
prim = ev->prim;
if (flag == LLC_IND) {
skb_get(ev->data.pdu.skb); skb_get(ev->data.pdu.skb);
sap->ind(prim); sap->ind(ev->prim);
} }
llc_sap_free_ev(sap, ev); llc_sap_free_ev(sap, ev);
} }
...@@ -112,8 +107,8 @@ void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb, ...@@ -112,8 +107,8 @@ void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb,
struct llc_sap_state_ev *ev) struct llc_sap_state_ev *ev)
{ {
struct llc_pdu_un *pdu; struct llc_pdu_un *pdu;
struct llc_prim_if_block *prim = &llc_ind_prim; struct llc_prim_if_block *prim = &sap->llc_ind_prim;
union llc_u_prim_data *prim_data = llc_ind_prim.data; union llc_u_prim_data *prim_data = prim->data;
u8 lfb; u8 lfb;
llc_pdu_decode_sa(skb, prim_data->udata.saddr.mac); llc_pdu_decode_sa(skb, prim_data->udata.saddr.mac);
...@@ -122,7 +117,7 @@ void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb, ...@@ -122,7 +117,7 @@ void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb,
llc_pdu_decode_ssap(skb, &prim_data->udata.saddr.lsap); llc_pdu_decode_ssap(skb, &prim_data->udata.saddr.lsap);
prim_data->udata.pri = 0; prim_data->udata.pri = 0;
prim_data->udata.skb = skb; prim_data->udata.skb = skb;
pdu = (struct llc_pdu_un *)skb->nh.raw; pdu = llc_pdu_un_hdr(skb);
switch (LLC_U_PDU_RSP(pdu)) { switch (LLC_U_PDU_RSP(pdu)) {
case LLC_1_PDU_CMD_TEST: case LLC_1_PDU_CMD_TEST:
prim->prim = LLC_TEST_PRIM; prim->prim = LLC_TEST_PRIM;
...@@ -169,13 +164,8 @@ void llc_sap_send_pdu(struct llc_sap *sap, struct sk_buff *skb) ...@@ -169,13 +164,8 @@ void llc_sap_send_pdu(struct llc_sap *sap, struct sk_buff *skb)
*/ */
static void llc_sap_free_ev(struct llc_sap *sap, struct llc_sap_state_ev *ev) static void llc_sap_free_ev(struct llc_sap *sap, struct llc_sap_state_ev *ev)
{ {
if (ev->type == LLC_SAP_EV_TYPE_PDU) { if (ev->type == LLC_SAP_EV_TYPE_PDU)
struct llc_pdu_un *pdu = kfree_skb(ev->data.pdu.skb);
(struct llc_pdu_un *)ev->data.pdu.skb->nh.raw;
if (LLC_U_PDU_CMD(pdu) != LLC_1_PDU_CMD_UI)
kfree_skb(ev->data.pdu.skb);
}
kfree(ev); kfree(ev);
} }
......
...@@ -43,8 +43,6 @@ ...@@ -43,8 +43,6 @@
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include <linux/init.h> #include <linux/init.h>
#define dprintk(format, a...) printk(KERN_INFO __FUNCTION__ ": " format, ##a)
/* remember: uninitialized global data is zeroed because its in .bss */ /* remember: uninitialized global data is zeroed because its in .bss */
static u16 llc_ui_sap_last_autoport = LLC_SAP_DYN_START; static u16 llc_ui_sap_last_autoport = LLC_SAP_DYN_START;
static u16 llc_ui_sap_link_no_max[256]; static u16 llc_ui_sap_link_no_max[256];
...@@ -527,8 +525,6 @@ static int llc_ui_release(struct socket *sock) ...@@ -527,8 +525,6 @@ static int llc_ui_release(struct socket *sock)
llc_ui_remove_socket(sk); llc_ui_remove_socket(sk);
if (llc_ui->sap && !llc_ui_find_sap(llc_ui->sap->laddr.lsap)) if (llc_ui->sap && !llc_ui_find_sap(llc_ui->sap->laddr.lsap))
llc_sap_close(llc_ui->sap); llc_sap_close(llc_ui->sap);
dprintk("rxq=%d, txq=%d\n", skb_queue_len(&sk->receive_queue),
skb_queue_len(&sk->write_queue));
sock_orphan(sk); sock_orphan(sk);
sock->sk = NULL; sock->sk = NULL;
if (!atomic_read(&sk->wmem_alloc) && if (!atomic_read(&sk->wmem_alloc) &&
...@@ -1416,10 +1412,8 @@ static void llc_ui_ind_conn(struct llc_prim_if_block *prim) ...@@ -1416,10 +1412,8 @@ static void llc_ui_ind_conn(struct llc_prim_if_block *prim)
llc_sk(prim_data->sk)->laddr.lsap = prim->sap->laddr.lsap; llc_sk(prim_data->sk)->laddr.lsap = prim->sap->laddr.lsap;
sk = llc_ui_find_sk_by_addr(&llc_sk(prim_data->sk)->laddr, sk = llc_ui_find_sk_by_addr(&llc_sk(prim_data->sk)->laddr,
&prim_data->saddr, prim_data->dev); &prim_data->saddr, prim_data->dev);
if (!sk) { if (!sk)
dprintk("llc_ui_find_sk_by_addr failed\n");
goto out; goto out;
}
if (sk->type != SOCK_STREAM || sk->state != TCP_LISTEN) if (sk->type != SOCK_STREAM || sk->state != TCP_LISTEN)
goto out_put; goto out_put;
if (prim->data->conn.status) if (prim->data->conn.status)
...@@ -1469,10 +1463,8 @@ static void llc_ui_ind_data(struct llc_prim_if_block *prim) ...@@ -1469,10 +1463,8 @@ static void llc_ui_ind_data(struct llc_prim_if_block *prim)
memcpy(llc_ui->sllc_smac, llc_sk(prim_data->sk)->daddr.mac, memcpy(llc_ui->sllc_smac, llc_sk(prim_data->sk)->daddr.mac,
IFHWADDRLEN); IFHWADDRLEN);
/* queue skb to the user. */ /* queue skb to the user. */
if (sock_queue_rcv_skb(sk, skb)) { if (sock_queue_rcv_skb(sk, skb))
dprintk("sock_queue_rcv_skb failed!\n");
kfree_skb(skb); kfree_skb(skb);
}
out_put: out_put:
sock_put(sk); sock_put(sk);
out:; out:;
...@@ -1547,13 +1539,11 @@ static void llc_ui_conf_conn(struct llc_prim_if_block *prim) ...@@ -1547,13 +1539,11 @@ static void llc_ui_conf_conn(struct llc_prim_if_block *prim)
{ {
struct llc_prim_conn *prim_data = &prim->data->conn; struct llc_prim_conn *prim_data = &prim->data->conn;
struct llc_opt *llc_core = llc_sk(prim_data->sk); struct llc_opt *llc_core = llc_sk(prim_data->sk);
struct llc_ui_opt *llc_ui = llc_ui_sk(prim_data->sk);
struct sock* sk = llc_core->handler; struct sock* sk = llc_core->handler;
struct llc_ui_opt *llc_ui = llc_ui_sk(sk);
if (!sk) { if (!sk)
dprintk("llc_core->handler == NULL!\n");
goto out; goto out;
}
sock_hold(sk); sock_hold(sk);
if (sk->type != SOCK_STREAM || sk->state != TCP_SYN_SENT) if (sk->type != SOCK_STREAM || sk->state != TCP_SYN_SENT)
goto out_put; goto out_put;
...@@ -1562,8 +1552,6 @@ static void llc_ui_conf_conn(struct llc_prim_if_block *prim) ...@@ -1562,8 +1552,6 @@ static void llc_ui_conf_conn(struct llc_prim_if_block *prim)
sk->state = TCP_ESTABLISHED; sk->state = TCP_ESTABLISHED;
llc_ui->core_sk = prim_data->sk; llc_ui->core_sk = prim_data->sk;
} else { } else {
dprintk("prim->data->conn.status = %d\n",
prim->data->conn.status);
sk->socket->state = SS_UNCONNECTED; sk->socket->state = SS_UNCONNECTED;
sk->state = TCP_CLOSE; sk->state = TCP_CLOSE;
llc_ui->core_sk = NULL; llc_ui->core_sk = NULL;
...@@ -1633,7 +1621,7 @@ static int llc_ui_confirm(struct llc_prim_if_block *prim) ...@@ -1633,7 +1621,7 @@ static int llc_ui_confirm(struct llc_prim_if_block *prim)
llc_ui_conf_disc(prim); break; llc_ui_conf_disc(prim); break;
case LLC_RESET_PRIM: break; case LLC_RESET_PRIM: break;
default: default:
printk(KERN_ERR __FUNCTION__ ": unknown prim %d\n", printk(KERN_ERR "%s: unknown prim %d\n", __FUNCTION__,
prim->prim); prim->prim);
break; break;
} }
......
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