package org.freertr.rtr; import java.util.List; import java.util.Timer; import java.util.TimerTask; import org.freertr.addr.addrIsis; import org.freertr.addr.addrMac; import org.freertr.auth.authLocal; import org.freertr.cry.cryHashHmac; import org.freertr.cry.cryHashMd5; import org.freertr.ifc.ifcDn; import org.freertr.ifc.ifcEthTyp; import org.freertr.ifc.ifcNull; import org.freertr.ifc.ifcUp; import org.freertr.ip.ipFwdIface; import org.freertr.pack.packHolder; import org.freertr.tab.tabAverage; import org.freertr.tab.tabGen; import org.freertr.user.userHelping; import org.freertr.util.bits; import org.freertr.util.cmds; import org.freertr.util.counter; import org.freertr.util.debugger; import org.freertr.util.logger; import org.freertr.util.state; import org.freertr.enc.encTlv; import org.freertr.sec.secInfoCfg; import org.freertr.sec.secInfoUtl; /** * isis interface * * @author matecsaba */ public class rtrIsisIface implements Comparable, ifcUp { /** * ipinfo config */ public secInfoCfg ipInfoCfg; /** * the ip interface this works on */ protected final ipFwdIface iface; /** * the other ip interface this works on */ protected final ipFwdIface oface; /** * the l2 interface this works on */ private final ifcEthTyp ethtyp; /** * the l2 packet handler */ protected ifcDn upper = new ifcNull(); /** * levels allowed (bitmask) */ public int circuitLevel; /** * circuit id */ public int circuitID; /** * other enabled */ public boolean otherEna; /** * network type false=broadcast, true=point2point */ public boolean netPnt2pnt; /** * raw ethertype encapsulation */ public boolean rawEncap; private final rtrIsis lower; private Timer keepTimer; /** * own hardware address */ protected addrMac hwaddr; /** * counter */ protected counter cntr = new counter(); /** * send csnp */ public boolean sendCsnp; /** * suppress interface address */ public boolean suppressAddr; /** * unsuppress interface address */ public boolean unsuppressAddr; /** * suppress interface address */ public boolean suppressInt; /** * other unsuppress interface address */ public boolean othUnsuppAddr; /** * other suppress interface address */ public boolean othSuppAddr; /** * check neighbor address is connected */ public boolean connectedCheck; /** * other suppress interface address */ public boolean othSuppInt; /** * passive interface */ public boolean passiveInt; /** * hello timer */ public int helloTimer; /** * dead timer */ public int deadTimer; /** * retransmit timer */ public int retransTimer; /** * dis priority */ public int disPriority; /** * interface metric */ public int metric; /** * bfd enabled */ public boolean bfdTrigger; /** * authentication password */ public String authentication; /** * authentication mode: 1=cleartext, 2=md5 */ public int authenMode; /** * traffic eng suppression */ public boolean teSuppress; /** * traffic eng metric */ public int teMetric; /** * traffic eng bandwidth */ public long teBandwidth; /** * traffic eng affinity */ public int teAffinity; /** * traffic eng srlg */ public int teSrlg; /** * segment rou index */ public int srIndex; /** * other segment rou index */ public int srOthIdx; /** * segment rou node */ public boolean srNode; /** * segment rou pop */ public boolean srPop; /** * bier index */ public int brIndex; /** * bier subdomain */ public int brSub; /** * other bier index */ public int brOthIdx; /** * other bier subdomain */ public int brOthSub; /** * echo interval */ public int echoTimer; /** * echo parameters */ public tabAverage echoParam; /** * dynamic metric */ public int dynamicMetric; /** * neighbors */ protected tabGen neighs; private addrIsis lev1disA; private addrIsis lev2disA; private int lev1disI; private int lev2disI; private int lev1csnp; private int lev2csnp; /** * create one instance * * @param parent the isis protocol * @param ifc the ip interface to work on * @param oifc the other ip interface to work on * @param eth the eth interface to work on */ public rtrIsisIface(rtrIsis parent, ipFwdIface ifc, ipFwdIface oifc, ifcEthTyp eth) { lower = parent; iface = ifc; oface = oifc; ethtyp = eth; netPnt2pnt = true; circuitID = lower.getCircuitId(netPnt2pnt); circuitLevel = lower.operateLevel; helloTimer = 10000; deadTimer = 30000; retransTimer = 3000; disPriority = 64; authenMode = 1; metric = 10; echoTimer = 60000; echoParam = new tabAverage(1, 16777210); suppressInt = true; othSuppInt = true; connectedCheck = true; neighs = new tabGen(); hwaddr = new addrMac(); lev1disA = new addrIsis(); lev2disA = new addrIsis(); teMetric = 10; if (iface != null) { teBandwidth = iface.lower.getBandwidth(); } } public int compareTo(rtrIsisIface o) { if (iface.ifwNum < o.iface.ifwNum) { return -1; } if (iface.ifwNum > o.iface.ifwNum) { return +1; } return 0; } public String toString() { return "isis on " + iface; } /** * get configuration * * @param l list to add * @param beg beginning * @param filter filter defaults */ public void routerGetConfig(List l, String beg, int filter) { l.add(cmds.tabulator + beg + "enable"); cmds.cfgLine(l, !otherEna, cmds.tabulator, beg + "other-enable", ""); cmds.cfgLine(l, !passiveInt, cmds.tabulator, beg + "passive", ""); cmds.cfgLine(l, !rawEncap, cmds.tabulator, beg + "raw-encapsulation", ""); l.add(cmds.tabulator + beg + "circuit " + rtrIsis.level2string(circuitLevel)); String s; if (netPnt2pnt) { s = "point2point"; } else { s = "broadcast"; } l.add(cmds.tabulator + beg + "network " + s); cmds.cfgLine(l, !bfdTrigger, cmds.tabulator, beg + "bfd", ""); cmds.cfgLine(l, !sendCsnp, cmds.tabulator, beg + "send-csnp", ""); cmds.cfgLine(l, !suppressInt, cmds.tabulator, beg + "suppress-address", ""); cmds.cfgLine(l, !suppressAddr, cmds.tabulator, beg + "suppress-prefix", ""); cmds.cfgLine(l, !unsuppressAddr, cmds.tabulator, beg + "unsuppress-prefix", ""); cmds.cfgLine(l, !othSuppInt, cmds.tabulator, beg + "other-suppress-address", ""); cmds.cfgLine(l, !othSuppAddr, cmds.tabulator, beg + "other-suppress-prefix", ""); cmds.cfgLine(l, !othUnsuppAddr, cmds.tabulator, beg + "other-unsuppress-prefix", ""); cmds.cfgLine(l, !connectedCheck, cmds.tabulator, beg + "verify-source", ""); cmds.cfgLine(l, authentication == null, cmds.tabulator, beg + "password", authLocal.passwdEncode(authentication, (filter & 2) != 0)); String a; switch (authenMode) { case 0: a = "null"; break; case 1: a = "clear"; break; case 2: a = "md5"; break; default: a = "unknown=" + authenMode; break; } l.add(cmds.tabulator + beg + "authen-type " + a); l.add(cmds.tabulator + beg + "metric " + metric); l.add(cmds.tabulator + beg + "priority " + disPriority); l.add(cmds.tabulator + beg + "hello-time " + helloTimer); l.add(cmds.tabulator + beg + "dead-time " + deadTimer); l.add(cmds.tabulator + beg + "retransmit-time " + retransTimer); boolean b = false; if ((circuitLevel & 1) != 0) { b |= lower.level1.traffEng; } if ((circuitLevel & 2) != 0) { b |= lower.level2.traffEng; } if (b) { s = beg + "traffeng "; cmds.cfgLine(l, !teSuppress, cmds.tabulator, s + "suppress", ""); l.add(cmds.tabulator + s + "metric " + teMetric); l.add(cmds.tabulator + s + "bandwidth " + teBandwidth); l.add(cmds.tabulator + s + "affinity " + teAffinity); l.add(cmds.tabulator + s + "srlg " + teSrlg); } b = false; if ((circuitLevel & 1) != 0) { b |= lower.level1.segrouEna; } if ((circuitLevel & 2) != 0) { b |= lower.level2.segrouEna; } if (b) { s = beg + "segrout "; cmds.cfgLine(l, srIndex < 1, cmds.tabulator, s + "index", "" + srIndex); cmds.cfgLine(l, srOthIdx < 1, cmds.tabulator, s + "other-index", "" + srOthIdx); cmds.cfgLine(l, !srNode, cmds.tabulator, s + "node", ""); cmds.cfgLine(l, !srPop, cmds.tabulator, s + "pop", ""); } b = false; if ((circuitLevel & 1) != 0) { b |= lower.level1.bierEna; } if ((circuitLevel & 2) != 0) { b |= lower.level2.bierEna; } if (b) { s = beg + "bier "; cmds.cfgLine(l, brIndex < 1, cmds.tabulator, s + "index", "" + brIndex); cmds.cfgLine(l, brSub < 1, cmds.tabulator, s + "subdomain", "" + brSub); cmds.cfgLine(l, brOthIdx < 1, cmds.tabulator, s + "other-index", "" + brOthIdx); cmds.cfgLine(l, brOthSub < 1, cmds.tabulator, s + "other-subdomain", "" + brOthSub); } secInfoUtl.getConfig(l, ipInfoCfg, cmds.tabulator + beg + "ipinfo "); switch (dynamicMetric) { case 0: a = "disabled"; break; case 1: a = "icmpecho"; break; case 2: a = "udpecho"; break; case 3: a = "twamp"; break; default: a = "unknown=" + dynamicMetric; } cmds.cfgLine(l, dynamicMetric < 1, cmds.tabulator, beg + "dynamic-metric mode", a); l.add(cmds.tabulator + beg + "dynamic-metric time " + echoTimer); echoParam.getConfig(l, beg); } /** * do configuration * * @param a command * @param cmd parameters */ public void routerDoConfig(String a, cmds cmd) { if (a.equals("circuit")) { circuitLevel = rtrIsis.string2level(cmd.word()) & lower.operateLevel; lower.genLsps(3); return; } if (a.equals("network")) { a = cmd.word(); int i = -1; if (a.equals("point2point")) { i = 1; } if (a.equals("broadcast")) { i = 2; } if (i < 0) { return; } netPnt2pnt = i == 1; circuitID = lower.getCircuitId(netPnt2pnt); lower.genLsps(3); return; } if (a.equals("raw-encapsulation")) { rawEncap = true; unregister2eth(); register2eth(); return; } if (a.equals("passive")) { passiveInt = true; return; } if (a.equals("bfd")) { bfdTrigger = true; return; } if (a.equals("send-csnp")) { sendCsnp = true; return; } if (a.equals("suppress-prefix")) { suppressAddr = true; lower.genLsps(1); return; } if (a.equals("unsuppress-prefix")) { unsuppressAddr = true; lower.genLsps(1); return; } if (a.equals("suppress-address")) { suppressInt = true; lower.genLsps(1); return; } if (a.equals("other-suppress-prefix")) { othSuppAddr = true; lower.genLsps(1); return; } if (a.equals("other-unsuppress-prefix")) { othUnsuppAddr = true; lower.genLsps(1); return; } if (a.equals("other-suppress-address")) { othSuppInt = true; lower.genLsps(1); return; } if (a.equals("verify-source")) { connectedCheck = true; return; } if (a.equals("hello-time")) { helloTimer = bits.str2num(cmd.word()); restartTimer(false); return; } if (a.equals("dead-time")) { deadTimer = bits.str2num(cmd.word()); return; } if (a.equals("retransmit-time")) { retransTimer = bits.str2num(cmd.word()); return; } if (a.equals("priority")) { disPriority = bits.str2num(cmd.word()); return; } if (a.equals("metric")) { metric = bits.str2num(cmd.word()); lower.genLsps(3); return; } if (a.equals("other-enable")) { otherEna = oface != null; lower.genLsps(1); return; } if (a.equals("password")) { authentication = authLocal.passwdDecode(cmd.word()); return; } if (a.equals("authen-type")) { authenMode = 0; a = cmd.word(); if (a.equals("null")) { authenMode = 0; return; } if (a.equals("clear")) { authenMode = 1; return; } if (a.equals("md5")) { authenMode = 2; return; } return; } if (a.equals("traffeng")) { a = cmd.word(); if (a.equals("suppress")) { teSuppress = true; lower.genLsps(1); return; } if (a.equals("metric")) { teMetric = bits.str2num(cmd.word()); lower.genLsps(1); return; } if (a.equals("bandwidth")) { teBandwidth = bits.str2long(cmd.word()); lower.genLsps(1); return; } if (a.equals("affinity")) { teAffinity = bits.str2num(cmd.word()); lower.genLsps(1); return; } if (a.equals("srlg")) { teSrlg = bits.str2num(cmd.word()); lower.genLsps(1); return; } cmd.badCmd(); return; } if (a.equals("segrout")) { a = cmd.word(); if (a.equals("index")) { srIndex = bits.str2num(cmd.word()); lower.genLsps(3); return; } if (a.equals("other-index")) { srOthIdx = bits.str2num(cmd.word()); lower.genLsps(3); return; } if (a.equals("node")) { srNode = true; lower.genLsps(3); return; } if (a.equals("pop")) { srPop = true; lower.genLsps(3); return; } cmd.badCmd(); return; } if (a.equals("bier")) { a = cmd.word(); if (a.equals("index")) { brIndex = bits.str2num(cmd.word()); lower.genLsps(3); return; } if (a.equals("subdomain")) { brSub = bits.str2num(cmd.word()); lower.genLsps(3); return; } if (a.equals("other-index")) { brOthIdx = bits.str2num(cmd.word()); lower.genLsps(3); return; } if (a.equals("other-subdomain")) { brOthSub = bits.str2num(cmd.word()); lower.genLsps(3); return; } cmd.badCmd(); return; } if (a.equals("ipinfo")) { ipInfoCfg = secInfoUtl.doCfgStr(ipInfoCfg, cmd, false); return; } if (a.equals("dynamic-metric")) { a = cmd.word(); if (a.equals("mode")) { a = cmd.word(); dynamicMetric = 0; if (a.equals("disabled")) { dynamicMetric = 0; } if (a.equals("icmpecho")) { dynamicMetric = 1; } if (a.equals("udpecho")) { dynamicMetric = 2; } if (a.equals("twamp")) { dynamicMetric = 3; } lower.genLsps(3); return; } if (a.equals("time")) { echoTimer = bits.str2num(cmd.word()); return; } if (echoParam.doConfig(a, cmd)) { return; } if (a.equals("algo")) { echoParam.string2algo(cmd.word()); lower.genLsps(3); return; } cmd.badCmd(); return; } cmd.badCmd(); } /** * undo configuration * * @param a command * @param cmd parameters */ public void routerUnConfig(String a, cmds cmd) { if (a.equals("metric")) { metric = 10; lower.genLsps(3); return; } if (a.equals("passive")) { passiveInt = false; return; } if (a.equals("bfd")) { bfdTrigger = false; return; } if (a.equals("send-csnp")) { sendCsnp = false; return; } if (a.equals("raw-encapsulation")) { rawEncap = false; unregister2eth(); register2eth(); return; } if (a.equals("suppress-prefix")) { suppressAddr = false; lower.genLsps(1); return; } if (a.equals("unsuppress-prefix")) { unsuppressAddr = false; lower.genLsps(1); return; } if (a.equals("suppress-address")) { suppressInt = false; lower.genLsps(1); return; } if (a.equals("other-enable")) { otherEna = false; lower.genLsps(1); return; } if (a.equals("other-suppress-prefix")) { othSuppAddr = false; lower.genLsps(1); return; } if (a.equals("other-unsuppress-prefix")) { othUnsuppAddr = false; lower.genLsps(1); return; } if (a.equals("other-suppress-address")) { othSuppInt = false; lower.genLsps(1); return; } if (a.equals("verify-source")) { connectedCheck = false; return; } if (a.equals("password")) { authentication = null; return; } if (a.equals("authen-type")) { authenMode = 1; return; } if (a.equals("traffeng")) { a = cmd.word(); if (a.equals("suppress")) { teSuppress = false; lower.genLsps(1); return; } cmd.badCmd(); return; } if (a.equals("segrout")) { a = cmd.word(); if (a.equals("index")) { srIndex = 0; lower.genLsps(3); return; } if (a.equals("other-index")) { srOthIdx = 0; lower.genLsps(3); return; } if (a.equals("node")) { srNode = false; lower.genLsps(3); return; } if (a.equals("pop")) { srPop = false; lower.genLsps(3); return; } cmd.badCmd(); return; } if (a.equals("bier")) { a = cmd.word(); if (a.equals("index")) { brIndex = 0; lower.genLsps(3); return; } if (a.equals("subdomain")) { brSub = 0; lower.genLsps(3); return; } if (a.equals("other-index")) { brOthIdx = 0; lower.genLsps(3); return; } if (a.equals("other-subdomain")) { brOthSub = 0; lower.genLsps(3); return; } cmd.badCmd(); return; } if (a.equals("ipinfo")) { ipInfoCfg = secInfoUtl.doCfgStr(ipInfoCfg, cmd, true); return; } if (a.equals("dynamic-metric")) { a = cmd.word(); if (a.equals("mode")) { dynamicMetric = 0; lower.genLsps(3); return; } cmd.badCmd(); return; } cmd.badCmd(); } /** * get help text * * @param l list to update */ public static void routerGetHelp(userHelping l) { l.add(null, "4 . enable enable protocol processing"); l.add(null, "4 . other-enable enable other protocol processing"); l.add(null, "4 5 circuit set circuit type"); l.add(null, "5 . level1 level-1 circuit"); l.add(null, "5 . level2 level-2 circuit"); l.add(null, "5 . both level-1 and level-2 circuit"); l.add(null, "4 5 network set network type"); l.add(null, "5 . point2point point to point"); l.add(null, "5 . broadcast broadcast"); l.add(null, "4 . passive do not process packets"); l.add(null, "4 . bfd enable bfd triggered down"); l.add(null, "4 . raw-encapsulation use non-llc encapsulation"); l.add(null, "4 . suppress-prefix do not advertise interface"); l.add(null, "4 . unsuppress-prefix do advertise interface"); l.add(null, "4 . suppress-address do not advertise interface"); l.add(null, "4 . send-csnp always send csnp"); l.add(null, "4 5 metric interface metric"); l.add(null, "5 . metric"); l.add(null, "4 . other-suppress-prefix do not advertise other interface"); l.add(null, "4 . other-unsuppress-prefix do advertise other interface"); l.add(null, "4 . other-suppress-address do not advertise other interface"); l.add(null, "4 . verify-source check source address of updates"); l.add(null, "4 5 priority router priority"); l.add(null, "5 . priority 0=disable"); l.add(null, "4 5 hello-time time between hellos"); l.add(null, "5 . time in ms"); l.add(null, "4 5 dead-time time before neighbor down"); l.add(null, "5 . time in ms"); l.add(null, "4 5 retransmit-time time before retarnsmitting"); l.add(null, "5 . time in ms"); l.add(null, "4 5 password password for authentication"); l.add(null, "5 . set password"); l.add(null, "4 5 authen-type mode for authentication"); l.add(null, "5 . null use nothing"); l.add(null, "5 . clear use cleartext"); l.add(null, "5 . md5 use md5"); l.add(null, "4 5 traffeng traffic engineering parameters"); l.add(null, "5 . suppress do not advertise interface"); l.add(null, "5 6 metric set metric"); l.add(null, "6 . cost"); l.add(null, "5 6 bandwidth set bandwidth"); l.add(null, "6 . bandwidth"); l.add(null, "5 6 affinity set affinity"); l.add(null, "6 . affinity"); l.add(null, "5 6 srlg set srlg"); l.add(null, "6 . affinity"); l.add(null, "4 5 segrout segment routing parameters"); l.add(null, "5 6 index set index"); l.add(null, "6 . index"); l.add(null, "5 6 other-index set other index"); l.add(null, "6 . index"); l.add(null, "5 . node set node flag"); l.add(null, "5 . pop request php"); l.add(null, "4 5 bier bier parameters"); l.add(null, "5 6 index set index"); l.add(null, "6 . index"); l.add(null, "5 6 subdomain set subdomain"); l.add(null, "6 . index"); l.add(null, "5 6 other-index set other index"); l.add(null, "6 . index"); l.add(null, "5 6 other-subdomain set other subdomain"); l.add(null, "6 . index"); secInfoUtl.getHelp(l, 4, "ipinfo check peers"); l.add(null, "4 5 dynamic-metric dynamic peer metric"); l.add(null, "5 6 mode dynamic peer metric"); l.add(null, "6 . disabled forbid echo requests"); l.add(null, "6 . icmpecho icmp echo requests"); l.add(null, "6 . udpecho udp echo requests"); l.add(null, "6 . twamp twamp echo requests"); tabAverage.getHelp(l); } /** * close all neighbors */ protected void closeNeighbors() { for (int i = neighs.size(); i >= 0; i--) { rtrIsisNeigh ntry = neighs.get(i); if (ntry == null) { continue; } ntry.stopNow(); } lower.genLsps(3); } /** * setup timer thread * * @param shutdown set true to shut down */ public void restartTimer(boolean shutdown) { try { keepTimer.cancel(); } catch (Exception e) { } keepTimer = null; if (shutdown) { return; } keepTimer = new Timer(); rtrIsisIfaceHello task = new rtrIsisIfaceHello(this); keepTimer.schedule(task, 500, helloTimer); } /** * check if i've to peer with * * @param lev level to check * @param peer pere to check * @return true if yes, false if not */ protected boolean shouldIanswer(int lev, addrIsis peer) { if (netPnt2pnt) { return true; } if (amIdis(lev)) { return true; } return peer.compareTo(getDisAddr(lev)) == 0; } private rtrIsisNeigh findDIS(int lev) { if (netPnt2pnt) { return null; } int pri = disPriority; addrMac adr = hwaddr; rtrIsisNeigh dis = null; for (int i = 0; i < neighs.size(); i++) { rtrIsisNeigh ntry = neighs.get(i); if (ntry == null) { continue; } if (ntry.level.level != lev) { continue; } if (ntry.peerDisA.compareTo(ntry.rtrID) != 0) { continue; } if (ntry.rtrPri < pri) { continue; } if (ntry.rtrPri == pri) { if (adr.compareTo(ntry.ethAddr) > 0) { continue; } } dis = ntry; pri = ntry.rtrPri; adr = ntry.ethAddr; } return dis; } /** * elect dis for this interface * * @param lev level * @param adr dis address * @param cir dis circuit id * @return elected circuit id */ protected int electDIS(int lev, addrIsis adr, int cir) { addrIsis old = adr.copyBytes(); rtrIsisNeigh nei = findDIS(lev); int circ; if (nei == null) { adr.fromBuf(lower.routerID.getBytes(), 0); circ = circuitID; } else { adr.fromBuf(nei.peerDisA.getBytes(), 0); circ = nei.peerDisI; } if ((adr.compareTo(old) == 0) && (cir == circ)) { return circ; } if (debugger.rtrIsisEvnt) { logger.debug("l" + lev + " dis change, dis=" + adr); } lower.genLsps(3); return circ; } /** * get authentication data * * @param pck packet * @param typ message type * @param ofs offset of tlv * @return bytes in header */ protected byte[] getAuthData(packHolder pck, int typ, int ofs) { ofs += 3; switch (authenMode) { case 1: if (authentication == null) { return null; } byte[] buf = (" " + authentication).getBytes(); buf[0] = 1; return buf; case 2: if (authentication == null) { return null; } cryHashHmac h = new cryHashHmac(new cryHashMd5(), authentication.getBytes()); h.init(); int hshSiz = h.getHashSize(); h.update(rtrIsis.protDist); h.update(rtrIsisNeigh.msgTyp2headSiz(typ)); h.update(1); h.update(0); h.update(typ); h.update(1); h.update(0); h.update(lower.getMaxAreaAddr()); pck = pck.copyBytes(true, true); pck.merge2beg(); pck.hashData(h, 0, ofs); h.update(new byte[hshSiz]); if ((ofs + hshSiz) < pck.dataSize()) { pck.hashData(h, ofs + hshSiz, pck.dataSize() - ofs - hshSiz); } return bits.byteConcat(new byte[]{54}, h.finish()); default: return null; } } /** * check if i'm dis on the net * * @param lev level to check * @return true means yes, false means no */ protected boolean amIdis(int lev) { if (netPnt2pnt) { return false; } addrIsis adr = getDisAddr(lev); return lower.routerID.compareTo(adr) == 0; } /** * get dis address * * @param lev level to get * @return address */ protected addrIsis getDisAddr(int lev) { if (lev == 1) { return lev1disA; } else { return lev2disA; } } /** * get dis circuit * * @param lev level to get * @return address */ protected int getDisCirc(int lev) { if (lev == 1) { return lev1disI; } else { return lev2disI; } } /** * register to ethernet */ public void register2eth() { try { hwaddr = (addrMac) ethtyp.getHwAddr().copyBytes(); } catch (Exception e) { } if (rawEncap) { ethtyp.addET(rtrIsis.ethTyp, "isis", this); ethtyp.updateET(rtrIsis.ethTyp, this); } else { ethtyp.addLLC(rtrIsis.llcTyp, "isis", this); ethtyp.updateLLC(rtrIsis.llcTyp, this); } } /** * unregister from ethernet */ public void unregister2eth() { ethtyp.delLLC(rtrIsis.llcTyp); ethtyp.delET(rtrIsis.ethTyp); } /** * get counter * * @return counter */ public counter getCounter() { return cntr; } /** * set parent * * @param parent parent */ public void setParent(ifcDn parent) { upper = parent; } /** * set state * * @param stat state */ public void setState(state.states stat) { if (stat == state.states.up) { return; } closeNeighbors(); } /** * close interface */ public void closeUp() { } /** * received packet * * @param pck packet */ public void recvPack(packHolder pck) { cntr.rx(pck); if (passiveInt) { cntr.drop(pck, counter.reasons.notUp); return; } int i; if (rawEncap) { i = rtrIsis.ethTyp; } else { i = rtrIsis.llcTyp; } if (i != pck.msbGetW(0)) { // ethtype logger.info("got bad ethertype from " + pck.ETHsrc); cntr.drop(pck, counter.reasons.badEthTyp); return; } pck.getSkip(2); i = pck.getByte(0); // protocol discriminator if (i == 0x82) { // esis hello return; } if (i != rtrIsis.protDist) { logger.info("got bad protocol from " + pck.ETHsrc); iface.cntr.drop(pck, counter.reasons.badID); return; } int typ = pck.getByte(4) & 0x1f; // type i = pck.getByte(1); // length if (pck.dataSize() < i) { logger.info("got too small from " + pck.ETHsrc); iface.cntr.drop(pck, counter.reasons.tooSmall); return; } if (i != rtrIsisNeigh.msgTyp2headSiz(typ)) { logger.info("got bad header length from " + pck.ETHsrc); iface.cntr.drop(pck, counter.reasons.badSiz); return; } i = pck.getByte(2); // version if (i != 1) { logger.info("got bad version from " + pck.ETHsrc); iface.cntr.drop(pck, counter.reasons.badVer); return; } i = pck.getByte(3); // system id length if ((i != 0) && (i != addrIsis.size)) { logger.info("got bad sysid length from " + pck.ETHsrc); iface.cntr.drop(pck, counter.reasons.badVer); return; } i = pck.getByte(5); // version if (i != 1) { logger.info("got bad version from " + pck.ETHsrc); iface.cntr.drop(pck, counter.reasons.badVer); return; } // i = pck.getByte(6); // reserved // i = pck.getByte(7); // max areas pck.getSkip(8); int lev = rtrIsisNeigh.msgTyp2level(typ); if (lev == 3) { lev = pck.getByte(0); // circuit type } boolean needRetrans; switch (lev & circuitLevel) { case 1: needRetrans = recvPack(pck, typ, lower.level1); break; case 2: needRetrans = recvPack(pck, typ, lower.level2); break; case 3: needRetrans = recvPack(pck.copyBytes(true, true), typ, lower.level1); needRetrans |= recvPack(pck.copyBytes(true, true), typ, lower.level2); break; default: needRetrans = false; cntr.drop(pck, counter.reasons.badTyp); break; } if (needRetrans) { doRetrans(); } } private boolean recvPack(packHolder pck, int typ, rtrIsisLevel lev) { rtrIsisNeigh nei; if (netPnt2pnt) { nei = new rtrIsisNeigh(lower, lev, this, new addrMac()); } else { nei = new rtrIsisNeigh(lower, lev, this, pck.ETHsrc); } rtrIsisNeigh old = neighs.add(nei); if (old != null) { nei = old; } else { nei.startNow(); } int oldSt = nei.peerAdjState; nei.recvPack(pck, typ); return oldSt != nei.peerAdjState; } private void sendPack(packHolder pck, int typ) { if (debugger.rtrIsisTraf) { logger.debug("sending " + rtrIsisNeigh.msgTyp2string(typ) + " on " + upper); } pck.merge2beg(); switch (rtrIsisNeigh.msgTyp2level(typ)) { case 1: pck.ETHtrg.fromString("0180:c200:0014"); break; case 2: pck.ETHtrg.fromString("0180:c200:0015"); break; case 3: pck.ETHtrg.fromString("0900:2b00:0005"); break; } pck.ETHsrc.setAddr(hwaddr); pck.putByte(0, rtrIsis.protDist); // protocol discriminator pck.putByte(1, rtrIsisNeigh.msgTyp2headSiz(typ)); // header length pck.putByte(2, 1); // version pck.putByte(3, 0); // system id length pck.putByte(4, typ); // pdu type pck.putByte(5, 1); // version pck.putByte(6, 0); // reserved pck.putByte(7, lower.getMaxAreaAddr()); // max areas pck.putSkip(8); pck.merge2beg(); if (rawEncap) { pck.msbPutW(0, rtrIsis.ethTyp); } else { pck.msbPutW(0, rtrIsis.llcTyp); } pck.putSkip(2); pck.merge2beg(); upper.sendPack(pck); } /** * send psnp packet * * @param l list of lsps * @param lev level */ protected void sendPsnpPack(tabGen l, rtrIsisLevel lev) { packHolder pck = new packHolder(true, true); writeLspList(pck, l); pck.merge2beg(); pck.msbPutW(0, getAuthLen(lev) + pck.dataSize() + rtrIsisNeigh.msgTyp2headSiz(rtrIsisNeigh.msgTypL1psnp)); // pdu length pck.putAddr(2, lower.routerID); // source id pck.putByte(8, 0); // circuit id pck.putSkip(9); int typ; if (lev.level == 1) { typ = rtrIsisNeigh.msgTypL1psnp; } else { typ = rtrIsisNeigh.msgTypL2psnp; } writeAuthen(pck, lev, typ); sendPack(pck, typ); } /** * send csnp packet * * @param a first * @param b last * @param l list of lsps * @param lev level */ protected void sendCsnpPack(rtrIsisLsp a, rtrIsisLsp b, tabGen l, rtrIsisLevel lev) { packHolder pck = new packHolder(true, true); writeLspList(pck, l); pck.merge2beg(); pck.msbPutW(0, getAuthLen(lev) + pck.dataSize() + rtrIsisNeigh.msgTyp2headSiz(rtrIsisNeigh.msgTypL1csnp)); // pdu length pck.putAddr(2, lower.routerID); // source id pck.putByte(8, 0); // circuit id a.writeId(pck, 9); // start lsp id b.writeId(pck, 17); // stop lsp id pck.putSkip(25); int typ; if (lev.level == 1) { typ = rtrIsisNeigh.msgTypL1csnp; } else { typ = rtrIsisNeigh.msgTypL2csnp; } writeAuthen(pck, lev, typ); sendPack(pck, typ); } private int getAuthLen(rtrIsisLevel lev) { byte[] buf = lev.getAuthen(new packHolder(true, true), 0, 0); if (buf == null) { return 0; } return buf.length + 2; } private void writeAuthen(packHolder pck, rtrIsisLevel lev, int typ) { byte[] buf = lev.getAuthen(new packHolder(true, true), 0, 0); if (buf == null) { return; } encTlv tlv = rtrIsis.getTlv(); int siz = pck.headSize(); tlv.putBytes(pck, rtrIsisLsp.tlvAuthen, buf); buf = lev.getAuthen(pck, typ, siz); int len = pck.headSize() - siz; pck.putSkip(-len); tlv.putBytes(pck, rtrIsisLsp.tlvAuthen, buf); } private void writeLspList(packHolder pck, tabGen l) { packHolder p = new packHolder(true, true); encTlv tlv = rtrIsis.getTlv(); for (int i = 0; i < l.size(); i++) { rtrIsisLsp lsp = l.get(i); if (debugger.rtrIsisTraf) { logger.debug("lsp " + lsp); } p.putSkip(lsp.writeSeq(p, 0)); if (p.headSize() < 224) { continue; } p.merge2beg(); tlv.putBytes(pck, rtrIsisLsp.tlvLspEntries, p.getCopy()); p.clear(); } if (p.headSize() < 1) { return; } p.merge2beg(); tlv.putBytes(pck, rtrIsisLsp.tlvLspEntries, p.getCopy()); } /** * send lsp packet * * @param lsp lsp to send * @param lev level */ protected void sendLspPack(rtrIsisLsp lsp, rtrIsisLevel lev) { packHolder pck = new packHolder(true, true); pck.putSkip(lsp.writeData(pck, 0)); pck.merge2beg(); if (lev.level == 1) { sendPack(pck, rtrIsisNeigh.msgTypL1lsp); } else { sendPack(pck, rtrIsisNeigh.msgTypL2lsp); } } /** * send csnp packet * * @param lsp lsp to send * @param lev level */ protected void sendCsnpPack(rtrIsisLsp lsp, rtrIsisLevel lev) { tabGen l = new tabGen(); l.add(lsp); sendCsnpPack(lsp, lsp, l, lev); } /** * send psnp packet * * @param lsp lsp to send * @param lev level */ protected void sendPsnpPack(rtrIsisLsp lsp, rtrIsisLevel lev) { tabGen l = new tabGen(); l.add(lsp); sendPsnpPack(l, lev); } /** * send point2point hello */ protected void sendHelloP2p() { packHolder pck = new packHolder(true, true); pck.putByte(0, circuitLevel); // circuit type pck.putAddr(1, lower.routerID); // system id pck.msbPutW(7, deadTimer / 1000); pck.msbPutW(9, 0); // pdu length pck.putByte(11, circuitID); // local circuit id pck.putSkip(12); encTlv tlv = rtrIsis.getTlv(); int i = rtrIsisNeigh.statDown; int crc = 0; addrIsis adr = new addrIsis(); for (int o = 0; o < neighs.size(); o++) { rtrIsisNeigh ntry = neighs.get(o); if (ntry == null) { continue; } int p = ntry.getMyHandshake(); if (p > i) { continue; } i = p; adr = ntry.rtrID; crc = ntry.peerExtCirc; } tlv.valDat[0] = (byte) i; // state bits.msbPutD(tlv.valDat, 1, circuitID); // circuit id adr.toBuffer(tlv.valDat, 5); // neighbor system id bits.msbPutD(tlv.valDat, 11, crc); // neighbor circuit id tlv.putBytes(pck, rtrIsisLsp.tlvHandshake, 15, tlv.valDat); writeHelloTlvs(pck, rtrIsisNeigh.msgTypP2Phello); i = pck.headSize(); pck.msbPutW(9 - i, i + 8); // pdu length sendPack(pck, rtrIsisNeigh.msgTypP2Phello); } /** * send lan hello * * @param lev level to use */ protected void sendHelloLan(int lev) { packHolder pck = new packHolder(true, true); pck.putByte(0, circuitLevel); // circuit type pck.putAddr(1, lower.routerID); // system id pck.msbPutW(7, deadTimer / 1000); pck.msbPutW(9, 0); // pdu length pck.putByte(11, disPriority & 0x7f); // priority pck.putAddr(12, getDisAddr(lev)); // dis address pck.putByte(18, getDisCirc(lev)); // dis circuit pck.putSkip(19); encTlv tlv = rtrIsis.getTlv(); int i = 0; for (int o = 0; o < neighs.size(); o++) { rtrIsisNeigh ntry = neighs.get(o); if (ntry == null) { continue; } if (ntry.level.level != lev) { continue; } ntry.ethAddr.toBuffer(tlv.valDat, i); i += addrMac.size; } tlv.putBytes(pck, rtrIsisLsp.tlvLanNeigh, i, tlv.valDat); writeHelloTlvs(pck, rtrIsisNeigh.msgTypL1hello); i = pck.headSize(); pck.msbPutW(9 - i, i + 8); // pdu length if (lev == 1) { sendPack(pck, rtrIsisNeigh.msgTypL1hello); } else { sendPack(pck, rtrIsisNeigh.msgTypL2hello); } } private void writeHelloTlvs(packHolder pck, int typ) { encTlv tlv = rtrIsis.getTlv(); tlv.putBytes(pck, rtrIsisLsp.tlvProtSupp, lower.getNLPIDlst(otherEna)); if (lower.multiTopo) { tlv.putBytes(pck, rtrIsisLsp.tlvMultiTopo, lower.getMTopoLst(otherEna, 0)); } tlv.putBytes(pck, rtrIsisLsp.tlvAreaAddr, lower.areaID.getAddrDat(true)); lower.putAddrIface(false, iface.addr).putThis(pck); if (otherEna) { lower.putAddrIface(true, oface.addr).putThis(pck); } byte[] buf = getAuthData(pck, typ, 0); if (buf == null) { return; } int ofs = pck.headSize(); tlv.putBytes(pck, rtrIsisLsp.tlvAuthen, buf); int i = pck.headSize(); pck.msbPutW(9 - i, i + 8); // pdu length buf = getAuthData(pck, typ, ofs); pck.putSkip(ofs - i); tlv.putBytes(pck, rtrIsisLsp.tlvAuthen, buf); } private int sendLevCsnp(rtrIsisLevel lev, int frstSeq) { if (!sendCsnp && !amIdis(lev.level)) { return frstSeq; } if (frstSeq >= lev.lsps.size()) { frstSeq = 0; } int lastSeq = 1 + frstSeq + (lev.maxLspSize / 24); tabGen l = new tabGen(); for (int i = frstSeq; i <= lastSeq; i++) { rtrIsisLsp ntry = lev.lsps.get(i); if (ntry == null) { continue; } l.add(ntry); } rtrIsisLsp frstID = new rtrIsisLsp(); rtrIsisLsp lastID = new rtrIsisLsp(); if (frstSeq == 0) { frstID.setIDvalue(true); } else { frstID = l.get(0); } if (lastSeq >= lev.lsps.size()) { lastID.setIDvalue(false); } else { lastID = l.get(l.size() - 1); } sendCsnpPack(frstID, lastID, l, lev); return lastSeq; } /** * do timer work */ protected void doRetrans() { if (passiveInt) { return; } if (netPnt2pnt) { sendHelloP2p(); if ((circuitLevel & 1) != 0) { lev1csnp = sendLevCsnp(lower.level1, lev1csnp); } if ((circuitLevel & 2) != 0) { lev2csnp = sendLevCsnp(lower.level2, lev2csnp); } return; } if ((circuitLevel & 1) != 0) { lev1disI = electDIS(1, lev1disA, lev1disI); sendHelloLan(1); lev1csnp = sendLevCsnp(lower.level1, lev1csnp); } if ((circuitLevel & 2) != 0) { lev2disI = electDIS(2, lev2disA, lev2disI); sendHelloLan(2); lev2csnp = sendLevCsnp(lower.level2, lev2csnp); } } } class rtrIsisIfaceHello extends TimerTask { private final rtrIsisIface lower; public rtrIsisIfaceHello(rtrIsisIface parent) { lower = parent; } public void run() { try { lower.doRetrans(); } catch (Exception e) { logger.traceback(e); } } }