public bool Data(IPAddress client, int Port, byte[] data) { if (RunningSessions.ContainsKey(client) == false) { SessionData nses = new SessionData(); nses.Architecture = DHCPArchitecture.Undefined; nses.IP = client; nses.TFTPRootPath = Settings.TFTPRootPath + "Unknown\\"; lock (RunningSessions) RunningSessions.Add(client, nses); } SessionData ses = RunningSessions[client]; if (data.Length < 2) { TFTPPacketError err = new TFTPPacketError(TFTPErrorCode.IllegalTFTPOP, "Illegal TFTP OP"); ses.SendData(Port, client, err.GetBytes); return(false); } TFTPOpcode opcode = (TFTPOpcode)(((int)data[0] * 0x100) + ((int)data[1] * 0x1)); switch (opcode) { case TFTPOpcode.Read: { TFTPPacketReadReq rr = new TFTPPacketReadReq(data); if (rr.Malformed == true) { TFTPPacketError err = new TFTPPacketError(TFTPErrorCode.IllegalTFTPOP, "Malformed packet"); ses.SendData(Port, client, err.GetBytes); return(false); } if (string.IsNullOrWhiteSpace(rr.Filename) == true) { rr.Filename = ses.currentfilename; } if (string.IsNullOrWhiteSpace(rr.Filename) == true) { TFTPPacketError err = new TFTPPacketError(TFTPErrorCode.IllegalTFTPOP, "Malformed packet"); ses.SendData(Port, client, err.GetBytes); return(false); } ses.LastUpdated = DateTime.Now; if (ses.currentfile != null) { ses.currentfile.Close(); } ses.currentfile = null; ses.datatosend = null; ses.OpenACK = false; ses.currentfilename = rr.Filename; Console.WriteLine(client.ToString() + "(" + ses.Architecture.ToString() + ") requesting file: " + rr.Filename); rr.Filename = rr.Filename.Replace("/", "\\"); if (rr.Filename.StartsWith("\\") == true) { rr.Filename = rr.Filename.Substring(1, rr.Filename.Length - 1); } if (rr.Filename.EndsWith("\\") == true) { TFTPPacketError err = new TFTPPacketError(TFTPErrorCode.FileNotFound, "Invalid path"); ses.SendData(Port, client, err.GetBytes); return(false); } if (File.Exists(ses.TFTPRootPath + rr.Filename) == false) { TFTPPacketError err = new TFTPPacketError(TFTPErrorCode.FileNotFound, "File does not exist"); ses.SendData(Port, client, err.GetBytes); return(false); } ses.currentfile = File.Open(ses.TFTPRootPath + rr.Filename, FileMode.Open, FileAccess.Read, FileShare.Read); ses.blksize = rr.blksize == null ? 512 : rr.blksize.Value; if (ses.blksize > 1468) { ses.blksize = 1468; } ses.Sequence = null; ses.CurrentPos = 0; FileInfo info = new FileInfo(ses.TFTPRootPath + rr.Filename); ses.TotalSize = info.Length; ses.windowsize = rr.windowsize == null ? 1 : rr.windowsize.Value; List <string> Options = new List <string>(); if (rr.blksize != null) { Options.Add("blksize"); Options.Add(ses.blksize.ToString()); } if (rr.tsize != null) { Options.Add("tsize"); Options.Add(info.Length.ToString()); } if (rr.windowsize != null) { Options.Add("windowsize"); Options.Add(ses.windowsize.ToString()); } TFTPPacketOptAck oack = new TFTPPacketOptAck(Options); ses.OpenACK = true; ses.SendData(Port, client, oack.GetBytes); Console.WriteLine(client.ToString() + "(" + ses.Architecture.ToString() + ") got file: " + ses.TFTPRootPath + rr.Filename); break; } case TFTPOpcode.Write: { TFTPPacketError err = new TFTPPacketError(TFTPErrorCode.AccessViolation, "Writing not supported"); ses.SendData(Port, client, err.GetBytes); break; } case TFTPOpcode.Error: { ses.LastUpdated = DateTime.Now; if (ses.currentfile != null) { ses.currentfile.Close(); } ses.currentfile = null; ses.datatosend = null; ses.OpenACK = false; Console.WriteLine(client.ToString() + "(" + ses.Architecture.ToString() + ") got error from client"); break; } case TFTPOpcode.Ack: { TFTPPacketClientAck ack = new TFTPPacketClientAck(data); if (ack.Malformed == true) { TFTPPacketError err = new TFTPPacketError(TFTPErrorCode.IllegalTFTPOP, "Malformed packet"); ses.SendData(69, client, err.GetBytes); return(false); } ses.LastUpdated = DateTime.Now; if (ses.Sequence == null) { ses.Sequence = ack.Ack; } if (ack.Ack < ses.Sequence) { return(true); } if (ack.Ack != ses.Sequence) { TFTPPacketError err = new TFTPPacketError(TFTPErrorCode.IllegalTFTPOP, "Invalid sequence"); ses.SendData(Port, client, err.GetBytes); ses.LastSend = DateTime.Now; return(false); } ses.datatosend = new List <byte[]>(); long Read = ses.blksize; for (int i = 0; i < ses.windowsize; i++) { ses.LastSend = DateTime.Now; if (ses.CurrentPos + Read > ses.TotalSize) { Read = ses.TotalSize - ses.CurrentPos; } if (Read == 0) { break; } else { byte[] filedata = new byte[Read]; ses.currentfile.Read(filedata, 0, (int)Read); ses.Sequence++; TFTPData d = new TFTPData(ses.Sequence.Value, filedata); ses.OpenACK = true; ses.LastSend = DateTime.Now; ses.datatosendport = Port; ses.CurrentPos += Read; ses.datatosend.Add(d.GetBytes); } } foreach (byte[] b in ses.datatosend) { ses.SendData(Port, client, b); } if (Read == 0) { ses.OpenACK = false; ses.datatosend = null; ses.LastSend = DateTime.Now; } break; } default: { TFTPPacketError err = new TFTPPacketError(TFTPErrorCode.NotDefined, "Not defined OP " + opcode.ToString()); ses.SendData(Port, client, err.GetBytes); ses.OpenACK = false; return(false); } } return(true); }
public bool RegisterSession(IPAddress Client, DHCPArchitecture Architecture, string PathOverride) { if (Client == IPAddress.Any) { return(false); } lock (RunningSessions) { if (RunningSessions.ContainsKey(Client) == true) { if (RunningSessions[Client].currentfile != null) { RunningSessions[Client].currentfile.Close(); } RunningSessions.Remove(Client); } } SessionData ses = new SessionData(); ses.Architecture = Architecture; ses.IP = Client; ses.TFTPRootPath = Settings.TFTPRootPath; if (string.IsNullOrWhiteSpace(PathOverride) == false) { ses.TFTPRootPath += PathOverride; if (ses.TFTPRootPath.EndsWith("\\") == false) { ses.TFTPRootPath += "\\"; } if (Directory.Exists(ses.TFTPRootPath) == false) { PathOverride = ""; ses.TFTPRootPath = Settings.TFTPRootPath; } } if (string.IsNullOrWhiteSpace(PathOverride) == true) { switch (Architecture) { case DHCPArchitecture.ARC_x86: ses.TFTPRootPath += "ARC x86\\"; break; case DHCPArchitecture.DEC_ALPHA: ses.TFTPRootPath += "DEC Alpha\\"; break; case DHCPArchitecture.EFI_ByteCode: ses.TFTPRootPath += "EFI BC\\"; break; case DHCPArchitecture.EFI_EM64T: ses.TFTPRootPath += "EFI X64\\"; break; case DHCPArchitecture.EFI_IA32: ses.TFTPRootPath += "EFI X86\\"; break; case DHCPArchitecture.EFI_ITANIUM: ses.TFTPRootPath += "EFI ITANIUM\\"; break; case DHCPArchitecture.EFI_XScale: ses.TFTPRootPath += "EFI XScale\\"; break; case DHCPArchitecture.IA32Legacy: ses.TFTPRootPath += "BIOS\\"; break; case DHCPArchitecture.NEC_PC98: ses.TFTPRootPath += "NEC PC98\\"; break; default: ses.TFTPRootPath += "Unknown\\"; break; } } lock (RunningSessions) RunningSessions.Add(Client, ses); return(true); }