icmpprotocol.java
来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 231 行
JAVA
231 行
/*
* $Id: ICMPProtocol.java,v 1.1 2003/11/25 11:52:20 epr Exp $
*/
package org.jnode.net.ipv4.icmp;
import java.net.DatagramSocketImplFactory;
import java.net.SocketException;
import java.net.SocketImplFactory;
import org.apache.log4j.Logger;
import org.jnode.net.SocketBuffer;
import org.jnode.net.ipv4.IPv4Constants;
import org.jnode.net.ipv4.IPv4Header;
import org.jnode.net.ipv4.IPv4Protocol;
import org.jnode.net.ipv4.IPv4Service;
import org.jnode.util.Queue;
import org.jnode.util.QueueProcessor;
import org.jnode.util.QueueProcessorThread;
import org.jnode.util.Statistics;
/**
* Protocol handler of the ICMP protocol.
*
* @author Ewout Prangsma (epr@users.sourceforge.net)
*/
public class ICMPProtocol implements IPv4Protocol, IPv4Constants, ICMPConstants, QueueProcessor {
/** My logger */
private Logger log = Logger.getLogger(getClass());
/** The IP service we're a part of */
private final IPv4Service ipService;
/** The statistics */
private final ICMPStatistics stat = new ICMPStatistics();
/** Queue<SocketBuffer> for requests that need a reply */
private final Queue replyRequestQueue = new Queue();
private final QueueProcessorThread replyRequestsThread;
/**
* Create a new instance
* @param ipService
*/
public ICMPProtocol(IPv4Service ipService) {
this.ipService = ipService;
this.replyRequestsThread = new QueueProcessorThread("icmp-reply", replyRequestQueue, this);
replyRequestsThread.start();
}
/**
* @see org.jnode.net.ipv4.IPv4Protocol#getName()
*/
public String getName() {
return "icmp";
}
/**
* @see org.jnode.net.ipv4.IPv4Protocol#getProtocolID()
*/
public int getProtocolID() {
return IPPROTO_ICMP;
}
/**
* @see org.jnode.net.ipv4.IPv4Protocol#receive(org.jnode.net.SocketBuffer)
*/
public void receive(SocketBuffer skbuf) throws SocketException {
// Update statistics
stat.ipackets.inc();
final ICMPHeader hdr = createHeader(skbuf);
skbuf.setTransportLayerHeader(hdr);
skbuf.pull(hdr.getLength());
if (!hdr.isChecksumOk()) {
stat.badsum.inc();
return;
}
// TODO Process ICMP messages
switch (hdr.getType()) {
case ICMP_ECHO:
postReplyRequest(skbuf);
break;
default:
log.debug("GOT ICMP type " + hdr.getType() + ", code " + hdr.getCode());
}
}
/**
* Process an ICMP error message that has been received and matches
* this protocol.
* The skbuf is position directly after the ICMP header (thus contains
* the error IP header and error transport layer header).
* The transportLayerHeader property of skbuf is set to the
* ICMP message header.
*
* @param skbuf
* @throws SocketException
*/
public void receiveError(SocketBuffer skbuf)
throws SocketException {
// Ignore errors here
}
/**
* Gets the SocketImplFactory of this protocol.
* @throws SocketException If this protocol is not Socket based.
*/
public SocketImplFactory getSocketImplFactory()
throws SocketException {
throw new SocketException("ICMP is packet based");
}
/**
* Gets the DatagramSocketImplFactory of this protocol.
* @throws SocketException If this protocol is not DatagramSocket based.
*/
public DatagramSocketImplFactory getDatagramSocketImplFactory()
throws SocketException {
throw new SocketException("Not implemented yet");
}
/**
* Send an ICMP packet
* @param skbuf
*/
protected void send(IPv4Header ipHdr, ICMPHeader icmpHdr, SocketBuffer skbuf)
throws SocketException {
//Syslog.debug("ICMP.send");
stat.opackets.inc();
skbuf.setTransportLayerHeader(icmpHdr);
icmpHdr.prefixTo(skbuf);
ipService.transmit(ipHdr, skbuf);
}
/**
* Send a reply on an ICMP echo header.
* @param hdr
* @param skbuf
*/
private void sendEchoReply(ICMPEchoHeader hdr, SocketBuffer skbuf)
throws SocketException {
final IPv4Header ipHdr = (IPv4Header)skbuf.getNetworkLayerHeader();
final IPv4Header ipReplyHdr = new IPv4Header(ipHdr);
ipReplyHdr.swapAddresses();
ipReplyHdr.setTtl(0xFF);
send(ipReplyHdr, hdr.createReplyHeader(), new SocketBuffer(skbuf));
}
/**
* Create a type specific ICMP header. The type is read from the first
* first in the skbuf.
* @param skbuf
* @throws SocketException
*/
private ICMPHeader createHeader(SocketBuffer skbuf)
throws SocketException {
final int type = skbuf.get(0);
switch (type) {
case ICMP_DEST_UNREACH:
return new ICMPUnreachableHeader(skbuf);
case ICMP_TIMESTAMP:
case ICMP_TIMESTAMPREPLY:
return new ICMPTimestampHeader(skbuf);
case ICMP_ADDRESS:
case ICMP_ADDRESSREPLY:
return new ICMPAddressMaskHeader(skbuf);
case ICMP_ECHOREPLY:
case ICMP_ECHO:
return new ICMPEchoHeader(skbuf);
case ICMP_SOURCE_QUENCH:
case ICMP_REDIRECT:
case ICMP_TIME_EXCEEDED:
case ICMP_PARAMETERPROB:
case ICMP_INFO_REQUEST:
case ICMP_INFO_REPLY:
throw new SocketException("Not implemented");
default:
throw new SocketException("Unknown ICMP type " + type);
}
}
/**
* @see org.jnode.net.ipv4.IPv4Protocol#getStatistics()
*/
public Statistics getStatistics() {
return stat;
}
/**
* Post a request that needs a reply in the reply queue.
* @param skbuf
*/
private void postReplyRequest(SocketBuffer skbuf) {
replyRequestQueue.add(skbuf);
}
/**
* Process a request that needs a reply
* @param skbuf
*/
private void processReplyRequest(SocketBuffer skbuf) {
final ICMPHeader hdr = (ICMPHeader)skbuf.getTransportLayerHeader();
try {
switch (hdr.getType()) {
case ICMP_ECHO:
//Syslog.debug("<Send reply>");
sendEchoReply((ICMPEchoHeader)hdr, skbuf);
//Syslog.debug("</Send reply>");
break;
}
} catch (SocketException ex) {
log.debug("Error in ICMP reply", ex);
}
}
/**
* @see org.jnode.util.QueueProcessor#process(java.lang.Object)
*/
public void process(Object object) throws Exception {
processReplyRequest((SocketBuffer)object);
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?