xref: /linux/net/llc/llc_input.c (revision 0e59523b440c90ed1899476f32ad4e949282f43e)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * llc_input.c - Minimal input path for LLC
4  *
5  * Copyright (c) 1997 by Procom Technology, Inc.
6  * 		 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
7  */
8 #include <linux/netdevice.h>
9 #include <net/llc.h>
10 #include <net/llc_pdu.h>
11 
12 #if 0
13 #define dprintk(args...) printk(KERN_DEBUG args)
14 #else
15 #define dprintk(args...)
16 #endif
17 
18 /**
19  *	llc_fixup_skb - initializes skb pointers
20  *	@skb: This argument points to incoming skb
21  *
22  *	Initializes internal skb pointer to start of network layer by deriving
23  *	length of LLC header; finds length of LLC control field in LLC header
24  *	by looking at the two lowest-order bits of the first control field
25  *	byte; field is either 3 or 4 bytes long.
26  */
27 static inline int llc_fixup_skb(struct sk_buff *skb)
28 {
29 	u8 llc_len = 2;
30 	struct llc_pdu_un *pdu;
31 
32 	if (unlikely(!pskb_may_pull(skb, sizeof(*pdu))))
33 		return 0;
34 
35 	pdu = (struct llc_pdu_un *)skb->data;
36 	if ((pdu->ctrl_1 & LLC_PDU_TYPE_MASK) == LLC_PDU_TYPE_U)
37 		llc_len = 1;
38 	llc_len += 2;
39 
40 	if (unlikely(!pskb_may_pull(skb, llc_len)))
41 		return 0;
42 
43 	skb_pull(skb, llc_len);
44 	skb_reset_transport_header(skb);
45 	if (skb->protocol == htons(ETH_P_802_2)) {
46 		__be16 pdulen;
47 		s32 data_size;
48 
49 		if (skb->mac_len < ETH_HLEN)
50 			return 0;
51 
52 		pdulen = eth_hdr(skb)->h_proto;
53 		data_size = ntohs(pdulen) - llc_len;
54 
55 		if (data_size < 0 ||
56 		    !pskb_may_pull(skb, data_size))
57 			return 0;
58 		if (unlikely(pskb_trim_rcsum(skb, data_size)))
59 			return 0;
60 	}
61 	return 1;
62 }
63 
64 /**
65  *	llc_rcv - 802.2 entry point from net lower layers
66  *	@skb: received pdu
67  *	@dev: device that receive pdu
68  *	@pt: packet type
69  *	@orig_dev: the original receive net device
70  *
71  *	When the system receives a 802.2 frame this function is called. It
72  *	looks up the SAP the pdu is addressed to and passes the frame to its
73  *	handler, dropping it if the SAP is unknown or has no handler.
74  */
75 int llc_rcv(struct sk_buff *skb, struct net_device *dev,
76 	    struct packet_type *pt, struct net_device *orig_dev)
77 {
78 	int (*rcv)(struct sk_buff *, struct net_device *,
79 		   struct packet_type *, struct net_device *);
80 	struct llc_pdu_un *pdu;
81 	struct llc_sap *sap;
82 
83 	/*
84 	 * When the interface is in promisc. mode, drop all the crap that it
85 	 * receives, do not try to analyse it.
86 	 */
87 	if (unlikely(skb->pkt_type == PACKET_OTHERHOST)) {
88 		dprintk("%s: PACKET_OTHERHOST\n", __func__);
89 		goto drop;
90 	}
91 	skb = skb_share_check(skb, GFP_ATOMIC);
92 	if (unlikely(!skb))
93 		goto out;
94 	if (unlikely(!llc_fixup_skb(skb)))
95 		goto drop;
96 	pdu = llc_pdu_un_hdr(skb);
97 	sap = llc_sap_find(pdu->dsap);
98 	if (unlikely(!sap)) {/* unknown SAP */
99 		dprintk("%s: llc_sap_find(%02X) failed!\n", __func__,
100 			pdu->dsap);
101 		goto drop;
102 	}
103 	rcv = rcu_dereference(sap->rcv_func);
104 	if (likely(rcv))
105 		rcv(skb, dev, pt, orig_dev);
106 	else
107 		kfree_skb(skb);
108 	llc_sap_put(sap);
109 out:
110 	return 0;
111 drop:
112 	kfree_skb(skb);
113 	goto out;
114 }
115