18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *	NET3:	Support for 802.2 demultiplexing off Ethernet
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *		Demultiplex 802.2 encoded protocols. We match the entry by the
68c2ecf20Sopenharmony_ci *		SSAP/DSAP pair and then deliver to the registered datalink that
78c2ecf20Sopenharmony_ci *		matches. The control byte is ignored and handling of such items
88c2ecf20Sopenharmony_ci *		is up to the routine passed the frame.
98c2ecf20Sopenharmony_ci *
108c2ecf20Sopenharmony_ci *		Unlike the 802.3 datalink we have a list of 802.2 entries as
118c2ecf20Sopenharmony_ci *		there are multiple protocols to demux. The list is currently
128c2ecf20Sopenharmony_ci *		short (3 or 4 entries at most). The current demux assumes this.
138c2ecf20Sopenharmony_ci */
148c2ecf20Sopenharmony_ci#include <linux/module.h>
158c2ecf20Sopenharmony_ci#include <linux/netdevice.h>
168c2ecf20Sopenharmony_ci#include <linux/skbuff.h>
178c2ecf20Sopenharmony_ci#include <linux/slab.h>
188c2ecf20Sopenharmony_ci#include <net/datalink.h>
198c2ecf20Sopenharmony_ci#include <linux/mm.h>
208c2ecf20Sopenharmony_ci#include <linux/in.h>
218c2ecf20Sopenharmony_ci#include <linux/init.h>
228c2ecf20Sopenharmony_ci#include <net/llc.h>
238c2ecf20Sopenharmony_ci#include <net/p8022.h>
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_cistatic int p8022_request(struct datalink_proto *dl, struct sk_buff *skb,
268c2ecf20Sopenharmony_ci			 unsigned char *dest)
278c2ecf20Sopenharmony_ci{
288c2ecf20Sopenharmony_ci	llc_build_and_send_ui_pkt(dl->sap, skb, dest, dl->sap->laddr.lsap);
298c2ecf20Sopenharmony_ci	return 0;
308c2ecf20Sopenharmony_ci}
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_cistruct datalink_proto *register_8022_client(unsigned char type,
338c2ecf20Sopenharmony_ci					    int (*func)(struct sk_buff *skb,
348c2ecf20Sopenharmony_ci							struct net_device *dev,
358c2ecf20Sopenharmony_ci							struct packet_type *pt,
368c2ecf20Sopenharmony_ci							struct net_device *orig_dev))
378c2ecf20Sopenharmony_ci{
388c2ecf20Sopenharmony_ci	struct datalink_proto *proto;
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	proto = kmalloc(sizeof(*proto), GFP_ATOMIC);
418c2ecf20Sopenharmony_ci	if (proto) {
428c2ecf20Sopenharmony_ci		proto->type[0]		= type;
438c2ecf20Sopenharmony_ci		proto->header_length	= 3;
448c2ecf20Sopenharmony_ci		proto->request		= p8022_request;
458c2ecf20Sopenharmony_ci		proto->sap = llc_sap_open(type, func);
468c2ecf20Sopenharmony_ci		if (!proto->sap) {
478c2ecf20Sopenharmony_ci			kfree(proto);
488c2ecf20Sopenharmony_ci			proto = NULL;
498c2ecf20Sopenharmony_ci		}
508c2ecf20Sopenharmony_ci	}
518c2ecf20Sopenharmony_ci	return proto;
528c2ecf20Sopenharmony_ci}
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_civoid unregister_8022_client(struct datalink_proto *proto)
558c2ecf20Sopenharmony_ci{
568c2ecf20Sopenharmony_ci	llc_sap_put(proto->sap);
578c2ecf20Sopenharmony_ci	kfree(proto);
588c2ecf20Sopenharmony_ci}
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ciEXPORT_SYMBOL(register_8022_client);
618c2ecf20Sopenharmony_ciEXPORT_SYMBOL(unregister_8022_client);
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
64