fix 修复 rip v1 响应包 不正确
This commit is contained in:
		@@ -50,7 +50,7 @@ public class RIPService {
 | 
			
		||||
            // 示例:添加本地路由条目
 | 
			
		||||
            InetAddress localAddress = InetAddress.getByName("10.47.54.0");
 | 
			
		||||
            InetAddress subnetMask = InetAddress.getByName("255.255.255.0");
 | 
			
		||||
            InetAddress nextHop = InetAddress.getByName("192.168.192.10");
 | 
			
		||||
            InetAddress nextHop = InetAddress.getByName("0.0.0.0");
 | 
			
		||||
 | 
			
		||||
            RIPEntry entry = new RIPEntry();
 | 
			
		||||
            entry.setAddressFamily((short) 2); // AF_INET
 | 
			
		||||
 
 | 
			
		||||
@@ -2,5 +2,5 @@ package cn.x47.config;
 | 
			
		||||
 | 
			
		||||
public class Config {
 | 
			
		||||
    // 设置协议版本,1 表示 RIP v1,2 表示 RIP v2
 | 
			
		||||
    public static final byte RIP_VERSION = 2;
 | 
			
		||||
    public static final byte RIP_VERSION = 1;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,8 +5,8 @@ import cn.x47.model.RIPEntry;
 | 
			
		||||
import cn.x47.model.RIPPacket;
 | 
			
		||||
import io.netty.buffer.ByteBuf;
 | 
			
		||||
import io.netty.channel.ChannelHandlerContext;
 | 
			
		||||
import io.netty.handler.codec.MessageToMessageEncoder;
 | 
			
		||||
import io.netty.channel.socket.DatagramPacket;
 | 
			
		||||
import io.netty.handler.codec.MessageToMessageEncoder;
 | 
			
		||||
 | 
			
		||||
import java.net.InetSocketAddress;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
@@ -21,18 +21,23 @@ public class RIPPacketEncoder extends MessageToMessageEncoder<RIPPacket> {
 | 
			
		||||
        // 编码命令和版本
 | 
			
		||||
        buf.writeByte(msg.getCommand());
 | 
			
		||||
        buf.writeByte(msg.getVersion());
 | 
			
		||||
        buf.writeShort(0); // unused 字段
 | 
			
		||||
        buf.writeShort(msg.getUnused()); // unused 字段
 | 
			
		||||
 | 
			
		||||
        // 编码路由条目
 | 
			
		||||
        for (RIPEntry entry : msg.getEntries()) {
 | 
			
		||||
            buf.writeShort(entry.getAddressFamily());
 | 
			
		||||
            if (msg.getVersion() == 2) {
 | 
			
		||||
                buf.writeShort(entry.getRouteTag());
 | 
			
		||||
            } else if (msg.getVersion() == 1) {
 | 
			
		||||
                buf.writeShort(0);
 | 
			
		||||
            }
 | 
			
		||||
            buf.writeBytes(entry.getIpAddress().getAddress());
 | 
			
		||||
            if (msg.getVersion() == 2) {
 | 
			
		||||
                buf.writeBytes(entry.getSubnetMask().getAddress());
 | 
			
		||||
                buf.writeBytes(entry.getNextHop().getAddress());
 | 
			
		||||
            } else if (msg.getVersion() == 1) {
 | 
			
		||||
                buf.writeInt(0);
 | 
			
		||||
                buf.writeInt(0);
 | 
			
		||||
            }
 | 
			
		||||
            buf.writeInt(entry.getMetric());
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@ import java.net.InetAddress;
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
public class RIPEntry {
 | 
			
		||||
    //
 | 
			
		||||
    private short addressFamily;
 | 
			
		||||
    private short routeTag;            // RIP v2 特有
 | 
			
		||||
    private InetAddress ipAddress;
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@ import java.util.List;
 | 
			
		||||
public class RIPPacket {
 | 
			
		||||
    private byte command; // 1=Request, 2=Response
 | 
			
		||||
    private byte version; // 1=RIP v1, 2=RIP v2
 | 
			
		||||
    private short unused; // 未使用,设置为 0
 | 
			
		||||
    private short unused = 0; // 未使用,设置为 0
 | 
			
		||||
    private List<RIPEntry> entries;
 | 
			
		||||
 | 
			
		||||
    // 添加构造方法和 Getter/Setter
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,9 @@ import io.netty.channel.nio.NioEventLoopGroup;
 | 
			
		||||
import io.netty.channel.socket.DatagramChannel;
 | 
			
		||||
import io.netty.channel.socket.nio.NioDatagramChannel;
 | 
			
		||||
 | 
			
		||||
import java.net.InetAddress;
 | 
			
		||||
import java.net.UnknownHostException;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
public class RIPClient {
 | 
			
		||||
 | 
			
		||||
@@ -33,11 +36,14 @@ public class RIPClient {
 | 
			
		||||
 | 
			
		||||
    public void sendRipPacket(RIPPacket packet) {
 | 
			
		||||
        try {
 | 
			
		||||
            ChannelFuture future = bootstrap.bind(0).sync();
 | 
			
		||||
            ChannelFuture future = bootstrap.bind(InetAddress.getByName("192.168.123.45"), 520)
 | 
			
		||||
                    .sync();
 | 
			
		||||
            future.channel().writeAndFlush(packet).sync();
 | 
			
		||||
            future.channel().close();
 | 
			
		||||
        } catch (InterruptedException e) {
 | 
			
		||||
            e.printStackTrace();
 | 
			
		||||
        } catch (UnknownHostException e) {
 | 
			
		||||
            throw new RuntimeException(e);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										85
									
								
								src/test/java/RipV1PacketBuilder.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								src/test/java/RipV1PacketBuilder.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,85 @@
 | 
			
		||||
import java.net.InetAddress;
 | 
			
		||||
import java.io.ByteArrayOutputStream;
 | 
			
		||||
import java.io.DataOutputStream;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
 | 
			
		||||
public class RipV1PacketBuilder {
 | 
			
		||||
 | 
			
		||||
    public static byte[] buildRipV1RequestPacket() throws IOException {
 | 
			
		||||
        // 使用 ByteArrayOutputStream 和 DataOutputStream 来构建数据包
 | 
			
		||||
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
 | 
			
		||||
        DataOutputStream dos = new DataOutputStream(baos);
 | 
			
		||||
 | 
			
		||||
        // 1. Command (8比特) - 请求报文,值为 1
 | 
			
		||||
        dos.writeByte(1);  // 请求报文
 | 
			
		||||
 | 
			
		||||
        // 2. Version (8比特) - RIP v1,值为 1
 | 
			
		||||
        dos.writeByte(1);  // RIP v1
 | 
			
		||||
 | 
			
		||||
        // 3. Must be zero (16比特) - 保留字段,必须为零
 | 
			
		||||
        dos.writeShort(0); // 保留字段,填充为零
 | 
			
		||||
 | 
			
		||||
        // 4. Address Family Identifier (AFI) - 请求报文中为 0
 | 
			
		||||
        dos.writeShort(0); // 请求报文的 AFI 为 0
 | 
			
		||||
 | 
			
		||||
        // 5. IP Address (32比特) - 目标 IP 地址,RIP 请求报文中通常为 0.0.0.0
 | 
			
		||||
        InetAddress byName = InetAddress.getByName("200.0.2.0");
 | 
			
		||||
 | 
			
		||||
        // 6. Metric (32比特) - 请求报文的 Metric 为 16,表示不可达
 | 
			
		||||
        dos.writeInt(16); // Metric = 16
 | 
			
		||||
 | 
			
		||||
        // 转换成字节数组
 | 
			
		||||
        return baos.toByteArray();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static byte[] buildRipV1ResponsePacket() throws IOException {
 | 
			
		||||
        // 使用 ByteArrayOutputStream 和 DataOutputStream 来构建数据包
 | 
			
		||||
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
 | 
			
		||||
        DataOutputStream dos = new DataOutputStream(baos);
 | 
			
		||||
 | 
			
		||||
        // 1. Command (8比特) - 响应报文,值为 2
 | 
			
		||||
        dos.writeByte(2);  // 响应报文
 | 
			
		||||
 | 
			
		||||
        // 2. Version (8比特) - RIP v1,值为 1
 | 
			
		||||
        dos.writeByte(1);  // RIP v1
 | 
			
		||||
 | 
			
		||||
        // 3. Must be zero (16比特) - 保留字段,必须为零
 | 
			
		||||
        dos.writeShort(0); // 保留字段,填充为零
 | 
			
		||||
 | 
			
		||||
        // 4. Address Family Identifier (AFI) - 请求报文中为 0
 | 
			
		||||
        dos.writeShort(2); // 响应报文的 AFI 对于 IPv4 为 2
 | 
			
		||||
 | 
			
		||||
        dos.writeShort(0);
 | 
			
		||||
 | 
			
		||||
        // 5. IP Address (32比特) - 目标 IP 地址,假设响应报文中为某个 IP
 | 
			
		||||
        InetAddress byName = InetAddress.getByName("200.0.2.0");
 | 
			
		||||
        printByteArray(byName.getAddress());
 | 
			
		||||
 | 
			
		||||
        dos.write(byName.getAddress()); // 192.168.0.1(IPv4 地址)
 | 
			
		||||
 | 
			
		||||
        // 6. Metric (32比特) - 路由的 Metric
 | 
			
		||||
        dos.writeInt(1); // 假设 Metric 为 1
 | 
			
		||||
 | 
			
		||||
        // 转换成字节数组
 | 
			
		||||
        return baos.toByteArray();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void main(String[] args) throws IOException {
 | 
			
		||||
        byte[] requestPacket = buildRipV1RequestPacket();
 | 
			
		||||
        byte[] responsePacket = buildRipV1ResponsePacket();
 | 
			
		||||
 | 
			
		||||
        System.out.println("RIP v1 Request Packet: ");
 | 
			
		||||
        printByteArray(requestPacket);
 | 
			
		||||
 | 
			
		||||
        System.out.println("RIP v1 Response Packet: ");
 | 
			
		||||
        printByteArray(responsePacket);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 打印字节数组的辅助函数
 | 
			
		||||
    private static void printByteArray(byte[] byteArray) {
 | 
			
		||||
        for (byte b : byteArray) {
 | 
			
		||||
            System.out.printf("%02X ", b);
 | 
			
		||||
        }
 | 
			
		||||
        System.out.println();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										66
									
								
								src/test/java/RipV1Response.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								src/test/java/RipV1Response.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
			
		||||
import java.net.*;
 | 
			
		||||
import java.io.*;
 | 
			
		||||
 | 
			
		||||
public class RipV1Response {
 | 
			
		||||
 | 
			
		||||
    public static void main(String[] args) {
 | 
			
		||||
        try {
 | 
			
		||||
            // 创建一个数据包
 | 
			
		||||
            byte[] packet = createRipV1ResponsePacket();
 | 
			
		||||
 | 
			
		||||
            // 创建一个UDP Socket
 | 
			
		||||
//            DatagramSocket socket = new DatagramSocket();
 | 
			
		||||
            // 创建一个UDP Socket,并将其绑定到指定的 IP 地址
 | 
			
		||||
            DatagramSocket socket = new DatagramSocket(null);
 | 
			
		||||
            socket.bind(new InetSocketAddress(InetAddress.getByName("192.168.123.45"), 520)); // 使用特定的本地 IP 地址绑定端口
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            InetAddress address = InetAddress.getByName("224.0.0.9"); // RIPv1 默认的多播地址
 | 
			
		||||
 | 
			
		||||
            // 创建一个DatagramPacket并发送
 | 
			
		||||
            DatagramPacket sendPacket = new DatagramPacket(packet, packet.length, address, 520); // RIPv1 默认端口 520
 | 
			
		||||
            socket.send(sendPacket);
 | 
			
		||||
 | 
			
		||||
            System.out.println("RIP v1 Response packet sent!");
 | 
			
		||||
            socket.close();
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            e.printStackTrace();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 构建RIP v1 响应数据包
 | 
			
		||||
    public static byte[] createRipV1ResponsePacket() {
 | 
			
		||||
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
 | 
			
		||||
        DataOutputStream dos = new DataOutputStream(bos);
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            // 1. Command (8比特) - 响应报文 (Response)
 | 
			
		||||
            dos.writeByte(2); // Command = 2,表示响应报文
 | 
			
		||||
 | 
			
		||||
            // 2. Version (8比特) - RIP版本号 (RIP-1)
 | 
			
		||||
            dos.writeByte(1); // Version = 1,RIP-1
 | 
			
		||||
 | 
			
		||||
            // 3. Must be zero (16比特) - 保留字段,必须为零
 | 
			
		||||
            dos.writeShort(0); // 16比特的保留字段,填充0
 | 
			
		||||
 | 
			
		||||
            // 4. AFI (Address Family Identifier) (16比特) - 地址族标识符
 | 
			
		||||
            dos.writeShort(2); // AFI = 2,表示 IPv4 地址
 | 
			
		||||
 | 
			
		||||
            dos.writeShort(0);
 | 
			
		||||
 | 
			
		||||
            InetAddress byName = InetAddress.getByName("200.0.2.0");
 | 
			
		||||
            // 5. IP Address (32比特) - 路由目标 IP 地址
 | 
			
		||||
            dos.write(byName.getAddress()); // 192.168.0.1 的 IP 地址(32位)
 | 
			
		||||
 | 
			
		||||
            dos.writeInt(0);
 | 
			
		||||
            dos.writeInt(0);
 | 
			
		||||
            // 6. Metric (32比特) - 路由开销
 | 
			
		||||
            dos.writeInt(1); // Metric = 1,表示一个跳数
 | 
			
		||||
 | 
			
		||||
        } catch (IOException e) {
 | 
			
		||||
            e.printStackTrace();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return bos.toByteArray();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user