package org.freertr.ifc; import org.freertr.addr.addrMac; import org.freertr.cfg.cfgAll; import org.freertr.cfg.cfgIfc; import org.freertr.pack.packHolder; import org.freertr.pack.packPppOE; import org.freertr.tab.tabGen; import org.freertr.user.userFormat; import org.freertr.util.bits; 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; /** * ppp over ethernet (rfc2516) protocol server handler * * @author matecsaba */ public class ifcP2pOEserv implements ifcUp { /** * create instance */ public ifcP2pOEserv() { } /** * counter of this interface */ public counter cntr = new counter(); /** * server that sends our packets */ public ifcDn lower = new ifcNull(); /** * configured service name */ public String serviceNam = "pppoe"; /** * configured service delay */ public int serviceDly = 0; /** * interface to clone */ public cfgIfc clnIfc; /** * interface to attached */ public cfgIfc pktIfc; /** * list of clients */ public tabGen clnts = new tabGen(); /** * hardware address */ public addrMac hwaddr; public String toString() { String a = ""; if (!serviceNam.equals("pppoe")) { a += " name " + serviceNam; } if (serviceDly > 0) { a += " delay " + serviceDly; } return clnIfc.name + a; } /** * get show * * @param l list to append */ public void getShow(userFormat l) { for (int i = 0; i < clnts.size(); i++) { ifcP2pOEservSess ntry = clnts.get(i); if (ntry == null) { continue; } l.add(ntry.mac + "|" + ntry.sessid + "|" + ntry.ifc.name); } } /** * do clear * * @param peer peer ip */ public void doClear(addrMac peer) { ifcP2pOEservSess ntry = new ifcP2pOEservSess(this, peer); ntry = clnts.find(ntry); if (ntry == null) { return; } ntry.closeDn(); } public counter getCounter() { return cntr; } public void setState(state.states stat) { } public void closeUp() { } public void setParent(ifcDn parent) { lower = parent; hwaddr = (addrMac) lower.getHwAddr(); } private ifcP2pOEservSess findSessId(int id) { for (int i = 0; i < clnts.size(); i++) { ifcP2pOEservSess ntry = clnts.get(i); if (ntry == null) { continue; } if (ntry.sessid == id) { return ntry; } } return null; } /** * remove client from list * * @param ntry original entry */ public void delClient(ifcP2pOEservSess ntry) { clnts.del(ntry); } public void recvPack(packHolder pck) { packPppOE poe = new packPppOE(); if (poe.parseHeader(pck)) { cntr.drop(pck, counter.reasons.badHdr); return; } ifcP2pOEservSess ntry = new ifcP2pOEservSess(this, pck.ETHsrc); if (poe.cod == packPppOE.codeData) { ntry = clnts.find(ntry); if (ntry == null) { cntr.drop(pck, counter.reasons.badAddr); return; } if (ntry.sessid != poe.ses) { cntr.drop(pck, counter.reasons.badVal); return; } ntry.send2upper(pck); return; } if (debugger.ifcP2pOEserv) { logger.debug("rx " + packPppOE.code2string(poe.cod) + " sess=" + poe.ses); } encTlv tlv = new encTlv(packPppOE.tlv); byte[] host = null; for (;;) { if (tlv.getBytes(pck)) { break; } if (tlv.valTyp == packPppOE.typeEol) { break; } switch (tlv.valTyp) { case packPppOE.typeHstUnq: host = tlv.copyBytes(); break; case packPppOE.typeEol: case packPppOE.typeSrvNam: case packPppOE.typeACnam: case packPppOE.typeACcok: case packPppOE.typeRlySes: case packPppOE.typeVndSpc: case packPppOE.typeSrvNm: case packPppOE.typeSysErr: case packPppOE.typeGenErr: break; } } pck.clear(); pck.putStart(); pck.ETHsrc.setAddr(hwaddr); pck.ETHtrg.setAddr(ntry.mac); if (host != null) { tlv.putBytes(pck, packPppOE.typeHstUnq, host); } tlv.putStr(pck, packPppOE.typeACnam, cfgAll.hostName); tlv.putStr(pck, packPppOE.typeSrvNam, serviceNam); switch (poe.cod) { case packPppOE.codePadI: if (debugger.ifcP2pOEserv) { logger.debug("tx pado"); } packPppOE.updateHeader(pck, packPppOE.codePadO, 0); ifcDelay.sendPack(serviceDly, lower, pck); break; case packPppOE.codePadR: if (debugger.ifcP2pOEserv) { logger.debug("tx pads"); } ifcP2pOEservSess old = null; for (int i = 0; i < 16; i++) { ntry.sessid = bits.random(1, 0xfffe); old = findSessId(ntry.sessid); if (old == null) { break; } } if (old != null) { logger.error("failed to allocate session id"); break; } old = clnts.add(ntry); if (old != null) { ntry = old; } else { ntry.startUpper(); } packPppOE.updateHeader(pck, packPppOE.codePadS, ntry.sessid); lower.sendPack(pck); break; case packPppOE.codePadT: ntry = clnts.find(ntry); if (ntry == null) { return; } if (ntry.sessid != poe.ses) { return; } ntry.closeDn(); break; case packPppOE.codePadO: case packPppOE.codePadS: break; default: return; } } }