hc
2024-11-01 2f529f9b558ca1c1bd74be7437a84e4711743404
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/***
 *
 *  stack/eth.c - Ethernet-specific functions
 *
 *  Copyright (C) 2002 Ulrich Marx <marx@kammer.uni-hannover.de>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */
 
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
 
#include <rtdev.h>
#include <rtnet_internal.h>
 
/*
 *  Create the Ethernet MAC header for an arbitrary protocol layer
 *
 *  saddr=NULL  means use device source address
 *  daddr=NULL  means leave destination address (eg unresolved arp)
 */
int rt_eth_header(struct rtskb *skb, struct rtnet_device *rtdev,
         unsigned short type, void *daddr, void *saddr, unsigned len)
{
   struct ethhdr *eth = (struct ethhdr *)rtskb_push(skb, ETH_HLEN);
 
   /*
     *  Set rtskb mac field
     */
 
   skb->mac.ethernet = eth;
 
   /*
     *  Set the protocol type. For a packet of type ETH_P_802_3 we put the length
     *  in here instead. It is up to the 802.2 layer to carry protocol information.
     */
 
   if (type != ETH_P_802_3)
       eth->h_proto = htons(type);
   else
       eth->h_proto = htons(len);
 
   /*
     *  Set the source hardware address.
     */
 
   if (saddr)
       memcpy(eth->h_source, saddr, rtdev->addr_len);
   else
       memcpy(eth->h_source, rtdev->dev_addr, rtdev->addr_len);
 
   if (rtdev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
       memset(eth->h_dest, 0, rtdev->addr_len);
       return rtdev->hard_header_len;
   }
 
   if (daddr) {
       memcpy(eth->h_dest, daddr, rtdev->addr_len);
       return rtdev->hard_header_len;
   }
 
   return -rtdev->hard_header_len;
}
 
unsigned short rt_eth_type_trans(struct rtskb *skb, struct rtnet_device *rtdev)
{
   struct ethhdr *eth;
   unsigned char *rawp;
 
   rtcap_mark_incoming(skb);
 
   skb->mac.raw = skb->data;
   rtskb_pull(skb, rtdev->hard_header_len);
   eth = skb->mac.ethernet;
 
   if (*eth->h_dest & 1) {
       if (memcmp(eth->h_dest, rtdev->broadcast, ETH_ALEN) == 0)
           skb->pkt_type = PACKET_BROADCAST;
       else
           skb->pkt_type = PACKET_MULTICAST;
   }
 
   /*
     *  This ALLMULTI check should be redundant by 1.4
     *  so don't forget to remove it.
     *
     *  Seems, you forgot to remove it. All silly devices
     *  seems to set IFF_PROMISC.
     */
 
   else if (1 /*rtdev->flags&IFF_PROMISC*/) {
       if (memcmp(eth->h_dest, rtdev->dev_addr, ETH_ALEN))
           skb->pkt_type = PACKET_OTHERHOST;
   }
 
   if (ntohs(eth->h_proto) >= 1536)
       return eth->h_proto;
 
   rawp = skb->data;
 
   /*
     *  This is a magic hack to spot IPX packets. Older Novell breaks
     *  the protocol design and runs IPX over 802.3 without an 802.2 LLC
     *  layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
     *  won't work for fault tolerant netware but does for the rest.
     */
   if (*(unsigned short *)rawp == 0xFFFF)
       return htons(ETH_P_802_3);
 
   /*
     *  Real 802.2 LLC
     */
   return htons(ETH_P_802_2);
}
 
EXPORT_SYMBOL_GPL(rt_eth_header);
EXPORT_SYMBOL_GPL(rt_eth_type_trans);