root/net/llc/llc_input.c

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

DEFINITIONS

This source file includes following definitions.
  1. llc_add_pack
  2. llc_remove_pack
  3. llc_set_station_handler
  4. llc_pdu_type
  5. llc_fixup_skb
  6. llc_rcv

   1 /*
   2  * llc_input.c - Minimal input path for LLC
   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/netdevice.h>
  15 #include <linux/slab.h>
  16 #include <linux/export.h>
  17 #include <net/net_namespace.h>
  18 #include <net/llc.h>
  19 #include <net/llc_pdu.h>
  20 #include <net/llc_sap.h>
  21 
  22 #if 0
  23 #define dprintk(args...) printk(KERN_DEBUG args)
  24 #else
  25 #define dprintk(args...)
  26 #endif
  27 
  28 /*
  29  * Packet handler for the station, registerable because in the minimal
  30  * LLC core that is taking shape only the very minimal subset of LLC that
  31  * is needed for things like IPX, Appletalk, etc will stay, with all the
  32  * rest in the llc1 and llc2 modules.
  33  */
  34 static void (*llc_station_handler)(struct sk_buff *skb);
  35 
  36 /*
  37  * Packet handlers for LLC_DEST_SAP and LLC_DEST_CONN.
  38  */
  39 static void (*llc_type_handlers[2])(struct llc_sap *sap,
  40                                     struct sk_buff *skb);
  41 
  42 void llc_add_pack(int type, void (*handler)(struct llc_sap *sap,
  43                                             struct sk_buff *skb))
  44 {
  45         smp_wmb(); /* ensure initialisation is complete before it's called */
  46         if (type == LLC_DEST_SAP || type == LLC_DEST_CONN)
  47                 llc_type_handlers[type - 1] = handler;
  48 }
  49 
  50 void llc_remove_pack(int type)
  51 {
  52         if (type == LLC_DEST_SAP || type == LLC_DEST_CONN)
  53                 llc_type_handlers[type - 1] = NULL;
  54         synchronize_net();
  55 }
  56 
  57 void llc_set_station_handler(void (*handler)(struct sk_buff *skb))
  58 {
  59         /* Ensure initialisation is complete before it's called */
  60         if (handler)
  61                 smp_wmb();
  62 
  63         llc_station_handler = handler;
  64 
  65         if (!handler)
  66                 synchronize_net();
  67 }
  68 
  69 /**
  70  *      llc_pdu_type - returns which LLC component must handle for PDU
  71  *      @skb: input skb
  72  *
  73  *      This function returns which LLC component must handle this PDU.
  74  */
  75 static __inline__ int llc_pdu_type(struct sk_buff *skb)
  76 {
  77         int type = LLC_DEST_CONN; /* I-PDU or S-PDU type */
  78         struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
  79 
  80         if ((pdu->ctrl_1 & LLC_PDU_TYPE_MASK) != LLC_PDU_TYPE_U)
  81                 goto out;
  82         switch (LLC_U_PDU_CMD(pdu)) {
  83         case LLC_1_PDU_CMD_XID:
  84         case LLC_1_PDU_CMD_UI:
  85         case LLC_1_PDU_CMD_TEST:
  86                 type = LLC_DEST_SAP;
  87                 break;
  88         case LLC_2_PDU_CMD_SABME:
  89         case LLC_2_PDU_CMD_DISC:
  90         case LLC_2_PDU_RSP_UA:
  91         case LLC_2_PDU_RSP_DM:
  92         case LLC_2_PDU_RSP_FRMR:
  93                 break;
  94         default:
  95                 type = LLC_DEST_INVALID;
  96                 break;
  97         }
  98 out:
  99         return type;
 100 }
 101 
 102 /**
 103  *      llc_fixup_skb - initializes skb pointers
 104  *      @skb: This argument points to incoming skb
 105  *
 106  *      Initializes internal skb pointer to start of network layer by deriving
 107  *      length of LLC header; finds length of LLC control field in LLC header
 108  *      by looking at the two lowest-order bits of the first control field
 109  *      byte; field is either 3 or 4 bytes long.
 110  */
 111 static inline int llc_fixup_skb(struct sk_buff *skb)
 112 {
 113         u8 llc_len = 2;
 114         struct llc_pdu_un *pdu;
 115 
 116         if (unlikely(!pskb_may_pull(skb, sizeof(*pdu))))
 117                 return 0;
 118 
 119         pdu = (struct llc_pdu_un *)skb->data;
 120         if ((pdu->ctrl_1 & LLC_PDU_TYPE_MASK) == LLC_PDU_TYPE_U)
 121                 llc_len = 1;
 122         llc_len += 2;
 123 
 124         if (unlikely(!pskb_may_pull(skb, llc_len)))
 125                 return 0;
 126 
 127         skb->transport_header += llc_len;
 128         skb_pull(skb, llc_len);
 129         if (skb->protocol == htons(ETH_P_802_2)) {
 130                 __be16 pdulen = eth_hdr(skb)->h_proto;
 131                 s32 data_size = ntohs(pdulen) - llc_len;
 132 
 133                 if (data_size < 0 ||
 134                     !pskb_may_pull(skb, data_size))
 135                         return 0;
 136                 if (unlikely(pskb_trim_rcsum(skb, data_size)))
 137                         return 0;
 138         }
 139         return 1;
 140 }
 141 
 142 /**
 143  *      llc_rcv - 802.2 entry point from net lower layers
 144  *      @skb: received pdu
 145  *      @dev: device that receive pdu
 146  *      @pt: packet type
 147  *
 148  *      When the system receives a 802.2 frame this function is called. It
 149  *      checks SAP and connection of received pdu and passes frame to
 150  *      llc_{station,sap,conn}_rcv for sending to proper state machine. If
 151  *      the frame is related to a busy connection (a connection is sending
 152  *      data now), it queues this frame in the connection's backlog.
 153  */
 154 int llc_rcv(struct sk_buff *skb, struct net_device *dev,
 155             struct packet_type *pt, struct net_device *orig_dev)
 156 {
 157         struct llc_sap *sap;
 158         struct llc_pdu_sn *pdu;
 159         int dest;
 160         int (*rcv)(struct sk_buff *, struct net_device *,
 161                    struct packet_type *, struct net_device *);
 162         void (*sta_handler)(struct sk_buff *skb);
 163         void (*sap_handler)(struct llc_sap *sap, struct sk_buff *skb);
 164 
 165         if (!net_eq(dev_net(dev), &init_net))
 166                 goto drop;
 167 
 168         /*
 169          * When the interface is in promisc. mode, drop all the crap that it
 170          * receives, do not try to analyse it.
 171          */
 172         if (unlikely(skb->pkt_type == PACKET_OTHERHOST)) {
 173                 dprintk("%s: PACKET_OTHERHOST\n", __func__);
 174                 goto drop;
 175         }
 176         skb = skb_share_check(skb, GFP_ATOMIC);
 177         if (unlikely(!skb))
 178                 goto out;
 179         if (unlikely(!llc_fixup_skb(skb)))
 180                 goto drop;
 181         pdu = llc_pdu_sn_hdr(skb);
 182         if (unlikely(!pdu->dsap)) /* NULL DSAP, refer to station */
 183                goto handle_station;
 184         sap = llc_sap_find(pdu->dsap);
 185         if (unlikely(!sap)) {/* unknown SAP */
 186                 dprintk("%s: llc_sap_find(%02X) failed!\n", __func__,
 187                         pdu->dsap);
 188                 goto drop;
 189         }
 190         /*
 191          * First the upper layer protocols that don't need the full
 192          * LLC functionality
 193          */
 194         rcv = rcu_dereference(sap->rcv_func);
 195         dest = llc_pdu_type(skb);
 196         sap_handler = dest ? READ_ONCE(llc_type_handlers[dest - 1]) : NULL;
 197         if (unlikely(!sap_handler)) {
 198                 if (rcv)
 199                         rcv(skb, dev, pt, orig_dev);
 200                 else
 201                         kfree_skb(skb);
 202         } else {
 203                 if (rcv) {
 204                         struct sk_buff *cskb = skb_clone(skb, GFP_ATOMIC);
 205                         if (cskb)
 206                                 rcv(cskb, dev, pt, orig_dev);
 207                 }
 208                 sap_handler(sap, skb);
 209         }
 210         llc_sap_put(sap);
 211 out:
 212         return 0;
 213 drop:
 214         kfree_skb(skb);
 215         goto out;
 216 handle_station:
 217         sta_handler = READ_ONCE(llc_station_handler);
 218         if (!sta_handler)
 219                 goto drop;
 220         sta_handler(skb);
 221         goto out;
 222 }
 223 
 224 EXPORT_SYMBOL(llc_add_pack);
 225 EXPORT_SYMBOL(llc_remove_pack);
 226 EXPORT_SYMBOL(llc_set_station_handler);

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