arpnetworklayer.java

来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 297 行

JAVA
297
字号
/*
 * $Id: ARPNetworkLayer.java,v 1.2 2004/02/15 11:08:03 epr Exp $
 */
package org.jnode.net.arp;

import java.net.SocketException;
import java.util.Collection;
import java.util.Collections;

import org.apache.log4j.Logger;
import org.jnode.driver.ApiNotFoundException;
import org.jnode.driver.Device;
import org.jnode.driver.net.NetDeviceAPI;
import org.jnode.driver.net.NetworkException;
import org.jnode.net.HardwareAddress;
import org.jnode.net.InvalidLayerException;
import org.jnode.net.LayerAlreadyRegisteredException;
import org.jnode.net.NetworkLayer;
import org.jnode.net.NoSuchProtocolException;
import org.jnode.net.ProtocolAddress;
import org.jnode.net.ProtocolAddressInfo;
import org.jnode.net.SocketBuffer;
import org.jnode.net.TransportLayer;
import org.jnode.net.ethernet.EthernetConstants;
import org.jnode.util.Statistics;
import org.jnode.util.TimeoutException;

/**
 * @author epr
 */
public class ARPNetworkLayer implements NetworkLayer, ARPConstants {

	/** My logger */
	private final Logger log = Logger.getLogger(getClass());
	/** My statistics */
	private final ARPStatistics stat = new ARPStatistics();
	/** ARP cache */
	private static final ARPCache cache = new ARPCache();
	
	/**
	 * Create a new instance
	 */
	public ARPNetworkLayer() {
	}

	/**
	 * Gets the name of this type
	 */
	public String getName() {
		return "arp";
	}

	/**
	 * Gets the protocol ID this packettype handles
	 */
	public int getProtocolID() {
		return EthernetConstants.ETH_P_ARP;
	}

	/**
	 * Can this packet type process packets received from the given device?
	 */
	public boolean isAllowedForDevice(Device dev) {
		// For all devices
		return true;
	}

	/**
	 * Process a packet that has been received and matches getType()
	 * @param skbuf
	 * @param deviceAPI
	 * @throws SocketException
	 */
	public void receive(SocketBuffer skbuf, NetDeviceAPI deviceAPI) 
	throws SocketException {
		
		// Update statistics
		stat.ipackets.inc();
		
		final ARPHeader hdr = new ARPHeader(skbuf);
		skbuf.setNetworkLayerHeader(hdr);
		skbuf.pull(hdr.getLength());
		
		// Update the cache
		cache.set(hdr.getSrcHWAddress(), hdr.getSrcPAddress(), true);
		
		// Should we reply?
		switch (hdr.getOperation()) {
			case ARP_REQUEST: 
				processARPRequest(skbuf, hdr, deviceAPI); break;
			case ARP_REPLY:
				processARPReply(skbuf, hdr, deviceAPI); break;
			case RARP_REQUEST: 
				processRARPRequest(skbuf, hdr, deviceAPI); break;
			case RARP_REPLY:
				processRARPReply(skbuf, hdr, deviceAPI); break;
			default: {
				log.debug("Unknown ARP operation " + hdr.getOperation()); 
			}
		}
	}
	
	/**
	 * Process and ARP request.
	 * @param skbuf
	 * @param hdr
	 * @param deviceAPI
	 * @throws NetworkException
	 */
	private void processARPRequest(SocketBuffer skbuf, ARPHeader hdr, NetDeviceAPI deviceAPI) 
	throws SocketException {
		
		final ProtocolAddressInfo addrInfo = deviceAPI.getProtocolAddressInfo(hdr.getPType());
		if ((addrInfo != null) && (addrInfo.contains(hdr.getTargetPAddress()))) {
			//log.debug("Sending ARP reply");
			stat.arpreply.inc();
			stat.opackets.inc();
			hdr.swapAddresses();
			hdr.setSrcHWAddress(deviceAPI.getAddress());
			hdr.setOperation(ARP_REPLY);
			skbuf.clear();
			skbuf.setProtocolID(getProtocolID());
			hdr.prefixTo(skbuf);
			deviceAPI.transmit(skbuf, hdr.getTargetHWAddress());
		} else {
			//log.debug("ARP request, not my IP-address");				
		}
	}

	/**
	 * Process and ARP reply
	 * @param skbuf
	 * @param hdr
	 * @param deviceAPI
	 * @throws NetworkException
	 */
	private void processARPReply(SocketBuffer skbuf, ARPHeader hdr, NetDeviceAPI deviceAPI) 
	throws SocketException {
		// Nothing further todo
	}
	
	/**
	 * Process and RARP request
	 * @param skbuf
	 * @param hdr
	 * @param deviceAPI
	 * @throws NetworkException
	 */
	private void processRARPRequest(SocketBuffer skbuf, ARPHeader hdr, NetDeviceAPI deviceAPI) 
	throws SocketException {
		stat.rarpreq.inc();
		log.debug("GOT RARP Request");
	}
	
	/**
	 * Process and RARP reply
	 * @param skbuf
	 * @param hdr
	 * @param deviceAPI
	 * @throws NetworkException
	 */
	private void processRARPReply(SocketBuffer skbuf, ARPHeader hdr, NetDeviceAPI deviceAPI) 
	throws SocketException {
		log.debug("GOT RARP Reply");
}
	
	/**
	 * Gets the ARP cache.
	 */
	public ARPCache getCache() {
		return cache;
	}

	/**
	 * @see org.jnode.net.NetworkLayer#getStatistics()
	 */
	public Statistics getStatistics() {
		return stat;
	}

	/**
	 * @see org.jnode.net.NetworkLayer#registerTransportLayer(org.jnode.net.TransportLayer)
	 */
	public void registerTransportLayer(TransportLayer layer)
	throws LayerAlreadyRegisteredException, InvalidLayerException {
		throw new InvalidLayerException("ARP cannot register transportlayers");
	}

	/**
	 * @see org.jnode.net.NetworkLayer#unregisterTransportLayer(org.jnode.net.TransportLayer)
	 */
	public void unregisterTransportLayer(TransportLayer layer) {
		// Just ignore
	}
	
	/**
	 * Gets all registered transport-layers
	 */
	public Collection getTransportLayers() {
		return Collections.EMPTY_LIST;
	}
	
	/**
	 * Gets a registered transportlayer by its protocol ID.
	 * @param protocolID
	 */
	public TransportLayer getTransportLayer(int protocolID)
	throws NoSuchProtocolException {
		throw new NoSuchProtocolException("protocol " + protocolID);
	}
	
	/**
	 * Gets the hardware address for a given protocol address.
	 * @param address
	 * @param myAddress
	 * @param device
	 * @param timeout
	 * @throws TimeoutException
	 * @throws NetworkException
	 */
	public HardwareAddress getHardwareAddress(ProtocolAddress address, ProtocolAddress myAddress, Device device, long timeout)
	throws TimeoutException, NetworkException {
		final long start = System.currentTimeMillis();
		long lastReq = 0;
		
		if (address.equals(myAddress)) {
			// This is simple, just return my address
			return getAPI(device).getAddress();
		}
		
		while (true) {
			final HardwareAddress hwAddress = cache.get(address);
			if (hwAddress != null) {
				return hwAddress;
			}
			final long now = System.currentTimeMillis();
			if ((now - start) >= timeout) {
				// Still not correct response
				throw new TimeoutException("Timeout in ARP request");
			}
			// Try to send a request every few seconds
			if ((now - lastReq) >= ARP_REQUEST_DELAY) {
				lastReq = now;
				request(address, myAddress, device);
			} else {
				cache.waitForChanges(Math.min(timeout, ARP_REQUEST_DELAY));
			}
		}
		
	}

	/**
	 * Gets the protocol addresses for a given name, or null if not found.
	 * @param hostname
	 * @return
	 */
    public ProtocolAddress[] getHostByName(String hostname) {
        return null;
    }

	/**
	 * Create and transmit an ARP request
	 * @param address
	 * @param myAddress
	 * @param device
	 */	
	private void request(ProtocolAddress address, ProtocolAddress myAddress, Device device) 
	throws NetworkException {
		// Not found in the cache, make a request
		final NetDeviceAPI api = getAPI(device);
		final HardwareAddress srcHwAddr = api.getAddress();
		final HardwareAddress trgHwAddr = srcHwAddr.getDefaultBroadcastAddress();
		final int op = ARP_REQUEST;
		final int hwtype = srcHwAddr.getType();
		final int ptype = address.getType();
		
		final ARPHeader hdr = new ARPHeader(srcHwAddr, myAddress, trgHwAddr, address, op, hwtype, ptype);
		final SocketBuffer skbuf = new SocketBuffer();
		skbuf.setProtocolID(EthernetConstants.ETH_P_ARP);
		hdr.prefixTo(skbuf);
		
		api.transmit(skbuf, trgHwAddr);
	}
	
	/**
	 * Gets the NetDeviceAPI for a given device
	 * @param device
	 */
	private NetDeviceAPI getAPI(Device device) {
		try {
			return (NetDeviceAPI)device.getAPI(NetDeviceAPI.class);
		} catch (ApiNotFoundException ex) {
			throw new IllegalArgumentException("Not a network device " + device.getId());
		}
	}
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?