diff options
| author | Arnaldo Carvalho de Melo <acme@conectiva.com.br> | 2002-09-11 07:48:48 -0300 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@conectiva.com.br> | 2002-09-11 07:48:48 -0300 |
| commit | 269f04b762fa11f693d3c3167afcdd4ca505fca6 (patch) | |
| tree | d46f99f4f39506ab6e2c21871a051c651ef93967 | |
| parent | ebf9bc772851196b2a5e8daf4eadd609c734501f (diff) | |
[LLC] use just one struct sock per connection
With this PF_LLC is tightly integrated with the core and that is a
good thing 8)
. kill llc_ui_opt, the only non-duplicated bit is struct sockaddr_llc
and this now lives in llc_opt
. remove debug code from llc_sk_alloc/free (previously llc_sock_alloc/free)
. the skbs allocated for event processing don't need to have any payload
at all, just the skb->cb is enough, so remove the bogus 1 from alloc_skb
calls
. llc_conn_disc put on death row
. llc_process_tmr_ev callers have to hold the socket lock
. the request functions in llc_if.c doesn't hold the socket lock anymore
its up to its callers on the socket layer (llc_sock.c)
. llc_sk_alloc now receives a priority for sk_alloc call and is the
only way to alloc a new sock (from llc_mac and llc_sock, bottom and top)
. added the traditional struct sock REFCNT_DEBUG support for llc
. llc_sock was simplified and is on the zen route to cleanliness, wait for
the next patches, it'll shrink a lot when I zap all the crap (as in
not needed) list handling, using the existing list maintained in
struct llc_sap for that, probably splitting it in two, one for listening
sockets and other for (being) established ones. Ah, and the sap->ind
and sap->req and friends will die.
| -rw-r--r-- | include/linux/llc.h | 11 | ||||
| -rw-r--r-- | include/net/llc_conn.h | 64 | ||||
| -rw-r--r-- | include/net/llc_if.h | 2 | ||||
| -rw-r--r-- | net/llc/llc_actn.c | 2 | ||||
| -rw-r--r-- | net/llc/llc_c_ac.c | 42 | ||||
| -rw-r--r-- | net/llc/llc_conn.c | 34 | ||||
| -rw-r--r-- | net/llc/llc_if.c | 56 | ||||
| -rw-r--r-- | net/llc/llc_mac.c | 19 | ||||
| -rw-r--r-- | net/llc/llc_main.c | 59 | ||||
| -rw-r--r-- | net/llc/llc_sock.c | 619 |
10 files changed, 409 insertions, 499 deletions
diff --git a/include/linux/llc.h b/include/linux/llc.h index 824a149e9e6b..77ac5d9df544 100644 --- a/include/linux/llc.h +++ b/include/linux/llc.h @@ -78,17 +78,6 @@ enum llc_sockopts { #define LLC_SAP_DYN_STOP 0xDE #define LLC_SAP_DYN_TRIES 4 -struct sock; - -struct llc_ui_opt { - u16 link; /* network layer link number */ - struct llc_sap *sap; /* pointer to parent SAP */ - struct sock *core_sk; - struct net_device *dev; /* device to send to remote */ - struct sockaddr_llc addr; /* address sock is bound to */ -}; - -#define llc_ui_sk(__sk) ((struct llc_ui_opt *)(__sk)->protinfo) #define llc_ui_skb_cb(__skb) ((struct sockaddr_llc *)&((__skb)->cb[0])) #ifdef CONFIG_LLC_UI diff --git a/include/net/llc_conn.h b/include/net/llc_conn.h index ea7725fa705f..3b2d68e45075 100644 --- a/include/net/llc_conn.h +++ b/include/net/llc_conn.h @@ -2,7 +2,7 @@ #define LLC_CONN_H /* * Copyright (c) 1997 by Procom Technology, Inc. - * 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br> + * 2001, 2002 by Arnaldo Carvalho de Melo <acme@conectiva.com.br> * * This program can be redistributed or modified under the terms of the * GNU General Public License as published by the Free Software Foundation. @@ -13,8 +13,7 @@ */ #include <linux/timer.h> #include <net/llc_if.h> - -#define DEBUG_LLC_CONN_ALLOC +#include <linux/llc.h> struct llc_timer { struct timer_list timer; @@ -25,7 +24,7 @@ struct llc_timer { struct llc_opt { struct list_head node; /* entry in sap->sk_list.list */ struct sock *sk; /* sock that has this llc_opt */ - void *handler; /* for upper layers usage */ + struct sockaddr_llc addr; /* address sock is bound to */ u8 state; /* state of connection */ struct llc_sap *sap; /* pointer to parent SAP */ struct llc_addr laddr; /* lsap/mac pair */ @@ -80,60 +79,11 @@ struct llc_opt { struct llc_conn_state_ev; -extern struct sock *__llc_sock_alloc(int family); -extern void __llc_sock_free(struct sock *sk, u8 free); - -#ifdef DEBUG_LLC_CONN_ALLOC -#define dump_stack() printk(KERN_INFO "call trace: %p, %p, %p\n", \ - __builtin_return_address(0), \ - __builtin_return_address(1), \ - __builtin_return_address(2)); -#define llc_sock_alloc(family) ({ \ - struct sock *__sk = __llc_sock_alloc(family); \ - if (__sk) { \ - llc_sk(__sk)->f_alloc = __FUNCTION__; \ - llc_sk(__sk)->l_alloc = __LINE__; \ - } \ - __sk;}) -#define __llc_sock_assert(__sk) \ - if (llc_sk(__sk)->f_free) { \ - printk(KERN_ERR \ - "%p conn (alloc'd @ %s(%d)) " \ - "already freed @ %s(%d) " \ - "being used again @ %s(%d)\n", \ - llc_sk(__sk), \ - llc_sk(__sk)->f_alloc, llc_sk(__sk)->l_alloc, \ - llc_sk(__sk)->f_free, llc_sk(__sk)->l_free, \ - __FUNCTION__, __LINE__); \ - dump_stack(); -#define llc_sock_free(__sk) \ -{ \ - __llc_sock_assert(__sk) \ - } else { \ - __llc_sock_free(__sk, 0); \ - llc_sk(__sk)->f_free = __FUNCTION__; \ - llc_sk(__sk)->l_free = __LINE__; \ - } \ -} -#define llc_sock_assert(__sk) \ -{ \ - __llc_sock_assert(__sk); \ - return; } \ -} -#define llc_sock_assert_ret(__sk, __ret) \ -{ \ - __llc_sock_assert(__sk); \ - return __ret; } \ -} -#else /* DEBUG_LLC_CONN_ALLOC */ -#define llc_sock_alloc(family) __llc_sock_alloc(family) -#define llc_sock_free(__sk) __llc_sock_free(__sk, 1) -#define llc_sock_assert(__sk) -#define llc_sock_assert_ret(__sk) -#endif /* DEBUG_LLC_CONN_ALLOC */ +extern struct sock *llc_sk_alloc(int family, int priority); +extern void llc_sk_free(struct sock *sk); -extern void llc_sock_reset(struct sock *sk); -extern int llc_sock_init(struct sock *sk); +extern void llc_sk_reset(struct sock *sk); +extern int llc_sk_init(struct sock *sk); /* Access to a connection */ extern int llc_conn_state_process(struct sock *sk, struct sk_buff *skb); diff --git a/include/net/llc_if.h b/include/net/llc_if.h index 975485fc42c0..e294c1d976b1 100644 --- a/include/net/llc_if.h +++ b/include/net/llc_if.h @@ -73,8 +73,6 @@ struct llc_prim_conn { u8 pri; /* service_class */ struct net_device *dev; struct sock *sk; /* returned from REQUEST */ - void *handler; /* upper layer use, - stored in llc_opt->handler */ u16 link; struct sk_buff *skb; /* received SABME */ }; diff --git a/net/llc/llc_actn.c b/net/llc/llc_actn.c index cb8704409d8e..dadb22054749 100644 --- a/net/llc/llc_actn.c +++ b/net/llc/llc_actn.c @@ -134,7 +134,7 @@ int llc_station_ac_report_status(struct llc_station *station, static void llc_station_ack_tmr_callback(unsigned long timeout_data) { struct llc_station *station = (struct llc_station *)timeout_data; - struct sk_buff *skb = alloc_skb(1, GFP_ATOMIC); + struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC); station->ack_tmr_running = 0; if (skb) { diff --git a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c index bc296905424d..ecb6d6f1658d 100644 --- a/net/llc/llc_c_ac.c +++ b/net/llc/llc_c_ac.c @@ -1454,8 +1454,9 @@ int llc_conn_ac_set_f_flag_p(struct sock *sk, struct sk_buff *skb) void llc_conn_pf_cycle_tmr_cb(unsigned long timeout_data) { struct sock *sk = (struct sock *)timeout_data; - struct sk_buff *skb = alloc_skb(1, GFP_ATOMIC); + struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC); + bh_lock_sock(sk); llc_sk(sk)->pf_cycle_timer.running = 0; if (skb) { struct llc_conn_state_ev *ev = llc_conn_ev(skb); @@ -1464,13 +1465,15 @@ void llc_conn_pf_cycle_tmr_cb(unsigned long timeout_data) ev->data.tmr.timer_specific = NULL; llc_process_tmr_ev(sk, skb); } + bh_unlock_sock(sk); } static void llc_conn_busy_tmr_cb(unsigned long timeout_data) { struct sock *sk = (struct sock *)timeout_data; - struct sk_buff *skb = alloc_skb(1, GFP_ATOMIC); + struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC); + bh_lock_sock(sk); llc_sk(sk)->busy_state_timer.running = 0; if (skb) { struct llc_conn_state_ev *ev = llc_conn_ev(skb); @@ -1479,13 +1482,15 @@ static void llc_conn_busy_tmr_cb(unsigned long timeout_data) ev->data.tmr.timer_specific = NULL; llc_process_tmr_ev(sk, skb); } + bh_unlock_sock(sk); } void llc_conn_ack_tmr_cb(unsigned long timeout_data) { struct sock* sk = (struct sock *)timeout_data; - struct sk_buff *skb = alloc_skb(1, GFP_ATOMIC); + struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC); + bh_lock_sock(sk); llc_sk(sk)->ack_timer.running = 0; if (skb) { struct llc_conn_state_ev *ev = llc_conn_ev(skb); @@ -1494,13 +1499,15 @@ void llc_conn_ack_tmr_cb(unsigned long timeout_data) ev->data.tmr.timer_specific = NULL; llc_process_tmr_ev(sk, skb); } + bh_unlock_sock(sk); } static void llc_conn_rej_tmr_cb(unsigned long timeout_data) { struct sock *sk = (struct sock *)timeout_data; - struct sk_buff *skb = alloc_skb(1, GFP_ATOMIC); + struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC); + bh_lock_sock(sk); llc_sk(sk)->rej_sent_timer.running = 0; if (skb) { struct llc_conn_state_ev *ev = llc_conn_ev(skb); @@ -1509,6 +1516,7 @@ static void llc_conn_rej_tmr_cb(unsigned long timeout_data) ev->data.tmr.timer_specific = NULL; llc_process_tmr_ev(sk, skb); } + bh_unlock_sock(sk); } int llc_conn_ac_rst_vs(struct sock *sk, struct sk_buff *skb) @@ -1536,14 +1544,11 @@ int llc_conn_ac_upd_vs(struct sock *sk, struct sk_buff *skb) * llc_conn_disc - removes connection from SAP list and frees it * @sk: closed connection * @skb: occurred event - * - * Returns 2, to indicate the state machine that the connection was freed. */ int llc_conn_disc(struct sock *sk, struct sk_buff *skb) { - llc_sap_unassign_sock(llc_sk(sk)->sap, sk); - llc_sock_free(sk); - return 2; + /* FIXME: this thing seems to want to die */ + return 0; } /** @@ -1555,7 +1560,7 @@ int llc_conn_disc(struct sock *sk, struct sk_buff *skb) */ int llc_conn_reset(struct sock *sk, struct sk_buff *skb) { - llc_sock_reset(sk); + llc_sk_reset(sk); return 0; } @@ -1589,19 +1594,16 @@ u8 llc_circular_between(u8 a, u8 b, u8 c) */ static void llc_process_tmr_ev(struct sock *sk, struct sk_buff *skb) { - bh_lock_sock(sk); if (llc_sk(sk)->state == LLC_CONN_OUT_OF_SVC) { printk(KERN_WARNING "%s: timer called on closed connection\n", __FUNCTION__); llc_conn_free_ev(skb); - goto out; - } - if (!sk->lock.users) - llc_conn_state_process(sk, skb); - else { - llc_set_backlog_type(skb, LLC_EVENT); - sk_add_backlog(sk, skb); + } else { + if (!sk->lock.users) + llc_conn_state_process(sk, skb); + else { + llc_set_backlog_type(skb, LLC_EVENT); + sk_add_backlog(sk, skb); + } } -out: - bh_unlock_sock(sk); } diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c index ef6093acb1c3..46e54e9621ba 100644 --- a/net/llc/llc_conn.c +++ b/net/llc/llc_conn.c @@ -43,7 +43,7 @@ static int llc_offset_table[NBR_CONN_STATES][NBR_CONN_EV]; * @sk: connection * @skb: occurred event * - * Sends an event to connection state machine. after processing event + * Sends an event to connection state machine. After processing event * (executing it's actions and changing state), upper layer will be * indicated or confirmed, if needed. Returns 0 for success, 1 for * failure. The socket lock has to be held before calling this function. @@ -65,15 +65,6 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) llc_conn_free_ev(skb); else if (ind_prim && cfm_prim) skb_get(skb); -#ifdef THIS_BREAKS_DISCONNECT_NOTIFICATION_BADLY - /* check if the connection was freed by the state machine by - * means of llc_conn_disc */ - if (rc == 2) { - printk(KERN_INFO "%s: rc == 2\n", __FUNCTION__); - rc = -ECONNABORTED; - goto out; - } -#endif /* THIS_BREAKS_DISCONNECT_NOTIFICATION_BADLY */ if (!flag) /* indicate or confirm not required */ goto out; rc = 0; @@ -83,10 +74,13 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) * sock crap */ if (flag == LLC_DATA_PRIM + 1) { - struct sock *upper = llc_sk(skb->sk)->handler; - - skb->sk = upper; - if (sock_queue_rcv_skb(upper, skb)) { + if (sock_queue_rcv_skb(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__); @@ -105,10 +99,8 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) } if (!llc_data_accept_state(llc->state)) { /* In this state, we can send I pdu */ - struct sock* upper = llc_sk(skb->sk)->handler; - - if (upper) - wake_up(upper->sleep); + if (skb->sk) + skb->sk->write_space(skb->sk); } else rc = llc->failed_data_req = 1; kfree_skb(skb); @@ -118,7 +110,6 @@ out: void llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb) { - llc_sock_assert(sk); /* queue PDU to send to MAC layer */ skb_queue_tail(&sk->write_queue, skb); llc_conn_send_pdus(sk); @@ -380,11 +371,10 @@ static struct llc_conn_state_trans *llc_qualify_conn_ev(struct sock *sk, * llc_exec_conn_trans_actions - executes related actions * @sk: connection * @trans: transition that it's actions must be performed - * @skb: happened event + * @skb: event * * Executes actions that is related to happened event. Returns 0 for - * success, 1 to indicate failure of at least one action or 2 if the - * connection was freed (llc_conn_disc was called) + * success, 1 to indicate failure of at least one action. */ static int llc_exec_conn_trans_actions(struct sock *sk, struct llc_conn_state_trans *trans, diff --git a/net/llc/llc_if.c b/net/llc/llc_if.c index cab3de5fb797..8af1ec3a1417 100644 --- a/net/llc/llc_if.c +++ b/net/llc/llc_if.c @@ -15,6 +15,7 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/netdevice.h> +#include <linux/tcp.h> #include <asm/errno.h> #include <net/llc_if.h> #include <net/llc_sap.h> @@ -249,7 +250,6 @@ int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb) int rc = -ECONNABORTED; struct llc_opt *llc = llc_sk(sk); - lock_sock(sk); if (llc->state == LLC_CONN_STATE_ADM) goto out; rc = -EBUSY; @@ -269,7 +269,6 @@ int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb) skb->dev = llc->dev; rc = llc_conn_state_process(sk, skb); out: - release_sock(sk); return rc; } @@ -299,7 +298,6 @@ static void llc_confirm_impossible(struct llc_prim_if_block *prim) static int llc_conn_req_handler(struct llc_prim_if_block *prim) { int rc = -EBUSY; - struct llc_opt *llc; struct llc_sap *sap = prim->sap; struct sk_buff *skb; struct net_device *ddev = mac_dev_peer(prim->data->conn.dev, @@ -319,37 +317,16 @@ static int llc_conn_req_handler(struct llc_prim_if_block *prim) daddr.lsap = prim->data->conn.daddr.lsap; sk = llc_lookup_established(sap, &daddr, &laddr); if (sk) { - llc_confirm_impossible(prim); - goto out_put; - } - rc = -ENOMEM; - if (prim->data->conn.sk) { - sk = prim->data->conn.sk; - if (llc_sock_init(sk)) - goto out; - } else { - /* - * FIXME: this one will die as soon as core and - * llc_sock starts sharing a struct sock. - */ - sk = llc_sock_alloc(PF_LLC); - if (!sk) { + if (sk->state == TCP_ESTABLISHED) { llc_confirm_impossible(prim); - goto out; - } - prim->data->conn.sk = sk; + goto out_put; + } else + sock_put(sk); } + rc = -ENOMEM; + sk = prim->data->conn.sk; sock_hold(sk); - lock_sock(sk); - /* assign new connection to it's SAP */ - llc_sap_assign_sock(sap, sk); - llc = llc_sk(sk); - memcpy(&llc->daddr, &daddr, sizeof(llc->daddr)); - memcpy(&llc->laddr, &laddr, sizeof(llc->laddr)); - llc->dev = ddev; - llc->link = prim->data->conn.link; - llc->handler = prim->data->conn.handler; - skb = alloc_skb(1, GFP_ATOMIC); + skb = alloc_skb(0, GFP_ATOMIC); if (skb) { struct llc_conn_state_ev *ev = llc_conn_ev(skb); @@ -359,15 +336,10 @@ static int llc_conn_req_handler(struct llc_prim_if_block *prim) ev->data.prim.data = prim; rc = llc_conn_state_process(sk, skb); } - if (rc) { - llc_sap_unassign_sock(sap, sk); - llc_sock_free(sk); + if (rc) llc_confirm_impossible(prim); - } - release_sock(sk); out_put: sock_put(sk); -out: return rc; } @@ -388,7 +360,6 @@ static int llc_disc_req_handler(struct llc_prim_if_block *prim) struct sock* sk = prim->data->disc.sk; sock_hold(sk); - lock_sock(sk); if (llc_sk(sk)->state == LLC_CONN_STATE_ADM || llc_sk(sk)->state == LLC_CONN_OUT_OF_SVC) goto out; @@ -396,7 +367,7 @@ static int llc_disc_req_handler(struct llc_prim_if_block *prim) * Postpone unassigning the connection from its SAP and returning the * connection until all ACTIONs have been completely executed */ - skb = alloc_skb(1, GFP_ATOMIC); + skb = alloc_skb(0, GFP_ATOMIC); if (!skb) goto out; ev = llc_conn_ev(skb); @@ -406,7 +377,6 @@ static int llc_disc_req_handler(struct llc_prim_if_block *prim) ev->data.prim.data = prim; rc = llc_conn_state_process(sk, skb); out: - release_sock(sk); sock_put(sk); return rc; } @@ -426,8 +396,7 @@ static int llc_rst_req_handler(struct llc_prim_if_block *prim) int rc = 1; struct sock *sk = prim->data->res.sk; - lock_sock(sk); - skb = alloc_skb(1, GFP_ATOMIC); + skb = alloc_skb(0, GFP_ATOMIC); if (skb) { struct llc_conn_state_ev *ev = llc_conn_ev(skb); @@ -437,7 +406,6 @@ static int llc_rst_req_handler(struct llc_prim_if_block *prim) ev->data.prim.data = prim; rc = llc_conn_state_process(sk, skb); } - release_sock(sk); return rc; } @@ -498,7 +466,7 @@ static int llc_rst_rsp_handler(struct llc_prim_if_block *prim) * package as event and send it to connection event handler */ struct sock *sk = prim->data->res.sk; - struct sk_buff *skb = alloc_skb(1, GFP_ATOMIC); + struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC); if (skb) { struct llc_conn_state_ev *ev = llc_conn_ev(skb); diff --git a/net/llc/llc_mac.c b/net/llc/llc_mac.c index 0020b3801d6a..b8b031510043 100644 --- a/net/llc/llc_mac.c +++ b/net/llc/llc_mac.c @@ -27,7 +27,7 @@ #include <net/llc_s_ev.h> #include <linux/trdevice.h> -#if 1 +#if 0 #define dprintk(args...) printk(KERN_DEBUG args) #else #define dprintk(args...) @@ -123,23 +123,30 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev, sk = llc_lookup_established(sap, &saddr, &daddr); if (!sk) { + struct llc_opt *llc; + + dprintk("%s: llc_lookup_established failed\n", __FUNCTION__); /* * FIXME: here we'll pass the sk->family of the * listening socket, if found, when * llc_lookup_listener is added in the next patches. */ - sk = llc_sock_alloc(PF_LLC); + sk = llc_sk_alloc(PF_LLC, GFP_ATOMIC); if (!sk) goto drop; - memcpy(&llc_sk(sk)->daddr, &saddr, sizeof(saddr)); + llc = llc_sk(sk); + memcpy(&llc->laddr, &daddr, sizeof(llc->laddr)); + memcpy(&llc->daddr, &saddr, sizeof(llc->daddr)); llc_sap_assign_sock(sap, sk); sock_hold(sk); } skb->sk = sk; bh_lock_sock(sk); - if (!sk->lock.users) - rc = llc_conn_rcv(sk, skb); - else { + if (!sk->lock.users) { + /* rc = */ llc_conn_rcv(sk, skb); + rc = 0; + } else { + dprintk("%s: adding to backlog...\n", __FUNCTION__); llc_set_backlog_type(skb, LLC_PACKET); sk_add_backlog(sk, skb); rc = 0; diff --git a/net/llc/llc_main.c b/net/llc/llc_main.c index fe24722bd45a..a1768084605b 100644 --- a/net/llc/llc_main.c +++ b/net/llc/llc_main.c @@ -52,6 +52,11 @@ static int llc_rtn_all_conns(struct llc_sap *sap); static struct llc_station llc_main_station; /* only one of its kind */ +#undef LLC_REFCNT_DEBUG +#ifdef LLC_REFCNT_DEBUG +static atomic_t llc_sock_nr; +#endif + /** * llc_sap_alloc - allocates and initializes sap. * @@ -165,10 +170,12 @@ static int llc_backlog_rcv(struct sock *sk, struct sk_buff *skb) } /** - * llc_sock_init - Initialize a socket with default llc values. + * llc_sk_init - Initializes a socket with default llc values. * @sk: socket to intiailize. + * + * Initializes a socket with default llc values. */ -int llc_sock_init(struct sock* sk) +int llc_sk_init(struct sock* sk) { struct llc_opt *llc = kmalloc(sizeof(*llc), GFP_ATOMIC); int rc = -ENOMEM; @@ -198,61 +205,83 @@ out: } /** - * __llc_sock_alloc - Allocates LLC sock + * llc_sk_alloc - Allocates LLC sock * @family: upper layer protocol family + * @priority: for allocation (%GFP_KERNEL, %GFP_ATOMIC, etc) * * Allocates a LLC sock and initializes it. Returns the new LLC sock * or %NULL if there's no memory available for one */ -struct sock *__llc_sock_alloc(int family) +struct sock *llc_sk_alloc(int family, int priority) { - struct sock *sk = sk_alloc(family, GFP_ATOMIC, 1, NULL); + struct sock *sk = sk_alloc(family, priority, 1, NULL); + MOD_INC_USE_COUNT; if (!sk) - goto out; - if (llc_sock_init(sk)) + goto decmod; + if (llc_sk_init(sk)) goto outsk; sock_init_data(NULL, sk); +#ifdef LLC_REFCNT_DEBUG + atomic_inc(&llc_sock_nr); + printk(KERN_DEBUG "LLC socket %p created in %s, now we have %d alive\n", sk, + __FUNCTION__, atomic_read(&llc_sock_nr)); +#endif out: return sk; outsk: sk_free(sk); sk = NULL; +decmod: + MOD_DEC_USE_COUNT; goto out; } /** - * __llc_sock_free - Frees a LLC socket + * llc_sk_free - Frees a LLC socket * @sk - socket to free * * Frees a LLC socket */ -void __llc_sock_free(struct sock *sk, u8 free) +void llc_sk_free(struct sock *sk) { struct llc_opt *llc = llc_sk(sk); llc->state = LLC_CONN_OUT_OF_SVC; - /* stop all (possibly) running timers */ + /* Stop all (possibly) running timers */ llc_conn_ac_stop_all_timers(sk, NULL); #ifdef DEBUG_LLC_CONN_ALLOC printk(KERN_INFO "%s: unackq=%d, txq=%d\n", __FUNCTION__, skb_queue_len(&llc->pdu_unack_q), skb_queue_len(&sk->write_queue)); #endif + skb_queue_purge(&sk->receive_queue); skb_queue_purge(&sk->write_queue); skb_queue_purge(&llc->pdu_unack_q); - if (free) - sock_put(sk); +#ifdef LLC_REFCNT_DEBUG + if (atomic_read(&sk->refcnt) != 1) { + printk(KERN_DEBUG "Destruction of LLC sock %p delayed in %s, cnt=%d\n", + sk, __FUNCTION__, atomic_read(&sk->refcnt)); + printk(KERN_DEBUG "%d LLC sockets are still alive\n", + atomic_read(&llc_sock_nr)); + } else { + atomic_dec(&llc_sock_nr); + printk(KERN_DEBUG "LLC socket %p released in %s, %d are still alive\n", sk, + __FUNCTION__, atomic_read(&llc_sock_nr)); + } +#endif + sock_put(sk); + MOD_DEC_USE_COUNT; } /** - * llc_sock_reset - resets a connection + * llc_sk_reset - resets a connection * @sk: LLC socket to reset * * Resets a connection to the out of service state. Stops its timers * and frees any frames in the queues of the connection. */ -void llc_sock_reset(struct sock *sk) +void llc_sk_reset(struct sock *sk) { struct llc_opt *llc = llc_sk(sk); @@ -585,7 +614,7 @@ static int __init llc_init(void) skb_queue_head_init(&llc_main_station.mac_pdu_q); skb_queue_head_init(&llc_main_station.ev_q.list); spin_lock_init(&llc_main_station.ev_q.lock); - skb = alloc_skb(1, GFP_ATOMIC); + skb = alloc_skb(0, GFP_ATOMIC); if (!skb) goto err; llc_build_offset_table(); diff --git a/net/llc/llc_sock.c b/net/llc/llc_sock.c index 0b2c3a9966d4..5753d316feaf 100644 --- a/net/llc/llc_sock.c +++ b/net/llc/llc_sock.c @@ -11,6 +11,7 @@ * connections. * * Copyright (c) 2001 by Jay Schulist <jschlst@samba.org> + * 2002 by Arnaldo Carvalho de Melo <acme@conectiva.com.br> * * This program can be redistributed or modified under the terms of the * GNU General Public License as published by the Free Software Foundation. @@ -57,6 +58,13 @@ static int llc_ui_confirm(struct llc_prim_if_block *prim); static int llc_ui_wait_for_conn(struct sock *sk, int timeout); static int llc_ui_wait_for_disc(struct sock *sk, int timeout); static int llc_ui_wait_for_data(struct sock *sk, int timeout); +static int llc_ui_wait_for_busy_core(struct sock *sk, int timeout); + +#if 0 +#define dprintk(args...) printk(KERN_DEBUG args) +#else +#define dprintk(args...) +#endif /** * llc_ui_next_link_no - return the next unused link number for a sap @@ -130,7 +138,7 @@ static int llc_ui_send_conn(struct sock *sk, struct llc_sap *sap, struct sockaddr_llc *addr, struct net_device *dev, int link) { - struct llc_ui_opt *llc_ui = llc_ui_sk(sk); + struct llc_opt *llc = llc_sk(sk); union llc_u_prim_data prim_data; struct llc_prim_if_block prim; @@ -139,10 +147,9 @@ static int llc_ui_send_conn(struct sock *sk, struct llc_sap *sap, prim.prim = LLC_CONN_PRIM; prim_data.conn.dev = dev; prim_data.conn.link = link; - prim_data.conn.sk = NULL; - prim_data.conn.handler = sk; + prim_data.conn.sk = sk; prim_data.conn.pri = 0; - prim_data.conn.saddr.lsap = llc_ui->addr.sllc_ssap; + prim_data.conn.saddr.lsap = llc->addr.sllc_ssap; prim_data.conn.daddr.lsap = addr->sllc_dsap; memcpy(prim_data.conn.saddr.mac, dev->dev_addr, IFHWADDRLEN); memcpy(prim_data.conn.daddr.mac, addr->sllc_dmac, IFHWADDRLEN); @@ -159,55 +166,50 @@ static int llc_ui_send_conn(struct sock *sk, struct llc_sap *sap, */ static int llc_ui_send_disc(struct sock *sk) { - struct llc_ui_opt *llc_ui = llc_ui_sk(sk); + struct llc_opt *llc = llc_sk(sk); union llc_u_prim_data prim_data; struct llc_prim_if_block prim; int rc = 0; - if (sk->type != SOCK_STREAM || sk->state != TCP_ESTABLISHED) + if (sk->type != SOCK_STREAM || sk->state != TCP_ESTABLISHED) { + rc = 1; goto out; + } sk->state = TCP_CLOSING; prim.data = &prim_data; - prim.sap = llc_ui->sap; + prim.sap = llc->sap; prim.prim = LLC_DISC_PRIM; - prim_data.disc.sk = llc_ui->core_sk; - prim_data.disc.link = llc_ui->link; - rc = llc_ui->sap->req(&prim); + prim_data.disc.sk = sk; + prim_data.disc.link = llc->link; + rc = llc->sap->req(&prim); out: return rc; } /** * llc_ui_send_data - send data via reliable llc2 connection - * @sap: Sap the socket is bound to. * @sk: Connection the socket is using. * @skb: Data the user wishes to send. * @addr: Source and destination fields provided by the user. + * @noblock: can we block waiting for data? * * Send data via reliable llc2 connection. - * Returns 0 upon success, non-zero if action did not succeed. + * Returns 0 upon success, non-zero if action did not succeed. */ -static int llc_ui_send_data(struct llc_sap *sap, struct sock* sk, - struct sk_buff *skb, struct sockaddr_llc *addr) +static int llc_ui_send_data(struct sock* sk, struct sk_buff *skb, + struct sockaddr_llc *addr, int noblock) { - struct llc_ui_opt* llc_ui = llc_ui_sk(sk); - struct llc_opt* llc_core = llc_sk(llc_ui->core_sk); - int rc; + struct llc_opt* llc = llc_sk(sk); + int rc = 0; skb->protocol = llc_ui_protocol_type(addr->sllc_arphrd); - sock_hold(sk); -try: - rc = llc_build_and_send_pkt(llc_ui->core_sk, skb); - if (rc != -EBUSY) - goto out; - rc = wait_event_interruptible(sk->socket->wait, !llc_ui->core_sk || - !llc_core->failed_data_req); + if (llc_data_accept_state(llc->state) || llc->p_flag) { + int timeout = sock_sndtimeo(sk, noblock); + + rc = llc_ui_wait_for_busy_core(sk, timeout); + } if (!rc) - goto try; - if (!llc_ui->core_sk) - rc = -ENOTCONN; -out: - sock_put(sk); + rc = llc_build_and_send_pkt(sk, skb); return rc; } @@ -255,12 +257,12 @@ static __inline__ struct llc_sap *llc_ui_find_sap(u8 sap) read_lock_bh(&llc_ui_sockets_lock); for (sk = llc_ui_sockets; sk; sk = sk->next) { - struct llc_ui_opt *llc_ui = llc_ui_sk(sk); + struct llc_opt *llc = llc_sk(sk); - if (!llc_ui->sap) + if (!llc->sap) continue; - if (llc_ui->sap->laddr.lsap == sap) { - s = llc_ui->sap; + if (llc->sap->laddr.lsap == sap) { + s = llc->sap; break; } } @@ -274,13 +276,13 @@ static struct sock *__llc_ui_find_sk_by_exact(struct llc_addr *laddr, struct sock *sk; for (sk = llc_ui_sockets; sk; sk = sk->next) { - struct llc_ui_opt *llc_ui = llc_ui_sk(sk); + struct llc_opt *llc = llc_sk(sk); - if (llc_ui->addr.sllc_ssap == laddr->lsap && - llc_ui->addr.sllc_dsap == daddr->lsap && - llc_mac_null(llc_ui->addr.sllc_mmac) && - llc_mac_match(llc_ui->addr.sllc_smac, laddr->mac) && - llc_mac_match(llc_ui->addr.sllc_dmac, daddr->mac)) + if (llc->addr.sllc_ssap == laddr->lsap && + llc->addr.sllc_dsap == daddr->lsap && + llc_mac_null(llc->addr.sllc_mmac) && + llc_mac_match(llc->addr.sllc_smac, laddr->mac) && + llc_mac_match(llc->addr.sllc_dmac, daddr->mac)) break; } return sk; @@ -303,31 +305,31 @@ static struct sock *__llc_ui_find_sk_by_addr(struct llc_addr *laddr, struct sock *sk, *tmp_sk; for (sk = llc_ui_sockets; sk; sk = sk->next) { - struct llc_ui_opt *llc_ui = llc_ui_sk(sk); + struct llc_opt *llc = llc_sk(sk); - if (llc_ui->addr.sllc_ssap != laddr->lsap) + if (llc->addr.sllc_ssap != laddr->lsap) continue; - if (llc_mac_null(llc_ui->addr.sllc_smac)) { - if (!llc_mac_null(llc_ui->addr.sllc_mmac) && - !llc_mac_match(llc_ui->addr.sllc_mmac, - laddr->mac)) + if (llc_mac_null(llc->addr.sllc_smac)) { + if (!llc_mac_null(llc->addr.sllc_mmac) && + !llc_mac_match(llc->addr.sllc_mmac, + laddr->mac)) continue; break; } - if (dev && !llc_mac_null(llc_ui->addr.sllc_mmac) && - llc_mac_match(llc_ui->addr.sllc_mmac, laddr->mac) && - llc_mac_match(llc_ui->addr.sllc_smac, dev->dev_addr)) + if (dev && !llc_mac_null(llc->addr.sllc_mmac) && + llc_mac_match(llc->addr.sllc_mmac, laddr->mac) && + llc_mac_match(llc->addr.sllc_smac, dev->dev_addr)) break; if (dev->flags & IFF_LOOPBACK) break; - if (!llc_mac_match(llc_ui->addr.sllc_smac, laddr->mac)) + if (!llc_mac_match(llc->addr.sllc_smac, laddr->mac)) continue; tmp_sk = __llc_ui_find_sk_by_exact(laddr, daddr); if (tmp_sk) { sk = tmp_sk; break; } - if (llc_mac_null(llc_ui->addr.sllc_dmac)) + if (llc_mac_null(llc->addr.sllc_dmac)) break; } return sk; @@ -393,7 +395,8 @@ static __inline__ void llc_ui_remove_socket(struct sock *sk) sk->next->pprev = sk->pprev; *sk->pprev = sk->next; sk->pprev = NULL; - /* this only makes sense if the socket was inserted on the + /* + * This only makes sense if the socket was inserted on the * list, if sk->pprev is NULL it wasn't */ sock_put(sk); @@ -401,38 +404,13 @@ static __inline__ void llc_ui_remove_socket(struct sock *sk) write_unlock_bh(&llc_ui_sockets_lock); } -/** - * llc_ui_destroy_sk - destroy socket - * @data: Socket which is to be destroyed. - * - * Really destroy the socket. - */ -static void llc_ui_destroy_sk(struct sock *sk) -{ - skb_queue_purge(&sk->receive_queue); - skb_queue_purge(&sk->write_queue); - sock_put(sk); - MOD_DEC_USE_COUNT; -} - -/** - * llc_ui_destroy_timer - try to destroy socket again - * @data: Socket which is to be destroyed. - * - * Attempt to destroy a socket which was previously destroyed but - * was still in use at the time. - */ -static void llc_ui_destroy_timer(unsigned long data) +static void llc_ui_sk_init(struct socket *sock, struct sock *sk) { - struct sock *sk = (struct sock *)data; - - if (!atomic_read(&sk->wmem_alloc) && - !atomic_read(&sk->rmem_alloc) && sk->dead) - llc_ui_destroy_sk(sk); - else { - sk->timer.expires = jiffies + SOCK_DESTROY_TIME; - add_timer(&sk->timer); - } + sk->type = sock->type; + sk->sleep = &sock->wait; + sk->socket = sock; + sock->sk = sk; + sock->ops = &llc_ui_ops; } /** @@ -447,31 +425,17 @@ static void llc_ui_destroy_timer(unsigned long data) static int llc_ui_create(struct socket *sock, int protocol) { struct sock *sk; - struct llc_ui_opt *llc_ui; int rc = -ESOCKTNOSUPPORT; - MOD_INC_USE_COUNT; - if (sock->type != SOCK_DGRAM && sock->type != SOCK_STREAM) - goto decmod; - rc = -ENOMEM; - sk = sk_alloc(PF_LLC, GFP_KERNEL, 1, NULL); - if (!sk) - goto decmod; - llc_ui = kmalloc(sizeof(*llc_ui), GFP_KERNEL); - if (!llc_ui) - goto outsk; - memset(llc_ui, 0, sizeof(*llc_ui)); - rc = 0; - sock_init_data(sock, sk); - llc_ui_sk(sk) = llc_ui; - sock->ops = &llc_ui_ops; -out: + if (sock->type == SOCK_DGRAM || sock->type == SOCK_STREAM) { + rc = -ENOMEM; + sk = llc_sk_alloc(PF_LLC, GFP_KERNEL); + if (sk) { + rc = 0; + llc_ui_sk_init(sock, sk); + } + } return rc; -outsk: - sk_free(sk); -decmod: - MOD_DEC_USE_COUNT; - goto out; } /** @@ -483,33 +447,25 @@ decmod: static int llc_ui_release(struct socket *sock) { struct sock *sk = sock->sk; - struct llc_ui_opt *llc_ui; + struct llc_opt *llc; if (!sk) goto out; sock_hold(sk); lock_sock(sk); - llc_ui = llc_ui_sk(sk); - if (llc_ui->core_sk && !llc_ui_send_disc(sk)) + llc = llc_sk(sk); + dprintk("%s: closing local(%02X) remote(%02X)\n", __FUNCTION__, + llc->laddr.lsap, llc->daddr.lsap); + if (!llc_ui_send_disc(sk)) llc_ui_wait_for_disc(sk, sk->rcvtimeo); - llc_ui_remove_socket(sk); + llc_sap_unassign_sock(llc->sap, sk); release_sock(sk); + llc_ui_remove_socket(sk); - if (llc_ui->sap && !llc_ui_find_sap(llc_ui->sap->laddr.lsap)) - llc_sap_close(llc_ui->sap); - sock_orphan(sk); - sock->sk = NULL; - if (!atomic_read(&sk->wmem_alloc) && - !atomic_read(&sk->rmem_alloc) && sk->dead) - llc_ui_destroy_sk(sk); - else { - init_timer(&sk->timer); - sk->timer.expires = jiffies + SOCK_DESTROY_TIME; - sk->timer.function = llc_ui_destroy_timer; - sk->timer.data = (unsigned long)sk; - add_timer(&sk->timer); - } + if (llc->sap && list_empty(&llc->sap->sk_list.list)) + llc_sap_close(llc->sap); sock_put(sk); + llc_sk_free(sk); out: return 0; } @@ -563,7 +519,7 @@ out: static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr) { struct sock *sk = sock->sk; - struct llc_ui_opt *llc_ui = llc_ui_sk(sk); + struct llc_opt *llc = llc_sk(sk); struct llc_sap *sap; struct net_device *dev = NULL; int rc = -EINVAL; @@ -578,7 +534,7 @@ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr) rc = -ENETUNREACH; if (!dev) goto out; - llc_ui->dev = dev; + llc->dev = dev; } /* bind to a specific sap, optional. */ if (!addr->sllc_ssap) { @@ -619,10 +575,15 @@ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr) goto out; } } - memcpy(&llc_ui->addr, addr, sizeof(*addr)); - llc_ui->sap = sap; + llc->laddr.lsap = addr->sllc_ssap; + memcpy(llc->laddr.mac, llc->dev->dev_addr, IFHWADDRLEN); + llc->daddr.lsap = addr->sllc_dsap; + memcpy(llc->daddr.mac, addr->sllc_dmac, IFHWADDRLEN); + memcpy(&llc->addr, addr, sizeof(llc->addr)); rc = sk->zapped = 0; llc_ui_insert_socket(sk); + /* assign new connection to it's SAP */ + llc_sap_assign_sock(sap, sk); out: return rc; } @@ -651,6 +612,7 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) struct sock *sk = sock->sk; int rc = -EINVAL; + dprintk("%s: binding %02X\n", __FUNCTION__, addr->sllc_ssap); if (!sk->zapped || addrlen != sizeof(*addr)) goto out; rc = -EAFNOSUPPORT; @@ -686,7 +648,7 @@ static int llc_ui_shutdown(struct socket *sock, int how) goto out; rc = llc_ui_send_disc(sk); if (!rc) - llc_ui_wait_for_disc(sk, sk->rcvtimeo); + rc = llc_ui_wait_for_disc(sk, sk->rcvtimeo); /* Wake up anyone sleeping in poll */ sk->state_change(sk); out: @@ -712,7 +674,7 @@ static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr, int addrlen, int flags) { struct sock *sk = sock->sk; - struct llc_ui_opt *llc_ui = llc_ui_sk(sk); + struct llc_opt *llc = llc_sk(sk); struct sockaddr_llc *addr = (struct sockaddr_llc *)uaddr; struct net_device *dev; int rc = -EINVAL; @@ -730,14 +692,15 @@ static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr, if (rc) goto out; } - if (!llc_ui->dev) { + if (!llc->dev) { rtnl_lock(); dev = dev_getbyhwaddr(addr->sllc_arphrd, addr->sllc_smac); rtnl_unlock(); if (!dev) goto out; + llc->dev = dev; } else - dev = llc_ui->dev; + dev = llc->dev; if (sk->type != SOCK_STREAM) goto out; rc = -EALREADY; @@ -745,14 +708,17 @@ static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr, goto out; sock->state = SS_CONNECTING; sk->state = TCP_SYN_SENT; - llc_ui->link = llc_ui_next_link_no(llc_ui->sap->laddr.lsap); - rc = llc_ui_send_conn(sk, llc_ui->sap, addr, dev, llc_ui->link); + llc->link = llc_ui_next_link_no(llc->sap->laddr.lsap); + rc = llc_ui_send_conn(sk, llc->sap, addr, dev, llc->link); if (rc) { + dprintk("%s: llc_ui_send_conn failed :-(\n", __FUNCTION__); sock->state = SS_UNCONNECTED; sk->state = TCP_CLOSE; goto out; } rc = llc_ui_wait_for_conn(sk, sk->rcvtimeo); + if (rc) + dprintk("%s: llc_ui_wait_for_conn failed=%d\n", __FUNCTION__, rc); out: release_sock(sk); return rc; @@ -802,6 +768,12 @@ static int llc_ui_wait_for_disc(struct sock *sk, int timeout) add_wait_queue_exclusive(sk->sleep, &wait); for (;;) { __set_current_state(TASK_INTERRUPTIBLE); + rc = -ERESTARTSYS; + if (signal_pending(current)) + break; + rc = -EAGAIN; + if (!timeout) + break; rc = 0; if (sk->state != TCP_CLOSE) { release_sock(sk); @@ -809,12 +781,6 @@ static int llc_ui_wait_for_disc(struct sock *sk, int timeout) lock_sock(sk); } else break; - rc = -ERESTARTSYS; - if (signal_pending(current)) - break; - rc = -EAGAIN; - if (!timeout) - break; } __set_current_state(TASK_RUNNING); remove_wait_queue(sk->sleep, &wait); @@ -823,23 +789,12 @@ static int llc_ui_wait_for_disc(struct sock *sk, int timeout) static int llc_ui_wait_for_conn(struct sock *sk, int timeout) { - struct llc_ui_opt *llc_ui = llc_ui_sk(sk); DECLARE_WAITQUEUE(wait, current); int rc; add_wait_queue_exclusive(sk->sleep, &wait); for (;;) { __set_current_state(TASK_INTERRUPTIBLE); - rc = 0; - if (sk->state != TCP_ESTABLISHED) { - release_sock(sk); - timeout = schedule_timeout(timeout); - lock_sock(sk); - } else { - if (!llc_ui->core_sk) - rc = -EAGAIN; - break; - } rc = -EAGAIN; if (sk->state == TCP_CLOSE) break; @@ -849,6 +804,13 @@ static int llc_ui_wait_for_conn(struct sock *sk, int timeout) rc = -EAGAIN; if (!timeout) break; + rc = 0; + if (sk->state != TCP_ESTABLISHED) { + release_sock(sk); + timeout = schedule_timeout(timeout); + lock_sock(sk); + } else + break; } __set_current_state(TASK_RUNNING); remove_wait_queue(sk->sleep, &wait); @@ -858,11 +820,19 @@ static int llc_ui_wait_for_conn(struct sock *sk, int timeout) static int llc_ui_wait_for_data(struct sock *sk, int timeout) { DECLARE_WAITQUEUE(wait, current); - int rc; + int rc = 0; add_wait_queue_exclusive(sk->sleep, &wait); for (;;) { __set_current_state(TASK_INTERRUPTIBLE); + if (sk->shutdown & RCV_SHUTDOWN) + break; + rc = -ERESTARTSYS; + if (signal_pending(current)) + break; + rc = -EAGAIN; + if (!timeout) + break; rc = 0; if (skb_queue_empty(&sk->receive_queue)) { release_sock(sk); @@ -870,12 +840,38 @@ static int llc_ui_wait_for_data(struct sock *sk, int timeout) lock_sock(sk); } else break; + } + __set_current_state(TASK_RUNNING); + remove_wait_queue(sk->sleep, &wait); + return rc; +} + +static int llc_ui_wait_for_busy_core(struct sock *sk, int timeout) +{ + DECLARE_WAITQUEUE(wait, current); + struct llc_opt *llc = llc_sk(sk); + int rc; + + add_wait_queue_exclusive(sk->sleep, &wait); + for (;;) { + dprintk("%s: looping...\n", __FUNCTION__); + __set_current_state(TASK_INTERRUPTIBLE); + rc = -ENOTCONN; + if (sk->shutdown & RCV_SHUTDOWN) + break; rc = -ERESTARTSYS; if (signal_pending(current)) break; rc = -EAGAIN; if (!timeout) break; + rc = 0; + if (llc_data_accept_state(llc->state) || llc->p_flag) { + release_sock(sk); + timeout = schedule_timeout(timeout); + lock_sock(sk); + } else + break; } __set_current_state(TASK_RUNNING); remove_wait_queue(sk->sleep, &wait); @@ -894,11 +890,11 @@ static int llc_ui_wait_for_data(struct sock *sk, int timeout) static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags) { struct sock *sk = sock->sk, *newsk; - struct llc_ui_opt *llc_ui, *newllc_ui; - struct llc_opt *newllc_core; + struct llc_opt *llc, *newllc; struct sk_buff *skb; int rc = -EOPNOTSUPP; + dprintk("%s: accepting on %02X\n", __FUNCTION__, llc_sk(sk)->addr.sllc_ssap); lock_sock(sk); if (sk->type != SOCK_STREAM) goto out; @@ -909,40 +905,32 @@ static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags) rc = llc_ui_wait_for_data(sk, sk->rcvtimeo); if (rc) goto out; + dprintk("%s: got a new connection on %02X\n", __FUNCTION__, llc_sk(sk)->addr.sllc_ssap); skb = skb_dequeue(&sk->receive_queue); - rc = -EINVAL; if (!skb->sk) goto frees; - /* attach connection to a new socket. */ - rc = llc_ui_create(newsock, sk->protocol); - if (rc) - goto frees; rc = 0; - newsk = newsock->sk; + newsk = skb->sk; + /* attach connection to a new socket. */ + llc_ui_sk_init(newsock, newsk); newsk->pair = NULL; - newsk->socket = newsock; - newsk->sleep = &newsock->wait; newsk->zapped = 0; newsk->state = TCP_ESTABLISHED; newsock->state = SS_CONNECTED; - llc_ui = llc_ui_sk(sk); - newllc_ui = llc_ui_sk(newsk); - newllc_ui->sap = llc_ui->sap; - newllc_ui->dev = llc_ui->dev; - newllc_ui->core_sk = skb->sk; - newllc_core = llc_sk(newllc_ui->core_sk); - newllc_ui->link = newllc_core->link; - newllc_core->handler = newsk; - memcpy(&newllc_ui->addr, &llc_ui->addr, sizeof(newllc_ui->addr)); - memcpy(newllc_ui->addr.sllc_dmac, newllc_core->daddr.mac, IFHWADDRLEN); - newllc_ui->addr.sllc_dsap = newllc_core->daddr.lsap; + llc = llc_sk(sk); + newllc = llc_sk(newsk); + memcpy(&newllc->addr, &llc->addr, sizeof(newllc->addr)); + memcpy(newllc->addr.sllc_dmac, newllc->daddr.mac, IFHWADDRLEN); + newllc->addr.sllc_dsap = newllc->daddr.lsap; /* put original socket back into a clean listen state. */ sk->state = TCP_LISTEN; sk->ack_backlog--; llc_ui_insert_socket(newsk); skb->sk = NULL; + dprintk("%s: ok success on %02X, client on %02X\n", __FUNCTION__, + llc_sk(sk)->addr.sllc_ssap, newllc->addr.sllc_dsap); frees: kfree_skb(skb); out: @@ -967,12 +955,21 @@ static int llc_ui_recvmsg(struct socket *sock, struct msghdr *msg, int size, struct sock *sk = sock->sk; struct sockaddr_llc *uaddr = (struct sockaddr_llc *)msg->msg_name; struct sk_buff *skb; - int rc = -ENOMEM, copied = 0; + int rc = -ENOMEM, copied = 0, timeout; int noblock = flags & MSG_DONTWAIT; + dprintk("%s: receiving in %02X from %02X\n", __FUNCTION__, + llc_sk(sk)->laddr.lsap, llc_sk(sk)->daddr.lsap); lock_sock(sk); - skb = skb_recv_datagram(sk, flags, noblock, &rc); - if (!skb) + timeout = sock_rcvtimeo(sk, noblock); + rc = llc_ui_wait_for_data(sk, timeout); + if (rc) { + dprintk("%s: llc_ui_wait_for_data failed recv in %02X from %02X\n", + __FUNCTION__, llc_sk(sk)->laddr.lsap, llc_sk(sk)->daddr.lsap); + goto out; + } + skb = skb_dequeue(&sk->receive_queue); + if (!skb) /* shutdown */ goto out; copied = skb->len; if (copied > size) { @@ -986,7 +983,7 @@ static int llc_ui_recvmsg(struct socket *sock, struct msghdr *msg, int size, memcpy(uaddr, llc_ui_skb_cb(skb), sizeof(*uaddr)); msg->msg_namelen = sizeof(*uaddr); dgram_free: - skb_free_datagram(sk, skb); /* Free the datagram. */ + kfree_skb(skb); out: release_sock(sk); return rc ? : copied; @@ -1006,24 +1003,23 @@ static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm) { struct sock *sk = sock->sk; - struct llc_ui_opt *llc_ui = llc_ui_sk(sk); + struct llc_opt *llc = llc_sk(sk); struct sockaddr_llc *addr = (struct sockaddr_llc *)msg->msg_name; int flags = msg->msg_flags; + int noblock = flags & MSG_DONTWAIT; struct net_device *dev; struct sk_buff *skb; - int rc = -EOPNOTSUPP, size = 0; + int rc = -EINVAL, size = 0; + dprintk("%s: sending from %02X to %02X\n", __FUNCTION__, llc->laddr.lsap, llc->daddr.lsap); lock_sock(sk); - if (flags & ~MSG_DONTWAIT) - goto release; - rc = -EINVAL; if (addr) { if (msg->msg_namelen < sizeof(*addr)) goto release; } else { - if (llc_ui_addr_null(&llc_ui->addr)) + if (llc_ui_addr_null(&llc->addr)) goto release; - addr = &llc_ui->addr; + addr = &llc->addr; } /* must bind connection to sap if user hasn't done it. */ if (sk->zapped) { @@ -1032,7 +1028,7 @@ static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, int len, if (rc) goto release; } - if (!llc_ui->dev) { + if (!llc->dev) { rtnl_lock(); dev = dev_getbyhwaddr(addr->sllc_arphrd, addr->sllc_smac); rtnl_unlock(); @@ -1040,12 +1036,12 @@ static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, int len, if (!dev) goto release; } else - dev = llc_ui->dev; + dev = llc->dev; size = dev->hard_header_len + len + llc_ui_header_len(sk, addr); rc = -EMSGSIZE; if (size > dev->mtu) goto release; - skb = sock_alloc_send_skb(sk, size, flags & MSG_DONTWAIT, &rc); + skb = sock_alloc_send_skb(sk, size, noblock, &rc); if (!skb) goto release; skb->sk = sk; @@ -1053,30 +1049,32 @@ static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, int len, skb_reserve(skb, dev->hard_header_len + llc_ui_header_len(sk, addr)); rc = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); if (rc) - goto release; + goto out; if (addr->sllc_test) { - rc = llc_ui_send_llc1(llc_ui->sap, skb, addr, LLC_TEST_PRIM); + rc = llc_ui_send_llc1(llc->sap, skb, addr, LLC_TEST_PRIM); goto out; } if (addr->sllc_xid) { - rc = llc_ui_send_llc1(llc_ui->sap, skb, addr, LLC_XID_PRIM); + rc = llc_ui_send_llc1(llc->sap, skb, addr, LLC_XID_PRIM); goto out; } if (sk->type == SOCK_DGRAM || addr->sllc_ua) { - rc = llc_ui_send_llc1(llc_ui->sap, skb, addr, LLC_DATAUNIT_PRIM); + rc = llc_ui_send_llc1(llc->sap, skb, addr, LLC_DATAUNIT_PRIM); goto out; } rc = -ENOPROTOOPT; if (!(sk->type == SOCK_STREAM && !addr->sllc_ua)) goto out; - rc = -ENOTCONN; - if (!llc_ui->core_sk) - goto out; - rc = llc_ui_send_data(llc_ui->sap, sk, skb, addr); + rc = llc_ui_send_data(sk, skb, addr, noblock); + if (rc) + dprintk("%s: llc_ui_send_data failed: %d\n", __FUNCTION__, rc); out: if (rc) - skb_free_datagram(sk, skb); + kfree_skb(skb); release: + if (rc) + dprintk("%s: failed sending from %02X to %02X: %d\n", + __FUNCTION__, llc->laddr.lsap, llc->daddr.lsap, rc); release_sock(sk); return rc ? : len; } @@ -1095,7 +1093,7 @@ static int llc_ui_getname(struct socket *sock, struct sockaddr *uaddr, { struct sockaddr_llc sllc; struct sock *sk = sock->sk; - struct llc_ui_opt *llc_ui = llc_ui_sk(sk); + struct llc_opt *llc = llc_sk(sk); int rc = 0; lock_sock(sk); @@ -1107,20 +1105,19 @@ static int llc_ui_getname(struct socket *sock, struct sockaddr *uaddr, rc = -ENOTCONN; if (sk->state != TCP_ESTABLISHED) goto out; - if(llc_ui->dev) - sllc.sllc_arphrd = llc_ui->dev->type; - sllc.sllc_dsap = llc_sk(llc_ui->core_sk)->daddr.lsap; - memcpy(&sllc.sllc_dmac, &llc_sk(llc_ui->core_sk)->daddr.mac, - IFHWADDRLEN); + if(llc->dev) + sllc.sllc_arphrd = llc->dev->type; + sllc.sllc_dsap = llc->daddr.lsap; + memcpy(&sllc.sllc_dmac, &llc->daddr.mac, IFHWADDRLEN); } else { rc = -EINVAL; - if (!llc_ui->sap) + if (!llc->sap) goto out; - sllc.sllc_ssap = llc_ui->sap->laddr.lsap; + sllc.sllc_ssap = llc->sap->laddr.lsap; - if (llc_ui->dev) { - sllc.sllc_arphrd = llc_ui->dev->type; - memcpy(&sllc.sllc_smac, &llc_ui->dev->dev_addr, + if (llc->dev) { + sllc.sllc_arphrd = llc->dev->type; + memcpy(&sllc.sllc_smac, &llc->dev->dev_addr, IFHWADDRLEN); } } @@ -1160,61 +1157,56 @@ static int llc_ui_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen) { struct sock *sk = sock->sk; - struct llc_ui_opt *llc_ui = llc_ui_sk(sk); - struct llc_opt *llc_core; + struct llc_opt *llc = llc_sk(sk); int rc = -EINVAL, opt; lock_sock(sk); if (level != SOL_LLC || optlen != sizeof(int)) goto out; - rc = -ENOTCONN; - if (!llc_ui->core_sk) - goto out; rc = get_user(opt, (int *)optval); if (rc) goto out; rc = -EINVAL; - llc_core = llc_sk(llc_ui->core_sk); switch (optname) { case LLC_OPT_RETRY: if (opt > LLC_OPT_MAX_RETRY) goto out; - llc_core->n2 = opt; + llc->n2 = opt; break; case LLC_OPT_SIZE: if (opt > LLC_OPT_MAX_SIZE) goto out; - llc_core->n1 = opt; + llc->n1 = opt; break; case LLC_OPT_ACK_TMR_EXP: if (opt > LLC_OPT_MAX_ACK_TMR_EXP) goto out; - llc_core->ack_timer.expire = opt; + llc->ack_timer.expire = opt; break; case LLC_OPT_P_TMR_EXP: if (opt > LLC_OPT_MAX_P_TMR_EXP) goto out; - llc_core->pf_cycle_timer.expire = opt; + llc->pf_cycle_timer.expire = opt; break; case LLC_OPT_REJ_TMR_EXP: if (opt > LLC_OPT_MAX_REJ_TMR_EXP) goto out; - llc_core->rej_sent_timer.expire = opt; + llc->rej_sent_timer.expire = opt; break; case LLC_OPT_BUSY_TMR_EXP: if (opt > LLC_OPT_MAX_BUSY_TMR_EXP) goto out; - llc_core->busy_state_timer.expire = opt; + llc->busy_state_timer.expire = opt; break; case LLC_OPT_TX_WIN: if (opt > LLC_OPT_MAX_WIN) goto out; - llc_core->k = opt; + llc->k = opt; break; case LLC_OPT_RX_WIN: if (opt > LLC_OPT_MAX_WIN) goto out; - llc_core->rw = opt; + llc->rw = opt; break; default: rc = -ENOPROTOOPT; @@ -1240,40 +1232,35 @@ static int llc_ui_getsockopt(struct socket *sock, int level, int optname, char *optval, int *optlen) { struct sock *sk = sock->sk; - struct llc_ui_opt *llc_ui = llc_ui_sk(sk); - struct llc_opt *llc_core; + struct llc_opt *llc = llc_sk(sk); int val = 0, len = 0, rc = -EINVAL; lock_sock(sk); if (level != SOL_LLC) goto out; - rc = -ENOTCONN; - if (!llc_ui->core_sk) - goto out; rc = get_user(len, optlen); if (rc) goto out; rc = -EINVAL; if (len != sizeof(int)) goto out; - llc_core = llc_sk(llc_ui->core_sk); switch (optname) { case LLC_OPT_RETRY: - val = llc_core->n2; break; + val = llc->n2; break; case LLC_OPT_SIZE: - val = llc_core->n1; break; + val = llc->n1; break; case LLC_OPT_ACK_TMR_EXP: - val = llc_core->ack_timer.expire; break; + val = llc->ack_timer.expire; break; case LLC_OPT_P_TMR_EXP: - val = llc_core->pf_cycle_timer.expire; break; + val = llc->pf_cycle_timer.expire; break; case LLC_OPT_REJ_TMR_EXP: - val = llc_core->rej_sent_timer.expire; break; + val = llc->rej_sent_timer.expire; break; case LLC_OPT_BUSY_TMR_EXP: - val = llc_core->busy_state_timer.expire; break; + val = llc->busy_state_timer.expire; break; case LLC_OPT_TX_WIN: - val = llc_core->k; break; + val = llc->k; break; case LLC_OPT_RX_WIN: - val = llc_core->rw; break; + val = llc->rw; break; default: rc = -ENOPROTOOPT; goto out; @@ -1296,7 +1283,7 @@ static void llc_ui_ind_test(struct llc_prim_if_block *prim) { struct llc_prim_test *prim_data = &prim->data->test; struct sk_buff *skb = prim_data->skb; - struct sockaddr_llc *llc_ui = llc_ui_skb_cb(skb); + struct sockaddr_llc *addr = llc_ui_skb_cb(skb); struct sock *sk = llc_ui_find_sk_by_addr(&prim_data->daddr, &prim_data->saddr, skb->dev); if (!sk) @@ -1304,15 +1291,15 @@ static void llc_ui_ind_test(struct llc_prim_if_block *prim) if (sk->state == TCP_LISTEN) goto out_put; /* save primitive for use by the user. */ - llc_ui->sllc_family = AF_LLC; - llc_ui->sllc_arphrd = skb->dev->type; - llc_ui->sllc_test = 1; - llc_ui->sllc_xid = 0; - llc_ui->sllc_ua = 0; - llc_ui->sllc_dsap = prim_data->daddr.lsap; - memcpy(llc_ui->sllc_dmac, prim_data->daddr.mac, IFHWADDRLEN); - llc_ui->sllc_ssap = prim_data->saddr.lsap; - memcpy(llc_ui->sllc_smac, prim_data->saddr.mac, IFHWADDRLEN); + addr->sllc_family = AF_LLC; + addr->sllc_arphrd = skb->dev->type; + addr->sllc_test = 1; + addr->sllc_xid = 0; + addr->sllc_ua = 0; + addr->sllc_dsap = prim_data->daddr.lsap; + memcpy(addr->sllc_dmac, prim_data->daddr.mac, IFHWADDRLEN); + addr->sllc_ssap = prim_data->saddr.lsap; + memcpy(addr->sllc_smac, prim_data->saddr.mac, IFHWADDRLEN); /* queue skb to the user. */ if (sock_queue_rcv_skb(sk, skb)) kfree_skb(skb); @@ -1331,7 +1318,7 @@ static void llc_ui_ind_xid(struct llc_prim_if_block *prim) { struct llc_prim_xid *prim_data = &prim->data->xid; struct sk_buff *skb = prim_data->skb; - struct sockaddr_llc *llc_ui = llc_ui_skb_cb(skb); + struct sockaddr_llc *addr = llc_ui_skb_cb(skb); struct sock *sk = llc_ui_find_sk_by_addr(&prim_data->daddr, &prim_data->saddr, skb->dev); if (!sk) @@ -1339,15 +1326,15 @@ static void llc_ui_ind_xid(struct llc_prim_if_block *prim) if (sk->state == TCP_LISTEN) goto out_put; /* save primitive for use by the user. */ - llc_ui->sllc_family = AF_LLC; - llc_ui->sllc_arphrd = 0; - llc_ui->sllc_test = 0; - llc_ui->sllc_xid = 1; - llc_ui->sllc_ua = 0; - llc_ui->sllc_dsap = prim_data->daddr.lsap; - memcpy(llc_ui->sllc_dmac, prim_data->daddr.mac, IFHWADDRLEN); - llc_ui->sllc_ssap = prim_data->saddr.lsap; - memcpy(llc_ui->sllc_smac, prim_data->saddr.mac, IFHWADDRLEN); + addr->sllc_family = AF_LLC; + addr->sllc_arphrd = 0; + addr->sllc_test = 0; + addr->sllc_xid = 1; + addr->sllc_ua = 0; + addr->sllc_dsap = prim_data->daddr.lsap; + memcpy(addr->sllc_dmac, prim_data->daddr.mac, IFHWADDRLEN); + addr->sllc_ssap = prim_data->saddr.lsap; + memcpy(addr->sllc_smac, prim_data->saddr.mac, IFHWADDRLEN); /* queue skb to the user. */ if (sock_queue_rcv_skb(sk, skb)) kfree_skb(skb); @@ -1366,7 +1353,7 @@ static void llc_ui_ind_dataunit(struct llc_prim_if_block *prim) { struct llc_prim_unit_data *prim_data = &prim->data->udata; struct sk_buff *skb = prim_data->skb; - struct sockaddr_llc *llc_ui = llc_ui_skb_cb(skb); + struct sockaddr_llc *addr = llc_ui_skb_cb(skb); struct sock *sk = llc_ui_find_sk_by_addr(&prim_data->daddr, &prim_data->saddr, skb->dev); if (!sk) @@ -1374,15 +1361,15 @@ static void llc_ui_ind_dataunit(struct llc_prim_if_block *prim) if (sk->state == TCP_LISTEN) goto out_put; /* save primitive for use by the user. */ - llc_ui->sllc_family = AF_LLC; - llc_ui->sllc_arphrd = skb->dev->type; - llc_ui->sllc_test = 0; - llc_ui->sllc_xid = 0; - llc_ui->sllc_ua = 1; - llc_ui->sllc_dsap = prim_data->daddr.lsap; - memcpy(llc_ui->sllc_dmac, prim_data->daddr.mac, IFHWADDRLEN); - llc_ui->sllc_ssap = prim_data->saddr.lsap; - memcpy(llc_ui->sllc_smac, prim_data->saddr.mac, IFHWADDRLEN); + addr->sllc_family = AF_LLC; + addr->sllc_arphrd = skb->dev->type; + addr->sllc_test = 0; + addr->sllc_xid = 0; + addr->sllc_ua = 1; + addr->sllc_dsap = prim_data->daddr.lsap; + memcpy(addr->sllc_dmac, prim_data->daddr.mac, IFHWADDRLEN); + addr->sllc_ssap = prim_data->saddr.lsap; + memcpy(addr->sllc_smac, prim_data->saddr.mac, IFHWADDRLEN); /* queue skb to the user. */ if (sock_queue_rcv_skb(sk, skb)) kfree_skb(skb); @@ -1400,29 +1387,36 @@ out:; static void llc_ui_ind_conn(struct llc_prim_if_block *prim) { struct llc_prim_conn *prim_data = &prim->data->conn; - struct sock* sk; + struct sock* newsk = prim_data->sk, *parent; + struct llc_opt *newllc = llc_sk(newsk); struct sk_buff *skb2; - llc_sk(prim_data->sk)->laddr.lsap = prim->sap->laddr.lsap; - sk = llc_ui_find_sk_by_addr(&llc_sk(prim_data->sk)->laddr, - &prim_data->saddr, prim_data->dev); - if (!sk) + parent = llc_ui_find_sk_by_addr(&newllc->laddr, &prim_data->saddr, + prim_data->dev); + if (!parent) { + dprintk("%s: can't find a parent :-(\n", __FUNCTION__); goto out; - if (sk->type != SOCK_STREAM || sk->state != TCP_LISTEN) + } + dprintk("%s: found parent of remote %02X, its local %02X\n", __FUNCTION__, + newllc->daddr.lsap, llc_sk(parent)->laddr.lsap); + if (parent->type != SOCK_STREAM || parent->state != TCP_LISTEN) { + dprintk("%s: bad parent :-(\n", __FUNCTION__); goto out_put; - if (prim->data->conn.status) + } + if (prim->data->conn.status) { + dprintk("%s: bad status :-(\n", __FUNCTION__); goto out_put; /* bad status. */ + } /* give this connection a link number. */ - llc_sk(prim_data->sk)->link = - llc_ui_next_link_no(llc_sk(prim_data->sk)->laddr.lsap); + newllc->link = llc_ui_next_link_no(newllc->laddr.lsap); skb2 = alloc_skb(0, GFP_ATOMIC); if (!skb2) goto out_put; - skb2->sk = prim_data->sk; - skb_queue_tail(&sk->receive_queue, skb2); - sk->state_change(sk); + skb2->sk = newsk; + skb_queue_tail(&parent->receive_queue, skb2); + parent->state_change(parent); out_put: - sock_put(sk); + sock_put(parent); out:; } @@ -1435,14 +1429,13 @@ out:; static void llc_ui_ind_disc(struct llc_prim_if_block *prim) { struct llc_prim_disc *prim_data = &prim->data->disc; - struct sock* sk = llc_sk(prim_data->sk)->handler; + struct sock* sk = prim_data->sk; - if (!sk) - goto out; sock_hold(sk); - if (sk->type != SOCK_STREAM || sk->state != TCP_ESTABLISHED) + if (sk->type != SOCK_STREAM || sk->state != TCP_ESTABLISHED) { + dprintk("%s: bad socket...\n", __FUNCTION__); goto out_put; - llc_ui_sk(sk)->core_sk = NULL; + } sk->shutdown = SHUTDOWN_MASK; sk->socket->state = SS_UNCONNECTED; sk->state = TCP_CLOSE; @@ -1452,7 +1445,6 @@ static void llc_ui_ind_disc(struct llc_prim_if_block *prim) } out_put: sock_put(sk); -out:; } /** @@ -1475,8 +1467,8 @@ static int llc_ui_indicate(struct llc_prim_if_block *prim) case LLC_CONN_PRIM: llc_ui_ind_conn(prim); break; case LLC_DATA_PRIM: - printk(KERN_ERR "%s: shouldn't happen, LLC_DATA_PRIM " - "is gone for ->ind()...\n", __FUNCTION__); + dprintk("%s: shouldn't happen, LLC_DATA_PRIM " + "is gone for ->ind()...\n", __FUNCTION__); break; case LLC_DISC_PRIM: llc_ui_ind_disc(prim); break; @@ -1496,28 +1488,21 @@ static int llc_ui_indicate(struct llc_prim_if_block *prim) static void llc_ui_conf_conn(struct llc_prim_if_block *prim) { struct llc_prim_conn *prim_data = &prim->data->conn; - struct llc_opt *llc_core = llc_sk(prim_data->sk); - struct sock* sk = llc_core->handler; - struct llc_ui_opt *llc_ui = llc_ui_sk(sk); + struct sock* sk = prim_data->sk; - if (!sk) - goto out; sock_hold(sk); if (sk->type != SOCK_STREAM || sk->state != TCP_SYN_SENT) goto out_put; if (!prim->data->conn.status) { sk->socket->state = SS_CONNECTED; sk->state = TCP_ESTABLISHED; - llc_ui->core_sk = prim_data->sk; } else { sk->socket->state = SS_UNCONNECTED; sk->state = TCP_CLOSE; - llc_ui->core_sk = NULL; } sk->state_change(sk); out_put: sock_put(sk); -out:; } /** @@ -1529,20 +1514,16 @@ out:; static void llc_ui_conf_disc(struct llc_prim_if_block *prim) { struct llc_prim_disc *prim_data = &prim->data->disc; - struct sock* sk = llc_sk(prim_data->sk)->handler; + struct sock* sk = prim_data->sk; - if (!sk) - goto out; sock_hold(sk); if (sk->type != SOCK_STREAM || sk->state != TCP_CLOSING) goto out_put; - llc_ui_sk(sk)->core_sk = NULL; sk->socket->state = SS_UNCONNECTED; sk->state = TCP_CLOSE; sk->state_change(sk); out_put: sock_put(sk); -out:; } /** @@ -1559,8 +1540,8 @@ static int llc_ui_confirm(struct llc_prim_if_block *prim) case LLC_CONN_PRIM: llc_ui_conf_conn(prim); break; case LLC_DATA_PRIM: - printk(KERN_ERR "%s: shouldn't happen, LLC_DATA_PRIM " - "is gone for ->conf()...\n", __FUNCTION__); + dprintk("%s: shouldn't happen, LLC_DATA_PRIM " + "is gone for ->conf()...\n", __FUNCTION__); break; case LLC_DISC_PRIM: llc_ui_conf_disc(prim); break; @@ -1596,46 +1577,42 @@ static int llc_ui_get_info(char *buffer, char **start, off_t offset, int length) off_t pos = 0; off_t begin = 0; struct sock *s; - int len = sprintf(buffer, "SocketID SKt Mc local_mac_sap\t " - "remote_mac_sap\t tx_queue rx_queue st uid " - "link_no\n"); + int len = sprintf(buffer, "SKt Mc local_mac_sap " + "remote_mac_sap tx_queue rx_queue st uid " + "link\n"); /* Output the LLC socket data for the /proc filesystem */ read_lock_bh(&llc_ui_sockets_lock); for (s = llc_ui_sockets; s; s = s->next) { - struct llc_ui_opt *llc_ui = llc_ui_sk(s); - len += sprintf(buffer + len, "%p %02X %02X ", s, s->type, - !llc_mac_null(llc_ui->addr.sllc_mmac)); - if (llc_ui->sap) { - if (llc_ui->dev && - llc_mac_null(llc_ui->addr.sllc_mmac)) + struct llc_opt *llc = llc_sk(s); + + len += sprintf(buffer + len, "%2X %2X ", s->type, + !llc_mac_null(llc->addr.sllc_mmac)); + if (llc->sap) { + if (llc->dev && llc_mac_null(llc->addr.sllc_mmac)) llc_ui_format_mac(buffer + len, - llc_ui->dev->dev_addr); + llc->dev->dev_addr); else { - if (!llc_mac_null(llc_ui->addr.sllc_mmac)) + if (!llc_mac_null(llc->addr.sllc_mmac)) llc_ui_format_mac(buffer + len, - llc_ui->addr.sllc_mmac); + llc->addr.sllc_mmac); else sprintf(buffer + len, "00:00:00:00:00:00"); } len += MAC_FORMATTED_SIZE; len += sprintf(buffer + len, "@%02X ", - llc_ui->sap->laddr.lsap); + llc->sap->laddr.lsap); } else len += sprintf(buffer + len, "00:00:00:00:00:00@00 "); - llc_ui_format_mac(buffer + len, llc_ui->addr.sllc_dmac); + llc_ui_format_mac(buffer + len, llc->addr.sllc_dmac); len += MAC_FORMATTED_SIZE; len += sprintf(buffer + len, - "@%02X %08d:%08d %02d %-3d ", - llc_ui->addr.sllc_dsap, + "@%02X %8d %8d %2d %-3d ", + llc->addr.sllc_dsap, atomic_read(&s->wmem_alloc), atomic_read(&s->rmem_alloc), s->state, SOCK_INODE(s->socket)->i_uid); - if (llc_ui->core_sk) - len += sprintf(buffer + len, "%-7d\n", - llc_sk(llc_ui->core_sk)->link); - else - len += sprintf(buffer + len, "no_link\n"); + len += sprintf(buffer + len, "%-4d\n", llc->link); /* Are we still dumping unwanted data then discard the record */ pos = begin + len; @@ -1686,7 +1663,7 @@ static struct proto_ops SOCKOPS_WRAPPED(llc_ui_ops) = { SOCKOPS_WRAP(llc_ui, PF_LLC); static char llc_ui_banner[] __initdata = - KERN_INFO "NET4.0 IEEE 802.2 User Interface SAPs, Jay Schulist, 2001\n"; + KERN_INFO "NET4.0 IEEE 802.2 BSD sockets, Jay Schulist, 2001, Arnaldo C. Melo, 2002\n"; int __init llc_ui_init(void) { |
