/* Offset table on connection states transition diagram */
static int llc_offset_table[NBR_CONN_STATES][NBR_CONN_EV];
+static void llc_save_primitive(struct sock *sk, struct sk_buff* skb,
+ u8 ua, u8 test, u8 xid)
+{
+ struct llc_opt *llc = llc_sk(sk);
+ struct sockaddr_llc *addr = llc_ui_skb_cb(skb);
+
+ /* save primitive for use by the user. */
+ addr->sllc_family = sk->family;
+ addr->sllc_arphrd = skb->dev->type;
+ addr->sllc_test = test;
+ addr->sllc_xid = xid;
+ addr->sllc_ua = ua;
+ addr->sllc_dsap = llc->sap->laddr.lsap;
+ memcpy(addr->sllc_dmac, llc->laddr.mac, IFHWADDRLEN);
+ addr->sllc_ssap = llc->daddr.lsap;
+ memcpy(addr->sllc_smac, llc->daddr.mac, IFHWADDRLEN);
+}
+
/**
* llc_conn_state_process - sends event to connection state machine
* @sk: connection
struct llc_opt *llc = llc_sk(sk);
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;
*/
switch (flag) {
case LLC_DATA_PRIM + 1:
+ llc_save_primitive(sk, skb, 0, 0, 0);
if (sock_queue_rcv_skb(sk, skb)) {
/*
* FIXME: have to sync the LLC state
case LLC_CONN_PRIM + 1:
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->state = TCP_CLOSE;
} else {
fix_up_incoming_skb(skb);
pdu = llc_pdu_sn_hdr(skb);
if (!pdu->dsap) { /* NULL DSAP, refer to station */
+ dprintk("%s: calling llc_station_rcv!\n", __FUNCTION__);
llc_station_rcv(skb);
goto out;
}
sap = llc_sap_find(pdu->dsap);
- if (!sap) /* unknown SAP */
+ if (!sap) {/* unknown SAP */
+ dprintk("%s: llc_sap_find(%02X) failed!\n", __FUNCTION__, pdu->dsap);
goto drop;
+ }
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__);
llc_sap_rcv(sap, skb);
- else if (dest == LLC_DEST_CONN) {
+ } else if (dest == LLC_DEST_CONN) {
struct llc_addr saddr, daddr;
struct sock *sk;
int rc;
/* search thru events for this state until list exhausted or until
* its obvious the event is not valid for the current state
*/
- for (next_trans = curr_state->transitions; next_trans [i]->ev; i++)
+ for (next_trans = curr_state->transitions; next_trans[i]->ev; i++)
if (!next_trans[i]->ev(sap, skb)) {
/* got event match; return it */
rc = next_trans[i];
llc->laddr.lsap, llc->daddr.lsap);
if (!llc_send_disc(sk))
llc_ui_wait_for_disc(sk, sk->rcvtimeo);
- llc_sap_unassign_sock(llc->sap, sk);
release_sock(sk);
- llc_ui_remove_socket(sk);
-
+ if (!sk->zapped) {
+ llc_sap_unassign_sock(llc->sap, sk);
+ llc_ui_remove_socket(sk);
+ }
if (llc->sap && list_empty(&llc->sap->sk_list.list))
llc_sap_close(llc->sap);
sock_put(sk);
}
}
llc->laddr.lsap = addr->sllc_ssap;
- memcpy(llc->laddr.mac, llc->dev->dev_addr, IFHWADDRLEN);
+ if (llc->dev)
+ 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));