Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * INET     An implementation of the TCP/IP protocol suite for the LINUX
0004  *      operating system.  INET is implemented using the BSD Socket
0005  *      interface as the means of communication with the user level.
0006  *
0007  *      FDDI-type device handling.
0008  *
0009  * Version: @(#)fddi.c  1.0.0   08/12/96
0010  *
0011  * Authors: Lawrence V. Stefani, <stefani@lkg.dec.com>
0012  *
0013  *      fddi.c is based on previous eth.c and tr.c work by
0014  *          Ross Biro
0015  *          Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
0016  *          Mark Evans, <evansmp@uhura.aston.ac.uk>
0017  *          Florian La Roche, <rzsfl@rz.uni-sb.de>
0018  *          Alan Cox, <gw4pts@gw4pts.ampr.org>
0019  *
0020  *  Changes
0021  *      Alan Cox        :   New arp/rebuild header
0022  *      Maciej W. Rozycki   :   IPv6 support
0023  */
0024 
0025 #include <linux/module.h>
0026 #include <linux/types.h>
0027 #include <linux/kernel.h>
0028 #include <linux/string.h>
0029 #include <linux/mm.h>
0030 #include <linux/socket.h>
0031 #include <linux/in.h>
0032 #include <linux/inet.h>
0033 #include <linux/netdevice.h>
0034 #include <linux/fddidevice.h>
0035 #include <linux/if_ether.h>
0036 #include <linux/skbuff.h>
0037 #include <linux/errno.h>
0038 #include <net/arp.h>
0039 #include <net/sock.h>
0040 
0041 /*
0042  * Create the FDDI MAC header for an arbitrary protocol layer
0043  *
0044  * saddr=NULL   means use device source address
0045  * daddr=NULL   means leave destination address (eg unresolved arp)
0046  */
0047 
0048 static int fddi_header(struct sk_buff *skb, struct net_device *dev,
0049                unsigned short type,
0050                const void *daddr, const void *saddr, unsigned int len)
0051 {
0052     int hl = FDDI_K_SNAP_HLEN;
0053     struct fddihdr *fddi;
0054 
0055     if(type != ETH_P_IP && type != ETH_P_IPV6 && type != ETH_P_ARP)
0056         hl=FDDI_K_8022_HLEN-3;
0057     fddi = skb_push(skb, hl);
0058     fddi->fc             = FDDI_FC_K_ASYNC_LLC_DEF;
0059     if(type == ETH_P_IP || type == ETH_P_IPV6 || type == ETH_P_ARP)
0060     {
0061         fddi->hdr.llc_snap.dsap      = FDDI_EXTENDED_SAP;
0062         fddi->hdr.llc_snap.ssap      = FDDI_EXTENDED_SAP;
0063         fddi->hdr.llc_snap.ctrl      = FDDI_UI_CMD;
0064         fddi->hdr.llc_snap.oui[0]    = 0x00;
0065         fddi->hdr.llc_snap.oui[1]    = 0x00;
0066         fddi->hdr.llc_snap.oui[2]    = 0x00;
0067         fddi->hdr.llc_snap.ethertype     = htons(type);
0068     }
0069 
0070     /* Set the source and destination hardware addresses */
0071 
0072     if (saddr != NULL)
0073         memcpy(fddi->saddr, saddr, dev->addr_len);
0074     else
0075         memcpy(fddi->saddr, dev->dev_addr, dev->addr_len);
0076 
0077     if (daddr != NULL)
0078     {
0079         memcpy(fddi->daddr, daddr, dev->addr_len);
0080         return hl;
0081     }
0082 
0083     return -hl;
0084 }
0085 
0086 /*
0087  * Determine the packet's protocol ID and fill in skb fields.
0088  * This routine is called before an incoming packet is passed
0089  * up.  It's used to fill in specific skb fields and to set
0090  * the proper pointer to the start of packet data (skb->data).
0091  */
0092 
0093 __be16 fddi_type_trans(struct sk_buff *skb, struct net_device *dev)
0094 {
0095     struct fddihdr *fddi = (struct fddihdr *)skb->data;
0096     __be16 type;
0097 
0098     /*
0099      * Set mac.raw field to point to FC byte, set data field to point
0100      * to start of packet data.  Assume 802.2 SNAP frames for now.
0101      */
0102 
0103     skb->dev = dev;
0104     skb_reset_mac_header(skb);  /* point to frame control (FC) */
0105 
0106     if(fddi->hdr.llc_8022_1.dsap==0xe0)
0107     {
0108         skb_pull(skb, FDDI_K_8022_HLEN-3);
0109         type = htons(ETH_P_802_2);
0110     }
0111     else
0112     {
0113         skb_pull(skb, FDDI_K_SNAP_HLEN);        /* adjust for 21 byte header */
0114         type=fddi->hdr.llc_snap.ethertype;
0115     }
0116 
0117     /* Set packet type based on destination address and flag settings */
0118 
0119     if (*fddi->daddr & 0x01)
0120     {
0121         if (memcmp(fddi->daddr, dev->broadcast, FDDI_K_ALEN) == 0)
0122             skb->pkt_type = PACKET_BROADCAST;
0123         else
0124             skb->pkt_type = PACKET_MULTICAST;
0125     }
0126 
0127     else if (dev->flags & IFF_PROMISC)
0128     {
0129         if (memcmp(fddi->daddr, dev->dev_addr, FDDI_K_ALEN))
0130             skb->pkt_type = PACKET_OTHERHOST;
0131     }
0132 
0133     /* Assume 802.2 SNAP frames, for now */
0134 
0135     return type;
0136 }
0137 
0138 EXPORT_SYMBOL(fddi_type_trans);
0139 
0140 static const struct header_ops fddi_header_ops = {
0141     .create     = fddi_header,
0142 };
0143 
0144 
0145 static void fddi_setup(struct net_device *dev)
0146 {
0147     dev->header_ops     = &fddi_header_ops;
0148     dev->type       = ARPHRD_FDDI;
0149     dev->hard_header_len    = FDDI_K_SNAP_HLEN+3;   /* Assume 802.2 SNAP hdr len + 3 pad bytes */
0150     dev->mtu        = FDDI_K_SNAP_DLEN; /* Assume max payload of 802.2 SNAP frame */
0151     dev->min_mtu        = FDDI_K_SNAP_HLEN;
0152     dev->max_mtu        = FDDI_K_SNAP_DLEN;
0153     dev->addr_len       = FDDI_K_ALEN;
0154     dev->tx_queue_len   = 100;          /* Long queues on FDDI */
0155     dev->flags      = IFF_BROADCAST | IFF_MULTICAST;
0156 
0157     memset(dev->broadcast, 0xFF, FDDI_K_ALEN);
0158 }
0159 
0160 /**
0161  * alloc_fddidev - Register FDDI device
0162  * @sizeof_priv: Size of additional driver-private structure to be allocated
0163  *  for this FDDI device
0164  *
0165  * Fill in the fields of the device structure with FDDI-generic values.
0166  *
0167  * Constructs a new net device, complete with a private data area of
0168  * size @sizeof_priv.  A 32-byte (not bit) alignment is enforced for
0169  * this private data area.
0170  */
0171 struct net_device *alloc_fddidev(int sizeof_priv)
0172 {
0173     return alloc_netdev(sizeof_priv, "fddi%d", NET_NAME_UNKNOWN,
0174                 fddi_setup);
0175 }
0176 EXPORT_SYMBOL(alloc_fddidev);
0177 
0178 MODULE_LICENSE("GPL");