Commit a0aaef1c authored by David S. Miller's avatar David S. Miller

Merge bk://kernel.bkbits.net/acme/llc-2.6

into nuts.ninka.net:/disk1/davem/BK/net-2.5
parents 91d4dbf2 874d7485
......@@ -9,7 +9,7 @@ menu "Token Ring devices"
config TR
bool "Token Ring driver support"
depends on (PCI || ISA || MCA || CCW)
select LLC_CORE
select LLC
help
Token Ring is IBM's way of communication on a local network; the
rest of the world uses Ethernet. To participate on a Token Ring
......
#ifndef LLC_MAC_H
#define LLC_MAC_H
#ifndef LLC_H
#define LLC_H
/*
* Copyright (c) 1997 by Procom Technology, Inc.
* 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
......@@ -12,18 +12,80 @@
* See the GNU General Public License for more details.
*/
#include <linux/if.h>
#include <linux/if_ether.h>
#include <linux/list.h>
#include <linux/spinlock.h>
struct net_device;
struct packet_type;
struct sk_buff;
struct llc_addr {
unsigned char lsap;
unsigned char mac[IFHWADDRLEN];
};
#define LLC_SAP_STATE_INACTIVE 1
#define LLC_SAP_STATE_ACTIVE 2
/**
* struct llc_sap - Defines the SAP component
*
* @station - station this sap belongs to
* @state - sap state
* @p_bit - only lowest-order bit used
* @f_bit - only lowest-order bit used
* @laddr - SAP value in this 'lsap'
* @node - entry in station sap_list
* @sk_list - LLC sockets this one manages
*/
struct llc_sap {
unsigned char state;
unsigned char p_bit;
unsigned char f_bit;
int (*rcv_func)(struct sk_buff *skb,
struct net_device *dev,
struct packet_type *pt);
struct llc_addr laddr;
struct list_head node;
struct {
rwlock_t lock;
struct hlist_head list;
} sk_list;
};
#define LLC_DEST_INVALID 0 /* Invalid LLC PDU type */
#define LLC_DEST_SAP 1 /* Type 1 goes here */
#define LLC_DEST_CONN 2 /* Type 2 goes here */
extern struct list_head llc_sap_list;
extern rwlock_t llc_sap_list_lock;
extern unsigned char llc_station_mac_sa[ETH_ALEN];
extern int llc_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt);
extern u16 lan_hdrs_init(struct sk_buff *skb, u8 *sa, u8 *da);
struct llc_sap;
struct sk_buff;
extern int llc_mac_hdr_init(struct sk_buff *skb,
unsigned char *sa, unsigned char *da);
extern void llc_add_pack(int type, void (*handler)(struct llc_sap *sap,
struct sk_buff *skb));
extern void llc_remove_pack(int type);
#endif /* LLC_MAC_H */
extern void llc_set_station_handler(void (*handler)(struct sk_buff *skb));
extern struct llc_sap *llc_sap_open(unsigned char lsap,
int (*rcv)(struct sk_buff *skb,
struct net_device *dev,
struct packet_type *pt));
extern void llc_sap_close(struct llc_sap *sap);
extern struct llc_sap *llc_sap_find(unsigned char sap_value);
extern int llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb,
unsigned char *dmac, unsigned char dsap);
extern int llc_station_init(void);
extern void llc_station_exit(void);
#endif /* LLC_H */
#ifndef LLC_ACTN_H
#define LLC_ACTN_H
/*
* 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.
*/
/* Station component state transition actions */
#define LLC_STATION_AC_START_ACK_TMR 1
#define LLC_STATION_AC_SET_RETRY_CNT_0 2
#define LLC_STATION_AC_INC_RETRY_CNT_BY_1 3
#define LLC_STATION_AC_SET_XID_R_CNT_0 4
#define LLC_STATION_AC_INC_XID_R_CNT_BY_1 5
#define LLC_STATION_AC_SEND_NULL_DSAP_XID_C 6
#define LLC_STATION_AC_SEND_XID_R 7
#define LLC_STATION_AC_SEND_TEST_R 8
#define LLC_STATION_AC_REPORT_STATUS 9
/* All station state event action functions look like this */
typedef int (*llc_station_action_t)(struct llc_station *station,
struct sk_buff *skb);
extern int llc_station_ac_start_ack_timer(struct llc_station *station,
struct sk_buff *skb);
extern int llc_station_ac_set_retry_cnt_0(struct llc_station *station,
struct sk_buff *skb);
extern int llc_station_ac_inc_retry_cnt_by_1(struct llc_station *station,
struct sk_buff *skb);
extern int llc_station_ac_set_xid_r_cnt_0(struct llc_station *station,
struct sk_buff *skb);
extern int llc_station_ac_inc_xid_r_cnt_by_1(struct llc_station *station,
struct sk_buff *skb);
extern int llc_station_ac_send_null_dsap_xid_c(struct llc_station *station,
struct sk_buff *skb);
extern int llc_station_ac_send_xid_r(struct llc_station *station,
struct sk_buff *skb);
extern int llc_station_ac_send_test_r(struct llc_station *station,
struct sk_buff *skb);
extern int llc_station_ac_report_status(struct llc_station *station,
struct sk_buff *skb);
extern int llc_station_ac_report_status(struct llc_station *station,
struct sk_buff *skb);
extern void llc_station_ack_tmr_cb(unsigned long timeout_data);
#endif /* LLC_ACTN_H */
......@@ -15,6 +15,14 @@
#include <net/llc_if.h>
#include <linux/llc.h>
#define LLC_EVENT 1
#define LLC_PACKET 2
#define LLC_P_TIME 2
#define LLC_ACK_TIME 1
#define LLC_REJ_TIME 3
#define LLC_BUSY_TIME 3
struct llc_timer {
struct timer_list timer;
u16 expire; /* timer expire time */
......
#ifndef LLC_EVNT_H
#define LLC_EVNT_H
/*
* 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.
*/
/* Station component state transition events */
/* Types of events (possible values in 'ev->type') */
#define LLC_STATION_EV_TYPE_SIMPLE 1
#define LLC_STATION_EV_TYPE_CONDITION 2
#define LLC_STATION_EV_TYPE_PRIM 3
#define LLC_STATION_EV_TYPE_PDU 4 /* command/response PDU */
#define LLC_STATION_EV_TYPE_ACK_TMR 5
#define LLC_STATION_EV_TYPE_RPT_STATUS 6
/* Events */
#define LLC_STATION_EV_ENABLE_WITH_DUP_ADDR_CHECK 1
#define LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK 2
#define LLC_STATION_EV_ACK_TMR_EXP_LT_RETRY_CNT_MAX_RETRY 3
#define LLC_STATION_EV_ACK_TMR_EXP_EQ_RETRY_CNT_MAX_RETRY 4
#define LLC_STATION_EV_RX_NULL_DSAP_XID_C 5
#define LLC_STATION_EV_RX_NULL_DSAP_0_XID_R_XID_R_CNT_EQ 6
#define LLC_STATION_EV_RX_NULL_DSAP_1_XID_R_XID_R_CNT_EQ 7
#define LLC_STATION_EV_RX_NULL_DSAP_TEST_C 8
#define LLC_STATION_EV_DISABLE_REQ 9
struct llc_station_state_ev {
u8 type;
u8 prim;
u8 prim_type;
u8 reason;
struct list_head node; /* node in station->ev_q.list */
};
static __inline__ struct llc_station_state_ev *
llc_station_ev(struct sk_buff *skb)
{
return (struct llc_station_state_ev *)skb->cb;
}
typedef int (*llc_station_ev_t)(struct llc_station *station,
struct sk_buff *skb);
extern int llc_stat_ev_enable_with_dup_addr_check(struct llc_station *station,
struct sk_buff *skb);
extern int llc_stat_ev_enable_without_dup_addr_check(struct llc_station *station,
struct sk_buff *skb);
extern int llc_stat_ev_ack_tmr_exp_lt_retry_cnt_max_retry(struct llc_station *
station,
struct sk_buff *skb);
extern int llc_stat_ev_ack_tmr_exp_eq_retry_cnt_max_retry(struct llc_station *station,
struct sk_buff *skb);
extern int llc_stat_ev_rx_null_dsap_xid_c(struct llc_station *station,
struct sk_buff *skb);
extern int llc_stat_ev_rx_null_dsap_0_xid_r_xid_r_cnt_eq(struct llc_station *station,
struct sk_buff *skb);
extern int llc_stat_ev_rx_null_dsap_1_xid_r_xid_r_cnt_eq(struct llc_station *station,
struct sk_buff *skb);
extern int llc_stat_ev_rx_null_dsap_test_c(struct llc_station *station,
struct sk_buff *skb);
extern int llc_stat_ev_disable_req(struct llc_station *station,
struct sk_buff *skb);
#endif /* LLC_EVNT_H */
......@@ -16,6 +16,7 @@
#include <linux/if.h>
#include <linux/if_arp.h>
#include <linux/llc.h>
#include <net/llc.h>
#define LLC_DATAUNIT_PRIM 1
#define LLC_CONN_PRIM 2
......@@ -60,13 +61,6 @@
#define LLC_STATUS_CONFLICT 7 /* disconnect conn */
#define LLC_STATUS_RESET_DONE 8 /* */
/* Structures and types */
/* SAP/MAC Address pair */
struct llc_addr {
u8 lsap;
u8 mac[IFHWADDRLEN];
};
extern u8 llc_mac_null_var[IFHWADDRLEN];
/**
......
#ifndef LLC_MAIN_H
#define LLC_MAIN_H
/*
* 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.
*/
#define LLC_EVENT 1
#define LLC_PACKET 2
#define LLC_TYPE_1 1
#define LLC_TYPE_2 2
#define LLC_P_TIME 2
#define LLC_ACK_TIME 1
#define LLC_REJ_TIME 3
#define LLC_BUSY_TIME 3
/**
* struct llc_station - LLC station component
*
* SAP and connection resource manager, one per adapter.
*
* @state - state of station
* @xid_r_count - XID response PDU counter
* @mac_sa - MAC source address
* @sap_list - list of related SAPs
* @ev_q - events entering state mach.
* @mac_pdu_q - PDUs ready to send to MAC
*/
struct llc_station {
u8 state;
u8 xid_r_count;
struct timer_list ack_timer;
u8 retry_count;
u8 maximum_retry;
u8 mac_sa[6];
struct {
rwlock_t lock;
struct list_head list;
} sap_list;
struct {
struct sk_buff_head list;
spinlock_t lock;
} ev_q;
struct sk_buff_head mac_pdu_q;
};
extern struct llc_sap *llc_sap_alloc(void);
extern void llc_sap_save(struct llc_sap *sap);
extern void llc_free_sap(struct llc_sap *sap);
extern struct llc_sap *llc_sap_find(u8 lsap);
extern void llc_station_state_process(struct llc_station *station,
struct sk_buff *skb);
extern void llc_station_send_pdu(struct llc_station *station,
struct sk_buff *skb);
extern struct sk_buff *llc_alloc_frame(void);
extern struct llc_station llc_main_station;
#endif /* LLC_MAIN_H */
......@@ -11,10 +11,7 @@
*
* See the GNU General Public License for more details.
*/
/* Defines SAP component states */
#define LLC_SAP_STATE_INACTIVE 1
#define LLC_SAP_STATE_ACTIVE 2
#define LLC_NR_SAP_STATES 2 /* size of state table */
/* structures and types */
......
......@@ -2,7 +2,7 @@
#define LLC_SAP_H
/*
* Copyright (c) 1997 by Procom Technology,Inc.
* 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
* 2001-2003 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.
......@@ -11,50 +11,20 @@
*
* See the GNU General Public License for more details.
*/
#include <linux/skbuff.h>
#include <net/llc_if.h>
/**
* struct llc_sap - Defines the SAP component
*
* @station - station this sap belongs to
* @state - sap state
* @p_bit - only lowest-order bit used
* @f_bit - only lowest-order bit used
* @laddr - SAP value in this 'lsap'
* @node - entry in station sap_list
* @sk_list - LLC sockets this one manages
*/
struct llc_sap {
struct llc_station *station;
u8 state;
u8 p_bit;
u8 f_bit;
int (*rcv_func)(struct sk_buff *skb,
struct net_device *dev,
struct packet_type *pt);
struct llc_addr laddr;
struct list_head node;
struct {
rwlock_t lock;
struct hlist_head list;
} sk_list;
};
struct llc_sap;
struct sk_buff;
extern void llc_sap_state_process(struct llc_sap *sap, struct sk_buff *skb);
extern void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb);
extern void llc_save_primitive(struct sk_buff* skb, u8 prim);
extern void llc_save_primitive(struct sk_buff* skb, unsigned char prim);
extern struct sk_buff *llc_alloc_frame(void);
extern struct llc_sap *llc_sap_open(u8 lsap,
int (*rcv)(struct sk_buff *skb,
struct net_device *dev,
struct packet_type *pt));
extern void llc_sap_close(struct llc_sap *sap);
extern void llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb,
u8 *dmac, u8 dsap);
extern void llc_build_and_send_xid_pkt(struct llc_sap *sap, struct sk_buff *skb,
u8 *dmac, u8 dsap);
extern void llc_build_and_send_test_pkt(struct llc_sap *sap,
struct sk_buff *skb, u8 *dmac, u8 dsap);
struct sk_buff *skb,
unsigned char *dmac,
unsigned char dsap);
extern void llc_build_and_send_xid_pkt(struct llc_sap *sap,
struct sk_buff *skb,
unsigned char *dmac,
unsigned char dsap);
#endif /* LLC_SAP_H */
#ifndef LLC_STAT_H
#define LLC_STAT_H
/*
* 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.
*/
/* Station component state table */
/* Station component states */
#define LLC_STATION_STATE_DOWN 1 /* initial state */
#define LLC_STATION_STATE_DUP_ADDR_CHK 2
#define LLC_STATION_STATE_UP 3
#define LLC_NBR_STATION_STATES 3 /* size of state table */
/* Station component state table structure */
struct llc_station_state_trans {
llc_station_ev_t ev;
u8 next_state;
llc_station_action_t *ev_actions;
};
struct llc_station_state {
u8 curr_state;
struct llc_station_state_trans **transitions;
};
extern struct llc_station_state llc_station_state_table[LLC_NBR_STATION_STATES];
#endif /* LLC_STAT_H */
......@@ -22,8 +22,8 @@
#include <linux/mm.h>
#include <linux/in.h>
#include <linux/init.h>
#include <net/llc.h>
#include <net/p8022.h>
#include <net/llc_sap.h>
static int p8022_request(struct datalink_proto *dl, struct sk_buff *skb,
unsigned char *dest)
......
......@@ -15,8 +15,8 @@
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/datalink.h>
#include <net/llc.h>
#include <net/psnap.h>
#include <net/llc_sap.h>
#include <linux/mm.h>
#include <linux/in.h>
#include <linux/init.h>
......
......@@ -374,7 +374,7 @@ source "net/llc/Kconfig"
config IPX
tristate "The IPX protocol"
select LLC_CORE
select LLC
---help---
This is support for the Novell networking protocol, IPX, commonly
used for local networks of Windows machines. You need it if you
......@@ -411,7 +411,7 @@ source "net/ipx/Kconfig"
config ATALK
tristate "Appletalk protocol support"
select LLC_CORE
select LLC
---help---
AppleTalk is the protocol that Apple computers can use to communicate
on a network. If your Linux box is connected to such a network and you
......
......@@ -12,7 +12,7 @@ obj-$(CONFIG_NET) := socket.o core/
obj-$(CONFIG_COMPAT) += compat.o
# LLC has to be linked before the files in net/802/
obj-$(CONFIG_LLC_CORE) += llc/
obj-$(CONFIG_LLC) += llc/
obj-$(CONFIG_NET) += ethernet/ 802/ sched/ netlink/
obj-$(CONFIG_INET) += ipv4/ xfrm/
obj-$(CONFIG_UNIX) += unix/
......
config LLC_CORE
config LLC
tristate
depends on NET
config LLC2
tristate "ANSI/IEEE 802.2 LLC type 2 Support"
select LLC_CORE
select LLC
help
This is a Logical Link Layer type 2, connection oriented support.
Select this if you want to have support for PF_LLC sockets.
......@@ -12,14 +12,13 @@
# See the GNU General Public License for more details.
###########################################################################
obj-$(CONFIG_LLC_CORE) += llc_core.o
obj-$(CONFIG_LLC) += llc.o
llc_core-y := llc_mac.o llc_sap.o llc_s_st.o llc_s_ac.o llc_s_ev.o llc_main.o \
llc_actn.o llc_stat.o llc_evnt.o
llc-y := llc_core.o llc_input.o llc_output.o
obj-$(CONFIG_LLC2) += llc2.o
llc2-y := llc_if.o llc_c_ev.o llc_c_ac.o llc_conn.o llc_c_st.o llc_pdu.o \
af_llc.o
llc_sap.o llc_s_ac.o llc_s_ev.o llc_s_st.o af_llc.o llc_station.o
llc2-$(CONFIG_PROC_FS) += llc_proc.o
......@@ -24,14 +24,13 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/tcp.h>
#include <linux/rtnetlink.h>
#include <linux/init.h>
#include <net/llc.h>
#include <net/llc_sap.h>
#include <net/llc_pdu.h>
#include <net/llc_conn.h>
#include <net/llc_mac.h>
#include <net/llc_main.h>
#include <net/llc_proc.h>
#include <linux/rtnetlink.h>
#include <linux/init.h>
/* remember: uninitialized global data is zeroed because its in .bss */
static u16 llc_ui_sap_last_autoport = LLC_SAP_DYN_START;
......@@ -1053,6 +1052,7 @@ static int __init llc2_init(void)
int rc;
llc_build_offset_table();
llc_station_init();
llc_ui_sap_last_autoport = LLC_SAP_DYN_START;
rc = llc_proc_init();
if (!rc) {
......@@ -1065,6 +1065,7 @@ static int __init llc2_init(void)
static void __exit llc2_exit(void)
{
llc_station_exit();
llc_remove_pack(LLC_DEST_SAP);
llc_remove_pack(LLC_DEST_CONN);
sock_unregister(PF_LLC);
......
/*
* llc_actn.c - Implementation of actions of station component of LLC
*
* Description :
* Functions in this module are implementation of station component actions.
* Details of actions can be found in IEEE-802.2 standard document.
* All functions have one station and one event as input argument. All of
* them return 0 On success and 1 otherwise.
*
* Copyright (c) 1997 by Procom Technology, Inc.
* 2001-2003 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/netdevice.h>
#include <net/llc_if.h>
#include <net/llc_main.h>
#include <net/llc_evnt.h>
#include <net/llc_pdu.h>
#include <net/llc_mac.h>
int llc_station_ac_start_ack_timer(struct llc_station *station,
struct sk_buff *skb)
{
mod_timer(&station->ack_timer, jiffies + LLC_ACK_TIME * HZ);
return 0;
}
int llc_station_ac_set_retry_cnt_0(struct llc_station *station,
struct sk_buff *skb)
{
station->retry_count = 0;
return 0;
}
int llc_station_ac_inc_retry_cnt_by_1(struct llc_station *station,
struct sk_buff *skb)
{
station->retry_count++;
return 0;
}
int llc_station_ac_set_xid_r_cnt_0(struct llc_station *station,
struct sk_buff *skb)
{
station->xid_r_count = 0;
return 0;
}
int llc_station_ac_inc_xid_r_cnt_by_1(struct llc_station *station,
struct sk_buff *skb)
{
station->xid_r_count++;
return 0;
}
int llc_station_ac_send_null_dsap_xid_c(struct llc_station *station,
struct sk_buff *skb)
{
int rc = 1;
struct sk_buff *nskb = llc_alloc_frame();
if (!nskb)
goto out;
rc = 0;
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, 0, LLC_PDU_CMD);
llc_pdu_init_as_xid_cmd(nskb, LLC_XID_NULL_CLASS_2, 127);
lan_hdrs_init(nskb, station->mac_sa, station->mac_sa);
llc_station_send_pdu(station, nskb);
out:
return rc;
}
int llc_station_ac_send_xid_r(struct llc_station *station,
struct sk_buff *skb)
{
u8 mac_da[ETH_ALEN], dsap;
int rc = 1;
struct sk_buff* nskb = llc_alloc_frame();
if (!nskb)
goto out;
rc = 0;
nskb->dev = skb->dev;
llc_pdu_decode_sa(skb, mac_da);
llc_pdu_decode_ssap(skb, &dsap);
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP);
llc_pdu_init_as_xid_rsp(nskb, LLC_XID_NULL_CLASS_2, 127);
lan_hdrs_init(nskb, station->mac_sa, mac_da);
llc_station_send_pdu(station, nskb);
out:
return rc;
}
int llc_station_ac_send_test_r(struct llc_station *station,
struct sk_buff *skb)
{
u8 mac_da[ETH_ALEN], dsap;
int rc = 1;
struct sk_buff *nskb = llc_alloc_frame();
if (!nskb)
goto out;
rc = 0;
nskb->dev = skb->dev;
llc_pdu_decode_sa(skb, mac_da);
llc_pdu_decode_ssap(skb, &dsap);
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP);
llc_pdu_init_as_test_rsp(nskb, skb);
lan_hdrs_init(nskb, station->mac_sa, mac_da);
llc_station_send_pdu(station, nskb);
out:
return rc;
}
int llc_station_ac_report_status(struct llc_station *station,
struct sk_buff *skb)
{
return 0;
}
void llc_station_ack_tmr_cb(unsigned long timeout_data)
{
struct llc_station *station = (struct llc_station *)timeout_data;
struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC);
if (skb) {
struct llc_station_state_ev *ev = llc_station_ev(skb);
ev->type = LLC_STATION_EV_TYPE_ACK_TMR;
llc_station_state_process(station, skb);
}
}
This diff is collapsed.
......@@ -11,21 +11,16 @@
*
* See the GNU General Public License for more details.
*/
#include <linux/netdevice.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <net/llc_if.h>
#include <net/llc_sap.h>
#include <net/llc_conn.h>
#include <net/sock.h>
#include <linux/tcp.h>
#include <net/llc_main.h>
#include <net/llc_c_ev.h>
#include <net/llc_c_ac.h>
#include <net/llc_c_st.h>
#include <net/llc_mac.h>
#include <net/llc_pdu.h>
#include <net/llc_s_ev.h>
#if 0
#define dprintk(args...) printk(KERN_DEBUG args)
......
/*
* llc_core.c - Minimum needed routines for sap handling and module init/exit
*
* Copyright (c) 1997 by Procom Technology, Inc.
* 2001-2003 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/module.h>
#include <linux/interrupt.h>
#include <linux/if_ether.h>
#include <linux/netdevice.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <net/llc.h>
LIST_HEAD(llc_sap_list);
rwlock_t llc_sap_list_lock = RW_LOCK_UNLOCKED;
unsigned char llc_station_mac_sa[ETH_ALEN];
/**
* llc_sap_alloc - allocates and initializes sap.
*
* Allocates and initializes sap.
*/
struct llc_sap *llc_sap_alloc(void)
{
struct llc_sap *sap = kmalloc(sizeof(*sap), GFP_ATOMIC);
if (sap) {
memset(sap, 0, sizeof(*sap));
sap->state = LLC_SAP_STATE_ACTIVE;
memcpy(sap->laddr.mac, llc_station_mac_sa, ETH_ALEN);
rwlock_init(&sap->sk_list.lock);
}
return sap;
}
/**
* llc_add_sap - add sap to station list
* @sap: Address of the sap
*
* Adds a sap to the LLC's station sap list.
*/
void llc_add_sap(struct llc_sap *sap)
{
write_lock_bh(&llc_sap_list_lock);
list_add_tail(&sap->node, &llc_sap_list);
write_unlock_bh(&llc_sap_list_lock);
}
/**
* llc_del_sap - del sap from station list
* @sap: Address of the sap
*
* Removes a sap to the LLC's station sap list.
*/
void llc_del_sap(struct llc_sap *sap)
{
write_lock_bh(&llc_sap_list_lock);
list_del(&sap->node);
write_unlock_bh(&llc_sap_list_lock);
}
/**
* llc_sap_find - searchs a SAP in station
* @sap_value: sap to be found
*
* Searchs for a sap in the sap list of the LLC's station upon the sap ID.
* Returns the sap or %NULL if not found.
*/
struct llc_sap *llc_sap_find(unsigned char sap_value)
{
struct llc_sap* sap = NULL;
struct list_head *entry;
read_lock_bh(&llc_sap_list_lock);
list_for_each(entry, &llc_sap_list) {
sap = list_entry(entry, struct llc_sap, node);
if (sap->laddr.lsap == sap_value)
break;
}
if (entry == &llc_sap_list) /* not found */
sap = NULL;
read_unlock_bh(&llc_sap_list_lock);
return sap;
}
/**
* llc_sap_open - open interface to the upper layers.
* @lsap: SAP number.
* @func: rcv func for datalink protos
*
* Interface function to upper layer. Each one who wants to get a SAP
* (for example NetBEUI) should call this function. Returns the opened
* SAP for success, NULL for failure.
*/
struct llc_sap *llc_sap_open(unsigned char lsap,
int (*func)(struct sk_buff *skb,
struct net_device *dev,
struct packet_type *pt))
{
struct llc_sap *sap = llc_sap_find(lsap);
if (sap) { /* SAP already exists */
sap = NULL;
goto out;
}
sap = llc_sap_alloc();
if (!sap)
goto out;
sap->laddr.lsap = lsap;
sap->rcv_func = func;
llc_add_sap(sap);
out:
return sap;
}
/**
* llc_sap_close - close interface for upper layers.
* @sap: SAP to be closed.
*
* Close interface function to upper layer. Each one who wants to
* close an open SAP (for example NetBEUI) should call this function.
* Removes this sap from the list of saps in the station and then
* frees the memory for this sap.
*/
void llc_sap_close(struct llc_sap *sap)
{
WARN_ON(!hlist_empty(&sap->sk_list.list));
llc_del_sap(sap);
kfree(sap);
}
static struct packet_type llc_packet_type = {
.type = __constant_htons(ETH_P_802_2),
.func = llc_rcv,
.data = (void *)1,
};
static struct packet_type llc_tr_packet_type = {
.type = __constant_htons(ETH_P_TR_802_2),
.func = llc_rcv,
.data = (void *)1,
};
static int __init llc_init(void)
{
if (dev_base->next)
memcpy(llc_station_mac_sa, dev_base->next->dev_addr, ETH_ALEN);
else
memset(llc_station_mac_sa, 0, ETH_ALEN);
dev_add_pack(&llc_packet_type);
dev_add_pack(&llc_tr_packet_type);
return 0;
}
static void __exit llc_exit(void)
{
dev_remove_pack(&llc_packet_type);
dev_remove_pack(&llc_tr_packet_type);
}
module_init(llc_init);
module_exit(llc_exit);
EXPORT_SYMBOL(llc_station_mac_sa);
EXPORT_SYMBOL(llc_sap_list);
EXPORT_SYMBOL(llc_sap_list_lock);
EXPORT_SYMBOL(llc_sap_find);
EXPORT_SYMBOL(llc_sap_open);
EXPORT_SYMBOL(llc_sap_close);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Procom 1997, Jay Schullist 2001, Arnaldo C. Melo 2001-2003");
MODULE_DESCRIPTION("LLC IEEE 802.2 core support");
/*
* llc_evnt.c - LLC station component event match functions
* Description :
* Functions in this module are implementation of station component events.
* Details of events can be found in IEEE-802.2 standard document.
* All functions have one station and one event as input argument. All of
* them return 0 On success and 1 otherwise.
*
* Copyright (c) 1997 by Procom Technology, Inc.
* 2001-2003 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/socket.h>
#include <net/sock.h>
#include <net/llc_if.h>
#include <net/llc_main.h>
#include <net/llc_evnt.h>
#include <net/llc_pdu.h>
int llc_stat_ev_enable_with_dup_addr_check(struct llc_station *station,
struct sk_buff *skb)
{
struct llc_station_state_ev *ev = llc_station_ev(skb);
return ev->type == LLC_STATION_EV_TYPE_SIMPLE &&
ev->prim_type ==
LLC_STATION_EV_ENABLE_WITH_DUP_ADDR_CHECK ? 0 : 1;
}
int llc_stat_ev_enable_without_dup_addr_check(struct llc_station *station,
struct sk_buff *skb)
{
struct llc_station_state_ev *ev = llc_station_ev(skb);
return ev->type == LLC_STATION_EV_TYPE_SIMPLE &&
ev->prim_type ==
LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK ? 0 : 1;
}
int llc_stat_ev_ack_tmr_exp_lt_retry_cnt_max_retry(struct llc_station *station,
struct sk_buff *skb)
{
struct llc_station_state_ev *ev = llc_station_ev(skb);
return ev->type == LLC_STATION_EV_TYPE_ACK_TMR &&
station->retry_count < station->maximum_retry ? 0 : 1;
}
int llc_stat_ev_ack_tmr_exp_eq_retry_cnt_max_retry(struct llc_station *station,
struct sk_buff *skb)
{
struct llc_station_state_ev *ev = llc_station_ev(skb);
return ev->type == LLC_STATION_EV_TYPE_ACK_TMR &&
station->retry_count == station->maximum_retry ? 0 : 1;
}
int llc_stat_ev_rx_null_dsap_xid_c(struct llc_station *station,
struct sk_buff *skb)
{
struct llc_station_state_ev *ev = llc_station_ev(skb);
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
return ev->type == LLC_STATION_EV_TYPE_PDU &&
LLC_PDU_IS_CMD(pdu) && /* command PDU */
LLC_PDU_TYPE_IS_U(pdu) && /* U type PDU */
LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_XID &&
!pdu->dsap ? 0 : 1; /* NULL DSAP value */
}
int llc_stat_ev_rx_null_dsap_0_xid_r_xid_r_cnt_eq(struct llc_station *station,
struct sk_buff *skb)
{
struct llc_station_state_ev *ev = llc_station_ev(skb);
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
return ev->type == LLC_STATION_EV_TYPE_PDU &&
LLC_PDU_IS_RSP(pdu) && /* response PDU */
LLC_PDU_TYPE_IS_U(pdu) && /* U type PDU */
LLC_U_PDU_RSP(pdu) == LLC_1_PDU_CMD_XID &&
!pdu->dsap && /* NULL DSAP value */
!station->xid_r_count ? 0 : 1;
}
int llc_stat_ev_rx_null_dsap_1_xid_r_xid_r_cnt_eq(struct llc_station *station,
struct sk_buff *skb)
{
struct llc_station_state_ev *ev = llc_station_ev(skb);
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
return ev->type == LLC_STATION_EV_TYPE_PDU &&
LLC_PDU_IS_RSP(pdu) && /* response PDU */
LLC_PDU_TYPE_IS_U(pdu) && /* U type PDU */
LLC_U_PDU_RSP(pdu) == LLC_1_PDU_CMD_XID &&
!pdu->dsap && /* NULL DSAP value */
station->xid_r_count == 1 ? 0 : 1;
}
int llc_stat_ev_rx_null_dsap_test_c(struct llc_station *station,
struct sk_buff *skb)
{
struct llc_station_state_ev *ev = llc_station_ev(skb);
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
return ev->type == LLC_STATION_EV_TYPE_PDU &&
LLC_PDU_IS_CMD(pdu) && /* command PDU */
LLC_PDU_TYPE_IS_U(pdu) && /* U type PDU */
LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_TEST &&
!pdu->dsap ? 0 : 1; /* NULL DSAP */
}
int llc_stat_ev_disable_req(struct llc_station *station, struct sk_buff *skb)
{
struct llc_station_state_ev *ev = llc_station_ev(skb);
return ev->type == LLC_STATION_EV_TYPE_PRIM &&
ev->prim == LLC_DISABLE_PRIM &&
ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
}
......@@ -25,7 +25,6 @@
#include <net/llc_c_ev.h>
#include <net/llc_c_ac.h>
#include <net/llc_c_st.h>
#include <net/llc_main.h>
u8 llc_mac_null_var[IFHWADDRLEN];
......
/*
* llc_mac.c - Manages interface between LLC and MAC
* llc_input.c - Minimal input path for LLC
*
* Copyright (c) 1997 by Procom Technology, Inc.
* 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
......@@ -12,15 +12,9 @@
* See the GNU General Public License for more details.
*/
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/if_tr.h>
#include <linux/rtnetlink.h>
#include <net/llc_mac.h>
#include <net/llc.h>
#include <net/llc_pdu.h>
#include <net/llc_sap.h>
#include <net/llc_main.h>
#include <net/llc_evnt.h>
#include <linux/trdevice.h>
#if 0
#define dprintk(args...) printk(KERN_DEBUG args)
......@@ -28,14 +22,19 @@
#define dprintk(args...)
#endif
static int fix_up_incoming_skb(struct sk_buff *skb);
static void llc_station_rcv(struct sk_buff *skb);
/*
* Packet handler for the station, registerable because in the minimal
* LLC core that is taking shape only the very minimal subset of LLC that
* is needed for things like IPX, Appletalk, etc will stay, with all the
* rest in the llc1 and llc2 modules.
*/
static void (*llc_station_handler)(struct sk_buff *skb);
/*
* Packet handlers for LLC_DEST_SAP and LLC_DEST_CONN.
*/
static void (*llc_type_handlers[2])(struct llc_sap *sap,
struct sk_buff *skb);
struct sk_buff *skb);
void llc_add_pack(int type, void (*handler)(struct llc_sap *sap,
struct sk_buff *skb))
......@@ -50,6 +49,11 @@ void llc_remove_pack(int type)
llc_type_handlers[type] = NULL;
}
void llc_set_station_handler(void (*handler)(struct sk_buff *skb))
{
llc_station_handler = handler;
}
/**
* llc_pdu_type - returns which LLC component must handle for PDU
* @skb: input skb
......@@ -83,6 +87,38 @@ static __inline__ int llc_pdu_type(struct sk_buff *skb)
return type;
}
/**
* llc_fixup_skb - initializes skb pointers
* @skb: This argument points to incoming skb
*
* Initializes internal skb pointer to start of network layer by deriving
* length of LLC header; finds length of LLC control field in LLC header
* by looking at the two lowest-order bits of the first control field
* byte; field is either 3 or 4 bytes long.
*/
static inline int llc_fixup_skb(struct sk_buff *skb)
{
u8 llc_len = 2;
struct llc_pdu_sn *pdu;
if (!pskb_may_pull(skb, sizeof(*pdu)))
return 0;
pdu = (struct llc_pdu_sn *)skb->data;
if ((pdu->ctrl_1 & LLC_PDU_TYPE_MASK) == LLC_PDU_TYPE_U)
llc_len = 1;
llc_len += 2;
skb->h.raw += llc_len;
skb_pull(skb, llc_len);
if (skb->protocol == htons(ETH_P_802_2)) {
u16 pdulen = ((struct ethhdr *)skb->mac.raw)->h_proto,
data_size = ntohs(pdulen) - llc_len;
skb_trim(skb, data_size);
}
return 1;
}
/**
* llc_rcv - 802.2 entry point from net lower layers
* @skb: received pdu
......@@ -106,23 +142,20 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev,
* When the interface is in promisc. mode, drop all the crap that it
* receives, do not try to analyse it.
*/
if (skb->pkt_type == PACKET_OTHERHOST) {
if (unlikely(skb->pkt_type == PACKET_OTHERHOST)) {
dprintk("%s: PACKET_OTHERHOST\n", __FUNCTION__);
goto drop;
}
skb = skb_share_check(skb, GFP_ATOMIC);
if (!skb)
if (unlikely(!skb))
goto out;
if (!fix_up_incoming_skb(skb))
if (unlikely(!llc_fixup_skb(skb)))
goto drop;
pdu = llc_pdu_sn_hdr(skb);
if (!pdu->dsap) { /* NULL DSAP, refer to station */
dprintk("%s: calling llc_station_rcv!\n", __FUNCTION__);
llc_station_rcv(skb);
goto out;
}
if (unlikely(!pdu->dsap)) /* NULL DSAP, refer to station */
goto handle_station;
sap = llc_sap_find(pdu->dsap);
if (!sap) {/* unknown SAP */
if (unlikely(!sap)) {/* unknown SAP */
dprintk("%s: llc_sap_find(%02X) failed!\n", __FUNCTION__,
pdu->dsap);
goto drop;
......@@ -144,109 +177,13 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev,
drop:
kfree_skb(skb);
goto out;
}
/**
* fix_up_incoming_skb - initializes skb pointers
* @skb: This argument points to incoming skb
*
* Initializes internal skb pointer to start of network layer by deriving
* length of LLC header; finds length of LLC control field in LLC header
* by looking at the two lowest-order bits of the first control field
* byte; field is either 3 or 4 bytes long.
*/
static int fix_up_incoming_skb(struct sk_buff *skb)
{
u8 llc_len = 2;
struct llc_pdu_sn *pdu;
if (!pskb_may_pull(skb, sizeof(*pdu)))
return 0;
pdu = (struct llc_pdu_sn *)skb->data;
if ((pdu->ctrl_1 & LLC_PDU_TYPE_MASK) == LLC_PDU_TYPE_U)
llc_len = 1;
llc_len += 2;
skb->h.raw += llc_len;
skb_pull(skb, llc_len);
if (skb->protocol == htons(ETH_P_802_2)) {
u16 pdulen = ((struct ethhdr *)skb->mac.raw)->h_proto,
data_size = ntohs(pdulen) - llc_len;
skb_trim(skb, data_size);
}
return 1;
}
/*
* llc_station_rcv - send received pdu to the station state machine
* @skb: received frame.
*
* Sends data unit to station state machine.
*/
static void llc_station_rcv(struct sk_buff *skb)
{
struct llc_station_state_ev *ev = llc_station_ev(skb);
ev->type = LLC_STATION_EV_TYPE_PDU;
ev->reason = 0;
llc_station_state_process(&llc_main_station, skb);
}
/**
* lan_hdrs_init - fills MAC header fields
* @skb: Address of the frame to initialize its MAC header
* @sa: The MAC source address
* @da: The MAC destination address
*
* Fills MAC header fields, depending on MAC type. Returns 0, If MAC type
* is a valid type and initialization completes correctly 1, otherwise.
*/
u16 lan_hdrs_init(struct sk_buff *skb, u8 *sa, u8 *da)
{
u16 rc = 0;
switch (skb->dev->type) {
#ifdef CONFIG_TR
case ARPHRD_IEEE802_TR: {
struct trh_hdr *trh;
struct net_device *dev = skb->dev;
trh = (struct trh_hdr *)skb_push(skb, sizeof(*trh));
trh->ac = AC;
trh->fc = LLC_FRAME;
if (sa)
memcpy(trh->saddr, sa, dev->addr_len);
else
memset(trh->saddr, 0, dev->addr_len);
if (da) {
memcpy(trh->daddr, da, dev->addr_len);
tr_source_route(skb, trh, dev);
}
skb->mac.raw = skb->data;
break;
}
#endif
case ARPHRD_ETHER:
case ARPHRD_LOOPBACK: {
unsigned short len = skb->len;
struct ethhdr *eth;
skb->mac.raw = skb_push(skb, sizeof(*eth));
eth = (struct ethhdr *)skb->mac.raw;
eth->h_proto = htons(len);
memcpy(eth->h_dest, da, ETH_ALEN);
memcpy(eth->h_source, sa, ETH_ALEN);
break;
}
default:
printk(KERN_WARNING "Unknown DEVICE type : %d\n",
skb->dev->type);
rc = 1;
}
return rc;
handle_station:
if (!llc_station_handler)
goto drop;
llc_station_handler(skb);
goto out;
}
EXPORT_SYMBOL(llc_add_pack);
EXPORT_SYMBOL(llc_remove_pack);
EXPORT_SYMBOL(lan_hdrs_init);
EXPORT_SYMBOL(llc_set_station_handler);
This diff is collapsed.
/*
* llc_output.c - LLC minimal output path
*
* Copyright (c) 1997 by Procom Technology, Inc.
* 2001-2003 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 version 2 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 version 2 for more details.
*/
#include <linux/if_arp.h>
#include <linux/if_tr.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/llc.h>
#include <net/llc_pdu.h>
/**
* llc_mac_hdr_init - fills MAC header fields
* @skb: Address of the frame to initialize its MAC header
* @sa: The MAC source address
* @da: The MAC destination address
*
* Fills MAC header fields, depending on MAC type. Returns 0, If MAC type
* is a valid type and initialization completes correctly 1, otherwise.
*/
int llc_mac_hdr_init(struct sk_buff *skb, unsigned char *sa, unsigned char *da)
{
int rc = 0;
switch (skb->dev->type) {
#ifdef CONFIG_TR
case ARPHRD_IEEE802_TR: {
struct net_device *dev = skb->dev;
struct trh_hdr *trh;
trh = (struct trh_hdr *)skb_push(skb, sizeof(*trh));
trh->ac = AC;
trh->fc = LLC_FRAME;
if (sa)
memcpy(trh->saddr, sa, dev->addr_len);
else
memset(trh->saddr, 0, dev->addr_len);
if (da) {
memcpy(trh->daddr, da, dev->addr_len);
tr_source_route(skb, trh, dev);
}
skb->mac.raw = skb->data;
break;
}
#endif
case ARPHRD_ETHER:
case ARPHRD_LOOPBACK: {
unsigned short len = skb->len;
struct ethhdr *eth;
skb->mac.raw = skb_push(skb, sizeof(*eth));
eth = (struct ethhdr *)skb->mac.raw;
eth->h_proto = htons(len);
memcpy(eth->h_dest, da, ETH_ALEN);
memcpy(eth->h_source, sa, ETH_ALEN);
break;
}
default:
printk(KERN_WARNING "device type not supported: %d\n",
skb->dev->type);
rc = -EINVAL;
}
return rc;
}
/**
* llc_build_and_send_ui_pkt - unitdata request interface for upper layers
* @sap: sap to use
* @skb: packet to send
* @dmac: destination mac address
* @dsap: destination sap
*
* Upper layers calls this function when upper layer wants to send data
* using connection-less mode communication (UI pdu).
*
* Accept data frame from network layer to be sent using connection-
* less mode communication; timeout/retries handled by network layer;
* package primitive as an event and send to SAP event handler
*/
int llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb,
unsigned char *dmac, unsigned char dsap)
{
int rc;
llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap,
dsap, LLC_PDU_CMD);
llc_pdu_init_as_ui_cmd(skb);
rc = llc_mac_hdr_init(skb, skb->dev->dev_addr, dmac);
if (!rc)
rc = dev_queue_xmit(skb);
return rc;
}
EXPORT_SYMBOL(llc_mac_hdr_init);
EXPORT_SYMBOL(llc_build_and_send_ui_pkt);
#ifndef LLC_OUTPUT_H
#define LLC_OUTPUT_H
/*
* Copyright (c) 1997 by Procom Technology, Inc.
* 2001-2003 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 version 2 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 version 2 for more details.
*/
struct sk_buff;
int llc_mac_hdr_init(struct sk_buff *skb, unsigned char *sa, unsigned char *da);
#endif /* LLC_OUTPUT_H */
......@@ -11,11 +11,9 @@
*
* See the GNU General Public License for more details.
*/
#include <linux/netdevice.h>
#include <linux/if_tr.h>
#include <net/llc_pdu.h>
#include <net/llc_if.h>
#include <net/llc_main.h>
static void llc_pdu_decode_pdu_type(struct sk_buff *skb, u8 *type);
static u8 llc_pdu_get_pf_bit(struct llc_pdu_sn *pdu);
......
......@@ -20,13 +20,11 @@
#include <linux/errno.h>
#include <linux/seq_file.h>
#include <net/sock.h>
#include <net/llc.h>
#include <net/llc_c_ac.h>
#include <net/llc_c_ev.h>
#include <net/llc_c_st.h>
#include <net/llc_conn.h>
#include <net/llc_mac.h>
#include <net/llc_main.h>
#include <net/llc_sap.h>
static void llc_ui_format_mac(struct seq_file *seq, unsigned char *mac)
{
......@@ -41,7 +39,7 @@ static struct sock *llc_get_sk_idx(loff_t pos)
struct hlist_node *node;
struct sock *sk = NULL;
list_for_each(sap_entry, &llc_main_station.sap_list.list) {
list_for_each(sap_entry, &llc_sap_list) {
sap = list_entry(sap_entry, struct llc_sap, node);
read_lock_bh(&sap->sk_list.lock);
......@@ -66,7 +64,7 @@ static void *llc_seq_start(struct seq_file *seq, loff_t *pos)
{
loff_t l = *pos;
read_lock_bh(&llc_main_station.sap_list.lock);
read_lock_bh(&llc_sap_list_lock);
return l ? llc_get_sk_idx(--l) : SEQ_START_TOKEN;
}
......@@ -92,7 +90,7 @@ static void *llc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
read_unlock_bh(&sap->sk_list.lock);
sk = NULL;
for (;;) {
if (sap->node.next == &llc_main_station.sap_list.list)
if (sap->node.next == &llc_sap_list)
break;
sap = list_entry(sap->node.next, struct llc_sap, node);
read_lock_bh(&sap->sk_list.lock);
......@@ -115,7 +113,7 @@ static void llc_seq_stop(struct seq_file *seq, void *v)
read_unlock_bh(&sap->sk_list.lock);
}
read_unlock_bh(&llc_main_station.sap_list.lock);
read_unlock_bh(&llc_sap_list_lock);
}
static int llc_seq_socket_show(struct seq_file *seq, void *v)
......
......@@ -17,13 +17,14 @@
*
* See the GNU General Public License for more details.
*/
#include <linux/netdevice.h>
#include <net/llc_if.h>
#include <net/llc_sap.h>
#include <net/llc_main.h>
#include <net/llc_s_ev.h>
#include <net/llc.h>
#include <net/llc_pdu.h>
#include <net/llc_mac.h>
#include <net/llc_s_ac.h>
#include <net/llc_s_ev.h>
#include <net/llc_sap.h>
#include "llc_output.h"
/**
* llc_sap_action_unit_data_ind - forward UI PDU to network layer
......@@ -56,7 +57,7 @@ int llc_sap_action_send_ui(struct llc_sap *sap, struct sk_buff *skb)
llc_pdu_header_init(skb, LLC_PDU_TYPE_U, ev->saddr.lsap,
ev->daddr.lsap, LLC_PDU_CMD);
llc_pdu_init_as_ui_cmd(skb);
rc = lan_hdrs_init(skb, ev->saddr.mac, ev->daddr.mac);
rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac);
if (!rc)
rc = dev_queue_xmit(skb);
return rc;
......@@ -79,7 +80,7 @@ int llc_sap_action_send_xid_c(struct llc_sap *sap, struct sk_buff *skb)
llc_pdu_header_init(skb, LLC_PDU_TYPE_U, ev->saddr.lsap,
ev->daddr.lsap, LLC_PDU_CMD);
llc_pdu_init_as_xid_cmd(skb, LLC_XID_NULL_CLASS_2, 0);
rc = lan_hdrs_init(skb, ev->saddr.mac, ev->daddr.mac);
rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac);
if (!rc)
rc = dev_queue_xmit(skb);
return rc;
......@@ -109,7 +110,7 @@ int llc_sap_action_send_xid_r(struct llc_sap *sap, struct sk_buff *skb)
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap,
LLC_PDU_RSP);
llc_pdu_init_as_xid_rsp(nskb, LLC_XID_NULL_CLASS_2, 0);
rc = lan_hdrs_init(nskb, mac_sa, mac_da);
rc = llc_mac_hdr_init(nskb, mac_sa, mac_da);
if (!rc)
rc = dev_queue_xmit(nskb);
out:
......@@ -133,7 +134,7 @@ int llc_sap_action_send_test_c(struct llc_sap *sap, struct sk_buff *skb)
llc_pdu_header_init(skb, LLC_PDU_TYPE_U, ev->saddr.lsap,
ev->daddr.lsap, LLC_PDU_CMD);
llc_pdu_init_as_test_cmd(skb);
rc = lan_hdrs_init(skb, ev->saddr.mac, ev->daddr.mac);
rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac);
if (!rc)
rc = dev_queue_xmit(skb);
return rc;
......@@ -155,7 +156,7 @@ int llc_sap_action_send_test_r(struct llc_sap *sap, struct sk_buff *skb)
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap,
LLC_PDU_RSP);
llc_pdu_init_as_test_rsp(nskb, skb);
rc = lan_hdrs_init(nskb, mac_sa, mac_da);
rc = llc_mac_hdr_init(nskb, mac_sa, mac_da);
if (!rc)
rc = dev_queue_xmit(nskb);
out:
......
......@@ -11,17 +11,38 @@
*
* See the GNU General Public License for more details.
*/
#include <linux/skbuff.h>
#include <net/llc.h>
#include <net/llc_if.h>
#include <net/llc_conn.h>
#include <net/llc_pdu.h>
#include <net/llc_sap.h>
#include <net/llc_s_ev.h>
#include <net/llc_s_ac.h>
#include <net/llc_s_ev.h>
#include <net/llc_s_st.h>
#include <net/sock.h>
#include <linux/tcp.h>
#include <net/llc_main.h>
#include <net/llc_pdu.h>
#include <linux/if_tr.h>
#include <linux/llc.h>
/**
* llc_alloc_frame - allocates sk_buff for frame
*
* Allocates an sk_buff for frame and initializes sk_buff fields.
* Returns allocated skb or %NULL when out of memory.
*/
struct sk_buff *llc_alloc_frame(void)
{
struct sk_buff *skb = alloc_skb(128, GFP_ATOMIC);
if (skb) {
skb_reserve(skb, 50);
skb->nh.raw = skb->h.raw = skb->data;
skb->protocol = htons(ETH_P_802_2);
skb->dev = dev_base->next;
skb->mac.raw = skb->head;
}
return skb;
}
void llc_save_primitive(struct sk_buff* skb, u8 prim)
{
......@@ -180,36 +201,6 @@ void llc_sap_state_process(struct llc_sap *sap, struct sk_buff *skb)
kfree_skb(skb);
}
/**
* llc_build_and_send_ui_pkt - unitdata request interface for upper layers
* @sap: sap to use
* @skb: packet to send
* @dmac: destination mac address
* @dsap: destination sap
*
* Upper layers calls this function when upper layer wants to send data
* using connection-less mode communication (UI pdu).
*
* Accept data frame from network layer to be sent using connection-
* less mode communication; timeout/retries handled by network layer;
* package primitive as an event and send to SAP event handler
*/
void llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb,
u8 *dmac, u8 dsap)
{
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
ev->saddr.lsap = sap->laddr.lsap;
ev->daddr.lsap = dsap;
memcpy(ev->saddr.mac, skb->dev->dev_addr, IFHWADDRLEN);
memcpy(ev->daddr.mac, dmac, IFHWADDRLEN);
ev->type = LLC_SAP_EV_TYPE_PRIM;
ev->prim = LLC_DATAUNIT_PRIM;
ev->prim_type = LLC_PRIM_TYPE_REQ;
llc_sap_state_process(sap, skb);
}
/**
* llc_build_and_send_test_pkt - TEST interface for upper layers.
* @sap: sap to use
......@@ -325,79 +316,6 @@ void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb)
kfree_skb(skb);
}
/**
* llc_sap_alloc - allocates and initializes sap.
*
* Allocates and initializes sap.
*/
struct llc_sap *llc_sap_alloc(void)
{
struct llc_sap *sap = kmalloc(sizeof(*sap), GFP_ATOMIC);
if (sap) {
memset(sap, 0, sizeof(*sap));
sap->state = LLC_SAP_STATE_ACTIVE;
memcpy(sap->laddr.mac, llc_main_station.mac_sa, ETH_ALEN);
rwlock_init(&sap->sk_list.lock);
}
return sap;
}
/**
* llc_sap_open - open interface to the upper layers.
* @lsap: SAP number.
* @func: rcv func for datalink protos
*
* Interface function to upper layer. Each one who wants to get a SAP
* (for example NetBEUI) should call this function. Returns the opened
* SAP for success, NULL for failure.
*/
struct llc_sap *llc_sap_open(u8 lsap, int (*func)(struct sk_buff *skb,
struct net_device *dev,
struct packet_type *pt))
{
/* verify this SAP is not already open; if so, return error */
struct llc_sap *sap;
sap = llc_sap_find(lsap);
if (sap) { /* SAP already exists */
sap = NULL;
goto out;
}
/* sap requested does not yet exist */
sap = llc_sap_alloc();
if (!sap)
goto out;
/* allocated a SAP; initialize it and clear out its memory pool */
sap->laddr.lsap = lsap;
sap->rcv_func = func;
sap->station = &llc_main_station;
/* initialized SAP; add it to list of SAPs this station manages */
llc_sap_save(sap);
out:
return sap;
}
/**
* llc_sap_close - close interface for upper layers.
* @sap: SAP to be closed.
*
* Close interface function to upper layer. Each one who wants to
* close an open SAP (for example NetBEUI) should call this function.
* Removes this sap from the list of saps in the station and then
* frees the memory for this sap.
*/
void llc_sap_close(struct llc_sap *sap)
{
WARN_ON(!hlist_empty(&sap->sk_list.list));
write_lock_bh(&sap->station->sap_list.lock);
list_del(&sap->node);
write_unlock_bh(&sap->station->sap_list.lock);
kfree(sap);
}
EXPORT_SYMBOL(llc_sap_open);
EXPORT_SYMBOL(llc_sap_close);
EXPORT_SYMBOL(llc_save_primitive);
EXPORT_SYMBOL(llc_build_and_send_test_pkt);
EXPORT_SYMBOL(llc_build_and_send_ui_pkt);
......
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