Commit 229e0840 authored by David S. Miller's avatar David S. Miller

Merge nuts.ninka.net:/home/davem/src/BK/network-2.5

into nuts.ninka.net:/home/davem/src/BK/net-2.5
parents 02debc0e 10880106
...@@ -39,16 +39,16 @@ ...@@ -39,16 +39,16 @@
* An X.121 address, it is held as ASCII text, null terminated, up to 15 * An X.121 address, it is held as ASCII text, null terminated, up to 15
* digits and a null terminator. * digits and a null terminator.
*/ */
typedef struct { struct x25_address {
char x25_addr[16]; char x25_addr[16];
} x25_address; };
/* /*
* Linux X.25 Address structure, used for bind, and connect mostly. * Linux X.25 Address structure, used for bind, and connect mostly.
*/ */
struct sockaddr_x25 { struct sockaddr_x25 {
sa_family_t sx25_family; /* Must be AF_X25 */ sa_family_t sx25_family; /* Must be AF_X25 */
x25_address sx25_addr; /* X.121 Address */ struct x25_address sx25_addr; /* X.121 Address */
}; };
/* /*
...@@ -78,9 +78,9 @@ struct x25_subscrip_struct { ...@@ -78,9 +78,9 @@ struct x25_subscrip_struct {
* Routing table control structure. * Routing table control structure.
*/ */
struct x25_route_struct { struct x25_route_struct {
x25_address address; struct x25_address address;
unsigned int sigdigits; unsigned int sigdigits;
char device[200]; char device[200];
}; };
/* /*
......
...@@ -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 reason; u8 prim;
u8 status; u8 prim_type;
u8 flag; u8 reason;
struct llc_prim_if_block *ind_prim; u8 status;
struct llc_prim_if_block *cfm_prim; u8 ind_prim;
union llc_conn_ev_if data; u8 cfm_prim;
}; };
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,26 +31,12 @@ ...@@ -31,26 +31,12 @@
#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 reason; u8 prim;
union llc_stat_ev_if data; u8 prim_type;
struct list_head node; /* node in station->ev_q.list */ u8 reason;
struct list_head node; /* node in station->ev_q.list */
}; };
static __inline__ struct llc_station_state_ev * static __inline__ struct llc_station_state_ev *
......
/* 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 type; u8 prim;
u8 reason; u8 prim_type;
u8 ind_cfm_flag; u8 type;
struct llc_prim_if_block *prim; u8 reason;
union llc_sap_ev_if data; u8 ind_cfm_flag;
struct llc_addr saddr;
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"
};
...@@ -51,6 +51,25 @@ struct ra_msg { ...@@ -51,6 +51,25 @@ struct ra_msg {
__u32 retrans_timer; __u32 retrans_timer;
}; };
struct nd_opt_hdr {
__u8 nd_opt_type;
__u8 nd_opt_len;
} __attribute__((__packed__));
struct ndisc_options {
struct nd_opt_hdr *nd_opt_array[7];
struct nd_opt_hdr *nd_opt_piend;
};
#define nd_opts_src_lladdr nd_opt_array[ND_OPT_SOURCE_LL_ADDR]
#define nd_opts_tgt_lladdr nd_opt_array[ND_OPT_TARGET_LL_ADDR]
#define nd_opts_pi nd_opt_array[ND_OPT_PREFIX_INFO]
#define nd_opts_pi_end nd_opt_piend
#define nd_opts_rh nd_opt_array[ND_OPT_REDIRECT_HDR]
#define nd_opts_mtu nd_opt_array[ND_OPT_MTU]
extern struct nd_opt_hdr *ndisc_next_option(struct nd_opt_hdr *cur, struct nd_opt_hdr *end);
extern struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len, struct ndisc_options *ndopts);
extern int ndisc_init(struct net_proto_family *ops); extern int ndisc_init(struct net_proto_family *ops);
......
#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
...@@ -112,6 +112,7 @@ typedef enum { ...@@ -112,6 +112,7 @@ typedef enum {
SCTP_EVENT_TIMEOUT_T2_SHUTDOWN, SCTP_EVENT_TIMEOUT_T2_SHUTDOWN,
SCTP_EVENT_TIMEOUT_T3_RTX, SCTP_EVENT_TIMEOUT_T3_RTX,
SCTP_EVENT_TIMEOUT_T4_RTO, SCTP_EVENT_TIMEOUT_T4_RTO,
SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD,
SCTP_EVENT_TIMEOUT_HEARTBEAT, SCTP_EVENT_TIMEOUT_HEARTBEAT,
SCTP_EVENT_TIMEOUT_SACK, SCTP_EVENT_TIMEOUT_SACK,
SCTP_EVENT_TIMEOUT_AUTOCLOSE, SCTP_EVENT_TIMEOUT_AUTOCLOSE,
......
...@@ -114,7 +114,8 @@ extern sctp_protocol_t sctp_proto; ...@@ -114,7 +114,8 @@ extern sctp_protocol_t sctp_proto;
extern struct sock *sctp_get_ctl_sock(void); extern struct sock *sctp_get_ctl_sock(void);
extern int sctp_copy_local_addr_list(sctp_protocol_t *, sctp_bind_addr_t *, extern int sctp_copy_local_addr_list(sctp_protocol_t *, sctp_bind_addr_t *,
sctp_scope_t, int priority, int flags); sctp_scope_t, int priority, int flags);
extern sctp_pf_t *sctp_get_pf_specific(int family);
extern void sctp_set_pf_specific(int family, sctp_pf_t *);
/* /*
* sctp_socket.c * sctp_socket.c
......
...@@ -107,6 +107,9 @@ sctp_state_fn_t sctp_sf_timer_ignore; ...@@ -107,6 +107,9 @@ sctp_state_fn_t sctp_sf_timer_ignore;
sctp_state_fn_t sctp_sf_do_9_1_abort; sctp_state_fn_t sctp_sf_do_9_1_abort;
sctp_state_fn_t sctp_sf_cookie_wait_abort; sctp_state_fn_t sctp_sf_cookie_wait_abort;
sctp_state_fn_t sctp_sf_cookie_echoed_abort; sctp_state_fn_t sctp_sf_cookie_echoed_abort;
sctp_state_fn_t sctp_sf_shutdown_pending_abort;
sctp_state_fn_t sctp_sf_shutdown_sent_abort;
sctp_state_fn_t sctp_sf_shutdown_ack_sent_abort;
sctp_state_fn_t sctp_sf_do_5_1B_init; sctp_state_fn_t sctp_sf_do_5_1B_init;
sctp_state_fn_t sctp_sf_do_5_1C_ack; sctp_state_fn_t sctp_sf_do_5_1C_ack;
sctp_state_fn_t sctp_sf_do_5_1D_ce; sctp_state_fn_t sctp_sf_do_5_1D_ce;
...@@ -119,6 +122,7 @@ sctp_state_fn_t sctp_sf_tabort_8_4_8; ...@@ -119,6 +122,7 @@ sctp_state_fn_t sctp_sf_tabort_8_4_8;
sctp_state_fn_t sctp_sf_operr_notify; sctp_state_fn_t sctp_sf_operr_notify;
sctp_state_fn_t sctp_sf_t1_timer_expire; sctp_state_fn_t sctp_sf_t1_timer_expire;
sctp_state_fn_t sctp_sf_t2_timer_expire; sctp_state_fn_t sctp_sf_t2_timer_expire;
sctp_state_fn_t sctp_sf_t5_timer_expire;
sctp_state_fn_t sctp_sf_sendbeat_8_3; sctp_state_fn_t sctp_sf_sendbeat_8_3;
sctp_state_fn_t sctp_sf_beat_8_3; sctp_state_fn_t sctp_sf_beat_8_3;
sctp_state_fn_t sctp_sf_backbeat_8_3; sctp_state_fn_t sctp_sf_backbeat_8_3;
...@@ -134,6 +138,7 @@ sctp_state_fn_t sctp_sf_discard_chunk; ...@@ -134,6 +138,7 @@ sctp_state_fn_t sctp_sf_discard_chunk;
sctp_state_fn_t sctp_sf_do_5_2_1_siminit; sctp_state_fn_t sctp_sf_do_5_2_1_siminit;
sctp_state_fn_t sctp_sf_do_5_2_2_dupinit; sctp_state_fn_t sctp_sf_do_5_2_2_dupinit;
sctp_state_fn_t sctp_sf_do_5_2_4_dupcook; sctp_state_fn_t sctp_sf_do_5_2_4_dupcook;
sctp_state_fn_t sctp_sf_unk_chunk;
/* Prototypes for primitive event state functions. */ /* Prototypes for primitive event state functions. */
sctp_state_fn_t sctp_sf_do_prm_asoc; sctp_state_fn_t sctp_sf_do_prm_asoc;
...@@ -144,6 +149,9 @@ sctp_state_fn_t sctp_sf_cookie_echoed_prm_shutdown; ...@@ -144,6 +149,9 @@ sctp_state_fn_t sctp_sf_cookie_echoed_prm_shutdown;
sctp_state_fn_t sctp_sf_do_9_1_prm_abort; sctp_state_fn_t sctp_sf_do_9_1_prm_abort;
sctp_state_fn_t sctp_sf_cookie_wait_prm_abort; sctp_state_fn_t sctp_sf_cookie_wait_prm_abort;
sctp_state_fn_t sctp_sf_cookie_echoed_prm_abort; sctp_state_fn_t sctp_sf_cookie_echoed_prm_abort;
sctp_state_fn_t sctp_sf_shutdown_pending_prm_abort;
sctp_state_fn_t sctp_sf_shutdown_sent_prm_abort;
sctp_state_fn_t sctp_sf_shutdown_ack_sent_prm_abort;
sctp_state_fn_t sctp_sf_error_closed; sctp_state_fn_t sctp_sf_error_closed;
sctp_state_fn_t sctp_sf_error_shutdown; sctp_state_fn_t sctp_sf_error_shutdown;
sctp_state_fn_t sctp_sf_ignore_primitive; sctp_state_fn_t sctp_sf_ignore_primitive;
......
...@@ -255,6 +255,12 @@ typedef struct sctp_func { ...@@ -255,6 +255,12 @@ typedef struct sctp_func {
sctp_func_t *sctp_get_af_specific(const sockaddr_storage_t *address); sctp_func_t *sctp_get_af_specific(const sockaddr_storage_t *address);
/* Protocol family functions. */
typedef struct sctp_pf {
void (*event_msgname)(sctp_ulpevent_t *, char *, int *);
void (*skb_msgname)(struct sk_buff *, char *, int *);
} sctp_pf_t;
/* SCTP Socket type: UDP or TCP style. */ /* SCTP Socket type: UDP or TCP style. */
typedef enum { typedef enum {
SCTP_SOCKET_UDP = 0, SCTP_SOCKET_UDP = 0,
...@@ -280,6 +286,7 @@ struct sctp_opt { ...@@ -280,6 +286,7 @@ struct sctp_opt {
__u32 autoclose; __u32 autoclose;
__u8 nodelay; __u8 nodelay;
__u8 disable_fragments; __u8 disable_fragments;
sctp_pf_t *pf;
}; };
...@@ -845,6 +852,7 @@ int sctp_outqueue_set_output_handlers(sctp_outqueue_t *, ...@@ -845,6 +852,7 @@ int sctp_outqueue_set_output_handlers(sctp_outqueue_t *,
sctp_outqueue_ohandler_force_t force); sctp_outqueue_ohandler_force_t force);
void sctp_outqueue_restart(sctp_outqueue_t *); void sctp_outqueue_restart(sctp_outqueue_t *);
void sctp_retransmit(sctp_outqueue_t *, sctp_transport_t *, __u8); void sctp_retransmit(sctp_outqueue_t *, sctp_transport_t *, __u8);
void sctp_retransmit_mark(sctp_outqueue_t *, sctp_transport_t *, __u8);
/* These bind address data fields common between endpoints and associations */ /* These bind address data fields common between endpoints and associations */
...@@ -1128,6 +1136,11 @@ struct SCTP_association { ...@@ -1128,6 +1136,11 @@ struct SCTP_association {
*/ */
sctp_transport_t *primary_path; sctp_transport_t *primary_path;
/* Cache the primary path address here, when we
* need a an address for msg_name.
*/
sockaddr_storage_t primary_addr;
/* active_path /* active_path
* The path that we are currently using to * The path that we are currently using to
* transmit new data and most control chunks. * transmit new data and most control chunks.
...@@ -1183,7 +1196,7 @@ struct SCTP_association { ...@@ -1183,7 +1196,7 @@ struct SCTP_association {
int next_dup_tsn; int next_dup_tsn;
/* Do we need to sack the peer? */ /* Do we need to sack the peer? */
int sack_needed; uint8_t sack_needed;
/* These are capabilities which our peer advertised. */ /* These are capabilities which our peer advertised. */
__u8 ecn_capable; /* Can peer do ECN? */ __u8 ecn_capable; /* Can peer do ECN? */
......
...@@ -103,9 +103,9 @@ enum { ...@@ -103,9 +103,9 @@ enum {
struct x25_route { struct x25_route {
struct x25_route *next; struct x25_route *next;
x25_address address; /* Start of address range */ struct x25_address address; /* Start of address range */
unsigned int sigdigits; /* Number of sig digits */ unsigned int sigdigits; /* Number of sig digits */
struct net_device *dev; /* More than one for MLP */ struct net_device *dev; /* More than one for MLP */
}; };
struct x25_neigh { struct x25_neigh {
...@@ -120,7 +120,7 @@ struct x25_neigh { ...@@ -120,7 +120,7 @@ struct x25_neigh {
}; };
typedef struct { typedef struct {
x25_address source_addr, dest_addr; struct x25_address source_addr, dest_addr;
struct x25_neigh *neighbour; struct x25_neigh *neighbour;
unsigned int lci; unsigned int lci;
unsigned char state, condition, qbitincl, intflag; unsigned char state, condition, qbitincl, intflag;
...@@ -148,8 +148,10 @@ extern int sysctl_x25_reset_request_timeout; ...@@ -148,8 +148,10 @@ extern int sysctl_x25_reset_request_timeout;
extern int sysctl_x25_clear_request_timeout; extern int sysctl_x25_clear_request_timeout;
extern int sysctl_x25_ack_holdback_timeout; extern int sysctl_x25_ack_holdback_timeout;
extern int x25_addr_ntoa(unsigned char *, x25_address *, x25_address *); extern int x25_addr_ntoa(unsigned char *, struct x25_address *,
extern int x25_addr_aton(unsigned char *, x25_address *, x25_address *); struct x25_address *);
extern int x25_addr_aton(unsigned char *, struct x25_address *,
struct x25_address *);
extern unsigned int x25_new_lci(struct x25_neigh *); extern unsigned int x25_new_lci(struct x25_neigh *);
extern struct sock *x25_find_socket(unsigned int, struct x25_neigh *); extern struct sock *x25_find_socket(unsigned int, struct x25_neigh *);
extern void x25_destroy_socket(struct sock *); extern void x25_destroy_socket(struct sock *);
...@@ -194,7 +196,7 @@ extern void x25_kick(struct sock *); ...@@ -194,7 +196,7 @@ extern void x25_kick(struct sock *);
extern void x25_enquiry_response(struct sock *); extern void x25_enquiry_response(struct sock *);
/* x25_route.c */ /* x25_route.c */
extern struct net_device *x25_get_route(x25_address *); extern struct net_device *x25_get_route(struct x25_address *);
extern struct net_device *x25_dev_get(char *); extern struct net_device *x25_dev_get(char *);
extern void x25_route_device_down(struct net_device *); extern void x25_route_device_down(struct net_device *);
extern int x25_route_ioctl(unsigned int, void *); extern int x25_route_ioctl(unsigned int, void *);
......
...@@ -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");
......
...@@ -1252,7 +1252,7 @@ static struct ip_fwkernel *convert_ipfw(struct ip_fwuser *fwuser, int *errno) ...@@ -1252,7 +1252,7 @@ static struct ip_fwkernel *convert_ipfw(struct ip_fwuser *fwuser, int *errno)
return NULL; return NULL;
} }
fwkern = kmalloc(SIZEOF_STRUCT_IP_FW_KERNEL, GFP_KERNEL); fwkern = kmalloc(SIZEOF_STRUCT_IP_FW_KERNEL, GFP_ATOMIC);
if (!fwkern) { if (!fwkern) {
duprintf("convert_ipfw: kmalloc failed!\n"); duprintf("convert_ipfw: kmalloc failed!\n");
*errno = ENOMEM; *errno = ENOMEM;
......
This diff is collapsed.
...@@ -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; ev->reason = reason;
struct llc_prim_if_block *prim = &sap->llc_ind_prim; ev->ind_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->reason = reason;
ev->flag = 1;
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,110 +67,120 @@ void llc_save_primitive(struct sock *sk, struct sk_buff* skb, u8 prim) ...@@ -67,110 +67,120 @@ 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 (flag) {
case LLC_DATA_PRIM + 1:
llc_save_primitive(sk, skb, LLC_DATA_PRIM);
if (sock_queue_rcv_skb(sk, skb)) {
/*
* FIXME: have to sync the LLC state
* machine wrt mem usage with
* sk->{r,w}mem_alloc, will do
* this soon 8)
*/
printk(KERN_ERR
"%s: sock_queue_rcv_skb failed!\n",
__FUNCTION__);
kfree_skb(skb);
}
break;
case LLC_CONN_PRIM + 1: {
struct sock *parent = skb->sk;
skb->sk = sk; switch (ev->ind_prim) {
skb_queue_tail(&parent->receive_queue, skb); case LLC_DATA_PRIM:
sk->state_change(parent); llc_save_primitive(skb, LLC_DATA_PRIM);
if (sock_queue_rcv_skb(sk, skb)) {
/*
* shouldn't happen
*/
printk(KERN_ERR "%s: sock_queue_rcv_skb failed!\n",
__FUNCTION__);
kfree_skb(skb);
} }
break; break;
case LLC_DISC_PRIM + 1: case LLC_CONN_PRIM: {
sock_hold(sk); struct sock *parent = skb->sk;
if (sk->type == SOCK_STREAM && sk->state == TCP_ESTABLISHED) {
sk->shutdown = SHUTDOWN_MASK; skb->sk = sk;
sk->socket->state = SS_UNCONNECTED; skb_queue_tail(&parent->receive_queue, skb);
sk->state = TCP_CLOSE; sk->state_change(parent);
if (!sk->dead) { }
sk->state_change(sk); break;
sk->dead = 1; case LLC_DISC_PRIM:
} sock_hold(sk);
if (sk->type == SOCK_STREAM && sk->state == TCP_ESTABLISHED) {
sk->shutdown = SHUTDOWN_MASK;
sk->socket->state = SS_UNCONNECTED;
sk->state = TCP_CLOSE;
if (!sk->dead) {
sk->state_change(sk);
sk->dead = 1;
} }
}
kfree_skb(skb);
sock_put(sk);
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:
if (ev->ind_prim) {
printk(KERN_INFO "%s: received unknown %d prim!\n",
__FUNCTION__, ev->ind_prim);
kfree_skb(skb); kfree_skb(skb);
sock_put(sk);
break;
default:
llc->sap->ind(ind_prim);
} }
/* 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 { sk->socket->state = SS_CONNECTED;
sk->socket->state = SS_CONNECTED; 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); sk->socket->state = SS_UNCONNECTED;
goto out_kfree_skb; sk->state = TCP_CLOSE;
sk->state_change(sk);
} }
sk->socket->state = SS_UNCONNECTED;
sk->state = TCP_CLOSE;
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; ev->type = LLC_SAP_EV_TYPE_PRIM;
prim_data.udata.saddr.lsap = sap->laddr.lsap; ev->prim = LLC_DATAUNIT_PRIM;
prim_data.udata.daddr.lsap = dsap; ev->prim_type = LLC_PRIM_TYPE_REQ;
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->data.prim.prim = LLC_DATAUNIT_PRIM;
ev->data.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);
} }
...@@ -219,11 +193,10 @@ int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb) ...@@ -219,11 +193,10 @@ int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb)
goto out; goto out;
} }
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:
return rc; return rc;
...@@ -268,10 +241,9 @@ int llc_establish_connection(struct sock *sk, u8 *lmac, u8 *dmac, u8 dsap) ...@@ -268,10 +241,9 @@ int llc_establish_connection(struct sock *sk, u8 *lmac, u8 *dmac, u8 dsap)
if (skb) { if (skb) {
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:
...@@ -306,12 +278,11 @@ int llc_send_disc(struct sock *sk) ...@@ -306,12 +278,11 @@ int llc_send_disc(struct sock *sk)
skb = alloc_skb(0, GFP_ATOMIC); skb = alloc_skb(0, GFP_ATOMIC);
if (!skb) if (!skb)
goto out; goto out;
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);
...@@ -336,10 +306,9 @@ int llc_build_and_send_reset_pkt(struct sock *sk, ...@@ -336,10 +306,9 @@ int llc_build_and_send_reset_pkt(struct sock *sk,
if (skb) { if (skb) {
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;
......
...@@ -82,7 +82,7 @@ int mac_send_pdu(struct sk_buff *skb) ...@@ -82,7 +82,7 @@ int mac_send_pdu(struct sk_buff *skb)
* data now), it queues this frame in the connection's backlog. * data now), it queues this frame in the connection's backlog.
*/ */
int llc_rcv(struct sk_buff *skb, struct net_device *dev, int llc_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt) struct packet_type *pt)
{ {
struct llc_sap *sap; struct llc_sap *sap;
struct llc_pdu_sn *pdu; struct llc_pdu_sn *pdu;
...@@ -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)
llc_sap_rcv(sap, skb); 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);
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; for (sk = sap->sk_list.list; sk; sk = sk->next) {
list_for_each_safe(entry, tmp, &sap->sk_list.list) { llc_sk(sk)->state = LLC_CONN_STATE_TEMP;
struct llc_opt *llc = list_entry(entry, struct llc_opt, node);
llc->state = LLC_CONN_STATE_TEMP; if (llc_send_disc(sk))
if (llc_send_disc(llc->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,29 +60,54 @@ void llc_sap_assign_sock(struct llc_sap *sap, struct sock *sk) ...@@ -55,29 +60,54 @@ 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) {
sock_put(sk); if (sk->next)
spin_unlock_bh(&sap->sk_list.lock); 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(&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);
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);
} }
/** /**
...@@ -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: ev->prim = LLC_XID_PRIM; break;
prim->prim = LLC_XID_PRIM; case LLC_1_PDU_CMD_UI:
break; ev->prim = LLC_DATAUNIT_PRIM; break;
case LLC_1_PDU_CMD_UI:
if (skb->protocol == ntohs(ETH_P_TR_802_2)) {
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;
} }
/** /**
......
This diff is collapsed.
...@@ -1163,6 +1163,8 @@ static int htb_init(struct Qdisc *sch, struct rtattr *opt) ...@@ -1163,6 +1163,8 @@ static int htb_init(struct Qdisc *sch, struct rtattr *opt)
skb_queue_head_init(&q->direct_queue); skb_queue_head_init(&q->direct_queue);
q->direct_qlen = sch->dev->tx_queue_len; q->direct_qlen = sch->dev->tx_queue_len;
if (q->direct_qlen < 2) /* some devices have zero tx_queue_len */
q->direct_qlen = 2;
q->timer.function = htb_timer; q->timer.function = htb_timer;
q->timer.data = (unsigned long)sch; q->timer.data = (unsigned long)sch;
...@@ -1429,6 +1431,10 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, ...@@ -1429,6 +1431,10 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
if (!rtab || !ctab) goto failure; if (!rtab || !ctab) goto failure;
if (!cl) { /* new class */ if (!cl) { /* new class */
/* check for valid classid */
if (!classid || TC_H_MAJ(classid^sch->handle) || htb_find(classid,sch))
goto failure;
/* check maximal depth */ /* check maximal depth */
if (parent && parent->parent && parent->parent->level < 2) { if (parent && parent->parent && parent->parent->level < 2) {
printk(KERN_ERR "htb: tree is too deep\n"); printk(KERN_ERR "htb: tree is too deep\n");
......
...@@ -96,7 +96,7 @@ unsigned long update_adler32(unsigned long adler, ...@@ -96,7 +96,7 @@ unsigned long update_adler32(unsigned long adler,
* one subtract at the MOST, since buf[n] * one subtract at the MOST, since buf[n]
* is a max of 255. * is a max of 255.
*/ */
if(s1 >= BASE) if (s1 >= BASE)
s1 -= BASE; s1 -= BASE;
/* s2 = (s2 + s1) % BASE */ /* s2 = (s2 + s1) % BASE */
......
...@@ -66,7 +66,7 @@ static void sctp_assoc_bh_rcv(sctp_association_t *asoc); ...@@ -66,7 +66,7 @@ static void sctp_assoc_bh_rcv(sctp_association_t *asoc);
/* Allocate and initialize a new association */ /* Allocate and initialize a new association */
sctp_association_t *sctp_association_new(const sctp_endpoint_t *ep, sctp_association_t *sctp_association_new(const sctp_endpoint_t *ep,
const struct sock *sk, const struct sock *sk,
sctp_scope_t scope, int priority) sctp_scope_t scope, int priority)
{ {
sctp_association_t *asoc; sctp_association_t *asoc;
...@@ -91,7 +91,7 @@ sctp_association_t *sctp_association_new(const sctp_endpoint_t *ep, ...@@ -91,7 +91,7 @@ sctp_association_t *sctp_association_new(const sctp_endpoint_t *ep,
/* Intialize a new association from provided memory. */ /* Intialize a new association from provided memory. */
sctp_association_t *sctp_association_init(sctp_association_t *asoc, sctp_association_t *sctp_association_init(sctp_association_t *asoc,
const sctp_endpoint_t *ep, const sctp_endpoint_t *ep,
const struct sock *sk, const struct sock *sk,
sctp_scope_t scope, sctp_scope_t scope,
int priority) int priority)
...@@ -109,19 +109,19 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc, ...@@ -109,19 +109,19 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc,
asoc->ep = (sctp_endpoint_t *)ep; asoc->ep = (sctp_endpoint_t *)ep;
sctp_endpoint_hold(asoc->ep); sctp_endpoint_hold(asoc->ep);
/* Hold the sock. */ /* Hold the sock. */
asoc->base.sk = (struct sock *)sk; asoc->base.sk = (struct sock *)sk;
sock_hold(asoc->base.sk); sock_hold(asoc->base.sk);
/* Initialize the common base substructure. */ /* Initialize the common base substructure. */
asoc->base.type = SCTP_EP_TYPE_ASSOCIATION; asoc->base.type = SCTP_EP_TYPE_ASSOCIATION;
/* Initialize the object handling fields. */ /* Initialize the object handling fields. */
atomic_set(&asoc->base.refcnt, 1); atomic_set(&asoc->base.refcnt, 1);
asoc->base.dead = 0; asoc->base.dead = 0;
asoc->base.malloced = 0; asoc->base.malloced = 0;
/* Initialize the bind addr area. */ /* Initialize the bind addr area. */
sctp_bind_addr_init(&asoc->base.bind_addr, ep->base.bind_addr.port); sctp_bind_addr_init(&asoc->base.bind_addr, ep->base.bind_addr.port);
asoc->base.addr_lock = RW_LOCK_UNLOCKED; asoc->base.addr_lock = RW_LOCK_UNLOCKED;
...@@ -135,7 +135,7 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc, ...@@ -135,7 +135,7 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc,
asoc->pmtu = 0; asoc->pmtu = 0;
asoc->frag_point = 0; asoc->frag_point = 0;
/* Initialize the default association max_retrans and RTO values. */ /* Initialize the default association max_retrans and RTO values. */
asoc->max_retrans = ep->proto->max_retrans_association; asoc->max_retrans = ep->proto->max_retrans_association;
asoc->rto_initial = ep->proto->rto_initial; asoc->rto_initial = ep->proto->rto_initial;
asoc->rto_max = ep->proto->rto_max; asoc->rto_max = ep->proto->rto_max;
...@@ -288,7 +288,6 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc, ...@@ -288,7 +288,6 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc,
return NULL; return NULL;
} }
/* Free this association if possible. There may still be users, so /* Free this association if possible. There may still be users, so
* the actual deallocation may be delayed. * the actual deallocation may be delayed.
*/ */
...@@ -330,6 +329,11 @@ void sctp_association_free(sctp_association_t *asoc) ...@@ -330,6 +329,11 @@ void sctp_association_free(sctp_association_t *asoc)
sctp_association_put(asoc); sctp_association_put(asoc);
} }
/* Free peer's cached cookie. */
if (asoc->peer.cookie) {
kfree(asoc->peer.cookie);
}
/* Release the transport structures. */ /* Release the transport structures. */
list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {
transport = list_entry(pos, sctp_transport_t, transports); transport = list_entry(pos, sctp_transport_t, transports);
...@@ -342,7 +346,6 @@ void sctp_association_free(sctp_association_t *asoc) ...@@ -342,7 +346,6 @@ void sctp_association_free(sctp_association_t *asoc)
sctp_association_put(asoc); sctp_association_put(asoc);
} }
/* Cleanup and free up an association. */ /* Cleanup and free up an association. */
static void sctp_association_destroy(sctp_association_t *asoc) static void sctp_association_destroy(sctp_association_t *asoc)
{ {
...@@ -383,12 +386,11 @@ sctp_transport_t *sctp_assoc_add_peer(sctp_association_t *asoc, ...@@ -383,12 +386,11 @@ sctp_transport_t *sctp_assoc_add_peer(sctp_association_t *asoc,
}; };
/* Set the port if it has not been set yet. */ /* Set the port if it has not been set yet. */
if (0 == asoc->peer.port) { if (0 == asoc->peer.port) {
asoc->peer.port = *port; asoc->peer.port = *port;
} }
SCTP_ASSERT(*port == asoc->peer.port, ":Invalid port\n", SCTP_ASSERT(*port == asoc->peer.port, ":Invalid port\n", return NULL);
return NULL);
/* Check to see if this is a duplicate. */ /* Check to see if this is a duplicate. */
peer = sctp_assoc_lookup_paddr(asoc, addr); peer = sctp_assoc_lookup_paddr(asoc, addr);
...@@ -461,11 +463,21 @@ sctp_transport_t *sctp_assoc_add_peer(sctp_association_t *asoc, ...@@ -461,11 +463,21 @@ sctp_transport_t *sctp_assoc_add_peer(sctp_association_t *asoc,
sp = sctp_sk(asoc->base.sk); sp = sctp_sk(asoc->base.sk);
peer->hb_interval = sp->paddrparam.spp_hbinterval * HZ; peer->hb_interval = sp->paddrparam.spp_hbinterval * HZ;
/* Attach the remote transport to our asoc. */ /* Attach the remote transport to our asoc. */
list_add_tail(&peer->transports, &asoc->peer.transport_addr_list); list_add_tail(&peer->transports, &asoc->peer.transport_addr_list);
/* If we do not yet have a primary path, set one. */ /* If we do not yet have a primary path, set one. */
if (NULL == asoc->peer.primary_path) { if (NULL == asoc->peer.primary_path) {
asoc->peer.primary_path = peer;
/* Set a default msg_name for events. */
memcpy(&asoc->peer.primary_addr, &peer->ipaddr,
sizeof(sockaddr_storage_t));
asoc->peer.active_path = peer;
asoc->peer.retran_path = peer;
}
/* If we do not yet have a primary path, set one. */
if (NULL == asoc->peer.primary_path) {
asoc->peer.primary_path = peer; asoc->peer.primary_path = peer;
asoc->peer.active_path = peer; asoc->peer.active_path = peer;
asoc->peer.retran_path = peer; asoc->peer.retran_path = peer;
...@@ -617,7 +629,7 @@ __u32 __sctp_association_get_next_tsn(sctp_association_t *asoc) ...@@ -617,7 +629,7 @@ __u32 __sctp_association_get_next_tsn(sctp_association_t *asoc)
asoc->next_tsn++; asoc->next_tsn++;
asoc->unack_data++; asoc->unack_data++;
return retval; return retval;
} }
/* Allocate 'num' TSNs by incrementing the association's TSN by num. */ /* Allocate 'num' TSNs by incrementing the association's TSN by num. */
...@@ -739,7 +751,7 @@ int sctp_cmp_addr_exact(const sockaddr_storage_t *ss1, ...@@ -739,7 +751,7 @@ int sctp_cmp_addr_exact(const sockaddr_storage_t *ss1,
* Note: We are sly and return a shared, prealloced chunk. * Note: We are sly and return a shared, prealloced chunk.
*/ */
sctp_chunk_t *sctp_get_ecne_prepend(sctp_association_t *asoc) sctp_chunk_t *sctp_get_ecne_prepend(sctp_association_t *asoc)
{ {
sctp_chunk_t *chunk; sctp_chunk_t *chunk;
int need_ecne; int need_ecne;
__u32 lowest_tsn; __u32 lowest_tsn;
...@@ -892,7 +904,7 @@ static void sctp_assoc_bh_rcv(sctp_association_t *asoc) ...@@ -892,7 +904,7 @@ static void sctp_assoc_bh_rcv(sctp_association_t *asoc)
/* Check to see if the association is freed in response to /* Check to see if the association is freed in response to
* the incoming chunk. If so, get out of the while loop. * the incoming chunk. If so, get out of the while loop.
*/ */
if (!sctp_id2assoc(sk, associd)) if (!sctp_id2assoc(sk, associd))
goto out; goto out;
...@@ -967,7 +979,7 @@ void sctp_assoc_update(sctp_association_t *asoc, sctp_association_t *new) ...@@ -967,7 +979,7 @@ void sctp_assoc_update(sctp_association_t *asoc, sctp_association_t *new)
* and peer's streams. * and peer's streams.
*/ */
for (i = 0; i < SCTP_MAX_STREAM; i++) { for (i = 0; i < SCTP_MAX_STREAM; i++) {
asoc->ssn[i] = 0; asoc->ssn[i] = 0;
asoc->ulpq.ssn[i] = 0; asoc->ulpq.ssn[i] = 0;
} }
} else { } else {
......
/* SCTP kernel reference Implementation /* SCTP kernel reference Implementation
* Copyright (c) Cisco 1999,2000 * Copyright (c) Cisco 1999,2000
* Copyright (c) Motorola 1999,2000,2001 * Copyright (c) Motorola 1999,2000,2001
* Copyright (c) International Business Machines Corp., 2001 * Copyright (c) International Business Machines Corp., 2001
* Copyright (c) La Monte H.P. Yarroll 2001 * Copyright (c) La Monte H.P. Yarroll 2001
* *
* This file is part of the SCTP kernel reference implementation. * This file is part of the SCTP kernel reference implementation.
* *
* A collection class to handle the storage of transport addresses. * A collection class to handle the storage of transport addresses.
* *
* The SCTP reference implementation is free software; * The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of * you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by * the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option) * the Free Software Foundation; either version 2, or (at your option)
* any later version. * any later version.
* *
* The SCTP reference implementation is distributed in the hope that it * The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied * will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************ * ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to * along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330, * the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
* *
* Please send any bug reports or fixes you make to the * Please send any bug reports or fixes you make to the
* email address(es): * email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net> * lksctp developers <lksctp-developers@lists.sourceforge.net>
* *
* Or submit a bug report through the following website: * Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp * http://www.sf.net/projects/lksctp
* *
* Written or modified by: * Written or modified by:
* La Monte H.P. Yarroll <piggy@acm.org> * La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us> * Karl Knutson <karl@athena.chicago.il.us>
* Jon Grimm <jgrimm@us.ibm.com> * Jon Grimm <jgrimm@us.ibm.com>
* Daisy Chang <daisyc@us.ibm.com> * Daisy Chang <daisyc@us.ibm.com>
* *
* Any bugs reported given to us we will try to fix... any fixes shared will * Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release. * be incorporated into the next SCTP release.
*/ */
...@@ -83,7 +83,7 @@ int sctp_bind_addr_copy(sctp_bind_addr_t *dest, const sctp_bind_addr_t *src, ...@@ -83,7 +83,7 @@ int sctp_bind_addr_copy(sctp_bind_addr_t *dest, const sctp_bind_addr_t *src,
out: out:
if (error) if (error)
sctp_bind_addr_clean(dest); sctp_bind_addr_clean(dest);
return error; return error;
} }
...@@ -356,7 +356,7 @@ int sctp_in_scope(const sockaddr_storage_t *addr, sctp_scope_t scope) ...@@ -356,7 +356,7 @@ int sctp_in_scope(const sockaddr_storage_t *addr, sctp_scope_t scope)
case AF_INET: case AF_INET:
/* According to the SCTP IPv4 address scoping document - /* According to the SCTP IPv4 address scoping document -
* <draft-stewart-tsvwg-sctp-ipv4-00.txt>, the scope has * <draft-stewart-tsvwg-sctp-ipv4-00.txt>, the scope has
* a heirarchy of 5 levels: * a heirarchy of 5 levels:
* Level 0 - unusable SCTP addresses * Level 0 - unusable SCTP addresses
* Level 1 - loopback address * Level 1 - loopback address
* Level 2 - link-local addresses * Level 2 - link-local addresses
......
/* SCTP kernel reference Implementation Copyright (C) 1999-2001 /* SCTP kernel reference Implementation Copyright (C) 1999-2001
* Cisco, Motorola, and IBM * Cisco, Motorola, and IBM
* Copyright 2001 La Monte H.P. Yarroll * Copyright 2001 La Monte H.P. Yarroll
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
* These functions manipulate sctp command sequences. * These functions manipulate sctp command sequences.
* *
* The SCTP reference implementation is free software; * The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of * you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by * the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option) * the Free Software Foundation; either version 2, or (at your option)
* any later version. * any later version.
* *
* The SCTP reference implementation is distributed in the hope that it * The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied * will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************ * ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to * along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330, * the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
* *
* Please send any bug reports or fixes you make to the * Please send any bug reports or fixes you make to the
* email address(es): * email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net> * lksctp developers <lksctp-developers@lists.sourceforge.net>
* *
* Or submit a bug report through the following website: * Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp * http://www.sf.net/projects/lksctp
* *
* Written or modified by: * Written or modified by:
* La Monte H.P. Yarroll <piggy@acm.org> * La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us> * Karl Knutson <karl@athena.chicago.il.us>
* *
* Any bugs reported given to us we will try to fix... any fixes shared will * Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release. * be incorporated into the next SCTP release.
*/ */
......
...@@ -198,6 +198,7 @@ static const char *sctp_timer_tbl[] = { ...@@ -198,6 +198,7 @@ static const char *sctp_timer_tbl[] = {
"TIMEOUT_T2_SHUTDOWN", "TIMEOUT_T2_SHUTDOWN",
"TIMEOUT_T3_RTX", "TIMEOUT_T3_RTX",
"TIMEOUT_T4_RTO", "TIMEOUT_T4_RTO",
"TIMEOUT_T5_SHUTDOWN_GUARD",
"TIMEOUT_HEARTBEAT", "TIMEOUT_HEARTBEAT",
"TIMEOUT_SACK", "TIMEOUT_SACK",
"TIMEOUT_AUTOCLOSE", "TIMEOUT_AUTOCLOSE",
......
...@@ -5,46 +5,46 @@ ...@@ -5,46 +5,46 @@
* Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001 Nokia, Inc. * Copyright (c) 2001 Nokia, Inc.
* Copyright (c) 2001 La Monte H.P. Yarroll * Copyright (c) 2001 La Monte H.P. Yarroll
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
* This abstraction represents an SCTP endpoint. * This abstraction represents an SCTP endpoint.
* *
* This file is part of the implementation of the add-IP extension, * This file is part of the implementation of the add-IP extension,
* based on <draft-ietf-tsvwg-addip-sctp-02.txt> June 29, 2001, * based on <draft-ietf-tsvwg-addip-sctp-02.txt> June 29, 2001,
* for the SCTP kernel reference Implementation. * for the SCTP kernel reference Implementation.
* *
* The SCTP reference implementation is free software; * The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of * you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by * the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option) * the Free Software Foundation; either version 2, or (at your option)
* any later version. * any later version.
* *
* The SCTP reference implementation is distributed in the hope that it * The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied * will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************ * ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to * along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330, * the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
* *
* Please send any bug reports or fixes you make to the * Please send any bug reports or fixes you make to the
* email address(es): * email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net> * lksctp developers <lksctp-developers@lists.sourceforge.net>
* *
* Or submit a bug report through the following website: * Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp * http://www.sf.net/projects/lksctp
* *
* Written or modified by: * Written or modified by:
* La Monte H.P. Yarroll <piggy@acm.org> * La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us> * Karl Knutson <karl@athena.chicago.il.us>
* Jon Grimm <jgrimm@austin.ibm.com> * Jon Grimm <jgrimm@austin.ibm.com>
* Daisy Chang <daisyc@us.ibm.com> * Daisy Chang <daisyc@us.ibm.com>
* Dajiang Zhang <dajiang.zhang@nokia.com> * Dajiang Zhang <dajiang.zhang@nokia.com>
* *
* Any bugs reported given to us we will try to fix... any fixes shared will * Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release. * be incorporated into the next SCTP release.
*/ */
...@@ -92,15 +92,16 @@ sctp_endpoint_t *sctp_endpoint_new(sctp_protocol_t *proto, ...@@ -92,15 +92,16 @@ sctp_endpoint_t *sctp_endpoint_new(sctp_protocol_t *proto,
sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep, sctp_protocol_t *proto, sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep, sctp_protocol_t *proto,
struct sock *sk, int priority) struct sock *sk, int priority)
{ {
sctp_opt_t *sp = sctp_sk(sk);
memset(ep, 0, sizeof(sctp_endpoint_t)); memset(ep, 0, sizeof(sctp_endpoint_t));
/* Initialize the base structure. */ /* Initialize the base structure. */
/* What type of endpoint are we? */ /* What type of endpoint are we? */
ep->base.type = SCTP_EP_TYPE_SOCKET; ep->base.type = SCTP_EP_TYPE_SOCKET;
/* Initialize the basic object fields. */ /* Initialize the basic object fields. */
atomic_set(&ep->base.refcnt, 1); atomic_set(&ep->base.refcnt, 1);
ep->base.dead = 0; ep->base.dead = 0;
ep->base.malloced = 1; ep->base.malloced = 1;
/* Create an input queue. */ /* Create an input queue. */
...@@ -129,22 +130,30 @@ sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep, sctp_protocol_t *proto, ...@@ -129,22 +130,30 @@ sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep, sctp_protocol_t *proto,
/* Set up the base timeout information. */ /* Set up the base timeout information. */
ep->timeouts[SCTP_EVENT_TIMEOUT_NONE] = 0; ep->timeouts[SCTP_EVENT_TIMEOUT_NONE] = 0;
ep->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] ep->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] =
= SCTP_DEFAULT_TIMEOUT_T1_COOKIE; SCTP_DEFAULT_TIMEOUT_T1_COOKIE;
ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] =
= SCTP_DEFAULT_TIMEOUT_T1_INIT; SCTP_DEFAULT_TIMEOUT_T1_INIT;
ep->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] ep->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] =
= sctp_sk(sk)->rtoinfo.srto_initial; sp->rtoinfo.srto_initial;
ep->timeouts[SCTP_EVENT_TIMEOUT_T3_RTX] = 0; ep->timeouts[SCTP_EVENT_TIMEOUT_T3_RTX] = 0;
ep->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = 0; ep->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = 0;
ep->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT]
= SCTP_DEFAULT_TIMEOUT_HEARTBEAT; /* sctpimpguide-05 Section 2.12.2
ep->timeouts[SCTP_EVENT_TIMEOUT_SACK] * If the 'T5-shutdown-guard' timer is used, it SHOULD be set to the
= SCTP_DEFAULT_TIMEOUT_SACK; * recommended value of 5 times 'RTO.Max'.
ep->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] */
= sctp_sk(sk)->autoclose * HZ; ep->timeouts[SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD]
ep->timeouts[SCTP_EVENT_TIMEOUT_PMTU_RAISE] = 5 * sp->rtoinfo.srto_max;
= SCTP_DEFAULT_TIMEOUT_PMTU_RAISE;
ep->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] =
SCTP_DEFAULT_TIMEOUT_HEARTBEAT;
ep->timeouts[SCTP_EVENT_TIMEOUT_SACK] =
SCTP_DEFAULT_TIMEOUT_SACK;
ep->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
sp->autoclose * HZ;
ep->timeouts[SCTP_EVENT_TIMEOUT_PMTU_RAISE] =
SCTP_DEFAULT_TIMEOUT_PMTU_RAISE;
/* Set up the default send/receive buffer space. */ /* Set up the default send/receive buffer space. */
...@@ -251,9 +260,10 @@ sctp_endpoint_t *sctp_endpoint_is_match(sctp_endpoint_t *ep, ...@@ -251,9 +260,10 @@ sctp_endpoint_t *sctp_endpoint_is_match(sctp_endpoint_t *ep,
* We do a linear search of the associations for this endpoint. * We do a linear search of the associations for this endpoint.
* We return the matching transport address too. * We return the matching transport address too.
*/ */
sctp_association_t *__sctp_endpoint_lookup_assoc(const sctp_endpoint_t *endpoint, sctp_association_t *__sctp_endpoint_lookup_assoc(
const sockaddr_storage_t *paddr, const sctp_endpoint_t *endpoint,
sctp_transport_t **transport) const sockaddr_storage_t *paddr,
sctp_transport_t **transport)
{ {
int rport; int rport;
sctp_association_t *asoc; sctp_association_t *asoc;
...@@ -310,7 +320,7 @@ static void sctp_endpoint_bh_rcv(sctp_endpoint_t *ep) ...@@ -310,7 +320,7 @@ static void sctp_endpoint_bh_rcv(sctp_endpoint_t *ep)
asoc = NULL; asoc = NULL;
inqueue = &ep->base.inqueue; inqueue = &ep->base.inqueue;
sk = ep->base.sk; sk = ep->base.sk;
while (NULL != (chunk = sctp_pop_inqueue(inqueue))) { while (NULL != (chunk = sctp_pop_inqueue(inqueue))) {
subtype.chunk = chunk->chunk_hdr->type; subtype.chunk = chunk->chunk_hdr->type;
...@@ -343,15 +353,15 @@ static void sctp_endpoint_bh_rcv(sctp_endpoint_t *ep) ...@@ -343,15 +353,15 @@ static void sctp_endpoint_bh_rcv(sctp_endpoint_t *ep)
/* FIX ME We really would rather NOT have to use /* FIX ME We really would rather NOT have to use
* GFP_ATOMIC. * GFP_ATOMIC.
*/ */
error = sctp_do_sm(SCTP_EVENT_T_CHUNK, subtype, state, error = sctp_do_sm(SCTP_EVENT_T_CHUNK, subtype, state,
ep, asoc, chunk, GFP_ATOMIC); ep, asoc, chunk, GFP_ATOMIC);
if (error != 0) if (error != 0)
goto err_out; goto err_out;
/* Check to see if the endpoint is freed in response to /* Check to see if the endpoint is freed in response to
* the incoming chunk. If so, get out of the while loop. * the incoming chunk. If so, get out of the while loop.
*/ */
if (!sctp_sk(sk)->ep) if (!sctp_sk(sk)->ep)
goto out; goto out;
} }
...@@ -360,10 +370,5 @@ static void sctp_endpoint_bh_rcv(sctp_endpoint_t *ep) ...@@ -360,10 +370,5 @@ static void sctp_endpoint_bh_rcv(sctp_endpoint_t *ep)
/* Is this the right way to pass errors up to the ULP? */ /* Is this the right way to pass errors up to the ULP? */
if (error) if (error)
ep->base.sk->err = -error; ep->base.sk->err = -error;
out: out:
} }
...@@ -5,43 +5,43 @@ ...@@ -5,43 +5,43 @@
* Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001 Nokia, Inc. * Copyright (c) 2001 Nokia, Inc.
* Copyright (c) 2001 La Monte H.P. Yarroll * Copyright (c) 2001 La Monte H.P. Yarroll
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
* These functions handle all input from the IP layer into SCTP. * These functions handle all input from the IP layer into SCTP.
* *
* The SCTP reference implementation is free software; * The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of * you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by * the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option) * the Free Software Foundation; either version 2, or (at your option)
* any later version. * any later version.
* *
* The SCTP reference implementation is distributed in the hope that it * The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied * will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************ * ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to * along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330, * the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
* *
* Please send any bug reports or fixes you make to the * Please send any bug reports or fixes you make to the
* email address(es): * email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net> * lksctp developers <lksctp-developers@lists.sourceforge.net>
* *
* Or submit a bug report through the following website: * Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp * http://www.sf.net/projects/lksctp
* *
* Written or modified by: * Written or modified by:
* La Monte H.P. Yarroll <piggy@acm.org> * La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us> * Karl Knutson <karl@athena.chicago.il.us>
* Xingang Guo <xingang.guo@intel.com> * Xingang Guo <xingang.guo@intel.com>
* Jon Grimm <jgrimm@us.ibm.com> * Jon Grimm <jgrimm@us.ibm.com>
* Hui Huang <hui.huang@nokia.com> * Hui Huang <hui.huang@nokia.com>
* Daisy Chang <daisyc@us.ibm.com> * Daisy Chang <daisyc@us.ibm.com>
* *
* Any bugs reported given to us we will try to fix... any fixes shared will * Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release. * be incorporated into the next SCTP release.
*/ */
...@@ -57,7 +57,7 @@ ...@@ -57,7 +57,7 @@
#include <net/sctp/sm.h> #include <net/sctp/sm.h>
/* Forward declarations for internal helpers. */ /* Forward declarations for internal helpers. */
static int sctp_rcv_ootb(struct sk_buff *); static int sctp_rcv_ootb(struct sk_buff *);
sctp_association_t *__sctp_rcv_lookup(struct sk_buff *skb, sctp_association_t *__sctp_rcv_lookup(struct sk_buff *skb,
const sockaddr_storage_t *laddr, const sockaddr_storage_t *laddr,
const sockaddr_storage_t *paddr, const sockaddr_storage_t *paddr,
...@@ -639,7 +639,7 @@ static sctp_association_t *__sctp_rcv_initack_lookup(struct sk_buff *skb, ...@@ -639,7 +639,7 @@ static sctp_association_t *__sctp_rcv_initack_lookup(struct sk_buff *skb,
/* Lookup an association for an inbound skb. */ /* Lookup an association for an inbound skb. */
sctp_association_t *__sctp_rcv_lookup(struct sk_buff *skb, sctp_association_t *__sctp_rcv_lookup(struct sk_buff *skb,
const sockaddr_storage_t *paddr, const sockaddr_storage_t *paddr,
const sockaddr_storage_t *laddr, const sockaddr_storage_t *laddr,
sctp_transport_t **transportp) sctp_transport_t **transportp)
{ {
sctp_association_t *asoc; sctp_association_t *asoc;
......
...@@ -2,36 +2,36 @@ ...@@ -2,36 +2,36 @@
* Copyright (c) 2001 Nokia, Inc. * Copyright (c) 2001 Nokia, Inc.
* Copyright (c) 2001 La Monte H.P. Yarroll * Copyright (c) 2001 La Monte H.P. Yarroll
* Copyright (c) 2002 International Business Machines, Corp. * Copyright (c) 2002 International Business Machines, Corp.
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
* SCTP over IPv6. * SCTP over IPv6.
* *
* The SCTP reference implementation is free software; * The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of * you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by * the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option) * the Free Software Foundation; either version 2, or (at your option)
* any later version. * any later version.
* *
* The SCTP reference implementation is distributed in the hope that it * The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied * will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************ * ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to * along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330, * the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
* *
* Please send any bug reports or fixes you make to the * Please send any bug reports or fixes you make to the
* email address(es): * email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net> * lksctp developers <lksctp-developers@lists.sourceforge.net>
* *
* Or submit a bug report through the following website: * Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp * http://www.sf.net/projects/lksctp
* *
* Written or modified by: * Written or modified by:
* Le Yanqun <yanqun.le@nokia.com> * Le Yanqun <yanqun.le@nokia.com>
* Hui Huang <hui.huang@nokia.com> * Hui Huang <hui.huang@nokia.com>
* La Monte H.P. Yarroll <piggy@acm.org> * La Monte H.P. Yarroll <piggy@acm.org>
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
* *
* Based on: * Based on:
* linux/net/ipv6/tcp_ipv6.c * linux/net/ipv6/tcp_ipv6.c
* *
* Any bugs reported given to us we will try to fix... any fixes shared will * Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release. * be incorporated into the next SCTP release.
*/ */
...@@ -145,7 +145,7 @@ static inline int sctp_v6_xmit(struct sk_buff *skb) ...@@ -145,7 +145,7 @@ static inline int sctp_v6_xmit(struct sk_buff *skb)
IPV6_ADDR_LOOPBACK)) { IPV6_ADDR_LOOPBACK)) {
ipv6_addr_copy(&saddr, &np->daddr); ipv6_addr_copy(&saddr, &np->daddr);
} }
} }
fl.fl6_src = &saddr; fl.fl6_src = &saddr;
} else { } else {
fl.fl6_src = &np->saddr; fl.fl6_src = &np->saddr;
...@@ -177,7 +177,7 @@ int sctp_v6_get_dst_mtu(const sockaddr_storage_t *address) ...@@ -177,7 +177,7 @@ int sctp_v6_get_dst_mtu(const sockaddr_storage_t *address)
if (dst) { if (dst) {
dst_mtu = dst->pmtu; dst_mtu = dst->pmtu;
SCTP_DEBUG_PRINTK("sctp_v6_get_dst_mtu: " SCTP_DEBUG_PRINTK("sctp_v6_get_dst_mtu: "
"ip6_route_output: dev:%s pmtu:%d\n", "ip6_route_output: dev:%s pmtu:%d\n",
dst->dev->name, dst_mtu); dst->dev->name, dst_mtu);
dst_release(dst); dst_release(dst);
} else { } else {
...@@ -189,11 +189,85 @@ int sctp_v6_get_dst_mtu(const sockaddr_storage_t *address) ...@@ -189,11 +189,85 @@ int sctp_v6_get_dst_mtu(const sockaddr_storage_t *address)
return dst_mtu; return dst_mtu;
} }
/* Initialize a PF_INET6 socket msg_name. */
static void sctp_inet6_msgname(char *msgname, int *addr_len)
{
struct sockaddr_in6 *sin6;
sin6 = (struct sockaddr_in6 *)msgname;
sin6->sin6_family = AF_INET6;
sin6->sin6_flowinfo = 0;
sin6->sin6_scope_id = 0;
*addr_len = sizeof(struct sockaddr_in6);
}
/* Initialize a PF_INET msgname from a ulpevent. */
static void sctp_inet6_event_msgname(sctp_ulpevent_t *event, char *msgname, int *addrlen)
{
struct sockaddr_in6 *sin6, *sin6from;
if (msgname) {
sockaddr_storage_t *addr;
sctp_inet6_msgname(msgname, addrlen);
sin6 = (struct sockaddr_in6 *)msgname;
sin6->sin6_port = htons(event->asoc->peer.port);
addr = &event->asoc->peer.primary_addr;
/* Note: If we go to a common v6 format, this code
* will change.
*/
/* Map ipv4 address into v4-mapped-on-v6 address. */
if (AF_INET == addr->sa.sa_family) {
/* FIXME: Easy, but there was no way to test this
* yet.
*/
return;
}
sin6from = &event->asoc->peer.primary_addr.v6;
ipv6_addr_copy(&sin6->sin6_addr, &sin6from->sin6_addr);
}
}
/* Initialize a msg_name from an inbound skb. */
static void sctp_inet6_skb_msgname(struct sk_buff *skb, char *msgname,
int *addr_len)
{
struct sctphdr *sh;
struct sockaddr_in6 *sin6;
if (msgname) {
sctp_inet6_msgname(msgname, addr_len);
sin6 = (struct sockaddr_in6 *)msgname;
sh = (struct sctphdr *)skb->h.raw;
sin6->sin6_port = sh->source;
/* FIXME: Map ipv4 address into v4-mapped-on-v6 address. */
if (__constant_htons(ETH_P_IP) == skb->protocol) {
/* FIXME: Easy, but there was no way to test this
* yet.
*/
return;
}
/* Otherwise, just copy the v6 address. */
ipv6_addr_copy(&sin6->sin6_addr, &skb->nh.ipv6h->saddr);
if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) {
struct inet6_skb_parm *opt =
(struct inet6_skb_parm *) skb->cb;
sin6->sin6_scope_id = opt->iif;
}
}
}
static struct proto_ops inet6_seqpacket_ops = { static struct proto_ops inet6_seqpacket_ops = {
.family = PF_INET6, .family = PF_INET6,
.release = inet6_release, .release = inet6_release,
.bind = inet6_bind, .bind = inet6_bind,
.connect = inet_dgram_connect, .connect = inet_dgram_connect,
.socketpair = sock_no_socketpair, .socketpair = sock_no_socketpair,
.accept = inet_accept, .accept = inet_accept,
.getname = inet6_getname, .getname = inet6_getname,
...@@ -238,15 +312,22 @@ static sctp_func_t sctp_ipv6_specific = { ...@@ -238,15 +312,22 @@ static sctp_func_t sctp_ipv6_specific = {
.sa_family = AF_INET6, .sa_family = AF_INET6,
}; };
static sctp_pf_t sctp_pf_inet6_specific = {
.event_msgname = sctp_inet6_event_msgname,
.skb_msgname = sctp_inet6_skb_msgname,
};
/* Initialize IPv6 support and register with inet6 stack. */ /* Initialize IPv6 support and register with inet6 stack. */
int sctp_v6_init(void) int sctp_v6_init(void)
{ {
/* Add SCTPv6 to inetsw6 linked list. */ /* Add SCTPv6 to inetsw6 linked list. */
inet6_register_protosw(&sctpv6_protosw); inet6_register_protosw(&sctpv6_protosw);
/* Register inet6 protocol. */ /* Register inet6 protocol. */
inet6_add_protocol(&sctpv6_protocol); inet6_add_protocol(&sctpv6_protocol);
/* Register the SCTP specfic PF_INET6 functions. */
sctp_set_pf_specific(PF_INET6, &sctp_pf_inet6_specific);
/* Fill in address family info. */ /* Fill in address family info. */
INIT_LIST_HEAD(&sctp_ipv6_specific.list); INIT_LIST_HEAD(&sctp_ipv6_specific.list);
list_add_tail(&sctp_ipv6_specific.list, &sctp_proto.address_families); list_add_tail(&sctp_ipv6_specific.list, &sctp_proto.address_families);
......
...@@ -2,41 +2,41 @@ ...@@ -2,41 +2,41 @@
* Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001 International Business Machines, Corp. * Copyright (c) 2001 International Business Machines, Corp.
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
* These functions handle output processing. * These functions handle output processing.
* *
* The SCTP reference implementation is free software; * The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of * you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by * the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option) * the Free Software Foundation; either version 2, or (at your option)
* any later version. * any later version.
* *
* The SCTP reference implementation is distributed in the hope that it * The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied * will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************ * ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to * along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330, * the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
* *
* Please send any bug reports or fixes you make to the * Please send any bug reports or fixes you make to the
* email address(es): * email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net> * lksctp developers <lksctp-developers@lists.sourceforge.net>
* *
* Or submit a bug report through the following website: * Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp * http://www.sf.net/projects/lksctp
* *
* Written or modified by: * Written or modified by:
* La Monte H.P. Yarroll <piggy@acm.org> * La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us> * Karl Knutson <karl@athena.chicago.il.us>
* Jon Grimm <jgrimm@austin.ibm.com> * Jon Grimm <jgrimm@austin.ibm.com>
* Sridhar Samudrala <sri@us.ibm.com> * Sridhar Samudrala <sri@us.ibm.com>
* *
* Any bugs reported given to us we will try to fix... any fixes shared will * Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release. * be incorporated into the next SCTP release.
*/ */
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
#include <linux/ip.h> #include <linux/ip.h>
#include <linux/ipv6.h> #include <linux/ipv6.h>
#include <linux/init.h> #include <linux/init.h>
#include <net/inet_ecn.h> #include <net/inet_ecn.h>
#include <net/icmp.h> #include <net/icmp.h>
#ifndef TEST_FRAME #ifndef TEST_FRAME
...@@ -113,7 +113,7 @@ void sctp_packet_free(sctp_packet_t *packet) ...@@ -113,7 +113,7 @@ void sctp_packet_free(sctp_packet_t *packet)
{ {
sctp_chunk_t *chunk; sctp_chunk_t *chunk;
while (NULL != while (NULL !=
(chunk = (sctp_chunk_t *)skb_dequeue(&packet->chunks))) { (chunk = (sctp_chunk_t *)skb_dequeue(&packet->chunks))) {
sctp_free_chunk(chunk); sctp_free_chunk(chunk);
} }
...@@ -129,7 +129,8 @@ void sctp_packet_free(sctp_packet_t *packet) ...@@ -129,7 +129,8 @@ void sctp_packet_free(sctp_packet_t *packet)
* as it can fit in the packet, but any more data that does not fit in this * as it can fit in the packet, but any more data that does not fit in this
* packet can be sent only after receiving the COOKIE_ACK. * packet can be sent only after receiving the COOKIE_ACK.
*/ */
sctp_xmit_t sctp_packet_transmit_chunk(sctp_packet_t *packet, sctp_chunk_t *chunk) sctp_xmit_t sctp_packet_transmit_chunk(sctp_packet_t *packet,
sctp_chunk_t *chunk)
{ {
sctp_xmit_t retval; sctp_xmit_t retval;
int error = 0; int error = 0;
...@@ -181,8 +182,8 @@ sctp_xmit_t sctp_packet_append_chunk(sctp_packet_t *packet, sctp_chunk_t *chunk) ...@@ -181,8 +182,8 @@ sctp_xmit_t sctp_packet_append_chunk(sctp_packet_t *packet, sctp_chunk_t *chunk)
/* Both control chunks and data chunks with TSNs are /* Both control chunks and data chunks with TSNs are
* non-fragmentable. * non-fragmentable.
*/ */
int fragmentable = sctp_chunk_is_data(chunk) int fragmentable = sctp_chunk_is_data(chunk) &&
&& (!chunk->has_tsn); (!chunk->has_tsn);
if (packet_empty) { if (packet_empty) {
if (fragmentable) { if (fragmentable) {
retval = SCTP_XMIT_MUST_FRAG; retval = SCTP_XMIT_MUST_FRAG;
...@@ -221,10 +222,8 @@ sctp_xmit_t sctp_packet_append_chunk(sctp_packet_t *packet, sctp_chunk_t *chunk) ...@@ -221,10 +222,8 @@ sctp_xmit_t sctp_packet_append_chunk(sctp_packet_t *packet, sctp_chunk_t *chunk)
} }
/* It is OK to send this chunk. */ /* It is OK to send this chunk. */
skb_queue_tail(&packet->chunks, skb_queue_tail(&packet->chunks, (struct sk_buff *)chunk);
(struct sk_buff *)chunk);
packet->size += chunk_len; packet->size += chunk_len;
finish: finish:
return retval; return retval;
} }
...@@ -305,7 +304,7 @@ int sctp_packet_transmit(sctp_packet_t *packet) ...@@ -305,7 +304,7 @@ int sctp_packet_transmit(sctp_packet_t *packet)
*/ */
if ((1 == chunk->num_times_sent) && if ((1 == chunk->num_times_sent) &&
(!transport->rto_pending)) { (!transport->rto_pending)) {
chunk->rtt_in_progress = 1; chunk->rtt_in_progress = 1;
transport->rto_pending = 1; transport->rto_pending = 1;
} }
packet_has_data = 1; packet_has_data = 1;
...@@ -337,9 +336,9 @@ int sctp_packet_transmit(sctp_packet_t *packet) ...@@ -337,9 +336,9 @@ int sctp_packet_transmit(sctp_packet_t *packet)
} }
/* Build the SCTP header. */ /* Build the SCTP header. */
sh = (struct sctphdr *) skb_push(nskb, sizeof(struct sctphdr)); sh = (struct sctphdr *)skb_push(nskb, sizeof(struct sctphdr));
sh->source = htons(packet->source_port); sh->source = htons(packet->source_port);
sh->dest = htons(packet->destination_port); sh->dest = htons(packet->destination_port);
/* From 6.8 Adler-32 Checksum Calculation: /* From 6.8 Adler-32 Checksum Calculation:
* After the packet is constructed (containing the SCTP common * After the packet is constructed (containing the SCTP common
...@@ -349,8 +348,8 @@ int sctp_packet_transmit(sctp_packet_t *packet) ...@@ -349,8 +348,8 @@ int sctp_packet_transmit(sctp_packet_t *packet)
* 1) Fill in the proper Verification Tag in the SCTP common * 1) Fill in the proper Verification Tag in the SCTP common
* header and initialize the checksum field to 0's. * header and initialize the checksum field to 0's.
*/ */
sh->vtag = htonl(packet->vtag); sh->vtag = htonl(packet->vtag);
sh->checksum = 0; sh->checksum = 0;
/* 2) Calculate the Adler-32 checksum of the whole packet, /* 2) Calculate the Adler-32 checksum of the whole packet,
* including the SCTP common header and all the * including the SCTP common header and all the
...@@ -467,7 +466,8 @@ static void sctp_packet_reset(sctp_packet_t *packet) ...@@ -467,7 +466,8 @@ static void sctp_packet_reset(sctp_packet_t *packet)
} }
/* This private function handles the specifics of appending DATA chunks. */ /* This private function handles the specifics of appending DATA chunks. */
static sctp_xmit_t sctp_packet_append_data(sctp_packet_t *packet, sctp_chunk_t *chunk) static sctp_xmit_t sctp_packet_append_data(sctp_packet_t *packet,
sctp_chunk_t *chunk)
{ {
sctp_xmit_t retval = SCTP_XMIT_OK; sctp_xmit_t retval = SCTP_XMIT_OK;
size_t datasize, rwnd, inflight; size_t datasize, rwnd, inflight;
...@@ -502,12 +502,13 @@ static sctp_xmit_t sctp_packet_append_data(sctp_packet_t *packet, sctp_chunk_t * ...@@ -502,12 +502,13 @@ static sctp_xmit_t sctp_packet_append_data(sctp_packet_t *packet, sctp_chunk_t *
} }
} }
/* sctpimpguide-05 2.14.2 D) When the time comes for the sender to /* sctpimpguide-05 2.14.2
* D) When the time comes for the sender to
* transmit new DATA chunks, the protocol parameter Max.Burst MUST * transmit new DATA chunks, the protocol parameter Max.Burst MUST
* first be applied to limit how many new DATA chunks may be sent. * first be applied to limit how many new DATA chunks may be sent.
* The limit is applied by adjusting cwnd as follows: * The limit is applied by adjusting cwnd as follows:
* if((flightsize + Max.Burst*MTU) < cwnd) * if ((flightsize + Max.Burst * MTU) < cwnd)
* cwnd = flightsize + Max.Burst*MTU * cwnd = flightsize + Max.Burst * MTU
*/ */
max_burst_bytes = transport->asoc->max_burst * transport->asoc->pmtu; max_burst_bytes = transport->asoc->max_burst * transport->asoc->pmtu;
if ((transport->flight_size + max_burst_bytes) < transport->cwnd) { if ((transport->flight_size + max_burst_bytes) < transport->cwnd) {
...@@ -516,11 +517,11 @@ static sctp_xmit_t sctp_packet_append_data(sctp_packet_t *packet, sctp_chunk_t * ...@@ -516,11 +517,11 @@ static sctp_xmit_t sctp_packet_append_data(sctp_packet_t *packet, sctp_chunk_t *
"transport: %p, cwnd: %d, " "transport: %p, cwnd: %d, "
"ssthresh: %d, flight_size: %d, " "ssthresh: %d, flight_size: %d, "
"pba: %d\n", "pba: %d\n",
__FUNCTION__, transport, __FUNCTION__, transport,
transport->cwnd, transport->cwnd,
transport->ssthresh, transport->ssthresh,
transport->flight_size, transport->flight_size,
transport->partial_bytes_acked); transport->partial_bytes_acked);
} }
/* RFC 2960 6.1 Transmission of DATA Chunks /* RFC 2960 6.1 Transmission of DATA Chunks
...@@ -552,7 +553,3 @@ static sctp_xmit_t sctp_packet_append_data(sctp_packet_t *packet, sctp_chunk_t * ...@@ -552,7 +553,3 @@ static sctp_xmit_t sctp_packet_append_data(sctp_packet_t *packet, sctp_chunk_t *
finish: finish:
return retval; return retval;
} }
This diff is collapsed.
/* SCTP kernel reference Implementation /* SCTP kernel reference Implementation
* Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 1999-2001 Motorola, Inc.
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
* These functions implement the SCTP primitive functions from Section 10. * These functions implement the SCTP primitive functions from Section 10.
* *
* Note that the descriptions from the specification are USER level * Note that the descriptions from the specification are USER level
* functions--this file is the functions which populate the struct proto * functions--this file is the functions which populate the struct proto
* for SCTP which is the BOTTOM of the sockets interface. * for SCTP which is the BOTTOM of the sockets interface.
* *
* The SCTP reference implementation is free software; * The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of * you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by * the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option) * the Free Software Foundation; either version 2, or (at your option)
* any later version. * any later version.
* *
* The SCTP reference implementation is distributed in the hope that it * The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied * will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************ * ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to * along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330, * the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
* *
* Please send any bug reports or fixes you make to the * Please send any bug reports or fixes you make to the
* email address(es): * email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net> * lksctp developers <lksctp-developers@lists.sourceforge.net>
* *
* Or submit a bug report through the following website: * Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp * http://www.sf.net/projects/lksctp
* *
* Written or modified by: * Written or modified by:
* La Monte H.P. Yarroll <piggy@acm.org> * La Monte H.P. Yarroll <piggy@acm.org>
* Narasimha Budihal <narasimha@refcode.org> * Narasimha Budihal <narasimha@refcode.org>
* Karl Knutson <karl@athena.chicago.il.us> * Karl Knutson <karl@athena.chicago.il.us>
* *
* Any bugs reported given to us we will try to fix... any fixes shared will * Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release. * be incorporated into the next SCTP release.
*/ */
......
...@@ -66,6 +66,9 @@ struct proc_dir_entry *proc_net_sctp; ...@@ -66,6 +66,9 @@ struct proc_dir_entry *proc_net_sctp;
*/ */
static struct socket *sctp_ctl_socket; static struct socket *sctp_ctl_socket;
static sctp_pf_t *sctp_pf_inet6_specific;
static sctp_pf_t *sctp_pf_inet_specific;
extern struct net_proto_family inet_family_ops; extern struct net_proto_family inet_family_ops;
/* Return the address of the control sock. */ /* Return the address of the control sock. */
...@@ -91,7 +94,7 @@ void sctp_proc_init(void) ...@@ -91,7 +94,7 @@ void sctp_proc_init(void)
void sctp_proc_exit(void) void sctp_proc_exit(void)
{ {
if (proc_net_sctp) { if (proc_net_sctp) {
proc_net_sctp= NULL; proc_net_sctp = NULL;
remove_proc_entry("net/sctp", 0); remove_proc_entry("net/sctp", 0);
} }
} }
...@@ -135,7 +138,8 @@ static inline void sctp_v4_get_local_addr_list(sctp_protocol_t *proto, ...@@ -135,7 +138,8 @@ static inline void sctp_v4_get_local_addr_list(sctp_protocol_t *proto,
* the protocol structure. * the protocol structure.
* FIXME: Make this an address family function. * FIXME: Make this an address family function.
*/ */
static inline void sctp_v6_get_local_addr_list(sctp_protocol_t *proto, struct net_device *dev) static inline void sctp_v6_get_local_addr_list(sctp_protocol_t *proto,
struct net_device *dev)
{ {
#ifdef SCTP_V6_SUPPORT #ifdef SCTP_V6_SUPPORT
/* FIXME: The testframe doesn't support this function. */ /* FIXME: The testframe doesn't support this function. */
...@@ -227,8 +231,8 @@ int sctp_copy_local_addr_list(sctp_protocol_t *proto, sctp_bind_addr_t *bp, ...@@ -227,8 +231,8 @@ int sctp_copy_local_addr_list(sctp_protocol_t *proto, sctp_bind_addr_t *bp,
long flags __attribute__ ((unused)); long flags __attribute__ ((unused));
sctp_spin_lock_irqsave(&proto->local_addr_lock, flags); sctp_spin_lock_irqsave(&proto->local_addr_lock, flags);
list_for_each(pos, &proto->local_addr_list) { list_for_each(pos, &proto->local_addr_list) {
addr = list_entry(pos, struct sockaddr_storage_list, list); addr = list_entry(pos, struct sockaddr_storage_list, list);
if (sctp_in_scope(&addr->a, scope)) { if (sctp_in_scope(&addr->a, scope)) {
/* Now that the address is in scope, check to see if /* Now that the address is in scope, check to see if
* the address type is really supported by the local * the address type is really supported by the local
...@@ -239,8 +243,7 @@ int sctp_copy_local_addr_list(sctp_protocol_t *proto, sctp_bind_addr_t *bp, ...@@ -239,8 +243,7 @@ int sctp_copy_local_addr_list(sctp_protocol_t *proto, sctp_bind_addr_t *bp,
(((AF_INET6 == addr->a.sa.sa_family) && (((AF_INET6 == addr->a.sa.sa_family) &&
(copy_flags & SCTP_ADDR6_ALLOWED) && (copy_flags & SCTP_ADDR6_ALLOWED) &&
(copy_flags & SCTP_ADDR6_PEERSUPP)))) { (copy_flags & SCTP_ADDR6_PEERSUPP)))) {
error = sctp_add_bind_addr(bp, error = sctp_add_bind_addr(bp, &addr->a,
&addr->a,
priority); priority);
if (error) if (error)
goto end_copy; goto end_copy;
...@@ -286,7 +289,8 @@ int sctp_v4_get_dst_mtu(const sockaddr_storage_t *address) ...@@ -286,7 +289,8 @@ int sctp_v4_get_dst_mtu(const sockaddr_storage_t *address)
/* Event handler for inet device events. /* Event handler for inet device events.
* Basically, whenever there is an event, we re-build our local address list. * Basically, whenever there is an event, we re-build our local address list.
*/ */
static int sctp_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) static int sctp_netdev_event(struct notifier_block *this, unsigned long event,
void *ptr)
{ {
long flags __attribute__ ((unused)); long flags __attribute__ ((unused));
...@@ -312,8 +316,8 @@ int sctp_ctl_sock_init(void) ...@@ -312,8 +316,8 @@ int sctp_ctl_sock_init(void)
err = sock_create(family, SOCK_SEQPACKET, IPPROTO_SCTP, err = sock_create(family, SOCK_SEQPACKET, IPPROTO_SCTP,
&sctp_ctl_socket); &sctp_ctl_socket);
if (err < 0) { if (err < 0) {
printk(KERN_ERR printk(KERN_ERR
"SCTP: Failed to create the SCTP control socket.\n"); "SCTP: Failed to create the SCTP control socket.\n");
return err; return err;
} }
sctp_ctl_socket->sk->allocation = GFP_ATOMIC; sctp_ctl_socket->sk->allocation = GFP_ATOMIC;
...@@ -347,6 +351,52 @@ sctp_func_t *sctp_get_af_specific(const sockaddr_storage_t *address) ...@@ -347,6 +351,52 @@ sctp_func_t *sctp_get_af_specific(const sockaddr_storage_t *address)
return retval; return retval;
} }
/* Common code to initialize a AF_INET msg_name. */
static void sctp_inet_msgname(char *msgname, int *addr_len)
{
struct sockaddr_in *sin;
sin = (struct sockaddr_in *)msgname;
*addr_len = sizeof(struct sockaddr_in);
sin->sin_family = AF_INET;
memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
}
/* Copy the primary address of the peer primary address as the msg_name. */
static void sctp_inet_event_msgname(sctp_ulpevent_t *event, char *msgname, int *addr_len)
{
struct sockaddr_in *sin, *sinfrom;
if (msgname) {
sctp_inet_msgname(msgname, addr_len);
sin = (struct sockaddr_in *)msgname;
sinfrom = &event->asoc->peer.primary_addr.v4;
sin->sin_port = htons(event->asoc->peer.port);
sin->sin_addr.s_addr = sinfrom->sin_addr.s_addr;
}
}
/* Initialize and copy out a msgname from an inbound skb. */
static void sctp_inet_skb_msgname(struct sk_buff *skb, char *msgname, int *addr_len)
{
struct sctphdr *sh;
struct sockaddr_in *sin;
if (msgname) {
sctp_inet_msgname(msgname, addr_len);
sin = (struct sockaddr_in *)msgname;
sh = (struct sctphdr *)skb->h.raw;
sin->sin_port = sh->source;
sin->sin_addr.s_addr = skb->nh.iph->saddr;
}
}
static sctp_pf_t sctp_pf_inet = {
.event_msgname = sctp_inet_event_msgname,
.skb_msgname = sctp_inet_skb_msgname,
};
/* Registration for netdev events. */ /* Registration for netdev events. */
struct notifier_block sctp_netdev_notifier = { struct notifier_block sctp_netdev_notifier = {
.notifier_call = sctp_netdev_event, .notifier_call = sctp_netdev_event,
...@@ -403,6 +453,34 @@ sctp_func_t sctp_ipv4_specific = { ...@@ -403,6 +453,34 @@ sctp_func_t sctp_ipv4_specific = {
.sa_family = AF_INET, .sa_family = AF_INET,
}; };
sctp_pf_t *sctp_get_pf_specific(int family) {
switch (family) {
case PF_INET:
return sctp_pf_inet_specific;
case PF_INET6:
return sctp_pf_inet6_specific;
default:
return NULL;
}
}
/* Set the PF specific function table. */
void sctp_set_pf_specific(int family, sctp_pf_t *pf)
{
switch (family) {
case PF_INET:
sctp_pf_inet_specific = pf;
break;
case PF_INET6:
sctp_pf_inet6_specific = pf;
break;
default:
BUG();
break;
}
}
/* Initialize the universe into something sensible. */ /* Initialize the universe into something sensible. */
int sctp_init(void) int sctp_init(void)
{ {
...@@ -421,9 +499,11 @@ int sctp_init(void) ...@@ -421,9 +499,11 @@ int sctp_init(void)
/* Initialize object count debugging. */ /* Initialize object count debugging. */
sctp_dbg_objcnt_init(); sctp_dbg_objcnt_init();
/* Initialize the SCTP specific PF functions. */
sctp_set_pf_specific(PF_INET, &sctp_pf_inet);
/* /*
* 14. Suggested SCTP Protocol Parameter Values * 14. Suggested SCTP Protocol Parameter Values
*/ */
/* The following protocol parameters are RECOMMENDED: */ /* The following protocol parameters are RECOMMENDED: */
/* RTO.Initial - 3 seconds */ /* RTO.Initial - 3 seconds */
sctp_proto.rto_initial = SCTP_RTO_INITIAL; sctp_proto.rto_initial = SCTP_RTO_INITIAL;
...@@ -468,7 +548,7 @@ int sctp_init(void) ...@@ -468,7 +548,7 @@ int sctp_init(void)
sctp_proto.assoc_hashbucket = (sctp_hashbucket_t *) sctp_proto.assoc_hashbucket = (sctp_hashbucket_t *)
kmalloc(4096 * sizeof(sctp_hashbucket_t), GFP_KERNEL); kmalloc(4096 * sizeof(sctp_hashbucket_t), GFP_KERNEL);
if (!sctp_proto.assoc_hashbucket) { if (!sctp_proto.assoc_hashbucket) {
printk (KERN_ERR "SCTP: Failed association hash alloc.\n"); printk(KERN_ERR "SCTP: Failed association hash alloc.\n");
status = -ENOMEM; status = -ENOMEM;
goto err_ahash_alloc; goto err_ahash_alloc;
} }
...@@ -482,7 +562,7 @@ int sctp_init(void) ...@@ -482,7 +562,7 @@ int sctp_init(void)
sctp_proto.ep_hashbucket = (sctp_hashbucket_t *) sctp_proto.ep_hashbucket = (sctp_hashbucket_t *)
kmalloc(64 * sizeof(sctp_hashbucket_t), GFP_KERNEL); kmalloc(64 * sizeof(sctp_hashbucket_t), GFP_KERNEL);
if (!sctp_proto.ep_hashbucket) { if (!sctp_proto.ep_hashbucket) {
printk (KERN_ERR "SCTP: Failed endpoint_hash alloc.\n"); printk(KERN_ERR "SCTP: Failed endpoint_hash alloc.\n");
status = -ENOMEM; status = -ENOMEM;
goto err_ehash_alloc; goto err_ehash_alloc;
} }
...@@ -497,7 +577,7 @@ int sctp_init(void) ...@@ -497,7 +577,7 @@ int sctp_init(void)
sctp_proto.port_hashtable = (sctp_bind_hashbucket_t *) sctp_proto.port_hashtable = (sctp_bind_hashbucket_t *)
kmalloc(4096 * sizeof(sctp_bind_hashbucket_t), GFP_KERNEL); kmalloc(4096 * sizeof(sctp_bind_hashbucket_t), GFP_KERNEL);
if (!sctp_proto.port_hashtable) { if (!sctp_proto.port_hashtable) {
printk (KERN_ERR "SCTP: Failed bind hash alloc."); printk(KERN_ERR "SCTP: Failed bind hash alloc.");
status = -ENOMEM; status = -ENOMEM;
goto err_bhash_alloc; goto err_bhash_alloc;
} }
......
...@@ -9,36 +9,36 @@ ...@@ -9,36 +9,36 @@
* This file includes part of the implementation of the add-IP extension, * This file includes part of the implementation of the add-IP extension,
* based on <draft-ietf-tsvwg-addip-sctp-02.txt> June 29, 2001, * based on <draft-ietf-tsvwg-addip-sctp-02.txt> June 29, 2001,
* for the SCTP kernel reference Implementation. * for the SCTP kernel reference Implementation.
* *
* These functions work with the state functions in sctp_sm_statefuns.c * These functions work with the state functions in sctp_sm_statefuns.c
* to implement the state operations. These functions implement the * to implement the state operations. These functions implement the
* steps which require modifying existing data structures. * steps which require modifying existing data structures.
* *
* The SCTP reference implementation is free software; * The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of * you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by * the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option) * the Free Software Foundation; either version 2, or (at your option)
* any later version. * any later version.
* *
* The SCTP reference implementation is distributed in the hope that it * The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied * will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************ * ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to * along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330, * the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
* *
* Please send any bug reports or fixes you make to the * Please send any bug reports or fixes you make to the
* email address(es): * email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net> * lksctp developers <lksctp-developers@lists.sourceforge.net>
* *
* Or submit a bug report through the following website: * Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp * http://www.sf.net/projects/lksctp
* *
* Written or modified by: * Written or modified by:
* La Monte H.P. Yarroll <piggy@acm.org> * La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us> * Karl Knutson <karl@athena.chicago.il.us>
* C. Robin <chris@hundredacre.ac.uk> * C. Robin <chris@hundredacre.ac.uk>
...@@ -73,7 +73,7 @@ ...@@ -73,7 +73,7 @@
* support any address type. * support any address type.
*/ */
static const sctp_supported_addrs_param_t sat_param = { static const sctp_supported_addrs_param_t sat_param = {
{ {
SCTP_PARAM_SUPPORTED_ADDRESS_TYPES, SCTP_PARAM_SUPPORTED_ADDRESS_TYPES,
__constant_htons(SCTP_SAT_LEN), __constant_htons(SCTP_SAT_LEN),
}, },
...@@ -204,7 +204,7 @@ sctp_chunk_t *sctp_make_init(const sctp_association_t *asoc, ...@@ -204,7 +204,7 @@ sctp_chunk_t *sctp_make_init(const sctp_association_t *asoc,
* PLEASE DO NOT FIXME [This version does not support Host Name.] * PLEASE DO NOT FIXME [This version does not support Host Name.]
*/ */
retval = sctp_make_chunk(asoc, SCTP_CID_INIT, 0, chunksize); retval = sctp_make_chunk(asoc, SCTP_CID_INIT, 0, chunksize);
if (!retval) if (!retval)
goto nodata; goto nodata;
...@@ -1204,7 +1204,7 @@ sctp_association_t *sctp_make_temp_asoc(const sctp_endpoint_t *ep, ...@@ -1204,7 +1204,7 @@ sctp_association_t *sctp_make_temp_asoc(const sctp_endpoint_t *ep,
case 6: case 6:
asoc->c.peer_addr.v6.sin6_family = AF_INET6; asoc->c.peer_addr.v6.sin6_family = AF_INET6;
asoc->c.peer_addr.v6.sin6_port asoc->c.peer_addr.v6.sin6_port
= ntohs(chunk->sctp_hdr->source); = ntohs(chunk->sctp_hdr->source);
asoc->c.peer_addr.v6.sin6_flowinfo = 0; /* BUG BUG BUG */ asoc->c.peer_addr.v6.sin6_flowinfo = 0; /* BUG BUG BUG */
asoc->c.peer_addr.v6.sin6_addr = chunk->skb->nh.ipv6h->saddr; asoc->c.peer_addr.v6.sin6_addr = chunk->skb->nh.ipv6h->saddr;
...@@ -1245,7 +1245,7 @@ sctp_cookie_param_t *sctp_pack_cookie(const sctp_endpoint_t *ep, ...@@ -1245,7 +1245,7 @@ sctp_cookie_param_t *sctp_pack_cookie(const sctp_endpoint_t *ep,
* functions simpler to write. * functions simpler to write.
*/ */
if (bodysize % SCTP_COOKIE_MULTIPLE) if (bodysize % SCTP_COOKIE_MULTIPLE)
bodysize += SCTP_COOKIE_MULTIPLE bodysize += SCTP_COOKIE_MULTIPLE
- (bodysize % SCTP_COOKIE_MULTIPLE); - (bodysize % SCTP_COOKIE_MULTIPLE);
*cookie_len = headersize + bodysize; *cookie_len = headersize + bodysize;
...@@ -1418,6 +1418,7 @@ void sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid, ...@@ -1418,6 +1418,7 @@ void sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid,
__u8 *end; __u8 *end;
sctp_transport_t *transport; sctp_transport_t *transport;
struct list_head *pos, *temp; struct list_head *pos, *temp;
char *cookie;
/* We must include the address that the INIT packet came from. /* We must include the address that the INIT packet came from.
* This is the only address that matters for an INIT packet. * This is the only address that matters for an INIT packet.
...@@ -1437,7 +1438,7 @@ void sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid, ...@@ -1437,7 +1438,7 @@ void sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid,
for (param.v = peer_init->init_hdr.params; for (param.v = peer_init->init_hdr.params;
param.v < end; param.v < end;
param.v += WORD_ROUND(ntohs(param.p->length))) { param.v += WORD_ROUND(ntohs(param.p->length))) {
if (!sctp_process_param(asoc, param, peer_addr, cid, if (!sctp_process_param(asoc, param, peer_addr, cid,
priority)) priority))
goto clean_up; goto clean_up;
} }
...@@ -1461,7 +1462,7 @@ void sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid, ...@@ -1461,7 +1462,7 @@ void sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid,
*/ */
if (asoc->c.sinit_num_ostreams > if (asoc->c.sinit_num_ostreams >
ntohs(peer_init->init_hdr.num_inbound_streams)) { ntohs(peer_init->init_hdr.num_inbound_streams)) {
asoc->c.sinit_num_ostreams = asoc->c.sinit_num_ostreams =
ntohs(peer_init->init_hdr.num_inbound_streams); ntohs(peer_init->init_hdr.num_inbound_streams);
} }
...@@ -1471,6 +1472,15 @@ void sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid, ...@@ -1471,6 +1472,15 @@ void sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid,
/* Peer Rwnd : Current calculated value of the peer's rwnd. */ /* Peer Rwnd : Current calculated value of the peer's rwnd. */
asoc->peer.rwnd = asoc->peer.i.a_rwnd; asoc->peer.rwnd = asoc->peer.i.a_rwnd;
/* Copy cookie in case we need to resend COOKIE-ECHO. */
cookie = asoc->peer.cookie;
if (cookie) {
asoc->peer.cookie = kmalloc(asoc->peer.cookie_len, priority);
if (!asoc->peer.cookie)
goto clean_up;
memcpy(asoc->peer.cookie, cookie, asoc->peer.cookie_len);
}
/* RFC 2960 7.2.1 The initial value of ssthresh MAY be arbitrarily /* RFC 2960 7.2.1 The initial value of ssthresh MAY be arbitrarily
* high (for example, implementations MAY use the size of the receiver * high (for example, implementations MAY use the size of the receiver
* advertised window). * advertised window).
...@@ -1560,7 +1570,7 @@ int sctp_process_param(sctp_association_t *asoc, sctpParam_t param, ...@@ -1560,7 +1570,7 @@ int sctp_process_param(sctp_association_t *asoc, sctpParam_t param,
break; break;
case SCTP_PARAM_HOST_NAME_ADDRESS: case SCTP_PARAM_HOST_NAME_ADDRESS:
SCTP_DEBUG_PRINTK("unimplmented SCTP_HOST_NAME_ADDRESS\n"); SCTP_DEBUG_PRINTK("unimplemented SCTP_HOST_NAME_ADDRESS\n");
break; break;
case SCTP_PARAM_SUPPORTED_ADDRESS_TYPES: case SCTP_PARAM_SUPPORTED_ADDRESS_TYPES:
...@@ -1595,13 +1605,12 @@ int sctp_process_param(sctp_association_t *asoc, sctpParam_t param, ...@@ -1595,13 +1605,12 @@ int sctp_process_param(sctp_association_t *asoc, sctpParam_t param,
case SCTP_PARAM_STATE_COOKIE: case SCTP_PARAM_STATE_COOKIE:
asoc->peer.cookie_len = asoc->peer.cookie_len =
ntohs(param.p->length) - ntohs(param.p->length) - sizeof(sctp_paramhdr_t);
sizeof(sctp_paramhdr_t);
asoc->peer.cookie = param.cookie->body; asoc->peer.cookie = param.cookie->body;
break; break;
case SCTP_PARAM_HEATBEAT_INFO: case SCTP_PARAM_HEATBEAT_INFO:
SCTP_DEBUG_PRINTK("unimplmented " SCTP_DEBUG_PRINTK("unimplemented "
"SCTP_PARAM_HEATBEAT_INFO\n"); "SCTP_PARAM_HEATBEAT_INFO\n");
break; break;
......
/* SCTP kernel reference Implementation /* SCTP kernel reference Implementation
* Copyright (c) 1999 Cisco, Inc. * Copyright (c) 1999 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001-2002 International Business Machines Corp. * Copyright (c) 2001-2002 International Business Machines Corp.
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
* These functions work with the state functions in sctp_sm_statefuns.c * These functions work with the state functions in sctp_sm_statefuns.c
* to implement that state operations. These functions implement the * to implement that state operations. These functions implement the
* steps which require modifying existing data structures. * steps which require modifying existing data structures.
* *
* The SCTP reference implementation is free software; * The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of * you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by * the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option) * the Free Software Foundation; either version 2, or (at your option)
* any later version. * any later version.
* *
* The SCTP reference implementation is distributed in the hope that it * The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied * will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************ * ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to * along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330, * the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
* *
* Please send any bug reports or fixes you make to the * Please send any bug reports or fixes you make to the
* email address(es): * email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net> * lksctp developers <lksctp-developers@lists.sourceforge.net>
* *
* Or submit a bug report through the following website: * Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp * http://www.sf.net/projects/lksctp
* *
* Written or modified by: * Written or modified by:
* La Monte H.P. Yarroll <piggy@acm.org> * La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us> * Karl Knutson <karl@athena.chicago.il.us>
* Jon Grimm <jgrimm@austin.ibm.com> * Jon Grimm <jgrimm@austin.ibm.com>
...@@ -119,7 +119,7 @@ int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype, ...@@ -119,7 +119,7 @@ int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype,
int priority) int priority)
{ {
sctp_cmd_seq_t commands; sctp_cmd_seq_t commands;
sctp_sm_table_entry_t *state_fn; sctp_sm_table_entry_t *state_fn;
sctp_disposition_t status; sctp_disposition_t status;
int error = 0; int error = 0;
typedef const char *(printfn_t)(sctp_subtype_t); typedef const char *(printfn_t)(sctp_subtype_t);
...@@ -253,6 +253,7 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype, ...@@ -253,6 +253,7 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
sctp_chunk_t *new_obj; sctp_chunk_t *new_obj;
sctp_chunk_t *chunk; sctp_chunk_t *chunk;
sctp_packet_t *packet; sctp_packet_t *packet;
struct list_head *pos;
struct timer_list *timer; struct timer_list *timer;
unsigned long timeout; unsigned long timeout;
sctp_transport_t *t; sctp_transport_t *t;
...@@ -336,9 +337,8 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype, ...@@ -336,9 +337,8 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
case SCTP_CMD_PEER_INIT: case SCTP_CMD_PEER_INIT:
/* Process a unified INIT from the peer. */ /* Process a unified INIT from the peer. */
sctp_cmd_process_init(commands, sctp_cmd_process_init(commands, asoc, chunk,
asoc, chunk, command->obj.ptr, command->obj.ptr, priority);
priority);
break; break;
case SCTP_CMD_GEN_COOKIE_ECHO: case SCTP_CMD_GEN_COOKIE_ECHO:
...@@ -462,6 +462,7 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype, ...@@ -462,6 +462,7 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
break; break;
case SCTP_CMD_INIT_RESTART: case SCTP_CMD_INIT_RESTART:
/* Do the needed accounting and updates /* Do the needed accounting and updates
* associated with restarting an initialization * associated with restarting an initialization
* timer. * timer.
...@@ -474,6 +475,15 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype, ...@@ -474,6 +475,15 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
asoc->max_init_timeo; asoc->max_init_timeo;
} }
/* If we've sent any data bundled with
* COOKIE-ECHO we need to resend.
*/
list_for_each(pos, &asoc->peer.transport_addr_list) {
t = list_entry(pos, sctp_transport_t,
transports);
sctp_retransmit_mark(&asoc->outqueue, t, 0);
}
sctp_add_cmd_sf(commands, sctp_add_cmd_sf(commands,
SCTP_CMD_TIMER_RESTART, SCTP_CMD_TIMER_RESTART,
SCTP_TO(command->obj.to)); SCTP_TO(command->obj.to));
...@@ -602,7 +612,7 @@ static sctp_chunk_t *sctp_do_ecn_ecne_work(sctp_association_t *asoc, ...@@ -602,7 +612,7 @@ static sctp_chunk_t *sctp_do_ecn_ecne_work(sctp_association_t *asoc,
{ {
sctp_chunk_t *repl; sctp_chunk_t *repl;
sctp_transport_t *transport; sctp_transport_t *transport;
/* Our previously transmitted packet ran into some congestion /* Our previously transmitted packet ran into some congestion
* so we should take action by reducing cwnd and ssthresh * so we should take action by reducing cwnd and ssthresh
* and then ACK our peer that we we've done so by * and then ACK our peer that we we've done so by
...@@ -716,7 +726,7 @@ int sctp_gen_sack(sctp_association_t *asoc, int force, sctp_cmd_seq_t *commands) ...@@ -716,7 +726,7 @@ int sctp_gen_sack(sctp_association_t *asoc, int force, sctp_cmd_seq_t *commands)
error = sctp_push_outqueue(&asoc->outqueue, sack); error = sctp_push_outqueue(&asoc->outqueue, sack);
/* Stop the SACK timer. */ /* Stop the SACK timer. */
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_SACK)); SCTP_TO(SCTP_EVENT_TIMEOUT_SACK));
} }
...@@ -785,7 +795,7 @@ void sctp_generate_t3_rtx_event(unsigned long peer) ...@@ -785,7 +795,7 @@ void sctp_generate_t3_rtx_event(unsigned long peer)
if (!mod_timer(&transport->T3_rtx_timer, jiffies + (HZ/20))) if (!mod_timer(&transport->T3_rtx_timer, jiffies + (HZ/20)))
sctp_transport_hold(transport); sctp_transport_hold(transport);
goto out_unlock; goto out_unlock;
} }
/* Is this transport really dead and just waiting around for /* Is this transport really dead and just waiting around for
* the timer to let go of the reference? * the timer to let go of the reference?
...@@ -867,6 +877,14 @@ void sctp_generate_t2_shutdown_event(unsigned long data) ...@@ -867,6 +877,14 @@ void sctp_generate_t2_shutdown_event(unsigned long data)
sctp_generate_timeout_event(asoc, SCTP_EVENT_TIMEOUT_T2_SHUTDOWN); sctp_generate_timeout_event(asoc, SCTP_EVENT_TIMEOUT_T2_SHUTDOWN);
} }
void sctp_generate_t5_shutdown_guard_event(unsigned long data)
{
sctp_association_t *asoc = (sctp_association_t *)data;
sctp_generate_timeout_event(asoc,
SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD);
} /* sctp_generate_t5_shutdown_guard_event() */
void sctp_generate_autoclose_event(unsigned long data) void sctp_generate_autoclose_event(unsigned long data)
{ {
sctp_association_t *asoc = (sctp_association_t *) data; sctp_association_t *asoc = (sctp_association_t *) data;
...@@ -890,7 +908,7 @@ void sctp_generate_heartbeat_event(unsigned long data) ...@@ -890,7 +908,7 @@ void sctp_generate_heartbeat_event(unsigned long data)
if (!mod_timer(&transport->hb_timer, jiffies + (HZ/20))) if (!mod_timer(&transport->hb_timer, jiffies + (HZ/20)))
sctp_transport_hold(transport); sctp_transport_hold(transport);
goto out_unlock; goto out_unlock;
} }
/* Is this structure just waiting around for us to actually /* Is this structure just waiting around for us to actually
* get destroyed? * get destroyed?
...@@ -932,6 +950,7 @@ sctp_timer_event_t *sctp_timer_events[SCTP_NUM_TIMEOUT_TYPES] = { ...@@ -932,6 +950,7 @@ sctp_timer_event_t *sctp_timer_events[SCTP_NUM_TIMEOUT_TYPES] = {
sctp_generate_t2_shutdown_event, sctp_generate_t2_shutdown_event,
NULL, NULL,
NULL, NULL,
sctp_generate_t5_shutdown_guard_event,
sctp_generate_heartbeat_event, sctp_generate_heartbeat_event,
sctp_generate_sack_event, sctp_generate_sack_event,
sctp_generate_autoclose_event, sctp_generate_autoclose_event,
...@@ -1023,6 +1042,9 @@ static void sctp_cmd_assoc_failed(sctp_cmd_seq_t *commands, ...@@ -1023,6 +1042,9 @@ static void sctp_cmd_assoc_failed(sctp_cmd_seq_t *commands,
sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
SCTP_ULPEVENT(event)); SCTP_ULPEVENT(event));
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_CLOSED));
/* FIXME: We need to handle data that could not be sent or was not /* FIXME: We need to handle data that could not be sent or was not
* acked, if the user has enabled SEND_FAILED notifications. * acked, if the user has enabled SEND_FAILED notifications.
*/ */
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -4,45 +4,45 @@ ...@@ -4,45 +4,45 @@
* Copyright (c) 2001 International Business Machines Corp. * Copyright (c) 2001 International Business Machines Corp.
* Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001 La Monte H.P. Yarroll * Copyright (c) 2001 La Monte H.P. Yarroll
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
* This module provides the abstraction for an SCTP tranport representing * This module provides the abstraction for an SCTP tranport representing
* a remote transport address. For local transport addresses, we just use * a remote transport address. For local transport addresses, we just use
* sockaddr_storage_t. * sockaddr_storage_t.
* *
* The SCTP reference implementation is free software; * The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of * you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by * the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option) * the Free Software Foundation; either version 2, or (at your option)
* any later version. * any later version.
* *
* The SCTP reference implementation is distributed in the hope that it * The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied * will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************ * ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to * along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330, * the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
* *
* Please send any bug reports or fixes you make to the * Please send any bug reports or fixes you make to the
* email address(es): * email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net> * lksctp developers <lksctp-developers@lists.sourceforge.net>
* *
* Or submit a bug report through the following website: * Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp * http://www.sf.net/projects/lksctp
* *
* Written or modified by: * Written or modified by:
* La Monte H.P. Yarroll <piggy@acm.org> * La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us> * Karl Knutson <karl@athena.chicago.il.us>
* Jon Grimm <jgrimm@us.ibm.com> * Jon Grimm <jgrimm@us.ibm.com>
* Xingang Guo <xingang.guo@intel.com> * Xingang Guo <xingang.guo@intel.com>
* Hui Huang <hui.huang@nokia.com> * Hui Huang <hui.huang@nokia.com>
* Sridhar Samudrala <sri@us.ibm.com> * Sridhar Samudrala <sri@us.ibm.com>
* *
* Any bugs reported given to us we will try to fix... any fixes shared will * Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release. * be incorporated into the next SCTP release.
*/ */
...@@ -215,7 +215,7 @@ void sctp_transport_put(sctp_transport_t *transport) ...@@ -215,7 +215,7 @@ void sctp_transport_put(sctp_transport_t *transport)
sctp_transport_destroy(transport); sctp_transport_destroy(transport);
} }
/* Update transport's RTO based on the newly calculated RTT. */ /* Update transport's RTO based on the newly calculated RTT. */
void sctp_transport_update_rto(sctp_transport_t *tp, __u32 rtt) void sctp_transport_update_rto(sctp_transport_t *tp, __u32 rtt)
{ {
sctp_protocol_t *proto = sctp_get_protocol(); sctp_protocol_t *proto = sctp_get_protocol();
...@@ -263,7 +263,7 @@ void sctp_transport_update_rto(sctp_transport_t *tp, __u32 rtt) ...@@ -263,7 +263,7 @@ void sctp_transport_update_rto(sctp_transport_t *tp, __u32 rtt)
* seconds then it is rounded up to RTO.Min seconds. * seconds then it is rounded up to RTO.Min seconds.
*/ */
if (tp->rto < tp->asoc->rto_min) if (tp->rto < tp->asoc->rto_min)
tp->rto = tp->asoc->rto_min; tp->rto = tp->asoc->rto_min;
/* 6.3.1 C7) A maximum value may be placed on RTO provided it is /* 6.3.1 C7) A maximum value may be placed on RTO provided it is
* at least RTO.max seconds. * at least RTO.max seconds.
...@@ -381,13 +381,13 @@ void sctp_transport_lower_cwnd(sctp_transport_t *transport, ...@@ -381,13 +381,13 @@ void sctp_transport_lower_cwnd(sctp_transport_t *transport,
break; break;
case SCTP_LOWER_CWND_FAST_RTX: case SCTP_LOWER_CWND_FAST_RTX:
/* RFC 2960 7.2.4 Adjust the ssthresh and cwnd of the /* RFC 2960 7.2.4 Adjust the ssthresh and cwnd of the
* destination address(es) to which the missing DATA chunks * destination address(es) to which the missing DATA chunks
* were last sent, according to the formula described in * were last sent, according to the formula described in
* Section 7.2.3. * Section 7.2.3.
* *
* RFC 2960 7.2.3, sctpimpguide-05 2.9.2 Upon detection of * RFC 2960 7.2.3, sctpimpguide-05 2.9.2 Upon detection of
* packet losses from SACK (see Section 7.2.4), An endpoint * packet losses from SACK (see Section 7.2.4), An endpoint
* should do the following: * should do the following:
* ssthresh = max(cwnd/2, 2*MTU) * ssthresh = max(cwnd/2, 2*MTU)
* cwnd = ssthresh * cwnd = ssthresh
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -98,7 +98,7 @@ static int x25_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more) ...@@ -98,7 +98,7 @@ static int x25_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more)
*/ */
static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype) static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype)
{ {
x25_address source_addr, dest_addr; struct x25_address source_addr, dest_addr;
switch (frametype) { switch (frametype) {
case X25_CALL_ACCEPTED: { case X25_CALL_ACCEPTED: {
......
This diff is collapsed.
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