package org.freertr.pack; import org.freertr.addr.addrIP; import org.freertr.addr.addrIPv4; import org.freertr.addr.addrIPv6; import org.freertr.addr.addrMac; import org.freertr.ip.ipFwdIface; /** * virtual router redundancy protocol (rfc5798) packet * * @author matecsaba */ public class packVrrp { /** * create instance */ public packVrrp() { } /** * protocol number */ public final static int proto = 112; /** * advertisement */ public final static int typAdvert = 1; /** * protocol version */ public int version; /** * packet type */ public int type; /** * group number */ public int group; /** * ip version */ public boolean ipv4; /** * hello interval */ public int hello; /** * priority */ public int priority; /** * virtual ip address */ public addrIP virtual; public String toString() { return "ver=" + version + " ip4=" + ipv4 + " type=" + type2string(type) + " helo=" + hello + " pri=" + priority + " grp=" + group + " virt=" + virtual; } /** * convert type to string * * @param i type * @return string */ public static String type2string(int i) { switch (i) { case typAdvert: return "advertisement"; default: return "unknown=" + i; } } /** * generate group mac address * * @return generated */ public addrMac genMacAddr() { addrMac adr = new addrMac(); if (ipv4) { adr.fromString("0000.5e00.0100"); } else { adr.fromString("0000.5e00.0200"); } byte[] buf = adr.getBytes(); buf[buf.length - 1] = (byte) (group & 0xff); return adr; } /** * generate target ip address * * @return generated */ public addrIP genIpAddr() { addrIP adr = new addrIP(); if (ipv4) { adr.fromString("224.0.0.18"); } else { adr.fromString("ff02::12"); } return adr; } private addrIP getAddr(packHolder pck, int ofs) { addrIP res = new addrIP(); if (ipv4) { addrIPv4 a4 = new addrIPv4(); pck.getAddr(a4, ofs); res.fromIPv4addr(a4); } else { addrIPv6 a6 = new addrIPv6(); pck.getAddr(a6, ofs); res.fromIPv6addr(a6); } return res; } private int putAddr(packHolder pck, int ofs, addrIP adr) { if (ipv4) { addrIPv4 a4 = adr.toIPv4(); pck.putAddr(ofs, a4); return addrIPv4.size; } else { addrIPv6 a6 = adr.toIPv6(); pck.putAddr(ofs, a6); return addrIPv6.size; } } /** * parse one packet * * @param pck packet to read * @return false on success, true on error */ public boolean parsePacket(packHolder pck) { type = pck.getByte(0); // version + type version = type >>> 4; type &= 0xf; int i; if (version >= 3) { i = pck.pseudoIPsum(pck.dataSize()); } else { i = 0; } if (pck.getIPsum(0, pck.dataSize(), i) != 0xffff) { // sum return true; } group = pck.getByte(1); // group id priority = pck.getByte(2); // priority if (pck.getByte(3) < 1) { // address count return true; } if (version >= 3) { hello = (pck.msbGetW(4) & 0xfff) * 10; } else { // int authen = pck.getByte(4); // authentication type hello = pck.getByte(5) * 1000; // hello interval } virtual = getAddr(pck, 8); // address return false; } /** * create one packet * * @param pck packet to update * @param ifc interface to use */ public void createPacket(packHolder pck, ipFwdIface ifc) { pck.IPdf = false; pck.IPfrg = 0; pck.IPalrt = -1; pck.IPttl = 255; pck.IPtos = 0; pck.IPid = 0; pck.IPprt = proto; pck.IPtrg.setAddr(genIpAddr()); pck.IPsrc.setAddr(ifc.addr); pck.putByte(0, (version << 4) | type); // version + type pck.putByte(1, group); // group id pck.putByte(2, priority); // priority pck.putByte(3, 1); // number of addresses if (version >= 3) { pck.msbPutW(4, hello / 10); // hello interval } else { pck.putByte(4, 0); // authentication type pck.putByte(5, hello / 1000); // hello interval } pck.msbPutW(6, 0); // checksum int s = putAddr(pck, 8, virtual) + 8; int i; if (version >= 3) { i = pck.pseudoIPsum(s); } else { i = 0; } i = pck.putIPsum(0, s, i); pck.lsbPutW(6, 0xffff - i); // checksum pck.putSkip(s); // address if (version < 3) { pck.msbPutD(0, 0); // authentication 1 pck.msbPutD(4, 0); // authentication 2 pck.putSkip(8); } pck.merge2beg(); } }