llc_output.c 2.37 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
/*
 * llc_output.c - LLC minimal output path
 *
 * Copyright (c) 1997 by Procom Technology, Inc.
 * 		 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
 *
 * This program can be redistributed or modified under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation.
 * This program is distributed without any warranty or implied warranty
 * of merchantability or fitness for a particular purpose.
 *
 * See the GNU General Public License version 2 for more details.
 */

#include <linux/if_arp.h>
#include <linux/if_tr.h>
#include <linux/netdevice.h>
#include <linux/trdevice.h>
#include <linux/skbuff.h>
#include <net/llc.h>
#include <net/llc_pdu.h>

/**
 *	llc_mac_hdr_init - fills MAC header fields
 *	@skb: Address of the frame to initialize its MAC header
 *	@sa: The MAC source address
 *	@da: The MAC destination address
 *
 *	Fills MAC header fields, depending on MAC type. Returns 0, If MAC type
 *	is a valid type and initialization completes correctly 1, otherwise.
 */
33 34
int llc_mac_hdr_init(struct sk_buff *skb,
		     const unsigned char *sa, const unsigned char *da)
Linus Torvalds's avatar
Linus Torvalds committed
35
{
Octavian Purdila's avatar
Octavian Purdila committed
36
	int rc = -EINVAL;
Linus Torvalds's avatar
Linus Torvalds committed
37 38

	switch (skb->dev->type) {
Octavian Purdila's avatar
Octavian Purdila committed
39
	case ARPHRD_IEEE802_TR:
Linus Torvalds's avatar
Linus Torvalds committed
40
	case ARPHRD_ETHER:
Octavian Purdila's avatar
Octavian Purdila committed
41 42 43 44 45
	case ARPHRD_LOOPBACK:
		rc = dev_hard_header(skb, skb->dev, ETH_P_802_2, da, sa,
				     skb->len);
		if (rc > 0)
			rc = 0;
Linus Torvalds's avatar
Linus Torvalds committed
46 47
		break;
	default:
Octavian Purdila's avatar
Octavian Purdila committed
48
		WARN(1, "device type not supported: %d\n", skb->dev->type);
Linus Torvalds's avatar
Linus Torvalds committed
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
	}
	return rc;
}

/**
 *	llc_build_and_send_ui_pkt - unitdata request interface for upper layers
 *	@sap: sap to use
 *	@skb: packet to send
 *	@dmac: destination mac address
 *	@dsap: destination sap
 *
 *	Upper layers calls this function when upper layer wants to send data
 *	using connection-less mode communication (UI pdu).
 *
 *	Accept data frame from network layer to be sent using connection-
 *	less mode communication; timeout/retries handled by network layer;
 *	package primitive as an event and send to SAP event handler
 */
int llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb,
			      unsigned char *dmac, unsigned char dsap)
{
	int rc;
	llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap,
			    dsap, LLC_PDU_CMD);
	llc_pdu_init_as_ui_cmd(skb);
	rc = llc_mac_hdr_init(skb, skb->dev->dev_addr, dmac);
75
	if (likely(!rc))
Linus Torvalds's avatar
Linus Torvalds committed
76 77 78 79 80 81
		rc = dev_queue_xmit(skb);
	return rc;
}

EXPORT_SYMBOL(llc_mac_hdr_init);
EXPORT_SYMBOL(llc_build_and_send_ui_pkt);