^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * INET An implementation of the TCP/IP protocol suite for the LINUX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * operating system. INET is implemented using the BSD Socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * interface as the means of communication with the user level.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * FDDI-type device handling.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Version: @(#)fddi.c 1.0.0 08/12/96
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Authors: Lawrence V. Stefani, <stefani@lkg.dec.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * fddi.c is based on previous eth.c and tr.c work by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Ross Biro
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Mark Evans, <evansmp@uhura.aston.ac.uk>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * Florian La Roche, <rzsfl@rz.uni-sb.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * Alan Cox, <gw4pts@gw4pts.ampr.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * Changes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * Alan Cox : New arp/rebuild header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * Maciej W. Rozycki : IPv6 support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/socket.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/in.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/inet.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/fddidevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/if_ether.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <net/arp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <net/sock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * Create the FDDI MAC header for an arbitrary protocol layer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * saddr=NULL means use device source address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * daddr=NULL means leave destination address (eg unresolved arp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static int fddi_header(struct sk_buff *skb, struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) unsigned short type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) const void *daddr, const void *saddr, unsigned int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) int hl = FDDI_K_SNAP_HLEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct fddihdr *fddi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) if(type != ETH_P_IP && type != ETH_P_IPV6 && type != ETH_P_ARP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) hl=FDDI_K_8022_HLEN-3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) fddi = skb_push(skb, hl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) fddi->fc = FDDI_FC_K_ASYNC_LLC_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if(type == ETH_P_IP || type == ETH_P_IPV6 || type == ETH_P_ARP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) fddi->hdr.llc_snap.dsap = FDDI_EXTENDED_SAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) fddi->hdr.llc_snap.ssap = FDDI_EXTENDED_SAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) fddi->hdr.llc_snap.ctrl = FDDI_UI_CMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) fddi->hdr.llc_snap.oui[0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) fddi->hdr.llc_snap.oui[1] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) fddi->hdr.llc_snap.oui[2] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) fddi->hdr.llc_snap.ethertype = htons(type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) /* Set the source and destination hardware addresses */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (saddr != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) memcpy(fddi->saddr, saddr, dev->addr_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) memcpy(fddi->saddr, dev->dev_addr, dev->addr_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (daddr != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) memcpy(fddi->daddr, daddr, dev->addr_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return hl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return -hl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * Determine the packet's protocol ID and fill in skb fields.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * This routine is called before an incoming packet is passed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * up. It's used to fill in specific skb fields and to set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * the proper pointer to the start of packet data (skb->data).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) __be16 fddi_type_trans(struct sk_buff *skb, struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct fddihdr *fddi = (struct fddihdr *)skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) __be16 type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * Set mac.raw field to point to FC byte, set data field to point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * to start of packet data. Assume 802.2 SNAP frames for now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) skb->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) skb_reset_mac_header(skb); /* point to frame control (FC) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if(fddi->hdr.llc_8022_1.dsap==0xe0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) skb_pull(skb, FDDI_K_8022_HLEN-3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) type = htons(ETH_P_802_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) skb_pull(skb, FDDI_K_SNAP_HLEN); /* adjust for 21 byte header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) type=fddi->hdr.llc_snap.ethertype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /* Set packet type based on destination address and flag settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (*fddi->daddr & 0x01)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (memcmp(fddi->daddr, dev->broadcast, FDDI_K_ALEN) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) skb->pkt_type = PACKET_BROADCAST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) skb->pkt_type = PACKET_MULTICAST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) else if (dev->flags & IFF_PROMISC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (memcmp(fddi->daddr, dev->dev_addr, FDDI_K_ALEN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) skb->pkt_type = PACKET_OTHERHOST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) /* Assume 802.2 SNAP frames, for now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) EXPORT_SYMBOL(fddi_type_trans);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static const struct header_ops fddi_header_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) .create = fddi_header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) static void fddi_setup(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) dev->header_ops = &fddi_header_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) dev->type = ARPHRD_FDDI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) dev->hard_header_len = FDDI_K_SNAP_HLEN+3; /* Assume 802.2 SNAP hdr len + 3 pad bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) dev->mtu = FDDI_K_SNAP_DLEN; /* Assume max payload of 802.2 SNAP frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) dev->min_mtu = FDDI_K_SNAP_HLEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) dev->max_mtu = FDDI_K_SNAP_DLEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) dev->addr_len = FDDI_K_ALEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) dev->tx_queue_len = 100; /* Long queues on FDDI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) dev->flags = IFF_BROADCAST | IFF_MULTICAST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) memset(dev->broadcast, 0xFF, FDDI_K_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * alloc_fddidev - Register FDDI device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * @sizeof_priv: Size of additional driver-private structure to be allocated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * for this FDDI device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * Fill in the fields of the device structure with FDDI-generic values.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * Constructs a new net device, complete with a private data area of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * this private data area.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) struct net_device *alloc_fddidev(int sizeof_priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return alloc_netdev(sizeof_priv, "fddi%d", NET_NAME_UNKNOWN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) fddi_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) EXPORT_SYMBOL(alloc_fddidev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) MODULE_LICENSE("GPL");