root/net/llc/llc_if.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. llc_build_and_send_pkt
  2. llc_establish_connection
  3. llc_send_disc

   1 /*
   2  * llc_if.c - Defines LLC interface to upper layer
   3  *
   4  * Copyright (c) 1997 by Procom Technology, Inc.
   5  *               2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
   6  *
   7  * This program can be redistributed or modified under the terms of the
   8  * GNU General Public License as published by the Free Software Foundation.
   9  * This program is distributed without any warranty or implied warranty
  10  * of merchantability or fitness for a particular purpose.
  11  *
  12  * See the GNU General Public License for more details.
  13  */
  14 #include <linux/gfp.h>
  15 #include <linux/module.h>
  16 #include <linux/kernel.h>
  17 #include <linux/netdevice.h>
  18 #include <linux/errno.h>
  19 #include <net/llc_if.h>
  20 #include <net/llc_sap.h>
  21 #include <net/llc_s_ev.h>
  22 #include <net/llc_conn.h>
  23 #include <net/sock.h>
  24 #include <net/llc_c_ev.h>
  25 #include <net/llc_c_ac.h>
  26 #include <net/llc_c_st.h>
  27 #include <net/tcp_states.h>
  28 
  29 /**
  30  *      llc_build_and_send_pkt - Connection data sending for upper layers.
  31  *      @sk: connection
  32  *      @skb: packet to send
  33  *
  34  *      This function is called when upper layer wants to send data using
  35  *      connection oriented communication mode. During sending data, connection
  36  *      will be locked and received frames and expired timers will be queued.
  37  *      Returns 0 for success, -ECONNABORTED when the connection already
  38  *      closed and -EBUSY when sending data is not permitted in this state or
  39  *      LLC has send an I pdu with p bit set to 1 and is waiting for it's
  40  *      response.
  41  *
  42  *      This function always consumes a reference to the skb.
  43  */
  44 int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb)
  45 {
  46         struct llc_conn_state_ev *ev;
  47         int rc = -ECONNABORTED;
  48         struct llc_sock *llc = llc_sk(sk);
  49 
  50         if (unlikely(llc->state == LLC_CONN_STATE_ADM))
  51                 goto out_free;
  52         rc = -EBUSY;
  53         if (unlikely(llc_data_accept_state(llc->state) || /* data_conn_refuse */
  54                      llc->p_flag)) {
  55                 llc->failed_data_req = 1;
  56                 goto out_free;
  57         }
  58         ev = llc_conn_ev(skb);
  59         ev->type      = LLC_CONN_EV_TYPE_PRIM;
  60         ev->prim      = LLC_DATA_PRIM;
  61         ev->prim_type = LLC_PRIM_TYPE_REQ;
  62         skb->dev      = llc->dev;
  63         return llc_conn_state_process(sk, skb);
  64 
  65 out_free:
  66         kfree_skb(skb);
  67         return rc;
  68 }
  69 
  70 /**
  71  *      llc_establish_connection - Called by upper layer to establish a conn
  72  *      @sk: connection
  73  *      @lmac: local mac address
  74  *      @dmac: destination mac address
  75  *      @dsap: destination sap
  76  *
  77  *      Upper layer calls this to establish an LLC connection with a remote
  78  *      machine. This function packages a proper event and sends it connection
  79  *      component state machine. Success or failure of connection
  80  *      establishment will inform to upper layer via calling it's confirm
  81  *      function and passing proper information.
  82  */
  83 int llc_establish_connection(struct sock *sk, u8 *lmac, u8 *dmac, u8 dsap)
  84 {
  85         int rc = -EISCONN;
  86         struct llc_addr laddr, daddr;
  87         struct sk_buff *skb;
  88         struct llc_sock *llc = llc_sk(sk);
  89         struct sock *existing;
  90 
  91         laddr.lsap = llc->sap->laddr.lsap;
  92         daddr.lsap = dsap;
  93         memcpy(daddr.mac, dmac, sizeof(daddr.mac));
  94         memcpy(laddr.mac, lmac, sizeof(laddr.mac));
  95         existing = llc_lookup_established(llc->sap, &daddr, &laddr);
  96         if (existing) {
  97                 if (existing->sk_state == TCP_ESTABLISHED) {
  98                         sk = existing;
  99                         goto out_put;
 100                 } else
 101                         sock_put(existing);
 102         }
 103         sock_hold(sk);
 104         rc = -ENOMEM;
 105         skb = alloc_skb(0, GFP_ATOMIC);
 106         if (skb) {
 107                 struct llc_conn_state_ev *ev = llc_conn_ev(skb);
 108 
 109                 ev->type      = LLC_CONN_EV_TYPE_PRIM;
 110                 ev->prim      = LLC_CONN_PRIM;
 111                 ev->prim_type = LLC_PRIM_TYPE_REQ;
 112                 skb_set_owner_w(skb, sk);
 113                 rc = llc_conn_state_process(sk, skb);
 114         }
 115 out_put:
 116         sock_put(sk);
 117         return rc;
 118 }
 119 
 120 /**
 121  *      llc_send_disc - Called by upper layer to close a connection
 122  *      @sk: connection to be closed
 123  *
 124  *      Upper layer calls this when it wants to close an established LLC
 125  *      connection with a remote machine. This function packages a proper event
 126  *      and sends it to connection component state machine. Returns 0 for
 127  *      success, 1 otherwise.
 128  */
 129 int llc_send_disc(struct sock *sk)
 130 {
 131         u16 rc = 1;
 132         struct llc_conn_state_ev *ev;
 133         struct sk_buff *skb;
 134 
 135         sock_hold(sk);
 136         if (sk->sk_type != SOCK_STREAM || sk->sk_state != TCP_ESTABLISHED ||
 137             llc_sk(sk)->state == LLC_CONN_STATE_ADM ||
 138             llc_sk(sk)->state == LLC_CONN_OUT_OF_SVC)
 139                 goto out;
 140         /*
 141          * Postpone unassigning the connection from its SAP and returning the
 142          * connection until all ACTIONs have been completely executed
 143          */
 144         skb = alloc_skb(0, GFP_ATOMIC);
 145         if (!skb)
 146                 goto out;
 147         skb_set_owner_w(skb, sk);
 148         sk->sk_state  = TCP_CLOSING;
 149         ev            = llc_conn_ev(skb);
 150         ev->type      = LLC_CONN_EV_TYPE_PRIM;
 151         ev->prim      = LLC_DISC_PRIM;
 152         ev->prim_type = LLC_PRIM_TYPE_REQ;
 153         rc = llc_conn_state_process(sk, skb);
 154 out:
 155         sock_put(sk);
 156         return rc;
 157 }

/* [<][>][^][v][top][bottom][index][help] */