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