OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [uclinux/] [uClinux-2.0.x/] [net/] [ethernet/] [eth.c] - Blame information for rev 199

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/*
2
 * INET         An implementation of the TCP/IP protocol suite for the LINUX
3
 *              operating system.  INET is implemented using the  BSD Socket
4
 *              interface as the means of communication with the user level.
5
 *
6
 *              Ethernet-type device handling.
7
 *
8
 * Version:     @(#)eth.c       1.0.7   05/25/93
9
 *
10
 * Authors:     Ross Biro, <bir7@leland.Stanford.Edu>
11
 *              Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
12
 *              Mark Evans, <evansmp@uhura.aston.ac.uk>
13
 *              Florian  La Roche, <rzsfl@rz.uni-sb.de>
14
 *              Alan Cox, <gw4pts@gw4pts.ampr.org>
15
 *
16
 * Fixes:
17
 *              Mr Linux        : Arp problems
18
 *              Alan Cox        : Generic queue tidyup (very tiny here)
19
 *              Alan Cox        : eth_header ntohs should be htons
20
 *              Alan Cox        : eth_rebuild_header missing an htons and
21
 *                                minor other things.
22
 *              Tegge           : Arp bug fixes.
23
 *              Florian         : Removed many unnecessary functions, code cleanup
24
 *                                and changes for new arp and skbuff.
25
 *              Alan Cox        : Redid header building to reflect new format.
26
 *              Alan Cox        : ARP only when compiled with CONFIG_INET
27
 *              Greg Page       : 802.2 and SNAP stuff.
28
 *              Alan Cox        : MAC layer pointers/new format.
29
 *              Paul Gortmaker  : eth_copy_and_sum shouldn't csum padding.
30
 *              Alan Cox        : Protect against forwarding explosions with
31
 *                                older network drivers and IFF_ALLMULTI.
32
 *      Christer Weinigel       : Better rebuild header message.
33
 *              Russell King    : eth_header_cache_bind and eth_header_cache_update
34
 *                                only compiled if CONFIG_INET is selected
35
 *
36
 *              This program is free software; you can redistribute it and/or
37
 *              modify it under the terms of the GNU General Public License
38
 *              as published by the Free Software Foundation; either version
39
 *              2 of the License, or (at your option) any later version.
40
 */
41
#include <asm/segment.h>
42
#include <asm/system.h>
43
#include <linux/types.h>
44
#include <linux/kernel.h>
45
#include <linux/sched.h>
46
#include <linux/string.h>
47
#include <linux/mm.h>
48
#include <linux/socket.h>
49
#include <linux/in.h>
50
#include <linux/inet.h>
51
#include <linux/netdevice.h>
52
#include <linux/etherdevice.h>
53
#include <linux/skbuff.h>
54
#include <linux/errno.h>
55
#include <linux/config.h>
56
#include <net/arp.h>
57
#include <net/sock.h>
58
#include <asm/checksum.h>
59
 
60
void eth_setup(char *str, int *ints)
61
{
62
        struct device *d = dev_base;
63
 
64
        if (!str || !*str)
65
                return;
66
        while (d)
67
        {
68
                if (!strcmp(str,d->name))
69
                {
70
                        if (ints[0] > 0)
71
                                d->irq=ints[1];
72
                        if (ints[0] > 1)
73
                                d->base_addr=ints[2];
74
                        if (ints[0] > 2)
75
                                d->mem_start=ints[3];
76
                        if (ints[0] > 3)
77
                                d->mem_end=ints[4];
78
                        break;
79
                }
80
                d=d->next;
81
        }
82
}
83
 
84
 
85
/*
86
 *       Create the Ethernet MAC header for an arbitrary protocol layer
87
 *
88
 *      saddr=NULL      means use device source address
89
 *      daddr=NULL      means leave destination address (eg unresolved arp)
90
 */
91
 
92
int eth_header(struct sk_buff *skb, struct device *dev, unsigned short type,
93
           void *daddr, void *saddr, unsigned len)
94
{
95
        struct ethhdr *eth = (struct ethhdr *)skb_push(skb,ETH_HLEN);
96
 
97
        /*
98
         *      Set the protocol type. For a packet of type ETH_P_802_3 we put the length
99
         *      in here instead. It is up to the 802.2 layer to carry protocol information.
100
         */
101
 
102
        if(type!=ETH_P_802_3)
103
                eth->h_proto = htons(type);
104
        else
105
                eth->h_proto = htons(len);
106
 
107
        /*
108
         *      Set the source hardware address.
109
         */
110
 
111
        if(saddr)
112
                memcpy(eth->h_source,saddr,dev->addr_len);
113
        else
114
                memcpy(eth->h_source,dev->dev_addr,dev->addr_len);
115
 
116
        /*
117
         *      Anyway, the loopback-device should never use this function...
118
         */
119
 
120
        if (dev->flags & IFF_LOOPBACK)
121
        {
122
                memset(eth->h_dest, 0, dev->addr_len);
123
                return(dev->hard_header_len);
124
        }
125
 
126
        if(daddr)
127
        {
128
                memcpy(eth->h_dest,daddr,dev->addr_len);
129
                return dev->hard_header_len;
130
        }
131
 
132
        return -dev->hard_header_len;
133
}
134
 
135
 
136
/*
137
 *      Rebuild the Ethernet MAC header. This is called after an ARP
138
 *      (or in future other address resolution) has completed on this
139
 *      sk_buff. We now let ARP fill in the other fields.
140
 */
141
 
142
int eth_rebuild_header(void *buff, struct device *dev, unsigned long dst,
143
                        struct sk_buff *skb)
144
{
145
        struct ethhdr *eth = (struct ethhdr *)buff;
146
 
147
        /*
148
         *      Only ARP/IP is currently supported
149
         */
150
 
151
        if(eth->h_proto != htons(ETH_P_IP))
152
        {
153
                printk(KERN_DEBUG "%s: unable to resolve type %X addresses.\n",dev->name,(int)eth->h_proto);
154
                memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
155
                return 0;
156
        }
157
 
158
        /*
159
         *      Try to get ARP to resolve the header.
160
         */
161
#ifdef CONFIG_INET       
162
        return arp_find(eth->h_dest, dst, dev, dev->pa_addr, skb)? 1 : 0;
163
#else
164
        return 0;
165
#endif  
166
}
167
 
168
 
169
/*
170
 *      Determine the packet's protocol ID. The rule here is that we
171
 *      assume 802.3 if the type field is short enough to be a length.
172
 *      This is normal practice and works for any 'now in use' protocol.
173
 */
174
 
175
unsigned short eth_type_trans(struct sk_buff *skb, struct device *dev)
176
{
177
        struct ethhdr *eth;
178
        unsigned char *rawp;
179
 
180
        skb->mac.raw=skb->data;
181
        skb_pull(skb,dev->hard_header_len);
182
        eth= skb->mac.ethernet;
183
 
184
        if(*eth->h_dest&1)
185
        {
186
                if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0)
187
                        skb->pkt_type=PACKET_BROADCAST;
188
                else
189
                        skb->pkt_type=PACKET_MULTICAST;
190
        }
191
 
192
        /*
193
         *      This ALLMULTI check should be redundant by 1.4
194
         *      so don't forget to remove it.
195
         */
196
 
197
        else if(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))
198
        {
199
                if(memcmp(eth->h_dest,dev->dev_addr, ETH_ALEN))
200
                        skb->pkt_type=PACKET_OTHERHOST;
201
        }
202
 
203
        if (ntohs(eth->h_proto) >= 1536)
204
                return eth->h_proto;
205
 
206
        rawp = skb->data;
207
 
208
        /*
209
         *      This is a magic hack to spot IPX packets. Older Novell breaks
210
         *      the protocol design and runs IPX over 802.3 without an 802.2 LLC
211
         *      layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
212
         *      won't work for fault tolerant netware but does for the rest.
213
         */
214
        if (*(unsigned short *)rawp == 0xFFFF)
215
                return htons(ETH_P_802_3);
216
 
217
        /*
218
         *      Real 802.2 LLC
219
         */
220
        return htons(ETH_P_802_2);
221
}
222
 
223
#ifdef CONFIG_INET
224
/*
225
 * Upper level calls this function to bind hardware header cache entry.
226
 * If the call is successful, then corresponding Address Resolution Protocol
227
 * (maybe, not ARP) takes responsibility for updating cache content.
228
 */
229
 
230
void eth_header_cache_bind(struct hh_cache ** hhp, struct device *dev,
231
                           unsigned short htype, __u32 daddr)
232
{
233
        struct hh_cache *hh;
234
 
235
        if (htype != ETH_P_IP)
236
        {
237
                printk(KERN_DEBUG "eth_header_cache_bind: %04x cache is not implemented\n", htype);
238
                return;
239
        }
240
        if (arp_bind_cache(hhp, dev, htype, daddr))
241
                return;
242
        if ((hh=*hhp) != NULL)
243
        {
244
                memcpy(hh->hh_data+6, dev->dev_addr, ETH_ALEN);
245
                hh->hh_data[12] = htype>>8;
246
                hh->hh_data[13] = htype&0xFF;
247
        }
248
}
249
 
250
/*
251
 * Called by Address Resolution module to notify changes in address.
252
 */
253
 
254
void eth_header_cache_update(struct hh_cache *hh, struct device *dev, unsigned char * haddr)
255
{
256
        if (hh->hh_type != ETH_P_IP)
257
        {
258
                printk(KERN_DEBUG "eth_header_cache_update: %04x cache is not implemented\n", hh->hh_type);
259
                return;
260
        }
261
        memcpy(hh->hh_data, haddr, ETH_ALEN);
262
        hh->hh_uptodate = 1;
263
}
264
#endif
265
 
266
/*
267
 *      Copy from an ethernet device memory space to an sk_buff while checksumming if IP
268
 */
269
 
270
void eth_copy_and_sum(struct sk_buff *dest, unsigned char *src, int length, int base)
271
{
272
#ifdef CONFIG_IP_ROUTER
273
        memcpy(dest->data,src,length);
274
#else
275
        struct ethhdr *eth;
276
        struct iphdr *iph;
277
        int ip_length;
278
 
279
        IS_SKB(dest);
280
        eth=(struct ethhdr *)src;
281
        if(eth->h_proto!=htons(ETH_P_IP))
282
        {
283
                memcpy(dest->data,src,length);
284
                return;
285
        }
286
        /*
287
         * We have to watch for padded packets. The csum doesn't include the
288
         * padding, and there is no point in copying the padding anyway.
289
         * We have to use the smaller of length and ip_length because it
290
         * can happen that ip_length > length.
291
         */
292
        memcpy(dest->data,src,sizeof(struct iphdr)+ETH_HLEN);   /* ethernet is always >= 34 */
293
        length -= sizeof(struct iphdr) + ETH_HLEN;
294
        iph=(struct iphdr*)(src+ETH_HLEN);
295
        ip_length = ntohs(iph->tot_len) - sizeof(struct iphdr);
296
 
297
        /* Also watch out for bogons - min IP size is 8 (rfc-1042) */
298
        if ((ip_length <= length) && (ip_length > 7))
299
                length=ip_length;
300
 
301
        dest->csum=csum_partial_copy(src+sizeof(struct iphdr)+ETH_HLEN,dest->data+sizeof(struct iphdr)+ETH_HLEN,length,base);
302
        dest->ip_summed=1;
303
#endif  
304
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.