Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * llc_input.c - Minimal input path for LLC
0003  *
0004  * Copyright (c) 1997 by Procom Technology, Inc.
0005  *       2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
0006  *
0007  * This program can be redistributed or modified under the terms of the
0008  * GNU General Public License as published by the Free Software Foundation.
0009  * This program is distributed without any warranty or implied warranty
0010  * of merchantability or fitness for a particular purpose.
0011  *
0012  * See the GNU General Public License for more details.
0013  */
0014 #include <linux/netdevice.h>
0015 #include <linux/slab.h>
0016 #include <linux/export.h>
0017 #include <net/net_namespace.h>
0018 #include <net/llc.h>
0019 #include <net/llc_pdu.h>
0020 #include <net/llc_sap.h>
0021 
0022 #if 0
0023 #define dprintk(args...) printk(KERN_DEBUG args)
0024 #else
0025 #define dprintk(args...)
0026 #endif
0027 
0028 /*
0029  * Packet handler for the station, registerable because in the minimal
0030  * LLC core that is taking shape only the very minimal subset of LLC that
0031  * is needed for things like IPX, Appletalk, etc will stay, with all the
0032  * rest in the llc1 and llc2 modules.
0033  */
0034 static void (*llc_station_handler)(struct sk_buff *skb);
0035 
0036 /*
0037  * Packet handlers for LLC_DEST_SAP and LLC_DEST_CONN.
0038  */
0039 static void (*llc_type_handlers[2])(struct llc_sap *sap,
0040                     struct sk_buff *skb);
0041 
0042 void llc_add_pack(int type, void (*handler)(struct llc_sap *sap,
0043                         struct sk_buff *skb))
0044 {
0045     smp_wmb(); /* ensure initialisation is complete before it's called */
0046     if (type == LLC_DEST_SAP || type == LLC_DEST_CONN)
0047         llc_type_handlers[type - 1] = handler;
0048 }
0049 
0050 void llc_remove_pack(int type)
0051 {
0052     if (type == LLC_DEST_SAP || type == LLC_DEST_CONN)
0053         llc_type_handlers[type - 1] = NULL;
0054     synchronize_net();
0055 }
0056 
0057 void llc_set_station_handler(void (*handler)(struct sk_buff *skb))
0058 {
0059     /* Ensure initialisation is complete before it's called */
0060     if (handler)
0061         smp_wmb();
0062 
0063     llc_station_handler = handler;
0064 
0065     if (!handler)
0066         synchronize_net();
0067 }
0068 
0069 /**
0070  *  llc_pdu_type - returns which LLC component must handle for PDU
0071  *  @skb: input skb
0072  *
0073  *  This function returns which LLC component must handle this PDU.
0074  */
0075 static __inline__ int llc_pdu_type(struct sk_buff *skb)
0076 {
0077     int type = LLC_DEST_CONN; /* I-PDU or S-PDU type */
0078     struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
0079 
0080     if ((pdu->ctrl_1 & LLC_PDU_TYPE_MASK) != LLC_PDU_TYPE_U)
0081         goto out;
0082     switch (LLC_U_PDU_CMD(pdu)) {
0083     case LLC_1_PDU_CMD_XID:
0084     case LLC_1_PDU_CMD_UI:
0085     case LLC_1_PDU_CMD_TEST:
0086         type = LLC_DEST_SAP;
0087         break;
0088     case LLC_2_PDU_CMD_SABME:
0089     case LLC_2_PDU_CMD_DISC:
0090     case LLC_2_PDU_RSP_UA:
0091     case LLC_2_PDU_RSP_DM:
0092     case LLC_2_PDU_RSP_FRMR:
0093         break;
0094     default:
0095         type = LLC_DEST_INVALID;
0096         break;
0097     }
0098 out:
0099     return type;
0100 }
0101 
0102 /**
0103  *  llc_fixup_skb - initializes skb pointers
0104  *  @skb: This argument points to incoming skb
0105  *
0106  *  Initializes internal skb pointer to start of network layer by deriving
0107  *  length of LLC header; finds length of LLC control field in LLC header
0108  *  by looking at the two lowest-order bits of the first control field
0109  *  byte; field is either 3 or 4 bytes long.
0110  */
0111 static inline int llc_fixup_skb(struct sk_buff *skb)
0112 {
0113     u8 llc_len = 2;
0114     struct llc_pdu_un *pdu;
0115 
0116     if (unlikely(!pskb_may_pull(skb, sizeof(*pdu))))
0117         return 0;
0118 
0119     pdu = (struct llc_pdu_un *)skb->data;
0120     if ((pdu->ctrl_1 & LLC_PDU_TYPE_MASK) == LLC_PDU_TYPE_U)
0121         llc_len = 1;
0122     llc_len += 2;
0123 
0124     if (unlikely(!pskb_may_pull(skb, llc_len)))
0125         return 0;
0126 
0127     skb->transport_header += llc_len;
0128     skb_pull(skb, llc_len);
0129     if (skb->protocol == htons(ETH_P_802_2)) {
0130         __be16 pdulen = eth_hdr(skb)->h_proto;
0131         s32 data_size = ntohs(pdulen) - llc_len;
0132 
0133         if (data_size < 0 ||
0134             !pskb_may_pull(skb, data_size))
0135             return 0;
0136         if (unlikely(pskb_trim_rcsum(skb, data_size)))
0137             return 0;
0138     }
0139     return 1;
0140 }
0141 
0142 /**
0143  *  llc_rcv - 802.2 entry point from net lower layers
0144  *  @skb: received pdu
0145  *  @dev: device that receive pdu
0146  *  @pt: packet type
0147  *  @orig_dev: the original receive net device
0148  *
0149  *  When the system receives a 802.2 frame this function is called. It
0150  *  checks SAP and connection of received pdu and passes frame to
0151  *  llc_{station,sap,conn}_rcv for sending to proper state machine. If
0152  *  the frame is related to a busy connection (a connection is sending
0153  *  data now), it queues this frame in the connection's backlog.
0154  */
0155 int llc_rcv(struct sk_buff *skb, struct net_device *dev,
0156         struct packet_type *pt, struct net_device *orig_dev)
0157 {
0158     struct llc_sap *sap;
0159     struct llc_pdu_sn *pdu;
0160     int dest;
0161     int (*rcv)(struct sk_buff *, struct net_device *,
0162            struct packet_type *, struct net_device *);
0163     void (*sta_handler)(struct sk_buff *skb);
0164     void (*sap_handler)(struct llc_sap *sap, struct sk_buff *skb);
0165 
0166     if (!net_eq(dev_net(dev), &init_net))
0167         goto drop;
0168 
0169     /*
0170      * When the interface is in promisc. mode, drop all the crap that it
0171      * receives, do not try to analyse it.
0172      */
0173     if (unlikely(skb->pkt_type == PACKET_OTHERHOST)) {
0174         dprintk("%s: PACKET_OTHERHOST\n", __func__);
0175         goto drop;
0176     }
0177     skb = skb_share_check(skb, GFP_ATOMIC);
0178     if (unlikely(!skb))
0179         goto out;
0180     if (unlikely(!llc_fixup_skb(skb)))
0181         goto drop;
0182     pdu = llc_pdu_sn_hdr(skb);
0183     if (unlikely(!pdu->dsap)) /* NULL DSAP, refer to station */
0184            goto handle_station;
0185     sap = llc_sap_find(pdu->dsap);
0186     if (unlikely(!sap)) {/* unknown SAP */
0187         dprintk("%s: llc_sap_find(%02X) failed!\n", __func__,
0188             pdu->dsap);
0189         goto drop;
0190     }
0191     /*
0192      * First the upper layer protocols that don't need the full
0193      * LLC functionality
0194      */
0195     rcv = rcu_dereference(sap->rcv_func);
0196     dest = llc_pdu_type(skb);
0197     sap_handler = dest ? READ_ONCE(llc_type_handlers[dest - 1]) : NULL;
0198     if (unlikely(!sap_handler)) {
0199         if (rcv)
0200             rcv(skb, dev, pt, orig_dev);
0201         else
0202             kfree_skb(skb);
0203     } else {
0204         if (rcv) {
0205             struct sk_buff *cskb = skb_clone(skb, GFP_ATOMIC);
0206             if (cskb)
0207                 rcv(cskb, dev, pt, orig_dev);
0208         }
0209         sap_handler(sap, skb);
0210     }
0211     llc_sap_put(sap);
0212 out:
0213     return 0;
0214 drop:
0215     kfree_skb(skb);
0216     goto out;
0217 handle_station:
0218     sta_handler = READ_ONCE(llc_station_handler);
0219     if (!sta_handler)
0220         goto drop;
0221     sta_handler(skb);
0222     goto out;
0223 }
0224 
0225 EXPORT_SYMBOL(llc_add_pack);
0226 EXPORT_SYMBOL(llc_remove_pack);
0227 EXPORT_SYMBOL(llc_set_station_handler);