/*
** This file is part of Filius, a network construction and simulation software.
**
** Originally created at the University of Siegen, Institute "Didactics of
** Informatics and E-Learning" by a students' project group:
** members (2006-2007):
** André Asschoff, Johannes Bade, Carsten Dittich, Thomas Gerding,
** Nadja Haßler, Ernst Johannes Klebert, Michell Weyer
** supervisors:
** Stefan Freischlad (maintainer until 2009), Peer Stechert
** Project is maintained since 2010 by Christian Eibl <filius@c.fameibl.de>
** and Stefan Freischlad
** Filius is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 2 of the License, or
** (at your option) version 3.
**
** Filius is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied
** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
** PURPOSE. See the GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Filius. If not, see <http://www.gnu.org/licenses/>.
*/
package filius.software.dhcp;
import java.util.StringTokenizer;
import java.util.ListIterator;
import filius.Main;
import filius.exception.VerbindungsException;
import filius.gui.GUIContainer;
import filius.hardware.Verbindung;
import filius.software.clientserver.ClientAnwendung;
import filius.software.transportschicht.UDPSocket;
public class DHCPClient extends ClientAnwendung {
private int zustand;
private String dhcpserverIP = "255.255.255.255";
public static final int IP_ZUGEWIESEN = 99;
public static final int ABBRUCH = -1, INIT_DHCP = 2, CONFIG = 3;
public void starten() {
Main.debug.println("INVOKED ("+this.hashCode()+", T"+this.getId()+") "+getClass()+" (DHCPClient), starten()");
super.starten();
ausfuehren("konfiguriere", null);
}
public void konfiguriere() {
Main.debug.println("INVOKED ("+this.hashCode()+", T"+this.getId()+") "+getClass()+" (DHCPClient), konfiguriere()");
getSystemSoftware().setzeIPAdresse("0.0.0.0");
getSystemSoftware().setzeNetzmaske("0.0.0.0");
getSystemSoftware().setStandardGateway("");
ListIterator<DHCPServer> it;
boolean allDHCPserversStarted;
// es muss gewaehrleistet werden, dass der DHCP-Server bereits
// gestartet worden ist! (sofern denn einer als "aktiv" gekennzeichnet ist!)
try {
do {
it = GUIContainer.getGUIContainer().getMenu().getDHCPservers().listIterator();
allDHCPserversStarted = true;
DHCPServer server;
while (it.hasNext()) {
server = it.next();
if (!server.isStarted()) {
allDHCPserversStarted = false;
Main.debug.println("WARNING ("+this.hashCode()+"): DHCP server on '"+server.getSystemSoftware().getKnoten().getName()+"' has NOT been started --> waiting");
break;
}
else {
//Main.debug.println("DHCPClient:\tserver on '"+server.getSystemSoftware().getKnoten().getName()+"' has been started");
}
}
Thread.sleep(100);
} while (!allDHCPserversStarted);
}
catch (InterruptedException e) {
e.printStackTrace(Main.debug);
}
//Main.debug.println("DHCP-Client wurde gestartet.");
starteDatenaustausch();
}
private void starteDatenaustausch() {
Main.debug.println("INVOKED ("+this.hashCode()+", T"+this.getId()+") "+getClass()+" (DHCPClient), starteDatenaustausch()");
String antwort = "";
String angeboteneIP = "";
String typ = null;
String mac;
boolean erfolg;
long start;
int fehlerzaehler = 0;
StringTokenizer st = null;
UDPSocket socket = (UDPSocket) this.socket;
int maxFehler = 5;
zustand = INIT_DHCP;
try {
socket = new UDPSocket(getSystemSoftware(), "255.255.255.255", 67, 68);
socket.verbinden();
//Main.debug.println(getClass() + "\n\tkonfiguriere() -> zustand = "
//+ zustand);
while (zustand != IP_ZUGEWIESEN && zustand != ABBRUCH
&& fehlerzaehler < maxFehler) {
if (zustand == INIT_DHCP) {
socket.senden("DHCPDISCOVER "
+ getSystemSoftware().holeIPAdresse() + " "
+ getSystemSoftware().holeMACAdresse() + " "
+ dhcpserverIP);
start = System.currentTimeMillis();
do {
mac = null;
typ = null;
erfolg = false;
antwort = socket.empfangen(Verbindung.holeRTT());
if (antwort != null) {
st = new StringTokenizer(antwort, " ");
typ = st.nextToken().trim();
st.nextToken();
mac = st.nextToken().trim();
erfolg = mac.equalsIgnoreCase(getSystemSoftware()
.holeMACAdresse())
&& typ.equalsIgnoreCase("DHCPOFFER");
}
}
while (!erfolg && System.currentTimeMillis() - start <= Verbindung.holeRTT());
//if(!erfolg) { Main.debug.println(getClass()+"\n\tTimeOut! (>"+Verbindung.holeRTT()); }
if (erfolg && st != null) {
dhcpserverIP = st.nextToken();
angeboteneIP = st.nextToken();
//Main.debug.println(getClass()
//+ "\n\tangebotene IP-Adresse: " + angeboteneIP);
zustand = CONFIG;
//zustand = ABBRUCH;
}
else {
fehlerzaehler++;
Main.debug.println("ERROR ("+this.hashCode()+"): DHCPOFFER erwartet, erhalten: " + typ);
}
}
else if (zustand == CONFIG) {
if (socket != null) socket.schliessen();
socket = new UDPSocket(getSystemSoftware(), dhcpserverIP, 67, 68);
socket.verbinden();
socket.senden("DHCPREQUEST "
+ getSystemSoftware().holeIPAdresse() + " "
+ getSystemSoftware().holeMACAdresse() + " "
+ dhcpserverIP + " " + angeboteneIP);
start = System.currentTimeMillis();
do {
mac = null;
typ = null;
erfolg = false;
antwort = socket.empfangen(Verbindung.holeRTT());
if (antwort != null) {
//Main.debug.println("DHCPClient, received response from DHCP Server:\n\t"
//+ "'"+antwort+"'" );
st = new StringTokenizer(antwort, " ");
typ = st.nextToken();
st.nextToken();
mac = st.nextToken();
erfolg = mac.equalsIgnoreCase(getSystemSoftware().holeMACAdresse())
&& (typ.equalsIgnoreCase("DHCPACK")
|| typ.equalsIgnoreCase("DHCPNAK"));
}
}
while (!erfolg && System.currentTimeMillis() - start <= Verbindung.holeRTT());
if (erfolg && st != null) {
if (typ.equalsIgnoreCase("DHCPNAK")) {
zustand = INIT_DHCP;
}
else {
st.nextToken();
st.nextToken();
getSystemSoftware().setzeIPAdresse(angeboteneIP);
if (st.hasMoreTokens()) { // set netmask
getSystemSoftware().setzeNetzmaske(st.nextToken());
if (st.hasMoreTokens()) { // set DNS server
getSystemSoftware().setStandardGateway(st.nextToken()); // set Gateway
if (st.hasMoreTokens()) { // set DNS server
getSystemSoftware().setDNSServer(st.nextToken());
}
}
}
zustand = IP_ZUGEWIESEN;
//Main.debug.println(getClass()
//+ "\n\tkonfiguriere(): IP-Adresse = "
//+ angeboteneIP);
}
}
else {
fehlerzaehler++;
}
}
if (fehlerzaehler == maxFehler) {
zustand = ABBRUCH;
Main.debug.println("ERROR ("+this.hashCode()+"): kein DHCPACK erhalten");
// set own value 169.254.x.x; resp. delete values
int block3 = (new java.util.Random()).nextInt(253) + 1;
int block4 = (new java.util.Random()).nextInt(253) + 1;
getSystemSoftware().setzeIPAdresse("169.254."+block3+"."+block4);
getSystemSoftware().setzeNetzmaske("255.255.0.0");
getSystemSoftware().setStandardGateway(""); // set Gateway
getSystemSoftware().setDNSServer("");
///////
fehlerzaehler = 0;
}
}
socket.schliessen();
}
catch (VerbindungsException e1) {
e1.printStackTrace(Main.debug);
}
this.getSystemSoftware().benachrichtigeBeobacher(null);
beenden();
}
}