/* * Linux ARCnet driver - RFC1201 (standard) packet encapsulation * * Written 1994-1999 by Avery Pennarun. * Derived from skeleton.c by Donald Becker. * * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com) * for sponsoring the further development of this driver. * * ********************** * * The original copyright of skeleton.c was as follows: * * skeleton.c Written 1993 by Donald Becker. * Copyright 1993 United States Government as represented by the * Director, National Security Agency. This software may only be used * and distributed according to the terms of the GNU General Public License as * modified by SRC, incorporated herein by reference. * * ********************** * * For more details, see drivers/net/arcnet.c * * **********************
*/
/* Determine a packet's protocol ID. * * With ARCnet we have to convert everything to Ethernet-style stuff.
*/ static __be16 type_trans(struct sk_buff *skb, struct net_device *dev)
{ struct archdr *pkt = (struct archdr *)skb->data; struct arc_rfc1201 *soft = &pkt->soft.rfc1201; int hdr_size = ARC_HDR_SIZE + RFC1201_HDR_SIZE;
/* Pull off the arcnet header. */
skb_reset_mac_header(skb);
skb_pull(skb, hdr_size);
if (pkt->hard.dest == 0) {
skb->pkt_type = PACKET_BROADCAST;
} elseif (dev->flags & IFF_PROMISC) { /* if we're not sending to ourselves :) */ if (pkt->hard.dest != dev->dev_addr[0])
skb->pkt_type = PACKET_OTHERHOST;
} /* now return the protocol number */ switch (soft->proto) { case ARC_P_IP: return htons(ETH_P_IP); case ARC_P_IPV6: return htons(ETH_P_IPV6); case ARC_P_ARP: return htons(ETH_P_ARP); case ARC_P_RARP: return htons(ETH_P_RARP);
case ARC_P_IPX: case ARC_P_NOVELL_EC: return htons(ETH_P_802_3); default:
dev->stats.rx_errors++;
dev->stats.rx_crc_errors++; return 0;
}
/* up to sizeof(pkt->soft) has already * been copied from the card
*/
memcpy(pkt, pkthdr, sizeof(struct archdr)); if (length > sizeof(pkt->soft))
lp->hw.copy_from_card(dev, bufnum,
ofs + sizeof(pkt->soft),
pkt->soft.raw + sizeof(pkt->soft),
length - sizeof(pkt->soft));
/* ARP packets have problems when sent from some DOS systems: * the source address is always 0! * So we take the hardware source addr (which is impossible * to fumble) and insert it ourselves.
*/ if (soft->proto == ARC_P_ARP) { struct arphdr *arp = (struct arphdr *)soft->payload;
/* make sure addresses are the right length */ if (arp->ar_hln == 1 && arp->ar_pln == 4) {
uint8_t *cptr = (uint8_t *)arp + sizeof(struct arphdr);
if (!*cptr) { /* is saddr = 00? */
arc_printk(D_EXTRA, dev, "ARP source address was 00h, set to %02Xh\n",
saddr);
dev->stats.rx_crc_errors++;
*cptr = saddr;
} else {
arc_printk(D_DURING, dev, "ARP source address (%Xh) is fine.\n",
*cptr);
}
} else {
arc_printk(D_NORMAL, dev, "funny-shaped ARP packet. (%Xh, %Xh)\n",
arp->ar_hln, arp->ar_pln);
dev->stats.rx_errors++;
dev->stats.rx_crc_errors++;
}
} if (BUGLVL(D_SKB))
arcnet_dump_skb(dev, skb, "rx");
skb->protocol = type_trans(skb, dev);
netif_rx(skb);
} else { /* split packet */ /* NOTE: MSDOS ARP packet correction should only need to * apply to unsplit packets, since ARP packets are so short. * * My interpretation of the RFC1201 document is that if a * packet is received out of order, the entire assembly * process should be aborted. * * The RFC also mentions "it is possible for successfully * received packets to be retransmitted." As of 0.40 all * previously received packets are allowed, not just the * most recent one. * * We allow multiple assembly processes, one for each * ARCnet card possible on the network. * Seems rather like a waste of memory, but there's no * other way to be reliable.
*/
arc_printk(D_RX, dev, "packet is split (splitflag=%d, seq=%d)\n",
soft->split_flag, in->sequence);
/* set the protocol ID according to RFC1201 */ switch (type) { case ETH_P_IP:
soft->proto = ARC_P_IP; break; case ETH_P_IPV6:
soft->proto = ARC_P_IPV6; break; case ETH_P_ARP:
soft->proto = ARC_P_ARP; break; case ETH_P_RARP:
soft->proto = ARC_P_RARP; break; case ETH_P_IPX: case ETH_P_802_3: case ETH_P_802_2:
soft->proto = ARC_P_IPX; break; case ETH_P_ATALK:
soft->proto = ARC_P_ATALK; break; default:
arc_printk(D_NORMAL, dev, "RFC1201: I don't understand protocol %d (%Xh)\n",
type, type);
dev->stats.tx_errors++;
dev->stats.tx_aborted_errors++; return 0;
}
/* Set the source hardware address. * * This is pretty pointless for most purposes, but it can help in * debugging. ARCnet does not allow us to change the source address * in the actual packet sent.
*/
pkt->hard.source = *dev->dev_addr;
/* see linux/net/ethernet/eth.c to see where I got the following */
if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) { /* FIXME: fill in the last byte of the dest ipaddr here * to better comply with RFC1051 in "noarp" mode. * For now, always broadcasting will probably at least get * packets sent out :)
*/
pkt->hard.dest = 0; return hdr_size;
} /* otherwise, drop in the dest address */
pkt->hard.dest = daddr; return hdr_size;
}
staticvoid load_pkt(struct net_device *dev, struct arc_hardware *hard, struct arc_rfc1201 *soft, int softlen, int bufnum)
{ struct arcnet_local *lp = netdev_priv(dev); int ofs;
/* assume length <= XMTU: someone should have handled that by now. */
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.