0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
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
0043
0044
0045
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
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
0088
0089
0090
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
0100
0101
0102
0103 skb->dev = dev;
0104 skb_reset_mac_header(skb);
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);
0114 type=fddi->hdr.llc_snap.ethertype;
0115 }
0116
0117
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
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;
0150 dev->mtu = FDDI_K_SNAP_DLEN;
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;
0155 dev->flags = IFF_BROADCAST | IFF_MULTICAST;
0156
0157 memset(dev->broadcast, 0xFF, FDDI_K_ALEN);
0158 }
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
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");