📄 eth.c
字号:
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Ethernet-type device handling.
*
* Version: @(#)eth.c 1.0.7 05/25/93
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* Mark Evans, <evansmp@uhura.aston.ac.uk>
* Florian La Roche, <rzsfl@rz.uni-sb.de>
* Alan Cox, <gw4pts@gw4pts.ampr.org>
*
* Fixes:
* Mr Linux : Arp problems
* Alan Cox : Generic queue tidyup (very tiny here)
* Alan Cox : eth_header ntohs should be htons
* Alan Cox : eth_rebuild_header missing an htons and
* minor other things.
* Tegge : Arp bug fixes.
* Florian : Removed many unnecessary functions, code cleanup
* and changes for new arp and skbuff.
* Alan Cox : Redid header building to reflect new format.
* Alan Cox : ARP only when compiled with CONFIG_INET
* Greg Page : 802.2 and SNAP stuff.
* Alan Cox : MAC layer pointers/new format.
* Paul Gortmaker : eth_copy_and_sum shouldn't csum padding.
* Alan Cox : Protect against forwarding explosions with
* older network drivers and IFF_ALLMULTI.
* Christer Weinigel : Better rebuild header message.
*
* 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.
*/
#if 0
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/socket.h>
#include <linux/inet.h>
#include <linux/ip.h>
#include <linux/etherdevice.h>
#include <linux/errno.h>
#include <linux/config.h>
#include <linux/init.h>
#include <net/dst.h>
#include <net/arp.h>
#include <net/sock.h>
#include <net/ipv6.h>
#endif
#include <hos_type.h>
#include <linux/in.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/if_ether.h>
#include <net/neighbour.h>
#include <hos_sys.h>
#if 0
static int __init eth_setup(char *str)
{
int ints[5];
struct ifmap map;
str = get_options(str, ARRAY_SIZE(ints), ints);
if (!str || !*str)
return 0;
/* Save settings */
memset(&map, -1, sizeof(map));
if (ints[0] > 0)
map.irq = ints[1];
if (ints[0] > 1)
map.base_addr = ints[2];
if (ints[0] > 2)
map.mem_start = ints[3];
if (ints[0] > 3)
map.mem_end = ints[4];
/* Add new entry to the list */
return netdev_boot_setup_add(str, &map);
}
__setup("ether=", eth_setup);
#endif
/*
* 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 eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
void *daddr, void *saddr, unsigned len)
{
struct ethhdr *eth = (struct ethhdr *)skb_push(skb,ETH_HLEN);
/*
* 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,dev->addr_len);
else
memcpy(eth->h_source,dev->dev_addr,dev->addr_len);
/*
* Anyway, the loopback-device should never use this function...
*/
if (dev->flags & (IFF_LOOPBACK|IFF_NOARP))
{
memset(eth->h_dest, 0, dev->addr_len);
return(dev->hard_header_len);
}
if(daddr)
{
memcpy(eth->h_dest,daddr,dev->addr_len);
return dev->hard_header_len;
}
return -dev->hard_header_len;
}
/*
* Rebuild the Ethernet MAC header. This is called after an ARP
* (or in future other address resolution) has completed on this
* sk_buff. We now let ARP fill in the other fields.
*
* This routine CANNOT use cached dst->neigh!
* Really, it is used only when dst->neigh is wrong.
*/
int eth_rebuild_header(struct sk_buff *skb)
{
struct ethhdr *eth = (struct ethhdr *)skb->data;
struct net_device *dev = skb->dev;
switch (eth->h_proto)
{
#ifdef CONFIG_INET
case __constant_htons(ETH_P_IP):
return arp_find(eth->h_dest, skb);
#endif
default:
printk(KERN_DEBUG
"%s: unable to resolve type %X addresses.\n",
dev->name, (int)eth->h_proto);
memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
break;
}
return 0;
}
/*
* Determine the packet's protocol ID. The rule here is that we
* assume 802.3 if the type field is short enough to be a length.
* This is normal practice and works for any 'now in use' protocol.
*/
/* 印朝晖把它改造成支持IEEE802.1Q 的VLAN */
unsigned short eth_type_trans(struct sk_buff *skb, struct net_device *dev)
{
/*struct ethhdr *eth;*/
struct vlanhdr *veth;
unsigned char *rawp;
skb->mac.raw=skb->data;
if(dev)
skb_pull(skb,dev->hard_header_len);
else
skb_pull(skb,VLAN_HLEN);
veth= skb->mac.vlan;
if(*veth->v_dest&1)
{
/*
if(memcmp(veth->v_dest,dev->broadcast, ETH_ALEN)==0)
skb->pkt_type=PACKET_BROADCAST;
else
skb->pkt_type=PACKET_MULTICAST;
*/
if(memcmp(veth->v_dest,0xFFFFFF,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 /*dev->flags&IFF_PROMISC*/)
{
if(dev)
if(memcmp(veth->v_dest,dev->dev_addr, ETH_ALEN))
skb->pkt_type=PACKET_OTHERHOST;
}
if(ntohs(veth->v_proto) == ETH_P_ARP)
return veth->v_proto;
/*
if (ntohs(veth->v_proto) >= 1536)
return veth->v_proto;
*/
#if 0
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);
#endif
/*
* Real 802.2 LLC
*/
/*
return htons(ETH_P_802_2);
*/
return htons(ETH_P_VLAN);
}
int eth_header_parse(struct sk_buff *skb, unsigned char *haddr)
{
struct ethhdr *eth = skb->mac.ethernet;
memcpy(haddr, eth->h_source, ETH_ALEN);
return ETH_ALEN;
}
int eth_header_cache(struct neighbour *neigh, struct hh_cache *hh)
{
unsigned short type = hh->hh_type;
struct ethhdr *eth = (struct ethhdr*)(((u8*)hh->hh_data) + 2);
struct net_device *dev = neigh->dev;
if (type == __constant_htons(ETH_P_802_3))
return -1;
eth->h_proto = type;
memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
memcpy(eth->h_dest, neigh->ha, dev->addr_len);
hh->hh_len = ETH_HLEN;
return 0;
}
/*
* Called by Address Resolution module to notify changes in address.
*/
void eth_header_cache_update(struct hh_cache *hh, struct net_device *dev, unsigned char * haddr)
{
memcpy(((u8*)hh->hh_data) + 2, haddr, dev->addr_len);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -