package org.freertr.serv; import java.util.List; import org.freertr.addr.addrIP; import org.freertr.cfg.cfgAceslst; import org.freertr.cfg.cfgAll; import org.freertr.cfg.cfgRtr; import org.freertr.pack.packHolder; import org.freertr.pipe.pipeLine; import org.freertr.pipe.pipeSide; import org.freertr.prt.prtGenConn; import org.freertr.prt.prtServS; import org.freertr.rtr.rtrBgpMon; import org.freertr.rtr.rtrBgpMrt; import org.freertr.rtr.rtrBgpTemp; import org.freertr.rtr.rtrBgpUtil; import org.freertr.tab.tabAceslstN; import org.freertr.tab.tabGen; import org.freertr.tab.tabListing; import org.freertr.user.userFilter; import org.freertr.user.userFormat; import org.freertr.user.userHelping; import org.freertr.util.bits; import org.freertr.util.cmds; import org.freertr.util.logFil; import org.freertr.util.logger; import org.freertr.enc.encTlv; /** * bgp monitoring (rfc7854) protocol to multi-threaded routing (rfc6396) toolkit * * @author matecsaba */ public class servBmp2mrt extends servGeneric implements prtServS { /** * create instance */ public servBmp2mrt() { } /** * port number */ public final static int port = 17971; /** * header size */ public final static int size = 6; /** * relays */ protected final tabGen relays = new tabGen(); /** * listeners */ protected final tabGen lstns = new tabGen(); private boolean bulkDown; private final tabGen stats = new tabGen(); private boolean local; private int rateInt; private int rateNum; private int listenBmp; private int listenRis; private int listenBgp; /** * as number */ protected int listenAsn; private servBmp2mrtRate rateTim; private logFil fileHandle; private tabListing, addrIP> dynAcl; private servBmp2mrtStat dynCfg; private rtrBgpTemp dynTmp; /** * defaults text */ public final static String[] defaultL = { "server bmp2mrt .*!" + cmds.tabulator + "port " + port, "server bmp2mrt .*!" + cmds.tabulator + "protocol " + proto2string(protoAllStrm), "server bmp2mrt .*!" + cmds.tabulator + cmds.negated + cmds.tabulator + "local", "server bmp2mrt .*!" + cmds.tabulator + cmds.negated + cmds.tabulator + "bulk-down", "server bmp2mrt .*!" + cmds.tabulator + "rate-down 0 0", "server bmp2mrt .*!" + cmds.tabulator + "max-time 0", "server bmp2mrt .*!" + cmds.tabulator + "max-pack 0", "server bmp2mrt .*!" + cmds.tabulator + "max-byte 0", "server bmp2mrt .*!" + cmds.tabulator + cmds.negated + cmds.tabulator + "listen-bmp", "server bmp2mrt .*!" + cmds.tabulator + cmds.negated + cmds.tabulator + "listen-bgp", "server bmp2mrt .*!" + cmds.tabulator + cmds.negated + cmds.tabulator + "listen-ris", "server bmp2mrt .*!" + cmds.tabulator + cmds.negated + cmds.tabulator + "file", "server bmp2mrt .*!" + cmds.tabulator + cmds.negated + cmds.tabulator + "backup", "server bmp2mrt .*!" + cmds.tabulator + cmds.negated + cmds.tabulator + "dyneigh" }; /** * defaults filter */ public static tabGen defaultF; public tabGen srvDefFlt() { return defaultF; } public void srvShRun(String beg, List l, int filter) { cmds.cfgLine(l, !local, beg, "local", ""); if (fileHandle == null) { l.add(beg + "no file"); } else { l.add(beg + "file " + fileHandle.name()); cmds.cfgLine(l, fileHandle.rotateN() == null, beg, "backup", fileHandle.rotateN()); l.add(beg + "max-time " + fileHandle.rotateT()); l.add(beg + "max-pack " + fileHandle.rotateL()); l.add(beg + "max-byte " + fileHandle.rotateS()); } cmds.cfgLine(l, listenBmp < 1, beg, "listen-bmp", "" + listenBmp); cmds.cfgLine(l, listenRis < 1, beg, "listen-ris", "" + listenRis); cmds.cfgLine(l, listenBgp < 1, beg, "listen-bgp", "" + listenBgp + " " + listenAsn); cmds.cfgLine(l, !bulkDown, beg, "bulk-down", ""); l.add(beg + "rate-down " + rateInt + " " + rateNum); if (dynCfg != null) { l.add(beg + "dyneigh " + dynAcl.listName + " " + dynCfg.getCfg(false) + " " + dynTmp.tempName); } else { l.add(beg + "no dyneigh"); } for (int i = 0; i < stats.size(); i++) { servBmp2mrtStat stat = stats.get(i); if (stat == null) { continue; } if (stat.nei == null) { continue; } if (stat.dyn) { continue; } l.add(beg + "neighbor " + stat.from + " " + stat.peer + " " + stat.getCfg(true)); } for (int i = 0; i < relays.size(); i++) { servBmp2mrtRelay rly = relays.get(i); if (rly == null) { continue; } l.add(beg + "relay " + rly); } } public boolean srvCfgStr(cmds cmd) { String s = cmd.word(); if (s.equals("relay")) { servBmp2mrtRelay rly = new servBmp2mrtRelay(); if (rly.fromString(cmd)) { return false; } if (relays.add(rly) != null) { cmd.error("already exists"); return false; } rly.startWork(); return false; } if (s.equals("rate-down")) { rateInt = bits.str2num(cmd.word()); rateNum = bits.str2num(cmd.word()); try { rateTim.stopWork(); } catch (Exception e) { } rateTim = null; if (rateInt < 1) { return false; } rateTim = new servBmp2mrtRate(this, rateInt); rateTim.startWork(); return false; } if (s.equals("listen-bmp")) { listenBmp = bits.str2num(cmd.word()); genStrmStart(this, new pipeLine(32768, false), listenBmp); return false; } if (s.equals("listen-ris")) { listenRis = bits.str2num(cmd.word()); genStrmStart(this, new pipeLine(32768, false), listenRis); return false; } if (s.equals("listen-bgp")) { listenBgp = bits.str2num(cmd.word()); listenAsn = bits.str2num(cmd.word()); genStrmStart(this, new pipeLine(32768, false), listenBgp); return false; } if (s.equals("bulk-down")) { bulkDown = true; return false; } if (s.equals("dyneigh")) { cfgAceslst acl = cfgAll.aclsFind(cmd.word(), false); if (acl == null) { cmd.error("no such access list"); return false; } dynCfg = new servBmp2mrtStat(); if (dynCfg.fromString(cmd, false)) { dynCfg = null; dynAcl = null; return false; } dynAcl = acl.aceslst; dynTmp = dynCfg.prc.findTemp(cmd.word()); if (dynTmp == null) { cmd.error("no such template"); dynCfg = null; dynAcl = null; return false; } return false; } if (s.equals("neighbor")) { addrIP a1 = new addrIP(); addrIP a2 = new addrIP(); a1.fromString(cmd.word()); a2.fromString(cmd.word()); servBmp2mrtStat stat = getStat(a1, a2, 2, 0); stat.fromString(cmd, true); return false; } if (s.equals("local")) { local = true; return false; } if (s.equals("max-time")) { if (fileHandle == null) { return false; } fileHandle.rotate(fileHandle.rotateN(), fileHandle.rotateS(), bits.str2num(cmd.word()), fileHandle.rotateL()); return false; } if (s.equals("max-pack")) { if (fileHandle == null) { return false; } fileHandle.rotate(fileHandle.rotateN(), fileHandle.rotateS(), fileHandle.rotateT(), bits.str2num(cmd.word())); return false; } if (s.equals("max-byte")) { if (fileHandle == null) { return false; } fileHandle.rotate(fileHandle.rotateN(), bits.str2num(cmd.word()), fileHandle.rotateT(), fileHandle.rotateL()); return false; } if (s.equals("backup")) { fileHandle.rotate(cmd.getRemaining(), fileHandle.rotateS(), fileHandle.rotateT(), fileHandle.rotateL()); return false; } if (s.equals("file")) { try { fileHandle.close(); } catch (Exception e) { } fileHandle = new logFil(cmd.getRemaining()); fileHandle.open(false); return false; } if (!s.equals(cmds.negated)) { return true; } s = cmd.word(); if (s.equals("relay")) { servBmp2mrtRelay rly = new servBmp2mrtRelay(); if (rly.fromString(cmd)) { return false; } rly = relays.del(rly); if (rly == null) { cmd.error("no such relay"); return false; } rly.stopWork(); return false; } if (s.equals("rate-down")) { rateInt = 0; rateNum = 0; try { rateTim.stopWork(); } catch (Exception e) { } rateTim = null; return false; } if (s.equals("listen-bmp")) { genericStop(listenBmp); listenBmp = 0; return false; } if (s.equals("listen-ris")) { genericStop(listenRis); listenRis = 0; return false; } if (s.equals("listen-bgp")) { genericStop(listenBgp); listenBmp = 0; listenAsn = 0; return false; } if (s.equals("bulk-down")) { bulkDown = false; return false; } if (s.equals("dyneigh")) { dynCfg = null; dynAcl = null; return false; } if (s.equals("neighbor")) { addrIP a1 = new addrIP(); addrIP a2 = new addrIP(); a1.fromString(cmd.word()); a2.fromString(cmd.word()); servBmp2mrtStat stat = getStat(a1, a2, 0, 0); if (stat == null) { cmd.error("no such peer"); return false; } stat.rouT = null; stat.rouI = 0; stat.rouD = false; stat.nei = null; return false; } if (s.equals("local")) { local = false; return false; } if (s.equals("max-time")) { if (fileHandle == null) { return false; } fileHandle.rotate(fileHandle.rotateN(), fileHandle.rotateS(), 0, fileHandle.rotateL()); return false; } if (s.equals("max-pack")) { if (fileHandle == null) { return false; } fileHandle.rotate(fileHandle.rotateN(), fileHandle.rotateS(), fileHandle.rotateT(), 0); return false; } if (s.equals("max-byte")) { if (fileHandle == null) { return false; } fileHandle.rotate(fileHandle.rotateN(), 0, fileHandle.rotateT(), fileHandle.rotateL()); return false; } if (s.equals("backup")) { fileHandle.rotate(null, 0, 0, 0); return false; } if (s.equals("file")) { try { fileHandle.close(); } catch (Exception e) { } fileHandle = null; return false; } return true; } public void srvHelp(userHelping l) { l.add(null, "1 . bulk-down down peers on speaker loss"); l.add(null, "1 2 rate-down down peers on inactivity"); l.add(null, "2 3 ms between checks"); l.add(null, "3 . packets between checks"); l.add(null, "1 2 file log to file"); l.add(null, "2 2,. name of file"); l.add(null, "1 . local log to syslog"); l.add(null, "1 2 listen-bmp bmp listen port"); l.add(null, "2 . port number"); l.add(null, "1 2 listen-bgp bgp listen port"); l.add(null, "2 3 port number"); l.add(null, "3 . as number"); l.add(null, "1 2 listen-ris ris listen port"); l.add(null, "2 . port number"); l.add(null, "1 2 max-time maximum time"); l.add(null, "2 . ms between backups"); l.add(null, "1 2 max-byte maximum bytes"); l.add(null, "2 . bytes between backups"); l.add(null, "1 2 max-pack maximum packets"); l.add(null, "2 . packets between backups"); l.add(null, "1 2 backup backup to file"); l.add(null, "2 2,. name of file"); l.add(null, "1 2 relay relay messages to bmp"); l.add(null, "2 3 proxy profile name"); l.add(null, "3 4 peer address"); l.add(null, "4 5,. peer port"); l.add(null, "5 . access list name"); l.add(null, "1 2 dyneigh parse messages from dynamic neighbors"); l.add(null, "2 3 access list on peer name"); l.add(null, "3 4 rx process received packets"); l.add(null, "3 4 tx process transmitted packets"); cfgRtr.getRouterList(l, 2, " to populate"); l.add(null, "5 6 process number"); l.add(null, "6 . template name"); l.add(null, "1 2 neighbor parse messages from neighbor"); l.add(null, "2 3 info source"); l.add(null, "3 4 reported address"); l.add(null, "4 5 rx process received packets"); l.add(null, "4 5 tx process transmitted packets"); cfgRtr.getRouterList(l, 3, " to populate"); l.add(null, "6 7 process number"); l.add(null, "7 . peer address"); } public String srvName() { return "bmp2mrt"; } public int srvPort() { return port; } public int srvProto() { return protoAllStrm; } public boolean srvInit() { genStrmStart(this, new pipeLine(32768, false), listenBmp); genStrmStart(this, new pipeLine(32768, false), listenRis); genStrmStart(this, new pipeLine(32768, false), listenBgp); genStrmStart(this, new pipeLine(32768, false), 0); return false; } public boolean srvDeinit() { genericStop(listenBmp); genericStop(listenRis); genericStop(listenBgp); genericStop(0); return false; } public boolean srvAccept(pipeSide pipe, prtGenConn id) { pipe.setTime(120000); if (id.portLoc == listenBmp) { new servBmp2mrtBmp(pipe, this, id); return false; } if (id.portLoc == listenBgp) { new servBmp2mrtBgp(pipe, this, id); return false; } if (id.portLoc == listenRis) { new servBmp2mrtRis(pipe, this, id); return false; } new servBmp2mrtConn(pipe, this, id); return false; } private servBmp2mrtStat getStat(addrIP from, addrIP peer, int crt, int as) { servBmp2mrtStat res = new servBmp2mrtStat(); res.from = from.copyBytes(); res.peer = peer.copyBytes(); res.asn = as; if (crt == 0) { return stats.find(res); } servBmp2mrtStat old = stats.add(res); if (old != null) { res = old; if (as != 0) { res.asn = as; } } else { res.state = crt == 1; } if (dynCfg == null) { return res; } if (res.nei != null) { return res; } packHolder pck = new packHolder(true, true); pck.IPsrc.setAddr(from); pck.IPtrg.setAddr(peer); pck.UDPtrg = as; if (!dynAcl.matches(false, false, pck)) { return res; } res.dyn = true; res.rouD = dynCfg.rouD; res.rouI = dynCfg.rouI; res.rouT = dynCfg.rouT; res.nei = dynCfg.prc.addListenPeer(peer, from, dynTmp); return res; } /** * got state * * @param as as number * @param src source of packet * @param spk got from speaker * @param st state */ public void gotState(int as, addrIP src, addrIP spk, boolean st) { servBmp2mrtStat stat = getStat(spk, src, 1, as); stat.state = st; stat.since = bits.getTime(); stat.change++; } /** * got bulk state * * @param spk got from speaker * @param st state */ public void gotState(addrIP spk, boolean st) { if (!bulkDown) { return; } long tim = bits.getTime(); for (int i = 0; i < stats.size(); i++) { servBmp2mrtStat stat = stats.get(i); if (stat == null) { continue; } if (spk.compareTo(stat.from) != 0) { continue; } stat.state = st; stat.since = tim; stat.change++; } } /** * got counters * * @param as as number * @param src source of packet * @param spk got from speaker * @param dat tlvs */ public void gotCounts(int as, addrIP src, addrIP spk, packHolder dat) { servBmp2mrtStat stat = getStat(spk, src, 2, as); encTlv tlv = rtrBgpMon.getTlv(); stat.repPack++; stat.repByte += dat.dataSize(); stat.repLast = bits.getTime(); for (;;) { if (tlv.getBytes(dat)) { break; } switch (tlv.valTyp) { case 0: // policy rejected stat.repPolRej = bits.msbGetD(tlv.valDat, 0); break; case 1: // duplicate advertisements stat.repDupAdv = bits.msbGetD(tlv.valDat, 0); break; case 2: // duplicate withdraws stat.repDupWit = bits.msbGetD(tlv.valDat, 0); break; case 3: // cluster list loop stat.repClstrL = bits.msbGetD(tlv.valDat, 0); break; case 4: // as path loop stat.repAsPath = bits.msbGetD(tlv.valDat, 0); break; case 5: // originator id stat.repOrgnId = bits.msbGetD(tlv.valDat, 0); break; case 6: // as confed loop stat.repAsConf = bits.msbGetD(tlv.valDat, 0); break; case 11: // withdraw threated updates stat.repWitUpd = bits.msbGetD(tlv.valDat, 0); break; case 12: // withdraw threated prefixes stat.repWitPrf = bits.msbGetD(tlv.valDat, 0); break; case 13: // duplicate updates stat.repDupUpd = bits.msbGetD(tlv.valDat, 0); break; } } } /** * got update * * @param as as number * @param src source of packet * @param spk got from speaker * @param dir direction: false=rx, true=tx * @param hlp helper packet * @param pck bgp message */ public void gotMessage(int as, addrIP src, addrIP spk, boolean dir, packHolder hlp, packHolder pck) { servBmp2mrtStat stat = getStat(spk, src, 1, as); stat.state = true; if (dir) { stat.packOut++; stat.byteOut += pck.dataSize(); } else { stat.packIn++; stat.byteIn += pck.dataSize(); } stat.packLast = bits.getTime(); stat.packRate += pck.dataSize(); if (local) { logger.info((dir ? "tx" : "rx") + " " + as + " " + src + " " + spk + " " + bits.byteDump(pck.getCopy(), 0, -1)); } if ((dir == stat.rouD) && (stat.nei != null)) { packHolder upd = pck.copyBytes(true, true); upd.merge2beg(); int typ = upd.getByte(rtrBgpUtil.sizeU - 1); upd.getSkip(rtrBgpUtil.sizeU); try { switch (typ) { case rtrBgpUtil.msgUpdate: stat.nei.conn.parseUpdate(upd, hlp); break; case rtrBgpUtil.msgOpen: stat.nei.conn.parseOpen(upd); break; } } catch (Exception e) { logger.traceback(e); } } if (fileHandle == null) { return; } byte[] hdr = new byte[128]; int len = rtrBgpMrt.putMrtHeader(hdr, bits.getTime(), dir, as, 0, src, spk, pck.dataSize()); fileHandle.add(hdr, 0, len, pck.getCopy(), 0, pck.dataSize()); } /** * do rate calculation */ public void doRates() { for (int i = 0; i < stats.size(); i++) { servBmp2mrtStat ntry = stats.get(i); ntry.state = ntry.packRate > rateNum; ntry.packRate = 0; } } /** * do clear */ public void doClear() { for (int i = 0; i < stats.size(); i++) { stats.get(i).change = 1; } } /** * get show * * @return result */ public userFormat getShow() { userFormat res = new userFormat("|", "from|peer|asnum|asname|state|change|ago|last"); for (int i = 0; i < stats.size(); i++) { res.add("" + stats.get(i)); } return res; } /** * get show * * @param frm from * @return result */ public userFormat getShow(addrIP frm) { servBmp2mrtStat res = new servBmp2mrtStat(); res.from = frm.copyBytes(); for (int i = 0; i < stats.size(); i++) { servBmp2mrtStat cur = stats.get(i); if (frm.compareTo(cur.from) != 0) { continue; } res.addCnts(cur); } return res.getShow(); } /** * get show * * @param frm from * @param per peer * @return result */ public userFormat getShow(addrIP frm, addrIP per) { servBmp2mrtStat stat = getStat(frm, per, 0, 0); if (stat == null) { return null; } return stat.getShow(); } }