Commit 44bb970a authored by Arnaldo Carvalho de Melo's avatar Arnaldo Carvalho de Melo

Merge hera.kernel.org:/home/acme/BK/llc-2.5.old

into hera.kernel.org:/home/acme/BK/llc-2.5
parents 02debc0e 87c9fe7c
...@@ -110,38 +110,14 @@ ...@@ -110,38 +110,14 @@
#define LLC_CONN_EV_QFY_S_FLAG_EQ_0 11 #define LLC_CONN_EV_QFY_S_FLAG_EQ_0 11
#define LLC_CONN_EV_QFY_INIT_P_F_CYCLE 12 #define LLC_CONN_EV_QFY_INIT_P_F_CYCLE 12
/* Event data interface; what is sent in an event package */
/* Event LLC_CONN_EV_TYPE_SIMPLE interface */
struct llc_conn_ev_simple_if {
u8 ev;
};
/* Event LLC_CONN_EV_TYPE_PRIM interface */
struct llc_conn_ev_prim_if {
u8 prim; /* connect, disconnect, reset, ... */
u8 type; /* request, indicate, response, conf */
struct llc_prim_if_block *data;
};
/* Event LLC_CONN_EV_TYPE_PDU interface */
struct llc_conn_ev_pdu_if {
u8 ev;
};
union llc_conn_ev_if {
struct llc_conn_ev_simple_if a; /* 'a' for simple, easy ... */
struct llc_conn_ev_prim_if prim;
struct llc_conn_ev_pdu_if pdu;
};
struct llc_conn_state_ev { struct llc_conn_state_ev {
u8 type; u8 type;
u8 prim;
u8 prim_type;
u8 reason; u8 reason;
u8 status; u8 status;
u8 flag; u8 ind_prim;
struct llc_prim_if_block *ind_prim; u8 cfm_prim;
struct llc_prim_if_block *cfm_prim;
union llc_conn_ev_if data;
}; };
static __inline__ struct llc_conn_state_ev *llc_conn_ev(struct sk_buff *skb) static __inline__ struct llc_conn_state_ev *llc_conn_ev(struct sk_buff *skb)
......
...@@ -66,18 +66,10 @@ struct llc_opt { ...@@ -66,18 +66,10 @@ struct llc_opt {
u32 rx_pdu_hdr; /* used for saving header of last pdu u32 rx_pdu_hdr; /* used for saving header of last pdu
received and caused sending FRMR. received and caused sending FRMR.
Used for resending FRMR */ Used for resending FRMR */
#ifdef DEBUG_LLC_CONN_ALLOC
char *f_alloc, /* function that allocated this connection */
*f_free; /* function that freed this connection */
int l_alloc, /* line that allocated this connection */
l_free; /* line that freed this connection */
#endif
}; };
#define llc_sk(__sk) ((struct llc_opt *)(__sk)->protinfo) #define llc_sk(__sk) ((struct llc_opt *)(__sk)->protinfo)
struct llc_conn_state_ev;
extern struct sock *llc_sk_alloc(int family, int priority); extern struct sock *llc_sk_alloc(int family, int priority);
extern void llc_sk_free(struct sock *sk); extern void llc_sk_free(struct sock *sk);
...@@ -100,6 +92,9 @@ extern struct sock *llc_lookup_established(struct llc_sap *sap, ...@@ -100,6 +92,9 @@ extern struct sock *llc_lookup_established(struct llc_sap *sap,
struct llc_addr *laddr); struct llc_addr *laddr);
extern struct sock *llc_lookup_listener(struct llc_sap *sap, extern struct sock *llc_lookup_listener(struct llc_sap *sap,
struct llc_addr *laddr); struct llc_addr *laddr);
extern struct sock *llc_lookup_dgram(struct llc_sap *sap,
struct llc_addr *laddr);
extern void llc_save_primitive(struct sk_buff* skb, u8 prim);
extern u8 llc_data_accept_state(u8 state); extern u8 llc_data_accept_state(u8 state);
extern void llc_build_offset_table(void); extern void llc_build_offset_table(void);
#endif /* LLC_CONN_H */ #endif /* LLC_CONN_H */
...@@ -31,25 +31,11 @@ ...@@ -31,25 +31,11 @@
#define LLC_STATION_EV_RX_NULL_DSAP_TEST_C 8 #define LLC_STATION_EV_RX_NULL_DSAP_TEST_C 8
#define LLC_STATION_EV_DISABLE_REQ 9 #define LLC_STATION_EV_DISABLE_REQ 9
/* Interfaces for various types of supported events */
struct llc_stat_ev_simple_if {
u8 ev;
};
struct llc_stat_ev_prim_if {
u8 prim; /* connect, disconnect, reset, ... */
u8 type; /* request, indicate, response, confirm */
};
union llc_stat_ev_if {
struct llc_stat_ev_simple_if a; /* 'a' for simple, easy ... */
struct llc_stat_ev_prim_if prim;
};
struct llc_station_state_ev { struct llc_station_state_ev {
u8 type; u8 type;
u8 prim;
u8 prim_type;
u8 reason; u8 reason;
union llc_stat_ev_if data;
struct list_head node; /* node in station->ev_q.list */ struct list_head node; /* node in station->ev_q.list */
}; };
......
/* if_ether.h needed for definition of ETH_DATA_LEN and ETH_ALEN
*/
#include "linux/if_ether.h"
/* frame layout based on par3.2 "LLC PDU format"
*/
typedef union { /* pdu layout from pages 40 & 44 */
struct { /* general header, all pdu types */
unsigned dsap : 8; /* dest service access point */
unsigned ssap : 8; /* source service access point */
unsigned f1 : 1; /* I- U- or S- format id bits */
unsigned f2 : 1;
unsigned : 6;
unsigned : 8;
} pdu_hdr;
struct {
char dummy1[2]; /* dsap + ssap */
char byte1;
char byte2;
} pdu_cntl; /* unformatted control bytes */
struct { /* header of an Information pdu */
unsigned char dummy2[2];
unsigned : 1;
unsigned ns : 7;
unsigned i_pflag : 1; /* poll/final bit */
unsigned nr : 7; /* N(R) */
unsigned char is_info[ ETH_DATA_LEN ];
} i_hdr;
struct { /* header of a Supervisory pdu */
unsigned char dummy3[2];
unsigned : 2;
unsigned ss : 2; /* supervisory function bits */
unsigned : 4;
unsigned s_pflag : 1; /* poll/final bit */
unsigned nr : 7; /* N(R) */
} s_hdr;
/* when accessing the P/F bit or the N(R) field there's no need to distinguish
I pdus from S pdus i_pflag and s_pflag / i_nr and s_nr map to the same
physical location.
*/
struct { /* header of an Unnumbered pdu */
unsigned char dummy4[2];
unsigned : 2;
unsigned mm1 : 2; /* modifier function part1 */
unsigned u_pflag : 1; /* P/F for U- pdus */
unsigned mm2 : 3; /* modifier function part2 */
unsigned char u_info[ ETH_DATA_LEN-1];
} u_hdr;
struct { /* mm field in an Unnumbered pdu */
unsigned char dummy5[2];
unsigned : 2;
unsigned mm : 6; /* must be masked to get ridd of P/F ! */
} u_mm;
} frame_type, *frameptr;
/* frame format test macros: */
#define IS_UFRAME( fr ) ( ( (fr)->pdu_hdr.f1) & ( (fr)->pdu_hdr.f2) )
#define IS_IFRAME( fr ) ( !( (fr)->pdu_hdr.f1) )
#define IS_SFRAME( fr ) ( ( (fr)->pdu_hdr.f1) & !( (fr)->pdu_hdr.f2) )
#define IS_RSP( fr ) ( fr->pdu_hdr.ssap & 0x01 )
/* The transition table, the _encode tables and some tests in the
source code depend on the numeric order of these values.
Think twice before changing.
*/
/* frame names for TYPE 2 operation: */
#define I_CMD 0
#define RR_CMD 1
#define RNR_CMD 2
#define REJ_CMD 3
#define DISC_CMD 4
#define SABME_CMD 5
#define I_RSP 6
#define RR_RSP 7
#define RNR_RSP 8
#define REJ_RSP 9
#define UA_RSP 10
#define DM_RSP 11
#define FRMR_RSP 12
/* junk frame name: */
#define BAD_FRAME 13
#define NO_FRAME 13
/* frame names for TYPE 1 operation: */
#define UI_CMD 14
#define XID_CMD 15
#define TEST_CMD 16
#define XID_RSP 17
#define TEST_RSP 18
...@@ -17,17 +17,17 @@ ...@@ -17,17 +17,17 @@
#include <linux/if_arp.h> #include <linux/if_arp.h>
#include <linux/llc.h> #include <linux/llc.h>
#define LLC_DATAUNIT_PRIM 0 #define LLC_DATAUNIT_PRIM 1
#define LLC_CONN_PRIM 1 #define LLC_CONN_PRIM 2
#define LLC_DATA_PRIM 2 #define LLC_DATA_PRIM 3
#define LLC_DISC_PRIM 3 #define LLC_DISC_PRIM 4
#define LLC_RESET_PRIM 4 #define LLC_RESET_PRIM 5
#define LLC_FLOWCONTROL_PRIM 5 /* Not supported at this time */ #define LLC_FLOWCONTROL_PRIM 6 /* Not supported at this time */
#define LLC_DISABLE_PRIM 6 #define LLC_DISABLE_PRIM 7
#define LLC_XID_PRIM 7 #define LLC_XID_PRIM 8
#define LLC_TEST_PRIM 8 #define LLC_TEST_PRIM 9
#define LLC_SAP_ACTIVATION 9 #define LLC_SAP_ACTIVATION 10
#define LLC_SAP_DEACTIVATION 10 #define LLC_SAP_DEACTIVATION 11
#define LLC_NBR_PRIMITIVES 11 #define LLC_NBR_PRIMITIVES 11
...@@ -67,66 +67,22 @@ struct llc_addr { ...@@ -67,66 +67,22 @@ struct llc_addr {
u8 mac[IFHWADDRLEN]; u8 mac[IFHWADDRLEN];
}; };
struct llc_prim_reset {
struct sock *sk;
u16 link;
};
/* Sending data in conection-less mode */
struct llc_prim_unit_data {
struct llc_addr saddr;
struct llc_addr daddr;
u8 pri;
struct sk_buff *skb; /* pointer to frame */
u8 lfb; /* largest frame bit (TR) */
};
struct llc_prim_xid {
struct llc_addr saddr;
struct llc_addr daddr;
u8 pri;
struct sk_buff *skb;
};
struct llc_prim_test {
struct llc_addr saddr;
struct llc_addr daddr;
u8 pri;
struct sk_buff *skb; /* pointer to frame */
};
union llc_u_prim_data {
struct llc_prim_reset res;
struct llc_prim_unit_data udata; /* unit data */
struct llc_prim_xid xid;
struct llc_prim_test test;
};
struct llc_sap; struct llc_sap;
/* Information block passed with all called primitives */ extern struct llc_sap *llc_sap_open(u8 lsap,
struct llc_prim_if_block { int (*func)(struct sk_buff *skb,
struct llc_sap *sap; struct net_device *dev,
u8 prim; struct packet_type *pt));
union llc_u_prim_data *data;
};
typedef int (*llc_prim_call_t)(struct llc_prim_if_block *prim_if);
extern struct llc_sap *llc_sap_open(llc_prim_call_t network_indicate,
llc_prim_call_t network_confirm, u8 lsap);
extern void llc_sap_close(struct llc_sap *sap); extern void llc_sap_close(struct llc_sap *sap);
extern int llc_establish_connection(struct sock *sk, u8 *lmac, extern int llc_establish_connection(struct sock *sk, u8 *lmac,
u8 *dmac, u8 dsap); u8 *dmac, u8 dsap);
extern int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb); extern int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb);
extern void llc_build_and_send_ui_pkt(struct llc_sap *sap, extern void llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb,
struct sk_buff *skb,
u8 *dmac, u8 dsap); u8 *dmac, u8 dsap);
extern void llc_build_and_send_xid_pkt(struct llc_sap *sap, extern void llc_build_and_send_xid_pkt(struct llc_sap *sap, struct sk_buff *skb,
struct sk_buff *skb,
u8 *dmac, u8 dsap); u8 *dmac, u8 dsap);
extern void llc_build_and_send_test_pkt(struct llc_sap *sap, extern void llc_build_and_send_test_pkt(struct llc_sap *sap, struct sk_buff *skb,
struct sk_buff *skb,
u8 *dmac, u8 dsap); u8 *dmac, u8 dsap);
extern int llc_send_disc(struct sock *sk); extern int llc_send_disc(struct sock *sk);
#endif /* LLC_IF_H */ #endif /* LLC_IF_H */
...@@ -43,7 +43,7 @@ struct llc_station { ...@@ -43,7 +43,7 @@ struct llc_station {
u8 maximum_retry; u8 maximum_retry;
u8 mac_sa[6]; u8 mac_sa[6];
struct { struct {
spinlock_t lock; rwlock_t lock;
struct list_head list; struct list_head list;
} sap_list; } sap_list;
struct { struct {
...@@ -52,7 +52,6 @@ struct llc_station { ...@@ -52,7 +52,6 @@ struct llc_station {
} ev_q; } ev_q;
struct sk_buff_head mac_pdu_q; struct sk_buff_head mac_pdu_q;
}; };
struct llc_station_state_ev;
extern struct llc_sap *llc_sap_alloc(void); extern struct llc_sap *llc_sap_alloc(void);
extern void llc_sap_save(struct llc_sap *sap); extern void llc_sap_save(struct llc_sap *sap);
......
char *frame_names[] =
{"I_CMD","RR_CMD","RNR_CMD","REJ_CMD","DISC_CMD",
"SABME_CMD","I_RSP","RR_RSP","RNR_RSP","REJ_RSP",
"UA_RSP","DM_RSP","FRMR_RSP","BAD_FRAME","UI_CMD",
"XID_CMD","TEST_CMD","XID_RSP","TEST_RSP"
};
...@@ -34,37 +34,14 @@ ...@@ -34,37 +34,14 @@
#define LLC_SAP_EV_RX_TEST_R 9 #define LLC_SAP_EV_RX_TEST_R 9
#define LLC_SAP_EV_DEACTIVATION_REQ 10 #define LLC_SAP_EV_DEACTIVATION_REQ 10
/* Interfaces for various types of supported events */
struct llc_sap_ev_simple_if {
u8 ev;
};
struct llc_prim_if_block;
struct llc_sap_ev_prim_if {
u8 prim; /* connect, disconnect, reset, ... */
u8 type; /* request, indicate, response, conf */
struct llc_prim_if_block *data;
};
struct llc_sap_ev_pdu_if {
u8 ev;
};
union llc_sap_ev_if {
struct llc_sap_ev_simple_if a; /* 'a' for simple, easy ... */
struct llc_sap_ev_prim_if prim;
struct llc_sap_ev_pdu_if pdu;
};
struct llc_prim_if_block;
struct llc_sap_state_ev { struct llc_sap_state_ev {
u8 prim;
u8 prim_type;
u8 type; u8 type;
u8 reason; u8 reason;
u8 ind_cfm_flag; u8 ind_cfm_flag;
struct llc_prim_if_block *prim; struct llc_addr saddr;
union llc_sap_ev_if data; struct llc_addr daddr;
}; };
static __inline__ struct llc_sap_state_ev *llc_sap_ev(struct sk_buff *skb) static __inline__ struct llc_sap_state_ev *llc_sap_ev(struct sk_buff *skb)
......
...@@ -12,36 +12,33 @@ ...@@ -12,36 +12,33 @@
* 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>
#include <net/llc_if.h>
/** /**
* struct llc_sap - Defines the SAP component * struct llc_sap - Defines the SAP component
* *
* @station - station this sap belongs to
* @state - sap state
* @p_bit - only lowest-order bit used * @p_bit - only lowest-order bit used
* @f_bit - only lowest-order bit used * @f_bit - only lowest-order bit used
* @ind - provided by network layer
* @conf - provided by network layer
* @laddr - SAP value in this 'lsap' * @laddr - SAP value in this 'lsap'
* @node - entry in station sap_list * @node - entry in station sap_list
* @sk_list - LLC sockets this one manages * @sk_list - LLC sockets this one manages
* @mac_pdu_q - PDUs ready to send to MAC
*/ */
struct llc_sap { struct llc_sap {
struct llc_station *parent_station; struct llc_station *station;
u8 state; u8 state;
u8 p_bit; u8 p_bit;
u8 f_bit; u8 f_bit;
llc_prim_call_t ind; int (*rcv_func)(struct sk_buff *skb,
llc_prim_call_t conf; struct net_device *dev,
struct llc_prim_if_block llc_ind_prim, llc_cfm_prim; struct packet_type *pt);
union llc_u_prim_data llc_ind_data_prim, llc_cfm_data_prim;
struct llc_addr laddr; struct llc_addr laddr;
struct list_head node; struct list_head node;
struct { struct {
spinlock_t lock; rwlock_t lock;
struct list_head list; struct sock *list;
} sk_list; } sk_list;
struct sk_buff_head mac_pdu_q;
}; };
struct llc_sap_state_ev;
extern void llc_sap_assign_sock(struct llc_sap *sap, struct sock *sk); extern void llc_sap_assign_sock(struct llc_sap *sap, struct sock *sk);
extern void llc_sap_unassign_sock(struct llc_sap *sap, struct sock *sk); extern void llc_sap_unassign_sock(struct llc_sap *sap, struct sock *sk);
......
char *state_names[] = {
"ADM","CONN","RESET_WAIT","RESET_CHECK","SETUP",
"RESET","D_CONN","ERROR","NORMAL"
};
#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 (*func)(struct sk_buff *skb,
int (*indicate)(struct llc_prim_if_block *prim)); struct net_device *dev,
struct packet_type *pt));
extern void unregister_8022_client(struct datalink_proto *proto); extern void unregister_8022_client(struct datalink_proto *proto);
#endif #endif
...@@ -33,7 +33,9 @@ static int p8022_request(struct datalink_proto *dl, struct sk_buff *skb, ...@@ -33,7 +33,9 @@ static int p8022_request(struct datalink_proto *dl, struct sk_buff *skb,
} }
struct datalink_proto *register_8022_client(unsigned char type, struct datalink_proto *register_8022_client(unsigned char type,
int (*indicate)(struct llc_prim_if_block *prim)) int (*func)(struct sk_buff *skb,
struct net_device *dev,
struct packet_type *pt))
{ {
struct datalink_proto *proto; struct datalink_proto *proto;
...@@ -42,7 +44,7 @@ struct datalink_proto *register_8022_client(unsigned char type, ...@@ -42,7 +44,7 @@ struct datalink_proto *register_8022_client(unsigned char type,
proto->type[0] = type; proto->type[0] = type;
proto->header_length = 3; proto->header_length = 3;
proto->request = p8022_request; proto->request = p8022_request;
proto->sap = llc_sap_open(indicate, NULL, type); proto->sap = llc_sap_open(type, func);
if (!proto->sap) { if (!proto->sap) {
kfree(proto); kfree(proto);
proto = NULL; proto = NULL;
......
...@@ -51,32 +51,26 @@ static struct datalink_proto *find_snap_client(unsigned char *desc) ...@@ -51,32 +51,26 @@ static struct datalink_proto *find_snap_client(unsigned char *desc)
/* /*
* A SNAP packet has arrived * A SNAP packet has arrived
*/ */
static int snap_indicate(struct llc_prim_if_block *prim) static int snap_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt)
{ {
struct sk_buff *skb;
struct datalink_proto *proto;
int rc = 1; int rc = 1;
static struct packet_type psnap_packet_type = { struct datalink_proto *proto = find_snap_client(skb->h.raw);
static struct packet_type snap_packet_type = {
.type = __constant_htons(ETH_P_SNAP), .type = __constant_htons(ETH_P_SNAP),
}; };
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_pull(skb, 5); skb_pull(skb, 5);
rc = proto->rcvfunc(skb, skb->dev, &psnap_packet_type); rc = proto->rcvfunc(skb, dev, &snap_packet_type);
} else { } else {
skb->sk = NULL; skb->sk = NULL;
kfree_skb(skb); kfree_skb(skb);
rc = 1; rc = 1;
} }
out:
return rc; return rc;
} }
...@@ -99,7 +93,7 @@ EXPORT_SYMBOL(unregister_snap_client); ...@@ -99,7 +93,7 @@ EXPORT_SYMBOL(unregister_snap_client);
static int __init snap_init(void) static int __init snap_init(void)
{ {
snap_sap = llc_sap_open(snap_indicate, NULL, 0xAA); snap_sap = llc_sap_open(0xAA, snap_rcv);
if (!snap_sap) 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");
......
...@@ -2252,22 +2252,6 @@ drop: kfree_skb(skb); ...@@ -2252,22 +2252,6 @@ 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)
{ {
...@@ -2560,7 +2544,7 @@ static int __init ipx_init(void) ...@@ -2560,7 +2544,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_8022_indicate); p8022_datalink = register_8022_client(ipx_8022_type, ipx_rcv);
if (!p8022_datalink) if (!p8022_datalink)
printk(ipx_llc_err_msg); printk(ipx_llc_err_msg);
......
...@@ -65,9 +65,7 @@ int llc_conn_ac_conn_ind(struct sock *sk, struct sk_buff *skb) ...@@ -65,9 +65,7 @@ int llc_conn_ac_conn_ind(struct sock *sk, struct sk_buff *skb)
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;
/* FIXME: find better way to notify upper layer */ ev->ind_prim = LLC_CONN_PRIM;
ev->flag = LLC_CONN_PRIM + 1;
ev->ind_prim = (void *)1;
rc = 0; rc = 0;
} }
return rc; return rc;
...@@ -77,8 +75,7 @@ int llc_conn_ac_conn_confirm(struct sock *sk, struct sk_buff *skb) ...@@ -77,8 +75,7 @@ int llc_conn_ac_conn_confirm(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_conn_state_ev *ev = llc_conn_ev(skb); struct llc_conn_state_ev *ev = llc_conn_ev(skb);
ev->flag = LLC_CONN_PRIM + 1; ev->cfm_prim = LLC_CONN_PRIM;
ev->cfm_prim = (void *)1;
return 0; return 0;
} }
...@@ -86,12 +83,7 @@ static int llc_conn_ac_data_confirm(struct sock *sk, struct sk_buff *skb) ...@@ -86,12 +83,7 @@ static int llc_conn_ac_data_confirm(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_conn_state_ev *ev = llc_conn_ev(skb); struct llc_conn_state_ev *ev = llc_conn_ev(skb);
/* ev->cfm_prim = LLC_DATA_PRIM;
* FIXME: find better way to tell upper layer that the packet was
* confirmed by the other endpoint
*/
ev->flag = LLC_DATA_PRIM + 1;
ev->cfm_prim = (void *)1;
return 0; return 0;
} }
...@@ -130,8 +122,7 @@ int llc_conn_ac_disc_ind(struct sock *sk, struct sk_buff *skb) ...@@ -130,8 +122,7 @@ int llc_conn_ac_disc_ind(struct sock *sk, struct sk_buff *skb)
} }
if (!rc) { if (!rc) {
ev->reason = reason; ev->reason = reason;
ev->flag = LLC_DISC_PRIM + 1; ev->ind_prim = LLC_DISC_PRIM;
ev->ind_prim = (void *)1;
} }
return rc; return rc;
} }
...@@ -141,8 +132,7 @@ int llc_conn_ac_disc_confirm(struct sock *sk, struct sk_buff *skb) ...@@ -141,8 +132,7 @@ int llc_conn_ac_disc_confirm(struct sock *sk, struct sk_buff *skb)
struct llc_conn_state_ev *ev = llc_conn_ev(skb); struct llc_conn_state_ev *ev = llc_conn_ev(skb);
ev->reason = ev->status; ev->reason = ev->status;
ev->flag = LLC_DISC_PRIM + 1; ev->cfm_prim = LLC_DISC_PRIM;
ev->cfm_prim = (void *)1;
return 0; return 0;
} }
...@@ -184,18 +174,8 @@ int llc_conn_ac_rst_ind(struct sock *sk, struct sk_buff *skb) ...@@ -184,18 +174,8 @@ int llc_conn_ac_rst_ind(struct sock *sk, struct sk_buff *skb)
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.link = llc->link;
prim->data = prim_data;
prim->prim = LLC_RESET_PRIM;
prim->sap = sap;
ev->reason = reason; ev->reason = reason;
ev->flag = 1; ev->ind_prim = LLC_RESET_PRIM;
ev->ind_prim = prim;
} }
return rc; return rc;
} }
...@@ -203,18 +183,9 @@ int llc_conn_ac_rst_ind(struct sock *sk, struct sk_buff *skb) ...@@ -203,18 +183,9 @@ int llc_conn_ac_rst_ind(struct sock *sk, struct sk_buff *skb)
int llc_conn_ac_rst_confirm(struct sock *sk, struct sk_buff *skb) int llc_conn_ac_rst_confirm(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_conn_state_ev *ev = llc_conn_ev(skb); struct llc_conn_state_ev *ev = llc_conn_ev(skb);
struct llc_opt *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap; ev->reason = 0;
struct llc_prim_if_block *prim = &sap->llc_cfm_prim; ev->cfm_prim = LLC_RESET_PRIM;
union llc_u_prim_data *prim_data = prim->data;
prim_data->res.sk = sk;
prim_data->res.link = llc->link;
prim->data = prim_data;
prim->prim = LLC_RESET_PRIM;
prim->sap = sap;
ev->flag = 1;
ev->cfm_prim = prim;
return 0; return 0;
} }
......
...@@ -101,48 +101,48 @@ int llc_conn_ev_conn_req(struct sock *sk, struct sk_buff *skb) ...@@ -101,48 +101,48 @@ int llc_conn_ev_conn_req(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_conn_state_ev *ev = llc_conn_ev(skb); struct llc_conn_state_ev *ev = llc_conn_ev(skb);
return ev->data.prim.prim == LLC_CONN_PRIM && return ev->prim == LLC_CONN_PRIM &&
ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1; ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
} }
int llc_conn_ev_conn_resp(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_conn_resp(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_conn_state_ev *ev = llc_conn_ev(skb); struct llc_conn_state_ev *ev = llc_conn_ev(skb);
return ev->data.prim.prim == LLC_CONN_PRIM && return ev->prim == LLC_CONN_PRIM &&
ev->data.prim.type == LLC_PRIM_TYPE_RESP ? 0 : 1; ev->prim_type == LLC_PRIM_TYPE_RESP ? 0 : 1;
} }
int llc_conn_ev_data_req(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_data_req(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_conn_state_ev *ev = llc_conn_ev(skb); struct llc_conn_state_ev *ev = llc_conn_ev(skb);
return ev->data.prim.prim == LLC_DATA_PRIM && return ev->prim == LLC_DATA_PRIM &&
ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1; ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
} }
int llc_conn_ev_disc_req(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_disc_req(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_conn_state_ev *ev = llc_conn_ev(skb); struct llc_conn_state_ev *ev = llc_conn_ev(skb);
return ev->data.prim.prim == LLC_DISC_PRIM && return ev->prim == LLC_DISC_PRIM &&
ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1; ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
} }
int llc_conn_ev_rst_req(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rst_req(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_conn_state_ev *ev = llc_conn_ev(skb); struct llc_conn_state_ev *ev = llc_conn_ev(skb);
return ev->data.prim.prim == LLC_RESET_PRIM && return ev->prim == LLC_RESET_PRIM &&
ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1; ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
} }
int llc_conn_ev_rst_resp(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rst_resp(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_conn_state_ev *ev = llc_conn_ev(skb); struct llc_conn_state_ev *ev = llc_conn_ev(skb);
return ev->data.prim.prim == LLC_RESET_PRIM && return ev->prim == LLC_RESET_PRIM &&
ev->data.prim.type == LLC_PRIM_TYPE_RESP ? 0 : 1; ev->prim_type == LLC_PRIM_TYPE_RESP ? 0 : 1;
} }
int llc_conn_ev_local_busy_detected(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_local_busy_detected(struct sock *sk, struct sk_buff *skb)
...@@ -150,7 +150,7 @@ int llc_conn_ev_local_busy_detected(struct sock *sk, struct sk_buff *skb) ...@@ -150,7 +150,7 @@ int llc_conn_ev_local_busy_detected(struct sock *sk, struct sk_buff *skb)
struct llc_conn_state_ev *ev = llc_conn_ev(skb); struct llc_conn_state_ev *ev = llc_conn_ev(skb);
return ev->type == LLC_CONN_EV_TYPE_SIMPLE && return ev->type == LLC_CONN_EV_TYPE_SIMPLE &&
ev->data.a.ev == LLC_CONN_EV_LOCAL_BUSY_DETECTED ? 0 : 1; ev->prim_type == LLC_CONN_EV_LOCAL_BUSY_DETECTED ? 0 : 1;
} }
int llc_conn_ev_local_busy_cleared(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_local_busy_cleared(struct sock *sk, struct sk_buff *skb)
...@@ -158,7 +158,7 @@ int llc_conn_ev_local_busy_cleared(struct sock *sk, struct sk_buff *skb) ...@@ -158,7 +158,7 @@ int llc_conn_ev_local_busy_cleared(struct sock *sk, struct sk_buff *skb)
struct llc_conn_state_ev *ev = llc_conn_ev(skb); struct llc_conn_state_ev *ev = llc_conn_ev(skb);
return ev->type == LLC_CONN_EV_TYPE_SIMPLE && return ev->type == LLC_CONN_EV_TYPE_SIMPLE &&
ev->data.a.ev == LLC_CONN_EV_LOCAL_BUSY_CLEARED ? 0 : 1; ev->prim_type == LLC_CONN_EV_LOCAL_BUSY_CLEARED ? 0 : 1;
} }
int llc_conn_ev_rx_bad_pdu(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_bad_pdu(struct sock *sk, struct sk_buff *skb)
...@@ -666,7 +666,7 @@ int llc_conn_ev_tx_buffer_full(struct sock *sk, struct sk_buff *skb) ...@@ -666,7 +666,7 @@ int llc_conn_ev_tx_buffer_full(struct sock *sk, struct sk_buff *skb)
struct llc_conn_state_ev *ev = llc_conn_ev(skb); struct llc_conn_state_ev *ev = llc_conn_ev(skb);
return ev->type == LLC_CONN_EV_TYPE_SIMPLE && return ev->type == LLC_CONN_EV_TYPE_SIMPLE &&
ev->data.a.ev == LLC_CONN_EV_TX_BUFF_FULL ? 0 : 1; ev->prim_type == LLC_CONN_EV_TX_BUFF_FULL ? 0 : 1;
} }
/* Event qualifier functions /* Event qualifier functions
......
...@@ -39,12 +39,12 @@ static struct llc_conn_state_trans *llc_qualify_conn_ev(struct sock *sk, ...@@ -39,12 +39,12 @@ static struct llc_conn_state_trans *llc_qualify_conn_ev(struct sock *sk,
/* Offset table on connection states transition diagram */ /* Offset table on connection states transition diagram */
static int llc_offset_table[NBR_CONN_STATES][NBR_CONN_EV]; static int llc_offset_table[NBR_CONN_STATES][NBR_CONN_EV];
void llc_save_primitive(struct sock *sk, struct sk_buff* skb, u8 prim) void llc_save_primitive(struct sk_buff* skb, u8 prim)
{ {
struct sockaddr_llc *addr = llc_ui_skb_cb(skb); struct sockaddr_llc *addr = llc_ui_skb_cb(skb);
/* save primitive for use by the user. */ /* save primitive for use by the user. */
addr->sllc_family = sk->family; addr->sllc_family = skb->sk->family;
addr->sllc_arphrd = skb->dev->type; addr->sllc_arphrd = skb->dev->type;
addr->sllc_test = prim == LLC_TEST_PRIM; addr->sllc_test = prim == LLC_TEST_PRIM;
addr->sllc_xid = prim == LLC_XID_PRIM; addr->sllc_xid = prim == LLC_XID_PRIM;
...@@ -67,48 +67,39 @@ void llc_save_primitive(struct sock *sk, struct sk_buff* skb, u8 prim) ...@@ -67,48 +67,39 @@ void llc_save_primitive(struct sock *sk, struct sk_buff* skb, u8 prim)
*/ */
int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
{ {
/* sending event to state machine */ int rc;
int rc = llc_conn_service(sk, skb);
struct llc_opt *llc = llc_sk(sk); struct llc_opt *llc = llc_sk(sk);
struct llc_conn_state_ev *ev = llc_conn_ev(skb); struct llc_conn_state_ev *ev = llc_conn_ev(skb);
u8 flag = ev->flag;
u8 status = ev->status;
struct llc_prim_if_block *ind_prim = ev->ind_prim;
struct llc_prim_if_block *cfm_prim = ev->cfm_prim;
/* ev->ind_prim = ev->cfm_prim = 0;
* FIXME: this will vanish as soon I get rid of the last prim crap rc = llc_conn_service(sk, skb); /* sending event to state machine */
*/ if (rc) {
if (flag != LLC_DATA_PRIM + 1 && flag != LLC_CONN_PRIM + 1 && printk(KERN_ERR "%s: llc_conn_service failed\n", __FUNCTION__);
flag != LLC_DISC_PRIM + 1) goto out_kfree_skb;
llc_conn_free_ev(skb); }
else if (ind_prim && cfm_prim)
skb_get(skb); if (!ev->ind_prim && !ev->cfm_prim) { /* indicate or confirm not required */
if (!flag) /* indicate or confirm not required */ if (!skb->list)
goto out_kfree_skb;
goto out; goto out;
rc = 0; }
if (ind_prim) { /* indication required */
/* if (ev->ind_prim && ev->cfm_prim)
* FIXME: this will be saner as soon I get rid of the double skb_get(skb);
* sock crap
*/ switch (ev->ind_prim) {
switch (flag) { case LLC_DATA_PRIM:
case LLC_DATA_PRIM + 1: llc_save_primitive(skb, LLC_DATA_PRIM);
llc_save_primitive(sk, skb, LLC_DATA_PRIM);
if (sock_queue_rcv_skb(sk, skb)) { if (sock_queue_rcv_skb(sk, skb)) {
/* /*
* FIXME: have to sync the LLC state * shouldn't happen
* machine wrt mem usage with
* sk->{r,w}mem_alloc, will do
* this soon 8)
*/ */
printk(KERN_ERR printk(KERN_ERR "%s: sock_queue_rcv_skb failed!\n",
"%s: sock_queue_rcv_skb failed!\n",
__FUNCTION__); __FUNCTION__);
kfree_skb(skb); kfree_skb(skb);
} }
break; break;
case LLC_CONN_PRIM + 1: { case LLC_CONN_PRIM: {
struct sock *parent = skb->sk; struct sock *parent = skb->sk;
skb->sk = sk; skb->sk = sk;
...@@ -116,7 +107,7 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) ...@@ -116,7 +107,7 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
sk->state_change(parent); sk->state_change(parent);
} }
break; break;
case LLC_DISC_PRIM + 1: case LLC_DISC_PRIM:
sock_hold(sk); sock_hold(sk);
if (sk->type == SOCK_STREAM && sk->state == TCP_ESTABLISHED) { if (sk->type == SOCK_STREAM && sk->state == TCP_ESTABLISHED) {
sk->shutdown = SHUTDOWN_MASK; sk->shutdown = SHUTDOWN_MASK;
...@@ -130,25 +121,34 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) ...@@ -130,25 +121,34 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
kfree_skb(skb); kfree_skb(skb);
sock_put(sk); sock_put(sk);
break; break;
case LLC_RESET_PRIM:
/*
* FIXME:
* RESET is not being notified to upper layers for now
*/
printk(KERN_INFO "%s: received a reset ind!\n", __FUNCTION__);
kfree_skb(skb);
break;
default: default:
llc->sap->ind(ind_prim); if (ev->ind_prim) {
printk(KERN_INFO "%s: received unknown %d prim!\n",
__FUNCTION__, ev->ind_prim);
kfree_skb(skb);
} }
/* No indication */
break;
} }
if (!cfm_prim) /* confirmation not required */
goto out; switch (ev->cfm_prim) {
/* FIXME: see FIXMEs above */ case LLC_DATA_PRIM:
switch (flag) {
case LLC_DATA_PRIM + 1:
if (!llc_data_accept_state(llc->state)) if (!llc_data_accept_state(llc->state))
/* In this state, we can send I pdu */
sk->write_space(sk); sk->write_space(sk);
else else
rc = llc->failed_data_req = 1; rc = llc->failed_data_req = 1;
break; break;
case LLC_CONN_PRIM + 1: case LLC_CONN_PRIM:
if (sk->type != SOCK_STREAM || sk->state != TCP_SYN_SENT) if (sk->type == SOCK_STREAM && sk->state == TCP_SYN_SENT) {
goto out_kfree_skb; if (ev->status) {
if (status) {
sk->socket->state = SS_UNCONNECTED; sk->socket->state = SS_UNCONNECTED;
sk->state = TCP_CLOSE; sk->state = TCP_CLOSE;
} else { } else {
...@@ -156,21 +156,31 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) ...@@ -156,21 +156,31 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
sk->state = TCP_ESTABLISHED; sk->state = TCP_ESTABLISHED;
} }
sk->state_change(sk); sk->state_change(sk);
}
break; break;
case LLC_DISC_PRIM + 1: case LLC_DISC_PRIM:
sock_hold(sk); sock_hold(sk);
if (sk->type != SOCK_STREAM || sk->state != TCP_CLOSING) { if (sk->type == SOCK_STREAM && sk->state == TCP_CLOSING) {
sock_put(sk);
goto out_kfree_skb;
}
sk->socket->state = SS_UNCONNECTED; sk->socket->state = SS_UNCONNECTED;
sk->state = TCP_CLOSE; sk->state = TCP_CLOSE;
sk->state_change(sk); sk->state_change(sk);
}
sock_put(sk); sock_put(sk);
break; break;
case LLC_RESET_PRIM:
/*
* FIXME:
* RESET is not being notified to upper layers for now
*/
printk(KERN_INFO "%s: received a reset conf!\n", __FUNCTION__);
break;
default: default:
llc->sap->conf(cfm_prim); if (ev->cfm_prim) {
goto out; printk(KERN_INFO "%s: received unknown %d prim!\n",
__FUNCTION__, ev->cfm_prim);
break;
}
goto out; /* No confirmation */
} }
out_kfree_skb: out_kfree_skb:
kfree_skb(skb); kfree_skb(skb);
...@@ -198,9 +208,7 @@ void llc_conn_rtn_pdu(struct sock *sk, struct sk_buff *skb) ...@@ -198,9 +208,7 @@ void llc_conn_rtn_pdu(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_conn_state_ev *ev = llc_conn_ev(skb); struct llc_conn_state_ev *ev = llc_conn_ev(skb);
/* FIXME: indicate that we should send this to the upper layer */ ev->ind_prim = LLC_DATA_PRIM;
ev->flag = LLC_DATA_PRIM + 1;
ev->ind_prim = (void *)1;
} }
/** /**
...@@ -355,12 +363,14 @@ void llc_conn_free_ev(struct sk_buff *skb) ...@@ -355,12 +363,14 @@ void llc_conn_free_ev(struct sk_buff *skb)
/* free the frame that is bound to this event */ /* free the frame that is bound to this event */
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
if (LLC_PDU_TYPE_IS_I(pdu) || !ev->flag || !ev->ind_prim) if (LLC_PDU_TYPE_IS_I(pdu) || !ev->ind_prim)
kfree_skb(skb); kfree_skb(skb);
} else if (ev->type == LLC_CONN_EV_TYPE_PRIM && } else if (ev->type == LLC_CONN_EV_TYPE_PRIM &&
ev->data.prim.prim != LLC_DATA_PRIM) ev->prim != LLC_DATA_PRIM)
kfree_skb(skb); kfree_skb(skb);
else if (ev->type == LLC_CONN_EV_TYPE_P_TMR) else if (ev->type == LLC_CONN_EV_TYPE_P_TMR ||
ev->type == LLC_CONN_EV_TYPE_BUSY_TMR ||
ev->type == LLC_CONN_EV_TYPE_REJ_TMR)
kfree_skb(skb); kfree_skb(skb);
} }
...@@ -483,27 +493,21 @@ static int llc_exec_conn_trans_actions(struct sock *sk, ...@@ -483,27 +493,21 @@ static int llc_exec_conn_trans_actions(struct sock *sk,
struct sock *llc_lookup_established(struct llc_sap *sap, struct llc_addr *daddr, struct sock *llc_lookup_established(struct llc_sap *sap, struct llc_addr *daddr,
struct llc_addr *laddr) struct llc_addr *laddr)
{ {
struct sock *rc = NULL; struct sock *rc;
struct list_head *entry;
spin_lock_bh(&sap->sk_list.lock); read_lock_bh(&sap->sk_list.lock);
if (list_empty(&sap->sk_list.list)) for (rc = sap->sk_list.list; rc; rc = rc->next) {
goto out; struct llc_opt *llc = llc_sk(rc);
list_for_each(entry, &sap->sk_list.list) {
struct llc_opt *llc = list_entry(entry, struct llc_opt, node);
if (llc->laddr.lsap == laddr->lsap && if (llc->laddr.lsap == laddr->lsap &&
llc->daddr.lsap == daddr->lsap && llc->daddr.lsap == daddr->lsap &&
llc_mac_match(llc->laddr.mac, laddr->mac) && llc_mac_match(llc->laddr.mac, laddr->mac) &&
llc_mac_match(llc->daddr.mac, daddr->mac)) { llc_mac_match(llc->daddr.mac, daddr->mac))
rc = llc->sk;
break; break;
} }
}
if (rc) if (rc)
sock_hold(rc); sock_hold(rc);
out: read_unlock_bh(&sap->sk_list.lock);
spin_unlock_bh(&sap->sk_list.lock);
return rc; return rc;
} }
...@@ -518,28 +522,49 @@ struct sock *llc_lookup_established(struct llc_sap *sap, struct llc_addr *daddr, ...@@ -518,28 +522,49 @@ struct sock *llc_lookup_established(struct llc_sap *sap, struct llc_addr *daddr,
*/ */
struct sock *llc_lookup_listener(struct llc_sap *sap, struct llc_addr *laddr) struct sock *llc_lookup_listener(struct llc_sap *sap, struct llc_addr *laddr)
{ {
struct sock *rc = NULL; struct sock *rc;
struct list_head *entry;
spin_lock_bh(&sap->sk_list.lock); read_lock_bh(&sap->sk_list.lock);
if (list_empty(&sap->sk_list.list)) for (rc = sap->sk_list.list; rc; rc = rc->next) {
goto out; struct llc_opt *llc = llc_sk(rc);
list_for_each(entry, &sap->sk_list.list) {
struct llc_opt *llc = list_entry(entry, struct llc_opt, node); if (rc->type == SOCK_STREAM && rc->state == TCP_LISTEN &&
llc->laddr.lsap == laddr->lsap &&
if (llc->sk->type != SOCK_STREAM || llc->sk->state != TCP_LISTEN || llc_mac_match(llc->laddr.mac, laddr->mac))
llc->laddr.lsap != laddr->lsap || break;
!llc_mac_match(llc->laddr.mac, laddr->mac))
continue;
rc = llc->sk;
} }
if (rc) if (rc)
sock_hold(rc); sock_hold(rc);
out: read_unlock_bh(&sap->sk_list.lock);
spin_unlock_bh(&sap->sk_list.lock);
return rc; return rc;
} }
/**
* llc_lookup_dgram - Finds dgram socket for the local sap/mac
* @sap: SAP
* @laddr: address of local LLC (MAC + SAP)
*
* Search socket list of the SAP and finds connection using the local
* mac, and local sap. Returns pointer for socket found, %NULL otherwise.
*/
struct sock *llc_lookup_dgram(struct llc_sap *sap, struct llc_addr *laddr)
{
struct sock *rc;
read_lock_bh(&sap->sk_list.lock);
for (rc = sap->sk_list.list; rc; rc = rc->next) {
struct llc_opt *llc = llc_sk(rc);
if (rc->type == SOCK_DGRAM &&
llc->laddr.lsap == laddr->lsap &&
llc_mac_match(llc->laddr.mac, laddr->mac))
break;
}
if (rc)
sock_hold(rc);
read_unlock_bh(&sap->sk_list.lock);
return rc;
}
/** /**
* llc_data_accept_state - designates if in this state data can be sent. * llc_data_accept_state - designates if in this state data can be sent.
* @state: state of connection. * @state: state of connection.
......
...@@ -29,7 +29,7 @@ int llc_stat_ev_enable_with_dup_addr_check(struct llc_station *station, ...@@ -29,7 +29,7 @@ int llc_stat_ev_enable_with_dup_addr_check(struct llc_station *station,
struct llc_station_state_ev *ev = llc_station_ev(skb); struct llc_station_state_ev *ev = llc_station_ev(skb);
return ev->type == LLC_STATION_EV_TYPE_SIMPLE && return ev->type == LLC_STATION_EV_TYPE_SIMPLE &&
ev->data.a.ev == ev->prim_type ==
LLC_STATION_EV_ENABLE_WITH_DUP_ADDR_CHECK ? 0 : 1; LLC_STATION_EV_ENABLE_WITH_DUP_ADDR_CHECK ? 0 : 1;
} }
...@@ -39,7 +39,7 @@ int llc_stat_ev_enable_without_dup_addr_check(struct llc_station *station, ...@@ -39,7 +39,7 @@ int llc_stat_ev_enable_without_dup_addr_check(struct llc_station *station,
struct llc_station_state_ev *ev = llc_station_ev(skb); struct llc_station_state_ev *ev = llc_station_ev(skb);
return ev->type == LLC_STATION_EV_TYPE_SIMPLE && return ev->type == LLC_STATION_EV_TYPE_SIMPLE &&
ev->data.a.ev == ev->prim_type ==
LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK ? 0 : 1; LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK ? 0 : 1;
} }
...@@ -120,6 +120,6 @@ int llc_stat_ev_disable_req(struct llc_station *station, struct sk_buff *skb) ...@@ -120,6 +120,6 @@ int llc_stat_ev_disable_req(struct llc_station *station, struct sk_buff *skb)
struct llc_station_state_ev *ev = llc_station_ev(skb); struct llc_station_state_ev *ev = llc_station_ev(skb);
return ev->type == LLC_STATION_EV_TYPE_PRIM && return ev->type == LLC_STATION_EV_TYPE_PRIM &&
ev->data.prim.prim == LLC_DISABLE_PRIM && ev->prim == LLC_DISABLE_PRIM &&
ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1; ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
} }
...@@ -30,17 +30,16 @@ ...@@ -30,17 +30,16 @@
/** /**
* llc_sap_open - open interface to the upper layers. * llc_sap_open - open interface to the upper layers.
* @nw_indicate: pointer to indicate function of upper layer.
* @nw_confirm: pointer to confirm function of upper layer.
* @lsap: SAP number. * @lsap: SAP number.
* @sap: pointer to allocated SAP (output argument). * @func: rcv func for datalink protos
* *
* Interface function to upper layer. Each one who wants to get a SAP * Interface function to upper layer. Each one who wants to get a SAP
* (for example NetBEUI) should call this function. Returns the opened * (for example NetBEUI) should call this function. Returns the opened
* SAP for success, NULL for failure. * SAP for success, NULL for failure.
*/ */
struct llc_sap *llc_sap_open(llc_prim_call_t nw_indicate, struct llc_sap *llc_sap_open(u8 lsap, int (*func)(struct sk_buff *skb,
llc_prim_call_t nw_confirm, u8 lsap) struct net_device *dev,
struct packet_type *pt))
{ {
/* verify this SAP is not already open; if so, return error */ /* verify this SAP is not already open; if so, return error */
struct llc_sap *sap; struct llc_sap *sap;
...@@ -57,9 +56,8 @@ struct llc_sap *llc_sap_open(llc_prim_call_t nw_indicate, ...@@ -57,9 +56,8 @@ struct llc_sap *llc_sap_open(llc_prim_call_t nw_indicate,
goto err; goto err;
/* allocated a SAP; initialize it and clear out its memory pool */ /* allocated a SAP; initialize it and clear out its memory pool */
sap->laddr.lsap = lsap; sap->laddr.lsap = lsap;
sap->ind = nw_indicate; sap->rcv_func = func;
sap->conf = nw_confirm; sap->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);
out: out:
...@@ -99,24 +97,16 @@ void llc_sap_close(struct llc_sap *sap) ...@@ -99,24 +97,16 @@ void llc_sap_close(struct llc_sap *sap)
void llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb, void llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb,
u8 *dmac, u8 dsap) u8 *dmac, u8 dsap)
{ {
union llc_u_prim_data prim_data;
struct llc_prim_if_block prim;
struct llc_sap_state_ev *ev = llc_sap_ev(skb); struct llc_sap_state_ev *ev = llc_sap_ev(skb);
prim.data = &prim_data; ev->saddr.lsap = sap->laddr.lsap;
prim.sap = sap; ev->daddr.lsap = dsap;
prim.prim = LLC_DATAUNIT_PRIM; memcpy(ev->saddr.mac, skb->dev->dev_addr, IFHWADDRLEN);
memcpy(ev->daddr.mac, dmac, IFHWADDRLEN);
prim_data.udata.skb = skb;
prim_data.udata.saddr.lsap = sap->laddr.lsap;
prim_data.udata.daddr.lsap = dsap;
memcpy(prim_data.udata.saddr.mac, skb->dev->dev_addr, IFHWADDRLEN);
memcpy(prim_data.udata.daddr.mac, dmac, IFHWADDRLEN);
ev->type = LLC_SAP_EV_TYPE_PRIM; ev->type = LLC_SAP_EV_TYPE_PRIM;
ev->data.prim.prim = LLC_DATAUNIT_PRIM; ev->prim = LLC_DATAUNIT_PRIM;
ev->data.prim.type = LLC_PRIM_TYPE_REQ; ev->prim_type = LLC_PRIM_TYPE_REQ;
ev->data.prim.data = &prim;
llc_sap_state_process(sap, skb); llc_sap_state_process(sap, skb);
} }
...@@ -130,27 +120,19 @@ void llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb, ...@@ -130,27 +120,19 @@ void llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb,
* This function is called when upper layer wants to send a TEST pdu. * This function is called when upper layer wants to send a TEST pdu.
* Returns 0 for success, 1 otherwise. * Returns 0 for success, 1 otherwise.
*/ */
void llc_build_and_send_test_pkt(struct llc_sap *sap, struct sk_buff *skb, void llc_build_and_send_test_pkt(struct llc_sap *sap,
u8 *dmac, u8 dsap) struct sk_buff *skb, u8 *dmac, u8 dsap)
{ {
union llc_u_prim_data prim_data;
struct llc_prim_if_block prim;
struct llc_sap_state_ev *ev = llc_sap_ev(skb); struct llc_sap_state_ev *ev = llc_sap_ev(skb);
prim.data = &prim_data; ev->saddr.lsap = sap->laddr.lsap;
prim.sap = sap; ev->daddr.lsap = dsap;
prim.prim = LLC_TEST_PRIM; memcpy(ev->saddr.mac, skb->dev->dev_addr, IFHWADDRLEN);
memcpy(ev->daddr.mac, dmac, IFHWADDRLEN);
prim_data.test.skb = skb;
prim_data.test.saddr.lsap = sap->laddr.lsap;
prim_data.test.daddr.lsap = dsap;
memcpy(prim_data.test.saddr.mac, skb->dev->dev_addr, IFHWADDRLEN);
memcpy(prim_data.test.daddr.mac, dmac, IFHWADDRLEN);
ev->type = LLC_SAP_EV_TYPE_PRIM; ev->type = LLC_SAP_EV_TYPE_PRIM;
ev->data.prim.prim = LLC_TEST_PRIM; ev->prim = LLC_TEST_PRIM;
ev->data.prim.type = LLC_PRIM_TYPE_REQ; ev->prim_type = LLC_PRIM_TYPE_REQ;
ev->data.prim.data = &prim;
llc_sap_state_process(sap, skb); llc_sap_state_process(sap, skb);
} }
...@@ -167,24 +149,16 @@ void llc_build_and_send_test_pkt(struct llc_sap *sap, struct sk_buff *skb, ...@@ -167,24 +149,16 @@ void llc_build_and_send_test_pkt(struct llc_sap *sap, struct sk_buff *skb,
void llc_build_and_send_xid_pkt(struct llc_sap *sap, struct sk_buff *skb, void llc_build_and_send_xid_pkt(struct llc_sap *sap, struct sk_buff *skb,
u8 *dmac, u8 dsap) u8 *dmac, u8 dsap)
{ {
union llc_u_prim_data prim_data;
struct llc_prim_if_block prim;
struct llc_sap_state_ev *ev = llc_sap_ev(skb); struct llc_sap_state_ev *ev = llc_sap_ev(skb);
prim.data = &prim_data; ev->saddr.lsap = sap->laddr.lsap;
prim.sap = sap; ev->daddr.lsap = dsap;
prim.prim = LLC_XID_PRIM; memcpy(ev->saddr.mac, skb->dev->dev_addr, IFHWADDRLEN);
memcpy(ev->daddr.mac, dmac, IFHWADDRLEN);
prim_data.xid.skb = skb;
prim_data.xid.saddr.lsap = sap->laddr.lsap;
prim_data.xid.daddr.lsap = dsap;
memcpy(prim_data.xid.saddr.mac, skb->dev->dev_addr, IFHWADDRLEN);
memcpy(prim_data.xid.daddr.mac, dmac, IFHWADDRLEN);
ev->type = LLC_SAP_EV_TYPE_PRIM; ev->type = LLC_SAP_EV_TYPE_PRIM;
ev->data.prim.prim = LLC_XID_PRIM; ev->prim = LLC_XID_PRIM;
ev->data.prim.type = LLC_PRIM_TYPE_REQ; ev->prim_type = LLC_PRIM_TYPE_REQ;
ev->data.prim.data = &prim;
llc_sap_state_process(sap, skb); llc_sap_state_process(sap, skb);
} }
...@@ -220,9 +194,8 @@ int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb) ...@@ -220,9 +194,8 @@ int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb)
} }
ev = llc_conn_ev(skb); ev = llc_conn_ev(skb);
ev->type = LLC_CONN_EV_TYPE_PRIM; ev->type = LLC_CONN_EV_TYPE_PRIM;
ev->data.prim.prim = LLC_DATA_PRIM; ev->prim = LLC_DATA_PRIM;
ev->data.prim.type = LLC_PRIM_TYPE_REQ; ev->prim_type = LLC_PRIM_TYPE_REQ;
ev->data.prim.data = NULL;
skb->dev = llc->dev; skb->dev = llc->dev;
rc = llc_conn_state_process(sk, skb); rc = llc_conn_state_process(sk, skb);
out: out:
...@@ -269,9 +242,8 @@ int llc_establish_connection(struct sock *sk, u8 *lmac, u8 *dmac, u8 dsap) ...@@ -269,9 +242,8 @@ int llc_establish_connection(struct sock *sk, u8 *lmac, u8 *dmac, u8 dsap)
struct llc_conn_state_ev *ev = llc_conn_ev(skb); struct llc_conn_state_ev *ev = llc_conn_ev(skb);
ev->type = LLC_CONN_EV_TYPE_PRIM; ev->type = LLC_CONN_EV_TYPE_PRIM;
ev->data.prim.prim = LLC_CONN_PRIM; ev->prim = LLC_CONN_PRIM;
ev->data.prim.type = LLC_PRIM_TYPE_REQ; ev->prim_type = LLC_PRIM_TYPE_REQ;
ev->data.prim.data = NULL;
rc = llc_conn_state_process(sk, skb); rc = llc_conn_state_process(sk, skb);
} }
out_put: out_put:
...@@ -309,9 +281,8 @@ int llc_send_disc(struct sock *sk) ...@@ -309,9 +281,8 @@ int llc_send_disc(struct sock *sk)
sk->state = TCP_CLOSING; sk->state = TCP_CLOSING;
ev = llc_conn_ev(skb); ev = llc_conn_ev(skb);
ev->type = LLC_CONN_EV_TYPE_PRIM; ev->type = LLC_CONN_EV_TYPE_PRIM;
ev->data.prim.prim = LLC_DISC_PRIM; ev->prim = LLC_DISC_PRIM;
ev->data.prim.type = LLC_PRIM_TYPE_REQ; ev->prim_type = LLC_PRIM_TYPE_REQ;
ev->data.prim.data = NULL;
rc = llc_conn_state_process(sk, skb); rc = llc_conn_state_process(sk, skb);
out: out:
sock_put(sk); sock_put(sk);
...@@ -327,8 +298,7 @@ int llc_send_disc(struct sock *sk) ...@@ -327,8 +298,7 @@ int llc_send_disc(struct sock *sk)
* it to connection component state machine. Returns 0 for success, 1 * it to connection component state machine. Returns 0 for success, 1
* otherwise. * otherwise.
*/ */
int llc_build_and_send_reset_pkt(struct sock *sk, int llc_build_and_send_reset_pkt(struct sock *sk)
struct llc_prim_if_block *prim)
{ {
int rc = 1; int rc = 1;
struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC); struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC);
...@@ -337,9 +307,8 @@ int llc_build_and_send_reset_pkt(struct sock *sk, ...@@ -337,9 +307,8 @@ int llc_build_and_send_reset_pkt(struct sock *sk,
struct llc_conn_state_ev *ev = llc_conn_ev(skb); struct llc_conn_state_ev *ev = llc_conn_ev(skb);
ev->type = LLC_CONN_EV_TYPE_PRIM; ev->type = LLC_CONN_EV_TYPE_PRIM;
ev->data.prim.prim = LLC_RESET_PRIM; ev->prim = LLC_RESET_PRIM;
ev->data.prim.type = LLC_PRIM_TYPE_REQ; ev->prim_type = LLC_PRIM_TYPE_REQ;
ev->data.prim.data = prim;
rc = llc_conn_state_process(sk, skb); rc = llc_conn_state_process(sk, skb);
} }
return rc; return rc;
......
...@@ -113,8 +113,22 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -113,8 +113,22 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev,
} }
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 */
dprintk("%s: calling llc_sap_rcv!\n", __FUNCTION__); if (sap->rcv_func)
sap->rcv_func(skb, dev, pt);
else {
struct llc_addr laddr;
struct sock *sk;
llc_pdu_decode_da(skb, laddr.mac);
llc_pdu_decode_dsap(skb, &laddr.lsap);
sk = llc_lookup_dgram(sap, &laddr);
if (!sk)
goto drop;
skb->sk = sk;
llc_sap_rcv(sap, skb); llc_sap_rcv(sap, skb);
sock_put(sk);
}
} else if (dest == LLC_DEST_CONN) { } else if (dest == LLC_DEST_CONN) {
struct llc_addr saddr, daddr; struct llc_addr saddr, daddr;
struct sock *sk; struct sock *sk;
......
...@@ -71,10 +71,6 @@ struct llc_sap *llc_sap_alloc(void) ...@@ -71,10 +71,6 @@ struct llc_sap *llc_sap_alloc(void)
sap->state = LLC_SAP_STATE_ACTIVE; sap->state = LLC_SAP_STATE_ACTIVE;
memcpy(sap->laddr.mac, llc_main_station.mac_sa, ETH_ALEN); memcpy(sap->laddr.mac, llc_main_station.mac_sa, ETH_ALEN);
spin_lock_init(&sap->sk_list.lock); spin_lock_init(&sap->sk_list.lock);
INIT_LIST_HEAD(&sap->sk_list.list);
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;
} }
...@@ -88,12 +84,10 @@ struct llc_sap *llc_sap_alloc(void) ...@@ -88,12 +84,10 @@ struct llc_sap *llc_sap_alloc(void)
*/ */
void llc_free_sap(struct llc_sap *sap) void llc_free_sap(struct llc_sap *sap)
{ {
struct llc_station *station = sap->parent_station;
llc_rtn_all_conns(sap); llc_rtn_all_conns(sap);
spin_lock_bh(&station->sap_list.lock); write_lock_bh(&sap->station->sap_list.lock);
list_del(&sap->node); list_del(&sap->node);
spin_unlock_bh(&station->sap_list.lock); write_unlock_bh(&sap->station->sap_list.lock);
kfree(sap); kfree(sap);
} }
...@@ -105,9 +99,9 @@ void llc_free_sap(struct llc_sap *sap) ...@@ -105,9 +99,9 @@ void llc_free_sap(struct llc_sap *sap)
*/ */
void llc_sap_save(struct llc_sap *sap) void llc_sap_save(struct llc_sap *sap)
{ {
spin_lock_bh(&llc_main_station.sap_list.lock); write_lock_bh(&llc_main_station.sap_list.lock);
list_add_tail(&sap->node, &llc_main_station.sap_list.list); list_add_tail(&sap->node, &llc_main_station.sap_list.list);
spin_unlock_bh(&llc_main_station.sap_list.lock); write_unlock_bh(&llc_main_station.sap_list.lock);
} }
/** /**
...@@ -122,7 +116,7 @@ struct llc_sap *llc_sap_find(u8 sap_value) ...@@ -122,7 +116,7 @@ struct llc_sap *llc_sap_find(u8 sap_value)
struct llc_sap* sap = NULL; struct llc_sap* sap = NULL;
struct list_head *entry; struct list_head *entry;
spin_lock_bh(&llc_main_station.sap_list.lock); read_lock_bh(&llc_main_station.sap_list.lock);
list_for_each(entry, &llc_main_station.sap_list.list) { list_for_each(entry, &llc_main_station.sap_list.list) {
sap = list_entry(entry, struct llc_sap, node); sap = list_entry(entry, struct llc_sap, node);
if (sap->laddr.lsap == sap_value) if (sap->laddr.lsap == sap_value)
...@@ -130,7 +124,7 @@ struct llc_sap *llc_sap_find(u8 sap_value) ...@@ -130,7 +124,7 @@ struct llc_sap *llc_sap_find(u8 sap_value)
} }
if (entry == &llc_main_station.sap_list.list) /* not found */ if (entry == &llc_main_station.sap_list.list) /* not found */
sap = NULL; sap = NULL;
spin_unlock_bh(&llc_main_station.sap_list.lock); read_unlock_bh(&llc_main_station.sap_list.lock);
return sap; return sap;
} }
...@@ -328,20 +322,18 @@ void llc_sk_reset(struct sock *sk) ...@@ -328,20 +322,18 @@ void llc_sk_reset(struct sock *sk)
static int llc_rtn_all_conns(struct llc_sap *sap) static int llc_rtn_all_conns(struct llc_sap *sap)
{ {
int rc = 0; int rc = 0;
struct list_head *entry, *tmp; struct sock *sk;
spin_lock_bh(&sap->sk_list.lock); write_lock_bh(&sap->sk_list.lock);
if (list_empty(&sap->sk_list.list))
goto out;
list_for_each_safe(entry, tmp, &sap->sk_list.list) {
struct llc_opt *llc = list_entry(entry, struct llc_opt, node);
llc->state = LLC_CONN_STATE_TEMP; for (sk = sap->sk_list.list; sk; sk = sk->next) {
if (llc_send_disc(llc->sk)) llc_sk(sk)->state = LLC_CONN_STATE_TEMP;
if (llc_send_disc(sk))
rc = 1; rc = 1;
} }
out:
spin_unlock_bh(&sap->sk_list.lock); write_unlock_bh(&sap->sk_list.lock);
return rc; return rc;
} }
...@@ -564,19 +556,19 @@ static char *llc_conn_state_names[] = { ...@@ -564,19 +556,19 @@ static char *llc_conn_state_names[] = {
static int llc_proc_get_info(char *bf, char **start, off_t offset, int length) static int llc_proc_get_info(char *bf, char **start, off_t offset, int length)
{ {
struct llc_opt *llc; struct list_head *sap_entry;
struct list_head *sap_entry, *llc_entry; struct sock *sk;
off_t begin = 0, pos = 0; off_t begin = 0, pos = 0;
int len = 0; int len = 0;
spin_lock_bh(&llc_main_station.sap_list.lock); read_lock_bh(&llc_main_station.sap_list.lock);
list_for_each(sap_entry, &llc_main_station.sap_list.list) { list_for_each(sap_entry, &llc_main_station.sap_list.list) {
struct llc_sap *sap = list_entry(sap_entry, struct llc_sap, struct llc_sap *sap = list_entry(sap_entry, struct llc_sap,
node); node);
len += sprintf(bf + len, "lsap=%02X\n", sap->laddr.lsap); len += sprintf(bf + len, "lsap=%02X\n", sap->laddr.lsap);
spin_lock_bh(&sap->sk_list.lock); read_lock_bh(&sap->sk_list.lock);
if (list_empty(&sap->sk_list.list)) { if (!sap->sk_list.list) {
len += sprintf(bf + len, "no connections\n"); len += sprintf(bf + len, "no connections\n");
goto unlock; goto unlock;
} }
...@@ -584,8 +576,9 @@ static int llc_proc_get_info(char *bf, char **start, off_t offset, int length) ...@@ -584,8 +576,9 @@ static int llc_proc_get_info(char *bf, char **start, off_t offset, int length)
"dsap state retr txw rxw " "dsap state retr txw rxw "
"pf ff sf df rs cs " "pf ff sf df rs cs "
"tack tpfc trs tbs blog busr\n"); "tack tpfc trs tbs blog busr\n");
list_for_each(llc_entry, &sap->sk_list.list) { for (sk = sap->sk_list.list; sk; sk = sk->next) {
llc = list_entry(llc_entry, struct llc_opt, node); struct llc_opt *llc = llc_sk(sk);
len += sprintf(bf + len, " %02X %-10s %3d %3d %3d " len += sprintf(bf + len, " %02X %-10s %3d %3d %3d "
"%2d %2d %2d " "%2d %2d %2d "
"%2d %2d %2d " "%2d %2d %2d "
...@@ -600,11 +593,10 @@ static int llc_proc_get_info(char *bf, char **start, off_t offset, int length) ...@@ -600,11 +593,10 @@ static int llc_proc_get_info(char *bf, char **start, off_t offset, int length)
timer_pending(&llc->pf_cycle_timer.timer), timer_pending(&llc->pf_cycle_timer.timer),
timer_pending(&llc->rej_sent_timer.timer), timer_pending(&llc->rej_sent_timer.timer),
timer_pending(&llc->busy_state_timer.timer), timer_pending(&llc->busy_state_timer.timer),
!!llc->sk->backlog.tail, !!sk->backlog.tail, sk->lock.users);
llc->sk->lock.users);
} }
unlock: unlock:
spin_unlock_bh(&sap->sk_list.lock); read_unlock_bh(&sap->sk_list.lock);
pos = begin + len; pos = begin + len;
if (pos < offset) { if (pos < offset) {
len = 0; /* Keep dumping into the buffer start */ len = 0; /* Keep dumping into the buffer start */
...@@ -613,7 +605,7 @@ static int llc_proc_get_info(char *bf, char **start, off_t offset, int length) ...@@ -613,7 +605,7 @@ static int llc_proc_get_info(char *bf, char **start, off_t offset, int length)
if (pos > offset + length) /* We have dumped enough */ if (pos > offset + length) /* We have dumped enough */
break; break;
} }
spin_unlock_bh(&llc_main_station.sap_list.lock); read_unlock_bh(&llc_main_station.sap_list.lock);
/* The data in question runs from begin to begin + len */ /* The data in question runs from begin to begin + len */
*start = bf + (offset - begin); /* Start of wanted data */ *start = bf + (offset - begin); /* Start of wanted data */
...@@ -634,8 +626,8 @@ static struct packet_type llc_tr_packet_type = { ...@@ -634,8 +626,8 @@ static struct packet_type llc_tr_packet_type = {
}; };
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, 2002\n"
KERN_INFO "NET4.0 IEEE 802.2 extended support\n"; KERN_INFO "NET 4.0 IEEE 802.2 extended support\n";
static char llc_error_msg[] __initdata = static char llc_error_msg[] __initdata =
KERN_ERR "LLC install NOT successful.\n"; KERN_ERR "LLC install NOT successful.\n";
...@@ -669,7 +661,7 @@ static int __init llc_init(void) ...@@ -669,7 +661,7 @@ static int __init llc_init(void)
llc_main_station.maximum_retry = 1; llc_main_station.maximum_retry = 1;
llc_main_station.state = LLC_STATION_STATE_DOWN; llc_main_station.state = LLC_STATION_STATE_DOWN;
ev->type = LLC_STATION_EV_TYPE_SIMPLE; ev->type = LLC_STATION_EV_TYPE_SIMPLE;
ev->data.a.ev = LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK; ev->prim_type = LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK;
rc = llc_station_next_state(&llc_main_station, skb); rc = llc_station_next_state(&llc_main_station, skb);
proc_net_create("802.2", 0, llc_proc_get_info); proc_net_create("802.2", 0, llc_proc_get_info);
llc_ui_init(); llc_ui_init();
...@@ -695,5 +687,5 @@ module_init(llc_init); ...@@ -695,5 +687,5 @@ module_init(llc_init);
module_exit(llc_exit); module_exit(llc_exit);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Procom, 1997, Arnaldo C. Melo, Jay Schullist, 2001"); MODULE_AUTHOR("Procom, 1997, Arnaldo C. Melo, Jay Schullist, 2001, 2002");
MODULE_DESCRIPTION("LLC 2.0, NET4.0 IEEE 802.2 extended support"); MODULE_DESCRIPTION("LLC 2.0, NET4.0 IEEE 802.2 extended support");
...@@ -51,14 +51,12 @@ int llc_sap_action_unitdata_ind(struct llc_sap *sap, struct sk_buff *skb) ...@@ -51,14 +51,12 @@ int llc_sap_action_unitdata_ind(struct llc_sap *sap, struct sk_buff *skb)
int llc_sap_action_send_ui(struct llc_sap *sap, struct sk_buff *skb) int llc_sap_action_send_ui(struct llc_sap *sap, struct sk_buff *skb)
{ {
struct llc_sap_state_ev *ev = llc_sap_ev(skb); struct llc_sap_state_ev *ev = llc_sap_ev(skb);
struct llc_prim_if_block *prim = ev->data.prim.data;
struct llc_prim_unit_data *prim_data = &prim->data->udata;
int rc; int rc;
llc_pdu_header_init(skb, LLC_PDU_TYPE_U, prim_data->saddr.lsap, llc_pdu_header_init(skb, LLC_PDU_TYPE_U, ev->saddr.lsap,
prim_data->daddr.lsap, LLC_PDU_CMD); ev->daddr.lsap, LLC_PDU_CMD);
llc_pdu_init_as_ui_cmd(skb); llc_pdu_init_as_ui_cmd(skb);
rc = lan_hdrs_init(skb, prim_data->saddr.mac, prim_data->daddr.mac); rc = lan_hdrs_init(skb, ev->saddr.mac, ev->daddr.mac);
if (!rc) if (!rc)
llc_sap_send_pdu(sap, skb); llc_sap_send_pdu(sap, skb);
return rc; return rc;
...@@ -76,14 +74,12 @@ int llc_sap_action_send_ui(struct llc_sap *sap, struct sk_buff *skb) ...@@ -76,14 +74,12 @@ int llc_sap_action_send_ui(struct llc_sap *sap, struct sk_buff *skb)
int llc_sap_action_send_xid_c(struct llc_sap *sap, struct sk_buff *skb) int llc_sap_action_send_xid_c(struct llc_sap *sap, struct sk_buff *skb)
{ {
struct llc_sap_state_ev *ev = llc_sap_ev(skb); struct llc_sap_state_ev *ev = llc_sap_ev(skb);
struct llc_prim_if_block *prim = ev->data.prim.data;
struct llc_prim_xid *prim_data = &prim->data->xid;
int rc; int rc;
llc_pdu_header_init(skb, LLC_PDU_TYPE_U, prim_data->saddr.lsap, llc_pdu_header_init(skb, LLC_PDU_TYPE_U, ev->saddr.lsap,
prim_data->daddr.lsap, LLC_PDU_CMD); ev->daddr.lsap, LLC_PDU_CMD);
llc_pdu_init_as_xid_cmd(skb, LLC_XID_NULL_CLASS_2, 0); llc_pdu_init_as_xid_cmd(skb, LLC_XID_NULL_CLASS_2, 0);
rc = lan_hdrs_init(skb, prim_data->saddr.mac, prim_data->daddr.mac); rc = lan_hdrs_init(skb, ev->saddr.mac, ev->daddr.mac);
if (!rc) if (!rc)
llc_sap_send_pdu(sap, skb); llc_sap_send_pdu(sap, skb);
return rc; return rc;
...@@ -132,14 +128,12 @@ int llc_sap_action_send_xid_r(struct llc_sap *sap, struct sk_buff *skb) ...@@ -132,14 +128,12 @@ int llc_sap_action_send_xid_r(struct llc_sap *sap, struct sk_buff *skb)
int llc_sap_action_send_test_c(struct llc_sap *sap, struct sk_buff *skb) int llc_sap_action_send_test_c(struct llc_sap *sap, struct sk_buff *skb)
{ {
struct llc_sap_state_ev *ev = llc_sap_ev(skb); struct llc_sap_state_ev *ev = llc_sap_ev(skb);
struct llc_prim_if_block *prim = ev->data.prim.data;
struct llc_prim_test *prim_data = &prim->data->test;
int rc; int rc;
llc_pdu_header_init(skb, LLC_PDU_TYPE_U, prim_data->saddr.lsap, llc_pdu_header_init(skb, LLC_PDU_TYPE_U, ev->saddr.lsap,
prim_data->daddr.lsap, LLC_PDU_CMD); ev->daddr.lsap, LLC_PDU_CMD);
llc_pdu_init_as_test_cmd(skb); llc_pdu_init_as_test_cmd(skb);
rc = lan_hdrs_init(skb, prim_data->saddr.mac, prim_data->daddr.mac); rc = lan_hdrs_init(skb, ev->saddr.mac, ev->daddr.mac);
if (!rc) if (!rc)
llc_sap_send_pdu(sap, skb); llc_sap_send_pdu(sap, skb);
return rc; return rc;
......
...@@ -25,7 +25,7 @@ int llc_sap_ev_activation_req(struct llc_sap *sap, struct sk_buff *skb) ...@@ -25,7 +25,7 @@ int llc_sap_ev_activation_req(struct llc_sap *sap, struct sk_buff *skb)
struct llc_sap_state_ev *ev = llc_sap_ev(skb); struct llc_sap_state_ev *ev = llc_sap_ev(skb);
return ev->type == LLC_SAP_EV_TYPE_SIMPLE && return ev->type == LLC_SAP_EV_TYPE_SIMPLE &&
ev->data.a.ev == LLC_SAP_EV_ACTIVATION_REQ ? 0 : 1; ev->prim_type == LLC_SAP_EV_ACTIVATION_REQ ? 0 : 1;
} }
int llc_sap_ev_rx_ui(struct llc_sap *sap, struct sk_buff *skb) int llc_sap_ev_rx_ui(struct llc_sap *sap, struct sk_buff *skb)
...@@ -43,8 +43,8 @@ int llc_sap_ev_unitdata_req(struct llc_sap *sap, struct sk_buff *skb) ...@@ -43,8 +43,8 @@ int llc_sap_ev_unitdata_req(struct llc_sap *sap, struct sk_buff *skb)
struct llc_sap_state_ev *ev = llc_sap_ev(skb); struct llc_sap_state_ev *ev = llc_sap_ev(skb);
return ev->type == LLC_SAP_EV_TYPE_PRIM && return ev->type == LLC_SAP_EV_TYPE_PRIM &&
ev->data.prim.prim == LLC_DATAUNIT_PRIM && ev->prim == LLC_DATAUNIT_PRIM &&
ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1; ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
} }
...@@ -53,8 +53,8 @@ int llc_sap_ev_xid_req(struct llc_sap *sap, struct sk_buff *skb) ...@@ -53,8 +53,8 @@ int llc_sap_ev_xid_req(struct llc_sap *sap, struct sk_buff *skb)
struct llc_sap_state_ev *ev = llc_sap_ev(skb); struct llc_sap_state_ev *ev = llc_sap_ev(skb);
return ev->type == LLC_SAP_EV_TYPE_PRIM && return ev->type == LLC_SAP_EV_TYPE_PRIM &&
ev->data.prim.prim == LLC_XID_PRIM && ev->prim == LLC_XID_PRIM &&
ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1; ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
} }
int llc_sap_ev_rx_xid_c(struct llc_sap *sap, struct sk_buff *skb) int llc_sap_ev_rx_xid_c(struct llc_sap *sap, struct sk_buff *skb)
...@@ -82,8 +82,8 @@ int llc_sap_ev_test_req(struct llc_sap *sap, struct sk_buff *skb) ...@@ -82,8 +82,8 @@ int llc_sap_ev_test_req(struct llc_sap *sap, struct sk_buff *skb)
struct llc_sap_state_ev *ev = llc_sap_ev(skb); struct llc_sap_state_ev *ev = llc_sap_ev(skb);
return ev->type == LLC_SAP_EV_TYPE_PRIM && return ev->type == LLC_SAP_EV_TYPE_PRIM &&
ev->data.prim.prim == LLC_TEST_PRIM && ev->prim == LLC_TEST_PRIM &&
ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1; ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
} }
int llc_sap_ev_rx_test_c(struct llc_sap *sap, struct sk_buff *skb) int llc_sap_ev_rx_test_c(struct llc_sap *sap, struct sk_buff *skb)
...@@ -111,5 +111,5 @@ int llc_sap_ev_deactivation_req(struct llc_sap *sap, struct sk_buff *skb) ...@@ -111,5 +111,5 @@ int llc_sap_ev_deactivation_req(struct llc_sap *sap, struct sk_buff *skb)
struct llc_sap_state_ev *ev = llc_sap_ev(skb); struct llc_sap_state_ev *ev = llc_sap_ev(skb);
return ev->type == LLC_SAP_EV_TYPE_SIMPLE && return ev->type == LLC_SAP_EV_TYPE_SIMPLE &&
ev->data.a.ev == LLC_SAP_EV_DEACTIVATION_REQ ? 0 : 1; ev->prim_type == LLC_SAP_EV_DEACTIVATION_REQ ? 0 : 1;
} }
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <net/llc_s_ac.h> #include <net/llc_s_ac.h>
#include <net/llc_s_st.h> #include <net/llc_s_st.h>
#include <net/sock.h> #include <net/sock.h>
#include <linux/tcp.h>
#include <net/llc_main.h> #include <net/llc_main.h>
#include <net/llc_mac.h> #include <net/llc_mac.h>
#include <net/llc_pdu.h> #include <net/llc_pdu.h>
...@@ -39,11 +40,15 @@ static struct llc_sap_state_trans *llc_find_sap_trans(struct llc_sap *sap, ...@@ -39,11 +40,15 @@ static struct llc_sap_state_trans *llc_find_sap_trans(struct llc_sap *sap,
*/ */
void llc_sap_assign_sock(struct llc_sap *sap, struct sock *sk) void llc_sap_assign_sock(struct llc_sap *sap, struct sock *sk)
{ {
spin_lock_bh(&sap->sk_list.lock); write_lock_bh(&sap->sk_list.lock);
llc_sk(sk)->sap = sap; llc_sk(sk)->sap = sap;
list_add_tail(&llc_sk(sk)->node, &sap->sk_list.list); sk->next = sap->sk_list.list;
if (sk->next)
sap->sk_list.list->pprev = &sk->next;
sap->sk_list.list = sk;
sk->pprev = &sap->sk_list.list;
sock_hold(sk); sock_hold(sk);
spin_unlock_bh(&sap->sk_list.lock); write_unlock_bh(&sap->sk_list.lock);
} }
/** /**
...@@ -55,28 +60,53 @@ void llc_sap_assign_sock(struct llc_sap *sap, struct sock *sk) ...@@ -55,28 +60,53 @@ void llc_sap_assign_sock(struct llc_sap *sap, struct sock *sk)
*/ */
void llc_sap_unassign_sock(struct llc_sap *sap, struct sock *sk) void llc_sap_unassign_sock(struct llc_sap *sap, struct sock *sk)
{ {
spin_lock_bh(&sap->sk_list.lock); write_lock_bh(&sap->sk_list.lock);
list_del(&llc_sk(sk)->node); if (sk->pprev) {
if (sk->next)
sk->next->pprev = sk->pprev;
*sk->pprev = sk->next;
sk->pprev = NULL;
/*
* This only makes sense if the socket was inserted on the
* list, if sk->pprev is NULL it wasn't
*/
sock_put(sk); sock_put(sk);
spin_unlock_bh(&sap->sk_list.lock); }
write_unlock_bh(&sap->sk_list.lock);
} }
/** /**
* llc_sap_state_process - sends event to SAP state machine * llc_sap_state_process - sends event to SAP state machine
* @sap: pointer to SAP * @sap: sap to use
* @skb: pointer to occurred event * @skb: pointer to occurred event
* *
* After executing actions of the event, upper layer will be indicated * After executing actions of the event, upper layer will be indicated
* if needed(on receiving an UI frame). * if needed(on receiving an UI frame). sk can be null for the
* datalink_proto case.
*/ */
void llc_sap_state_process(struct llc_sap *sap, struct sk_buff *skb) void llc_sap_state_process(struct llc_sap *sap, struct sk_buff *skb)
{ {
struct llc_sap_state_ev *ev = llc_sap_ev(skb); struct llc_sap_state_ev *ev = llc_sap_ev(skb);
/*
* We have to hold the skb, because llc_sap_next_state
* will kfree it in the sending path and we need to
* look at the skb->cb, where we encode llc_sap_state_ev.
*/
skb_get(skb);
ev->ind_cfm_flag = 0;
llc_sap_next_state(sap, skb); llc_sap_next_state(sap, skb);
if (ev->ind_cfm_flag == LLC_IND) if (ev->ind_cfm_flag == LLC_IND) {
sap->ind(ev->prim); if (skb->sk->state == TCP_LISTEN)
else if (ev->type == LLC_SAP_EV_TYPE_PDU) kfree_skb(skb);
else {
llc_save_primitive(skb, ev->prim);
/* queue skb to the user. */
if (sock_queue_rcv_skb(skb->sk, skb))
kfree_skb(skb);
}
}
kfree_skb(skb); kfree_skb(skb);
} }
...@@ -89,43 +119,17 @@ void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb) ...@@ -89,43 +119,17 @@ void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb)
{ {
struct llc_pdu_un *pdu; struct llc_pdu_un *pdu;
struct llc_sap_state_ev *ev = llc_sap_ev(skb); struct llc_sap_state_ev *ev = llc_sap_ev(skb);
struct llc_prim_if_block *prim = &sap->llc_ind_prim;
union llc_u_prim_data *prim_data = prim->data;
u8 lfb;
llc_pdu_decode_sa(skb, prim_data->udata.saddr.mac);
llc_pdu_decode_da(skb, prim_data->udata.daddr.mac);
llc_pdu_decode_dsap(skb, &prim_data->udata.daddr.lsap);
llc_pdu_decode_ssap(skb, &prim_data->udata.saddr.lsap);
prim_data->udata.pri = 0;
prim_data->udata.skb = skb;
pdu = llc_pdu_un_hdr(skb); 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; ev->prim = LLC_TEST_PRIM; break;
break;
case LLC_1_PDU_CMD_XID: case LLC_1_PDU_CMD_XID:
prim->prim = LLC_XID_PRIM; ev->prim = LLC_XID_PRIM; break;
break;
case LLC_1_PDU_CMD_UI: case LLC_1_PDU_CMD_UI:
if (skb->protocol == ntohs(ETH_P_TR_802_2)) { ev->prim = LLC_DATAUNIT_PRIM; break;
if (((struct trh_hdr *)skb->mac.raw)->rcf) {
lfb = ntohs(((struct trh_hdr *)
skb->mac.raw)->rcf) &
0x0070;
prim_data->udata.lfb = lfb >> 4;
} else {
lfb = 0xFF;
prim_data->udata.lfb = 0xFF;
}
}
prim->prim = LLC_DATAUNIT_PRIM;
break;
} }
prim->data = prim_data;
prim->sap = sap;
ev->ind_cfm_flag = LLC_IND; ev->ind_cfm_flag = LLC_IND;
ev->prim = prim;
} }
/** /**
......
...@@ -51,11 +51,7 @@ static u16 llc_ui_sap_last_autoport = LLC_SAP_DYN_START; ...@@ -51,11 +51,7 @@ 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];
static struct sockaddr_llc llc_ui_addrnull; static struct sockaddr_llc llc_ui_addrnull;
static struct proto_ops llc_ui_ops; static struct proto_ops llc_ui_ops;
static struct sock *llc_ui_sockets;
static rwlock_t llc_ui_sockets_lock = RW_LOCK_UNLOCKED;
static int llc_ui_indicate(struct llc_prim_if_block *prim);
static int llc_ui_confirm(struct llc_prim_if_block *prim);
static int llc_ui_wait_for_conn(struct sock *sk, int timeout); static int llc_ui_wait_for_conn(struct sock *sk, int timeout);
static int llc_ui_wait_for_disc(struct sock *sk, int timeout); static int llc_ui_wait_for_disc(struct sock *sk, int timeout);
static int llc_ui_wait_for_data(struct sock *sk, int timeout); static int llc_ui_wait_for_data(struct sock *sk, int timeout);
...@@ -145,103 +141,6 @@ static int llc_ui_send_data(struct sock* sk, struct sk_buff *skb, int noblock) ...@@ -145,103 +141,6 @@ static int llc_ui_send_data(struct sock* sk, struct sk_buff *skb, int noblock)
return rc; return rc;
} }
/**
* __llc_ui_find_sk_by_addr - return socket matching local mac + sap.
* @addr: Local address to match.
*
* Search the local socket list and return the socket which has a matching
* local (mac + sap) address (allows null mac). This search will work on
* unconnected and connected sockets, though find_by_link_no is recommend
* for connected sockets.
* Returns sock upon match, %NULL otherwise.
*/
static struct sock *__llc_ui_find_sk_by_addr(struct llc_addr *laddr,
struct llc_addr *daddr,
struct net_device *dev)
{
struct sock *sk;
for (sk = llc_ui_sockets; sk; sk = sk->next) {
struct llc_opt *llc = llc_sk(sk);
if (llc->addr.sllc_ssap != laddr->lsap)
continue;
if (llc_mac_null(llc->addr.sllc_smac)) {
if (!llc_mac_null(llc->addr.sllc_mmac) &&
!llc_mac_match(llc->addr.sllc_mmac,
laddr->mac))
continue;
break;
}
if (dev && !llc_mac_null(llc->addr.sllc_mmac) &&
llc_mac_match(llc->addr.sllc_mmac, laddr->mac) &&
llc_mac_match(llc->addr.sllc_smac, dev->dev_addr))
break;
if (dev->flags & IFF_LOOPBACK)
break;
if (!llc_mac_match(llc->addr.sllc_smac, laddr->mac))
continue;
if (llc_mac_null(llc->addr.sllc_dmac))
break;
}
return sk;
}
static struct sock *llc_ui_find_sk_by_addr(struct llc_addr *addr,
struct llc_addr *daddr,
struct net_device *dev)
{
struct sock *sk;
read_lock(&llc_ui_sockets_lock);
sk = __llc_ui_find_sk_by_addr(addr, daddr, dev);
if (sk)
sock_hold(sk);
read_unlock(&llc_ui_sockets_lock);
return sk;
}
/**
* llc_ui_insert_socket - insert socket into list
* @sk: Socket to insert.
*
* Insert a socket into the local llc socket list.
*/
static __inline__ void llc_ui_insert_socket(struct sock *sk)
{
write_lock_bh(&llc_ui_sockets_lock);
sk->next = llc_ui_sockets;
if (sk->next)
llc_ui_sockets->pprev = &sk->next;
llc_ui_sockets = sk;
sk->pprev = &llc_ui_sockets;
sock_hold(sk);
write_unlock_bh(&llc_ui_sockets_lock);
}
/**
* llc_ui_remove_socket - remove socket from list
* @sk: Socket to remove.
*
* Remove a socket from the local llc socket list.
*/
static __inline__ void llc_ui_remove_socket(struct sock *sk)
{
write_lock_bh(&llc_ui_sockets_lock);
if (sk->pprev) {
if (sk->next)
sk->next->pprev = sk->pprev;
*sk->pprev = sk->next;
sk->pprev = NULL;
/*
* This only makes sense if the socket was inserted on the
* list, if sk->pprev is NULL it wasn't
*/
sock_put(sk);
}
write_unlock_bh(&llc_ui_sockets_lock);
}
static void llc_ui_sk_init(struct socket *sock, struct sock *sk) static void llc_ui_sk_init(struct socket *sock, struct sock *sk)
{ {
sk->type = sock->type; sk->type = sock->type;
...@@ -296,12 +195,10 @@ static int llc_ui_release(struct socket *sock) ...@@ -296,12 +195,10 @@ static int llc_ui_release(struct socket *sock)
llc->laddr.lsap, llc->daddr.lsap); llc->laddr.lsap, llc->daddr.lsap);
if (!llc_send_disc(sk)) if (!llc_send_disc(sk))
llc_ui_wait_for_disc(sk, sk->rcvtimeo); llc_ui_wait_for_disc(sk, sk->rcvtimeo);
if (!sk->zapped) { if (!sk->zapped)
llc_sap_unassign_sock(llc->sap, sk); llc_sap_unassign_sock(llc->sap, sk);
llc_ui_remove_socket(sk);
}
release_sock(sk); release_sock(sk);
if (llc->sap && list_empty(&llc->sap->sk_list.list)) if (llc->sap && !llc->sap->sk_list.list)
llc_sap_close(llc->sap); llc_sap_close(llc->sap);
sock_put(sk); sock_put(sk);
llc_sk_free(sk); llc_sk_free(sk);
...@@ -384,8 +281,7 @@ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr) ...@@ -384,8 +281,7 @@ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr)
} }
sap = llc_sap_find(addr->sllc_ssap); sap = llc_sap_find(addr->sllc_ssap);
if (!sap) { if (!sap) {
sap = llc_sap_open(llc_ui_indicate, llc_ui_confirm, sap = llc_sap_open(addr->sllc_ssap, NULL);
addr->sllc_ssap);
rc = -EBUSY; /* some other network layer is using the sap */ rc = -EBUSY; /* some other network layer is using the sap */
if (!sap) if (!sap)
goto out; goto out;
...@@ -420,7 +316,6 @@ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr) ...@@ -420,7 +316,6 @@ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr)
llc->daddr.lsap = addr->sllc_dsap; llc->daddr.lsap = addr->sllc_dsap;
memcpy(llc->daddr.mac, addr->sllc_dmac, IFHWADDRLEN); memcpy(llc->daddr.mac, addr->sllc_dmac, IFHWADDRLEN);
memcpy(&llc->addr, addr, sizeof(llc->addr)); memcpy(&llc->addr, addr, sizeof(llc->addr));
llc_ui_insert_socket(sk);
/* assign new connection to it's SAP */ /* assign new connection to it's SAP */
llc_sap_assign_sock(sap, sk); llc_sap_assign_sock(sap, sk);
rc = sk->zapped = 0; rc = sk->zapped = 0;
...@@ -769,7 +664,6 @@ static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags) ...@@ -769,7 +664,6 @@ static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags)
/* put original socket back into a clean listen state. */ /* put original socket back into a clean listen state. */
sk->state = TCP_LISTEN; sk->state = TCP_LISTEN;
sk->ack_backlog--; sk->ack_backlog--;
llc_ui_insert_socket(newsk);
skb->sk = NULL; skb->sk = NULL;
dprintk("%s: ok success on %02X, client on %02X\n", __FUNCTION__, dprintk("%s: ok success on %02X, client on %02X\n", __FUNCTION__,
llc_sk(sk)->addr.sllc_ssap, newllc->addr.sllc_dsap); llc_sk(sk)->addr.sllc_ssap, newllc->addr.sllc_dsap);
...@@ -1126,178 +1020,6 @@ static int llc_ui_getsockopt(struct socket *sock, int level, int optname, ...@@ -1126,178 +1020,6 @@ static int llc_ui_getsockopt(struct socket *sock, int level, int optname,
return rc; return rc;
} }
/**
* llc_ui_ind_test - handle TEST indication
* @prim: Primitive block provided by the llc layer.
*
* handle TEST indication.
*/
static void llc_ui_ind_test(struct llc_prim_if_block *prim)
{
struct llc_prim_test *prim_data = &prim->data->test;
struct sk_buff *skb = prim_data->skb;
struct sockaddr_llc *addr = llc_ui_skb_cb(skb);
struct sock *sk = llc_ui_find_sk_by_addr(&prim_data->daddr,
&prim_data->saddr, skb->dev);
if (!sk)
goto out;
if (sk->state == TCP_LISTEN)
goto out_put;
/* save primitive for use by the user. */
addr->sllc_family = AF_LLC;
addr->sllc_arphrd = skb->dev->type;
addr->sllc_test = 1;
addr->sllc_xid = 0;
addr->sllc_ua = 0;
addr->sllc_dsap = prim_data->daddr.lsap;
memcpy(addr->sllc_dmac, prim_data->daddr.mac, IFHWADDRLEN);
addr->sllc_ssap = prim_data->saddr.lsap;
memcpy(addr->sllc_smac, prim_data->saddr.mac, IFHWADDRLEN);
/* queue skb to the user. */
if (sock_queue_rcv_skb(sk, skb))
kfree_skb(skb);
out_put:
sock_put(sk);
out:;
}
/**
* llc_ui_ind_xid - handle XID indication
* @prim: Primitive block provided by the llc layer.
*
* handle XID indication.
*/
static void llc_ui_ind_xid(struct llc_prim_if_block *prim)
{
struct llc_prim_xid *prim_data = &prim->data->xid;
struct sk_buff *skb = prim_data->skb;
struct sockaddr_llc *addr = llc_ui_skb_cb(skb);
struct sock *sk = llc_ui_find_sk_by_addr(&prim_data->daddr,
&prim_data->saddr, skb->dev);
if (!sk)
goto out;
if (sk->state == TCP_LISTEN)
goto out_put;
/* save primitive for use by the user. */
addr->sllc_family = AF_LLC;
addr->sllc_arphrd = 0;
addr->sllc_test = 0;
addr->sllc_xid = 1;
addr->sllc_ua = 0;
addr->sllc_dsap = prim_data->daddr.lsap;
memcpy(addr->sllc_dmac, prim_data->daddr.mac, IFHWADDRLEN);
addr->sllc_ssap = prim_data->saddr.lsap;
memcpy(addr->sllc_smac, prim_data->saddr.mac, IFHWADDRLEN);
/* queue skb to the user. */
if (sock_queue_rcv_skb(sk, skb))
kfree_skb(skb);
out_put:
sock_put(sk);
out:;
}
/**
* llc_ui_ind_dataunit - handle DATAUNIT indication
* @prim: Primitive block provided by the llc layer.
*
* handle DATAUNIT indication.
*/
static void llc_ui_ind_dataunit(struct llc_prim_if_block *prim)
{
struct llc_prim_unit_data *prim_data = &prim->data->udata;
struct sk_buff *skb = prim_data->skb;
struct sockaddr_llc *addr = llc_ui_skb_cb(skb);
struct sock *sk = llc_ui_find_sk_by_addr(&prim_data->daddr,
&prim_data->saddr, skb->dev);
if (!sk)
goto out;
if (sk->state == TCP_LISTEN)
goto out_put;
/* save primitive for use by the user. */
addr->sllc_family = AF_LLC;
addr->sllc_arphrd = skb->dev->type;
addr->sllc_test = 0;
addr->sllc_xid = 0;
addr->sllc_ua = 1;
addr->sllc_dsap = prim_data->daddr.lsap;
memcpy(addr->sllc_dmac, prim_data->daddr.mac, IFHWADDRLEN);
addr->sllc_ssap = prim_data->saddr.lsap;
memcpy(addr->sllc_smac, prim_data->saddr.mac, IFHWADDRLEN);
/* queue skb to the user. */
if (sock_queue_rcv_skb(sk, skb))
kfree_skb(skb);
out_put:
sock_put(sk);
out:;
}
/**
* llc_ui_indicate - LLC user interface hook into the LLC layer.
* @prim: Primitive block provided by the llc layer.
*
* LLC user interface hook into the LLC layer, every llc_ui sap references
* this function as its indicate handler.
* Always returns 0 to indicate reception of primitive.
*/
static int llc_ui_indicate(struct llc_prim_if_block *prim)
{
switch (prim->prim) {
case LLC_TEST_PRIM:
llc_ui_ind_test(prim); break;
case LLC_XID_PRIM:
llc_ui_ind_xid(prim); break;
case LLC_DATAUNIT_PRIM:
llc_ui_ind_dataunit(prim); break;
case LLC_CONN_PRIM:
dprintk("%s: shouldn't happen, LLC_CONN_PRIM "
"is gone for ->ind()...\n", __FUNCTION__);
break;
case LLC_DATA_PRIM:
dprintk("%s: shouldn't happen, LLC_DATA_PRIM "
"is gone for ->ind()...\n", __FUNCTION__);
break;
case LLC_DISC_PRIM:
dprintk("%s: shouldn't happen, LLC_DISC_PRIM "
"is gone for ->ind()...\n", __FUNCTION__);
break;
case LLC_RESET_PRIM:
default: break;
}
return 0;
}
/**
* llc_ui_confirm - LLC user interface hook into the LLC layer
* @prim: Primitive block provided by the llc layer.
*
* LLC user interface hook into the LLC layer, every llc_ui sap references
* this function as its confirm handler.
* Always returns 0 to indicate reception of primitive.
*/
static int llc_ui_confirm(struct llc_prim_if_block *prim)
{
switch (prim->prim) {
case LLC_CONN_PRIM:
dprintk("%s: shouldn't happen, LLC_CONN_PRIM "
"is gone for ->conf()...\n", __FUNCTION__);
break;
case LLC_DATA_PRIM:
dprintk("%s: shouldn't happen, LLC_DATA_PRIM "
"is gone for ->conf()...\n", __FUNCTION__);
break;
case LLC_DISC_PRIM:
dprintk("%s: shouldn't happen, LLC_DISC_PRIM "
"is gone for ->conf()...\n", __FUNCTION__);
break;
case LLC_RESET_PRIM: break;
default:
printk(KERN_ERR "%s: prim not supported%d\n", __FUNCTION__,
prim->prim);
break;
}
return 0;
}
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
#define MAC_FORMATTED_SIZE 17 #define MAC_FORMATTED_SIZE 17
static void llc_ui_format_mac(char *bf, unsigned char *mac) static void llc_ui_format_mac(char *bf, unsigned char *mac)
...@@ -1320,25 +1042,24 @@ static int llc_ui_get_info(char *buffer, char **start, off_t offset, int length) ...@@ -1320,25 +1042,24 @@ static int llc_ui_get_info(char *buffer, char **start, off_t offset, int length)
{ {
off_t pos = 0; off_t pos = 0;
off_t begin = 0; off_t begin = 0;
struct llc_opt *llc;
struct llc_sap *sap; struct llc_sap *sap;
struct list_head *sap_entry, *llc_entry; struct sock *sk;
struct list_head *sap_entry;
struct llc_station *station = llc_station_get(); struct llc_station *station = llc_station_get();
int len = sprintf(buffer, "SKt Mc local_mac_sap " int len = sprintf(buffer, "SKt Mc local_mac_sap "
"remote_mac_sap tx_queue rx_queue st uid " "remote_mac_sap tx_queue rx_queue st uid "
"link\n"); "link\n");
/* Output the LLC socket data for the /proc filesystem */ /* Output the LLC socket data for the /proc filesystem */
spin_lock_bh(&station->sap_list.lock); read_lock_bh(&station->sap_list.lock);
list_for_each(sap_entry, &station->sap_list.list) { list_for_each(sap_entry, &station->sap_list.list) {
sap = list_entry(sap_entry, struct llc_sap, node); sap = list_entry(sap_entry, struct llc_sap, node);
spin_lock_bh(&sap->sk_list.lock); read_lock_bh(&sap->sk_list.lock);
list_for_each(llc_entry, &sap->sk_list.list) { for (sk = sap->sk_list.list; sk; sk = sk->next) {
llc = list_entry(llc_entry, struct llc_opt, node); struct llc_opt *llc = llc_sk(sk);
len += sprintf(buffer + len, "%2X %2X ", len += sprintf(buffer + len, "%2X %2X ", sk->type,
llc->sk->type,
!llc_mac_null(llc->addr.sllc_mmac)); !llc_mac_null(llc->addr.sllc_mmac));
if (llc->dev && llc_mac_null(llc->addr.sllc_mmac)) if (llc->dev && llc_mac_null(llc->addr.sllc_mmac))
llc_ui_format_mac(buffer + len, llc_ui_format_mac(buffer + len,
...@@ -1358,12 +1079,11 @@ static int llc_ui_get_info(char *buffer, char **start, off_t offset, int length) ...@@ -1358,12 +1079,11 @@ static int llc_ui_get_info(char *buffer, char **start, off_t offset, int length)
len += sprintf(buffer + len, len += sprintf(buffer + len,
"@%02X %8d %8d %2d %3d ", "@%02X %8d %8d %2d %3d ",
llc->addr.sllc_dsap, llc->addr.sllc_dsap,
atomic_read(&llc->sk->wmem_alloc), atomic_read(&sk->wmem_alloc),
atomic_read(&llc->sk->rmem_alloc), atomic_read(&sk->rmem_alloc),
llc->sk->state, sk->state,
llc->sk->socket ? sk->socket ?
SOCK_INODE(llc->sk->socket)->i_uid : SOCK_INODE(sk->socket)->i_uid : -1);
-1);
len += sprintf(buffer + len, "%4d\n", llc->link); len += sprintf(buffer + len, "%4d\n", llc->link);
/* Are we still dumping unwanted data then discard the record */ /* Are we still dumping unwanted data then discard the record */
pos = begin + len; pos = begin + len;
...@@ -1375,9 +1095,9 @@ static int llc_ui_get_info(char *buffer, char **start, off_t offset, int length) ...@@ -1375,9 +1095,9 @@ static int llc_ui_get_info(char *buffer, char **start, off_t offset, int length)
if (pos > offset + length) /* We have dumped enough */ if (pos > offset + length) /* We have dumped enough */
break; break;
} }
spin_unlock_bh(&sap->sk_list.lock); read_unlock_bh(&sap->sk_list.lock);
} }
spin_unlock_bh(&station->sap_list.lock); read_unlock_bh(&station->sap_list.lock);
/* The data in question runs from begin to begin + len */ /* The data in question runs from begin to begin + len */
*start = buffer + offset - begin; /* Start of wanted data */ *start = buffer + offset - begin; /* Start of wanted data */
...@@ -1393,7 +1113,7 @@ static struct net_proto_family llc_ui_family_ops = { ...@@ -1393,7 +1113,7 @@ static struct net_proto_family llc_ui_family_ops = {
.create = llc_ui_create, .create = llc_ui_create,
}; };
static struct proto_ops SOCKOPS_WRAPPED(llc_ui_ops) = { static struct proto_ops llc_ui_ops = {
.family = PF_LLC, .family = PF_LLC,
.release = llc_ui_release, .release = llc_ui_release,
.bind = llc_ui_bind, .bind = llc_ui_bind,
...@@ -1413,9 +1133,6 @@ static struct proto_ops SOCKOPS_WRAPPED(llc_ui_ops) = { ...@@ -1413,9 +1133,6 @@ static struct proto_ops SOCKOPS_WRAPPED(llc_ui_ops) = {
.sendpage = sock_no_sendpage, .sendpage = sock_no_sendpage,
}; };
#include <linux/smp_lock.h>
SOCKOPS_WRAP(llc_ui, PF_LLC);
static char llc_ui_banner[] __initdata = static char llc_ui_banner[] __initdata =
KERN_INFO "NET4.0 IEEE 802.2 BSD sockets, Jay Schulist, 2001, Arnaldo C. Melo, 2002\n"; KERN_INFO "NET4.0 IEEE 802.2 BSD sockets, Jay Schulist, 2001, Arnaldo C. Melo, 2002\n";
......
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