1
0
mirror of https://github.com/livingcomputermuseum/IFS.git synced 2026-03-28 02:33:37 +00:00

Added AGPL License, completed readme.txt, general cleanup.

This commit is contained in:
Josh Dersch
2016-12-14 16:16:16 -08:00
parent ef6bd4cc97
commit 8975478a1c
42 changed files with 1101 additions and 126 deletions

View File

@@ -1,4 +1,21 @@
using IFS.Logging;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using IFS.Logging;
using System;
using System.Collections.Generic;
using System.IO;
@@ -25,7 +42,7 @@ namespace IFS
/// Administrators can read/write files in any directory.
///
/// The concept of a "guest" account is provided -- this user has no home directory and has read-only
/// access only to specifically marked public directories.
/// access only.
/// </summary>
public static class Authentication
{

View File

@@ -1,4 +1,21 @@
using IFS.BSP;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using IFS.BSP;
using System;
using System.Collections.Generic;

View File

@@ -1,4 +1,21 @@
using IFS.Gateway;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using IFS.Gateway;
using IFS.Logging;
using System;
@@ -168,8 +185,8 @@ namespace IFS.BSP
{
_inputLock.EnterWriteLock();
// We have some data right now, read it in.
// TODO: this code is ugly and it wants to die.
// We have some data right now, read it in, one
// byte at a time...
while (_inputQueue.Count > 0 && read < count)
{
ushort word = _inputQueue.Dequeue();
@@ -224,8 +241,7 @@ namespace IFS.BSP
/// </summary>
/// <returns></returns>
public byte ReadByte()
{
// TODO: optimize this
{
byte[] data = new byte[1];
Read(ref data, 1);
@@ -238,8 +254,7 @@ namespace IFS.BSP
/// </summary>
/// <returns></returns>
public ushort ReadUShort()
{
// TODO: optimize this
{
byte[] data = new byte[2];
Read(ref data, 2);

View File

@@ -1,4 +1,21 @@
using IFS.Gateway;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using IFS.Gateway;
using IFS.Logging;
using System;
using System.Collections.Generic;

View File

@@ -1,4 +1,21 @@
using IFS.Logging;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using IFS.Logging;
using System;
using System.Collections.Generic;
using System.IO;
@@ -27,10 +44,9 @@ namespace IFS.Boot
private static void LoadBootFileTables()
{
_numberToNameTable = new Dictionary<ushort, string>();
_numberToNameTable = new Dictionary<ushort, string>();
// TODO: fix hardcoded path
using (StreamReader sr = new StreamReader("Conf\\bootdirectory.txt"))
using (StreamReader sr = new StreamReader(Path.Combine("Conf", "bootdirectory.txt")))
{
int lineNumber = 0;
while (!sr.EndOfStream)

View File

@@ -1,4 +1,21 @@
using IFS.Gateway;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using IFS.Gateway;
using IFS.Logging;
using System;

View File

@@ -5,6 +5,4 @@
# <username>:<password hash>:[Admin|User]:<Full Name>:<home directory>
#
jdersch::Admin:Josh Dersch:jdersch
luser::User:Joe Luser:luser
sample::User:This is a Sample:sample

View File

@@ -14,10 +14,5 @@
1# ifs
42# Muffin
43# Pumpkin
43# Duplicate
45# Pumpkin
# to test
5#177# NotHere
44# Frunobulax
45# Phydeaux

View File

@@ -4,17 +4,17 @@
# All numbers are in decimal.
#
# Debug settings
LogTypes = Verbose
LogComponents = All
# Normal configuration
FTPRoot = c:\ifs\ftp
CopyDiskRoot = c:\ifs\copydisk
BootRoot = c:\ifs\boot
MailRoot = c:\ifs\mail
InterfaceType = RAW
InterfaceType = raw
InterfaceName = Ethernet
UDPPort = 42424
ServerNetwork = 1
ServerHost = 1
# Debug settings
LogTypes = None
LogComponents = None

View File

@@ -1,4 +1,21 @@
using IFS.Logging;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using IFS.Logging;
using System;
using System.Collections.Generic;
using System.IO;
@@ -56,6 +73,12 @@ namespace IFS
{
throw new InvalidConfigurationException("MaxWorkers must be >= 1.");
}
if (UDPPort == 0)
{
// Set to default.
UDPPort = 42424;
}
}
/// <summary>
@@ -68,6 +91,11 @@ namespace IFS
/// </summary>
public static readonly string InterfaceName;
/// <summary>
/// The UDP port to use when using a UDP interface.
/// </summary>
public static readonly int UDPPort;
/// <summary>
/// The network that this server lives on
/// </summary>

View File

@@ -1,4 +1,21 @@
using System;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
@@ -217,8 +234,7 @@ namespace IFS.IfsConsole
if (method == null)
{
// invalid argument count.
// todo: display usage?
// invalid argument count.
throw new ArgumentException(String.Format("Invalid argument count to command."));
}
@@ -560,8 +576,8 @@ namespace IFS.IfsConsole
}
}
[ConsoleFunction("show commands", "Shows debugger commands and their descriptions.")]
private void ShowCommands()
[ConsoleFunction("show commands", "Shows console commands and their descriptions.")]
private bool ShowCommands()
{
foreach (ConsoleCommand cmd in _commandList)
{
@@ -574,6 +590,8 @@ namespace IFS.IfsConsole
Console.WriteLine("{0} - {1}", cmd.Name, cmd.Description);
}
}
return false;
}
private ConsolePrompt _consolePrompt;

View File

@@ -1,4 +1,21 @@
using System;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

View File

@@ -1,4 +1,21 @@
using System;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -37,7 +54,7 @@ namespace IFS.IfsConsole
return false;
}
[ConsoleFunction("show user", "Displays information for the specified user")]
[ConsoleFunction("show user", "Displays information for the specified user", "<username>")]
private bool ShowUser(string username)
{
UserToken user = Authentication.GetUser(username);
@@ -54,7 +71,7 @@ namespace IFS.IfsConsole
return false;
}
[ConsoleFunction("set password", "Sets the password for the specified user")]
[ConsoleFunction("set password", "Sets the password for the specified user", "<username>")]
private bool SetPassword(string username)
{
UserToken user = Authentication.GetUser(username);
@@ -127,7 +144,7 @@ namespace IFS.IfsConsole
return false;
}
[ConsoleFunction("show active servers", "Displays active server statistics.", "")]
[ConsoleFunction("show active servers", "Displays active server statistics.")]
private bool ShowServers()
{
List<BSP.BSPWorkerBase> workers = BSP.BSPManager.EnumerateActiveWorkers();
@@ -149,7 +166,7 @@ namespace IFS.IfsConsole
return false;
}
[ConsoleFunction("quit", "Terminates the IFS process", "")]
[ConsoleFunction("quit", "Terminates the IFS process")]
private bool Quit()
{
return true;

View File

@@ -1,4 +1,21 @@
using System;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Text;

View File

@@ -1,4 +1,21 @@
using IFS.BSP;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using IFS.BSP;
using IFS.Logging;
using System;
@@ -253,7 +270,7 @@ namespace IFS.CopyDisk
// Sanity check that length is a reasonable value.
if (length > 2048)
{
// TODO: shut down channel
Channel.SendAbort("Block length is invalid.");
throw new InvalidOperationException(String.Format("Insane block length ({0})", length));
}
@@ -275,7 +292,7 @@ namespace IFS.CopyDisk
Log.Write(LogType.Verbose, LogComponent.CopyDisk, "Copydisk client is version {0}, '{1}'", vbIn.Code, vbIn.Herald.ToString());
// Send the response:
VersionYesNoBlock vbOut = new VersionYesNoBlock(CopyDiskBlock.Version, vbIn.Code, "LCM IFS CopyDisk of 26-Jan-2016");
VersionYesNoBlock vbOut = new VersionYesNoBlock(CopyDiskBlock.Version, vbIn.Code, "LCM+L IFS CopyDisk of 26-Jan-2016");
Channel.Send(Serializer.Serialize(vbOut));
}
break;

View File

@@ -1,4 +1,21 @@
using System;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -199,8 +216,7 @@ namespace IFS.CopyDisk
{
throw new InvalidOperationException("Disk address is out of range.");
}
// TODO: factor this logic out
int sector = address % _geometry.Sectors;
int track = (address / _geometry.Sectors) % _geometry.Tracks;
int cylinder = (address / (_geometry.Sectors * _geometry.Tracks));

View File

@@ -1,4 +1,21 @@
using System;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
@@ -120,9 +137,8 @@ namespace IFS
{
_hostAddressTable = new Dictionary<byte, Dictionary<byte, string>>();
_hostNameTable = new Dictionary<string, HostAddress>();
// TODO: do not hardcode path like this.
using (StreamReader sr = new StreamReader("Conf\\hosts.txt"))
using (StreamReader sr = new StreamReader(Path.Combine("Conf", "hosts.txt")))
{
int lineNumber = 0;
while (!sr.EndOfStream)
@@ -219,7 +235,7 @@ namespace IFS
}
// Hash the host by one or more names
for (int i=1;i<tokens.Length;i++)
for (int i = 1; i < tokens.Length; i++)
{
string hostName = tokens[i];
@@ -259,8 +275,8 @@ namespace IFS
}
networkTable.Add(host.Host, hostName);
}
}
}
}

Binary file not shown.

Binary file not shown.

View File

@@ -1,4 +1,21 @@
using IFS.Gateway;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using IFS.Gateway;
using IFS.Logging;
using System;

View File

@@ -1,4 +1,21 @@
using IFS.BSP;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using IFS.BSP;
using IFS.Logging;
using System;

View File

@@ -1,4 +1,21 @@
using IFS.Logging;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using IFS.Logging;
using System;
using System.Collections.Generic;

View File

@@ -1,4 +1,21 @@
using IFS.Gateway;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using IFS.Gateway;
using System;
using System.Collections.Generic;
using System.Linq;

View File

@@ -1,4 +1,21 @@
using IFS.Boot;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using IFS.Boot;
using IFS.CopyDisk;
using IFS.FTP;
using IFS.Gateway;
@@ -34,7 +51,10 @@ namespace IFS
private static void PrintHerald()
{
Console.WriteLine("LCM IFS v0.1, 4/19/2016.");
Console.WriteLine("LCM+L IFS v0.1, 12/14/2016.");
Console.WriteLine("(c) 2015, 2016 Living Computers: Museum+Labs.");
Console.WriteLine("Bug reports to joshd@livingcomputers.org");
Console.WriteLine();
Console.WriteLine();
}
@@ -74,12 +94,17 @@ namespace IFS
}
}
break;
default:
throw new InvalidConfigurationException(
String.Format("The specified interface type ({0}) is invalid.", Configuration.InterfaceType));
}
// Not found.
if (!bFound)
{
throw new InvalidConfigurationException("The specified network interface is invalid.");
throw new InvalidConfigurationException(
String.Format("The specified network interface ({0}) is invalid or unusable by IFS.", Configuration.InterfaceName));
}
}

View File

@@ -1,4 +1,21 @@
using IFS.BSP;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using IFS.BSP;
using IFS.Logging;
using System;
@@ -160,7 +177,7 @@ namespace IFS.FTP
//
// Return our Version.
FTPYesNoVersion serverVersion = new FTPYesNoVersion(1, "LCM IFS FTP of 4 Feb 2016.");
FTPYesNoVersion serverVersion = new FTPYesNoVersion(1, "LCM+L IFS FTP of 4 Feb 2016.");
SendFTPResponse(FTPCommand.Version, serverVersion);
}
break;
@@ -563,9 +580,10 @@ namespace IFS.FTP
Log.Write(LogType.Verbose, LogComponent.FTP, "Receiving file {0}.", fullFileName);
using (FileStream inFile = new FileStream(fullFileName, FileMode.Create, FileAccess.Write))
{
// TODO: move to constant. Possibly make max size configurable.
// For now, it seems very unlikely that any Alto is going to have a single file larger than 4mb.
lastMark = ReadUntilNextMark(out buffer, 4096 * 1024);
//
// For now, it seems very unlikely that any Alto is going to have a single file larger than 4mb, so
// reading the entire file into memory is somewhat reasonable...
lastMark = ReadUntilNextMark(out buffer, _maxFileSize);
// Write out to file
inFile.Write(buffer, 0, buffer.Length);
@@ -577,7 +595,7 @@ namespace IFS.FTP
{
// We failed while writing the file, send a No response to the client.
// Per the spec, we need to drain the client data first.
lastMark = ReadUntilNextMark(out buffer, 4096 * 1024); // TODO: move to constant
lastMark = ReadUntilNextMark(out buffer, _maxFileSize);
success = false;
Log.Write(LogType.Warning, LogComponent.FTP, "Failed to write {0}. Error '{1}'", fullFileName, e.Message);
@@ -596,8 +614,7 @@ namespace IFS.FTP
Log.Write(LogType.Verbose, LogComponent.FTP, "Client success code is {0}, {1}, '{2}'", lastMark, clientYesNo.Code, clientYesNo.Code);
if (!success)
{
// TODO: provide actual No codes.
{
SendFTPNoResponse(NoCode.FileBusy, "File transfer failed.");
}
else
@@ -643,7 +660,7 @@ namespace IFS.FTP
//
// Check the privileges of the user. If the user has write permissions
// then we are OK to delete. Otherwise, we must be deleteing files in the user's directory.
// then we are OK to delete. Otherwise, we must be deleting files in the user's directory.
//
string fullFileName = Path.Combine(Configuration.FTPRoot, fullPath);
if (userToken.Privileges != IFSPrivileges.ReadWrite &&
@@ -688,8 +705,7 @@ namespace IFS.FTP
Channel.Send(Serializer.Serialize(new FTPYesNoVersion(0, "File deleted successfully.")));
}
catch(Exception e)
{
// TODO: calculate real NO codes
{
Channel.SendMark((byte)FTPCommand.No, false);
Channel.Send(Serializer.Serialize(new FTPYesNoVersion((byte)NoCode.AccessDenied, e.Message)));
}
@@ -886,10 +902,9 @@ namespace IFS.FTP
try
{
Log.Write(LogType.Verbose, LogComponent.Mail, "Receiving mail file to memory...");
// TODO: move to constant. Possibly make max size configurable.
// For now, it seems very unlikely that any Alto is going to have a single file larger than 4mb.
lastMark = ReadUntilNextMark(out buffer, 4096 * 1024);
lastMark = ReadUntilNextMark(out buffer, _maxFileSize);
Log.Write(LogType.Verbose, LogComponent.Mail, "Received {0} bytes.", buffer.Length);
@@ -908,7 +923,7 @@ namespace IFS.FTP
{
// We failed while writing the mail file, send a No response to the client.
// Per the spec, we need to drain the client data first.
lastMark = ReadUntilNextMark(out buffer, 4096 * 1024); // TODO: move to constant
lastMark = ReadUntilNextMark(out buffer, _maxFileSize);
success = false;
Log.Write(LogType.Warning, LogComponent.Mail, "Failed to write mail file. Error '{1}'. Aborting.", e.Message);
@@ -927,8 +942,7 @@ namespace IFS.FTP
Log.Write(LogType.Verbose, LogComponent.Mail, "Client success code is {0}, {1}, '{2}'", lastMark, clientYesNo.Code, clientYesNo.Code);
if (!success)
{
// TODO: provide actual No codes.
{
SendFTPNoResponse(NoCode.TransientServerFailure, "Mail transfer failed.");
}
else
@@ -1238,6 +1252,9 @@ namespace IFS.FTP
private Thread _workerThread;
private bool _running;
// 4 megabytes as the maximum file size to accept.
private const int _maxFileSize = 4096 * 1024;
/// <summary>
/// The last set of mail files retrieved via a Retrieve-Mail operation.
/// Saved so that Flush-Mailbox can use it to delete only those mails that

View File

@@ -1,4 +1,21 @@
using System;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

View File

@@ -1,4 +1,21 @@
using IFS.Gateway;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using IFS.Gateway;
using IFS.Logging;
using System;
using System.Collections.Generic;
@@ -23,9 +40,11 @@ namespace IFS.Gateway
{
public GatewayInformationProtocol()
{
// TODO:
//
// TODO (once routing is implemented):
// load host tables, etc.
// spin up thread that spits out a GatewayInformation PUP periodically.
//
}
/// <summary>

View File

@@ -1,4 +1,21 @@
using IFS.Logging;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using IFS.Logging;
using IFS.Transport;
using PcapDotNet.Core;
using System.Net.NetworkInformation;

View File

@@ -136,6 +136,7 @@
<Content Include="Conf\bootdirectory.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="readme.txt" />
<None Include="Conf\ifs.cfg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
@@ -147,14 +148,6 @@
</Content>
</ItemGroup>
<ItemGroup />
<ItemGroup>
<None Include="Disks\diag.dsk">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Disks\tdisk8.dsk">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View File

@@ -1,4 +1,21 @@
#define LOGGING_ENABLED
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
#define LOGGING_ENABLED
using System;
using System.IO;
@@ -81,8 +98,7 @@ namespace IFS.Logging
(_components & component) != 0)
{
//
// My log has something to tell you...
// TODO: color based on type, etc.
// My log has something to tell you...
Console.WriteLine(component.ToString() + ": " + message, args);
if (_logStream != null)

View File

@@ -1,4 +1,21 @@
using IFS.Logging;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using IFS.Logging;
using System;
using System.Collections.Generic;
using System.IO;
@@ -88,9 +105,12 @@ namespace IFS.Mail
if (File.Exists(GetMailboxPathForFile(mailbox, mailFile)))
{
//
// Open the requested mail file.
// Get the timestamp for the mail file
//
return "26-MAY-79 02:33:00";
// TODO: need to adjust real date; as per a lot of Alto utilities they don't like
// dates too far past the 70s...
//return File.GetCreationTime(GetMailboxPathForFile(mailbox, mailFile)).ToString("dd-MMM-yy HH:mm:ss");
}
else

View File

@@ -1,4 +1,21 @@
using IFS.Boot;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using IFS.Boot;
using IFS.EFTP;
using IFS.Gateway;
using IFS.Logging;
@@ -229,8 +246,9 @@ namespace IFS
//
// For now, the assumption is that each name maps to at most one address.
//
//
string lookupName = Helpers.ArrayToString(p.Contents);
Log.Write(LogType.Verbose, LogComponent.MiscServices, "Name lookup is for '{0}'", lookupName);
HostAddress address = DirectoryServices.Instance.NameLookup(lookupName);
@@ -242,6 +260,8 @@ namespace IFS
PUP lookupReply = new PUP(PupType.NameLookupResponse, p.ID, p.SourcePort, localPort, lookupPort.ToArray());
Router.Instance.SendPup(lookupReply);
Log.Write(LogType.Verbose, LogComponent.MiscServices, "Address is '{0}'", address);
}
else
{
@@ -251,6 +271,8 @@ namespace IFS
PUP errorReply = new PUP(PupType.DirectoryLookupErrorReply, p.ID, p.SourcePort, localPort, Helpers.StringToArray(errorString));
Router.Instance.SendPup(errorReply);
Log.Write(LogType.Verbose, LogComponent.MiscServices, "Host is unknown.");
}
}

View File

@@ -1,4 +1,21 @@
using IFS.Logging;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using IFS.Logging;
using System;
using System.Collections.Generic;
using System.IO;
@@ -266,7 +283,7 @@ namespace IFS
_rawData = new byte[length];
stream.Read(_rawData, 0, length);
// Read fields in. TODO: investigate more efficient ways to do this.
// Read fields in.
Length = Helpers.ReadUShort(_rawData, 0);
// Sanity check size:

View File

@@ -1,4 +1,21 @@
using System;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

View File

@@ -1,4 +1,21 @@
using IFS.BSP;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using IFS.BSP;
using IFS.EFTP;
using IFS.Logging;
@@ -80,7 +97,7 @@ namespace IFS
else
{
// Not a protocol we handle; log it.
Log.Write(LogType.Normal, LogComponent.PUP, "Unhandled PUP protocol, source socket {0}, destination socket {1}, type {2}, dropped packet.", pup.SourcePort.Socket, pup.DestinationPort.Socket, pup.Type);
Log.Write(LogType.Normal, LogComponent.PUP, "Unhandled PUP protocol, source {0}, destination {1}, type {2}, dropped packet.", pup.SourcePort, pup.DestinationPort, pup.Type);
}
}
@@ -107,12 +124,12 @@ namespace IFS
// Connectionless
RegisterProtocol(new PUPProtocolEntry("Gateway Information", 2, ConnectionType.Connectionless, new GatewayInformationProtocol()));
RegisterProtocol(new PUPProtocolEntry("Misc Services", 0x4, ConnectionType.Connectionless, new MiscServicesProtocol()));
RegisterProtocol(new PUPProtocolEntry("Echo", 0x5, ConnectionType.Connectionless, new EchoProtocol()));
RegisterProtocol(new PUPProtocolEntry("Echo", 0x5, ConnectionType.Connectionless, new EchoProtocol()));
// RTP/BSP based:
RegisterProtocol(new PUPProtocolEntry("CopyDisk", 0x15 /* 25B */, ConnectionType.BSP, typeof(CopyDiskWorker)));
RegisterProtocol(new PUPProtocolEntry("FTP", 0x3, ConnectionType.BSP, typeof(FTPWorker)));
RegisterProtocol(new PUPProtocolEntry("Mail", 0x7, ConnectionType.BSP, typeof(FTPWorker)));
RegisterProtocol(new PUPProtocolEntry("Mail", 0x7, ConnectionType.BSP, typeof(FTPWorker)));
// Breath Of Life
_breathOfLifeServer = new BreathOfLife();

View File

@@ -1,4 +1,21 @@
using System.Reflection;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

View File

@@ -1,4 +1,21 @@
using System;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

View File

@@ -1,4 +1,21 @@
using System;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

View File

@@ -1,4 +1,21 @@
using System;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

View File

@@ -1,4 +1,21 @@
using IFS.Gateway;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using IFS.Gateway;
using PcapDotNet.Packets;
using System;
using System.Collections.Generic;

View File

@@ -1,4 +1,21 @@
using System;
/*
This file is part of IFS.
IFS is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
IFS 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with IFS. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Net;
using System.Net.Sockets;
@@ -25,7 +42,8 @@ namespace IFS.Transport
/// Any of these virtual or real Altos can, at any time, be running in Promiscuous mode, can send
/// arbitrary packets with any source or destination address in the header, or send broadcasts.
/// This makes address translation from the virtual (3M) side to the physical (UDP, 100M) side and
/// back again tricky.
/// back again tricky. It also makes it tricky to ensure an outgoing packet makes it to any and
/// all parties that may be interested (consider the Promiscuous Alto case.)
///
/// If each participant on the virtual network were to have a table mapping physical (UDP IP, 100M MAC) to
/// virtual (3M MAC) addresses then broadcasts could be avoided, but it complicates the logic in all
@@ -51,7 +69,7 @@ namespace IFS.Transport
// Try to set up UDP client.
try
{
_udpClient = new UdpClient(_udpPort, AddressFamily.InterNetwork);
_udpClient = new UdpClient(Configuration.UDPPort, AddressFamily.InterNetwork);
_udpClient.Client.Blocking = true;
_udpClient.EnableBroadcast = true;
_udpClient.MulticastLoopback = false;
@@ -69,7 +87,7 @@ namespace IFS.Transport
if (unicast.Address.AddressFamily == AddressFamily.InterNetwork)
{
_thisIPAddress = unicast.Address;
_broadcastEndpoint = new IPEndPoint(GetBroadcastAddress(_thisIPAddress, unicast.IPv4Mask), _udpPort);
_broadcastEndpoint = new IPEndPoint(GetBroadcastAddress(_thisIPAddress, unicast.IPv4Mask), Configuration.UDPPort);
break;
}
}
@@ -84,7 +102,7 @@ namespace IFS.Transport
{
Log.Write(LogType.Error, LogComponent.UDP,
"Error configuring UDP socket {0} for use with IFS on interface {1}. Ensure that the selected network interface is valid, configured properly, and that nothing else is using this port.",
_udpPort,
Configuration.UDPPort,
iface.Name);
Log.Write(LogType.Error, LogComponent.UDP,
@@ -143,8 +161,7 @@ namespace IFS.Transport
// Actual data
p.RawData.CopyTo(encapsulatedFrame, 6);
// Send as UDP broadcast.
// TODO: this could be done without broadcasts if we kept a table mapping IPs to 3mbit MACs.
// Send as UDP broadcast.
_udpClient.Send(encapsulatedFrame, encapsulatedFrame.Length, _broadcastEndpoint);
}
@@ -176,8 +193,7 @@ namespace IFS.Transport
// Actual data
data.CopyTo(encapsulatedFrame, 6);
// Send as UDP broadcast.
// TODO: this could be done without broadcasts if we kept a table mapping IPs to 3mbit MACs.
// Send as UDP broadcast.
_udpClient.Send(encapsulatedFrame, encapsulatedFrame.Length, _broadcastEndpoint);
}
@@ -237,7 +253,7 @@ namespace IFS.Transport
// properly.)
Log.Write(LogComponent.UDP, "UDP Receiver thread started.");
IPEndPoint groupEndPoint = new IPEndPoint(IPAddress.Any, _udpPort);
IPEndPoint groupEndPoint = new IPEndPoint(IPAddress.Any, Configuration.UDPPort);
while (true)
{
@@ -273,9 +289,7 @@ namespace IFS.Transport
// Thread used for receive
private Thread _receiveThread;
// UDP port (TODO: make configurable?)
private const int _udpPort = 42424;
private UdpClient _udpClient;
private IPEndPoint _broadcastEndpoint;

373
PUP/readme.txt Normal file
View File

@@ -0,0 +1,373 @@
Readme.txt for IFS v1.1:
1. Introduction and Overview
============================
In the 1970s, Xerox PARC developed a set of protocols based around the "PUP"
(the "PARC Universal Packet"). These were intended to be a stopgap until
something "real" could be designed and implemented, so the suite was referred
to as "IFS" ("Interim File Server"). That "real" implementation never came
into being during the Alto's lifetime, so the IFS was a permanent fixture of
the network environment at PARC during the heyday of the Alto.
The LCM+L's IFS implementation is an implementation of this protocol suite
that runs on a modern PC, and is designed to work with the ContrAlto Alto
emulator over either Raw Ethernet packets or UDP broadcasts.
It provides the following IFS services:
- BreathOfLife: Provides the "Breath Of Life" packet needed to bootstrap
an Alto over the network.
- EFTP/Boot: Provides boot files over the network.
- FTP: File Transfer Protocol.
- CopyDisk: Allows imaging and restoring of Alto disk packs over the
network.
- Misc. Services: Provides network name lookup, time and other miscellaneous
services.
- Mail: Delivers mail to other users.
The following services are not yet provided, but are planned:
- EFTP/Printing: Provides print services to networked Altos
- Gateway: Routes PUPs to other Alto networks across the Internet
If you have questions, or run into issues or have feature requests, please
feel free to e-mail me at joshd@livingcomputers.org.
1.1 Getting Started
-------------------
IFS does not provide an installer; unzip the archive to a directory on the
machine you wish to use as a server. Modify the configuration files in the
"Conf" directory to your liking (See Section 2.0) and run the "IFS.exe"
executable to run the IFS services. The startup banner will print and you'll
be at the Console command prompt (See Section 3.0 for details). The IFS
server is now running and is ready to serve your network of Altos.
1.2 Important Note
------------------
This IFS implementation is still a work in progress and should not be used for
any mission-critical or security-critical purposes. IFS protocols sent
passwords in plain-text and in general were not designed with tight security
in mind. All files (even those in user directories) are globally readable.
2.0 Configuration
=================
IFS uses a set of files in the "Conf" subdirectory to configure the server.
These include:
- accounts.txt: Defines the set of user accounts
- bootdirectory.txt: Maps boot numbers to boot files for network boot
- hosts.txt: Maps Inter-network numbers to names
- ifs.cfg: General configuration for the IFS server
2.1 ifs.cfg:
------------
ifs.cfg contains general configuration details for the server. It specifies
configuration for the network transport, directory paths and debugging options.
Directory configuration:
- FTPRoot: Specifies the path for the root of the FTP directory tree.
- CopyDiskRoot: Specifies the path for the directory to store CopyDisk
images.
- BootRoot: Specifies the path for boot images.
- MailRoot: Specifies the path for the root of the Mail directory tree.
(User mail folders are placed in this directory.)
Interface configuration:
- InterfaceType: "RAW" or "UDP". Specifies the transport to use for
communication.
- InterfaceName: The name of the host network adapter to use for
communication.
- UDPPort: The port number (decimal) to use for the UDP transport.
Network configuration:
- ServerNetwork: The IFS server's network number.
- ServerHost: The IFS server's host number.
Debugging configuration:
- LogTypes: The level of verbosity for logging. One of:
None, Normal, Warning, Error, Verbose, or All
- LogComponent: The components to log details about. One of:
None, Ethernet, RTP, BSP, MiscServices, CopyDisk,
DirectoryServices, PUP, FTP, BreathOfLife, EFTP,
BootServer, UDP, Mail, Configuration, or All
2.2 hosts.txt:
--------------
hosts.txt maps Xerox "inter-network" names to hostnames. If you're familiar
with /etc/hosts on UNIX-like machines, this will be very familiar.
Each line is either a comment (beginning with '#') or contains an inter-network
name and a hostname to associate with it, separated by whitespace. At this
time, each inter-network name maps to exactly one hostname.
A Xerox "inter-network name" defines a host number and a network number, and is
expressed in the format "<network>#<host>#", where both <network> and <host>
are octal values between 0 and 377. So, for example, an Alto on network 5
with host number 72 would have an inter-network name of "5#72#". Hosts on the
same network as the IFS server (see Section 2.1 for IFS server configuration)
need not specify the network number and have the format of "<host>#".
A Hostname is an alphanumeric sequence that must begin with a letter.
A hosts.txt entry for our Alto on network 5 with host number 72 providing said
system with name "alan" would thus look like:
5#72# alan
Or optionally, if our IFS server is on network 5:
72# alan
It is a good idea to provide an entry for the IFS server itself so that the
server can easily be reached by name. By default (unless ifs.cfg has been
changed), the IFS server's inter-network name is 1#1# (network 1, host 1).
2.3 bootdirectory.txt
---------------------
bootdirectory.txt maps boot numbers to the bootfile they correspond to. The
file format is very similar to the hosts.txt file -- each line consists of
either a comment (again beginning with '#') or contains a boot file number (in
octal) and the boot file to associate with it.
The boot files listed in bootdirectory.txt correspond to files placed in the
BootRoot directory, as specified in ifs.cfg (see Section 2.1 for details).
By default bootdirectory.txt contains a set of entries that map to the file
numbers conventionally used at Xerox PARC. This allows Alto programs and
subsystems that rely on this convention to work properly. It is advisable
to leave these as is for this reason. Anything past 100 (octal) is fair game
generally, configure those as you will.
Note that the IFS server does not include the actual boot files -- see Section
6.0 for details on where to find these files to populate your BootRoot
directory.
2.4 accounts.txt
----------------
accounts.txt defines user accounts for the IFS system.
Note: These accounts are unrelated to any user accounts that might be provided
by the host system (i.e.a Windows or Linux box that is running IFS). It is
*extremely* advisable to avoid using the same password for your IFS account
that you do for any real-world account (see Section 1.2).
Each line in accounts.txt consists of either a comment (beginning with '#')
or a user definition. If you're familiar with /etc/password on UNIX systems
this will look very familiar.
This file can be hand-edited using a text editor, but the file will be
re-generated if the Console (see Section 3.0) is used to add or modify user
accounts, so comments will be lost. It is generally advisable to use the
console to add, remove, or change user accounts.
Each user definition is a line in the format:
<username>:<password hash>:<privileges>:<full user name>:<home directory>
- username: an alphanumeric sequence starting with a letter. This
define's the user's login name.
- password hash: an encoded version of the user's password. This can be
edited, but is generally not advisable. See Section
3.0 for details on setting and changing user passwords.
- privileges: Either Admin (administrative privileges) or User (normal
user privileges). See section 4.0 for details.
- full user name: Self explanatory; the full name (i.e. Alan Kay) of the
user.
- home directory: The user's directory (which is placed under the FTPRoot
directory). See Section 4.0 for details on user
directories.
Changes made to this file while IFS is running will not take effect until IFS
is restarted. (This is another reason to use the Console to make changes --
see Section 3.0).
3.0 The Command Console
=======================
The IFS server provides a command console, designated by the ">" prompt. The
console provides numerous commands for managing the state of the server and
for managing user accounts.
The console provides simple command completion; hit the "TAB" key at any time
to see possible completions for the command you are entering.
The "show commmands" command displays a list of possible commands with brief
synopses and descriptions.
Here is a rundown of the basic command set:
show users - Displays the current user database (See Section 4.0)
show user <username> - Displays information for the specified user
(See Section 4.0)
set password <username> - Sets the password for the specified user
(See Section 4.0)
add user <username> <password> [User|Admin] <full name> <home directory>
- Adds a new user account (See section 4.0 for details)
remove user <username> - Removes an existing user account (See Section 4.0)
show active servers - Displays active server statistics.
quit - Terminates the IFS process
show commands - Shows console commands and their descriptions.
4.0 User Accounts, Authentication, and Security
===============================================
IFS provides a very simple model for user accounts, authentication and security.
It is by no means expected to be extensive or useful for all applications, nor
does it guarantee any level of security. It provides a set of facilities for
creating user accounts and assigning passwords and coarsely-grained permissions,
approximating the environment as it would have existed at Xerox PARC.
Rephrasing the note in Section 1.2: Do not rely on IFS for security or privacy.
Allow only trusted users into the network that hosts IFS, and use common sense.
4.1 User Accounts
-----------------
Each user account is defined by an entry in the accounts.txt file (as described
in section 2.4).
A new user account can be created either be editing the accounts.txt file, or
through use of the "add user" Console command. The latter is recommended.
Each user can be assigned a password, or have his/her password changed using
the "set password" command.
Every user gets his or her own user directory for files; this is a
subdirectory of the FTPRoot directory and will be automatically created by the
"add user" Console command (See Setion 3.0) and removed by the "remove user"
command.
There are exactly two levels of privilege possible: User and Admin. A user
with "User" level privileges has read/write access to their own user file
directory, and read-only access to all other file directories (including other user
directories). A user with "Admin" privileges has read-write access to all
directories.
Every user gets his or her own mail directory as a subdirectory
of the MailRoot directory. This directory is automatically created the first
time a user sends or receives mail. A given user's mail directory is only
readable (or writable) by that user, regardless of privilege.
Additionally, every user (including guest) has read access to disk images in
the CopyDiskRoot directory. Administrative users also have the ability to
write new images to this directory.
4.2 The Guest Account
---------------------
There is one special account, the "guest" account. The guest account does not
have an entry in the accounts.txt file, and has no password. The guest user
has read-only access, but has no user directory.
5.0 Network Transports: Care and Feeding
========================================
IFS simulates the original "Experimental" 3mbit Xerox Ethernet by encapsulating
3mbit packets in a modern transport, either via UDP broadcasts or via Raw
Ethernet packets.
The transport type is configured in the ifs.cfg file (See Section 2.1) via the
"InterfaceType" parameter. The UDP port can be defined by the "UDPPort" parameter,
if unspecified it defaults to 42424.
In both cases, packets are broadcast over the network. This is done in order
to make the use of the simulated network easier and to keep the implementation
simple as well. In general, Altos (simulated or otherwise) do not generate
large amounts of traffic as compared with the bandwidth of a modern network.
(The maximum throughput of an Alto transferring a file via FTP, for example,
is on the order of 20K/sec). It may be a good idea to run your IFS server
and Altos on a separate network segment if you are concerned about network
usage.
You cannot run both the IFS server and a ContrAlto emulator on the same machine
if they are configured to use UDP as the transport.
6.0 Where to Find Alto Files
============================
The IFS server distribution does not include any Alto files, but they can be
found in many places on the Internet.
Disk images (for use with the CopyDisk protocol) and some boot files can be
found on Bitsavers, at http://bitsavers.org/bits/Xerox/Alto/.
A wide variety of files, including programs, documentation, and related data
can be found in the CHM's Xerox PARC Alto filesystem archive at
http://xeroxalto.computerhistory.org/. The raw files can be downloaded and
placed in your FTPRoot or BootRoot directories as desired.
7.0 Xerox Documentation Reference
=================================
The following documents may be useful in actually using the Alto-land client
tools (FTP, CopyDisk, mail, etc) to communicate with the IFS server:
The Alto User's Handbook:
http://bitsavers.org/pdf/xerox/alto/Alto_Users_Handbook_Sep79.pdf
Alto Subsystems:
http://bitsavers.org/pdf/xerox/alto/memos_1981/Alto_Subsystems_May81.pdf
The following specifications were used to implement the IFS protocol suite:
FTP: http://xeroxalto.computerhistory.org/_cd8_/pup/.ftpspec.press!2.pdf
Boot: http://xeroxalto.computerhistory.org/_cd8_/pup/.altoboot.press!1.pdf
CopyDisk: http://xeroxalto.computerhistory.org/_cd8_/pup/.copydisk.press!1.pdf
Gateway:
http://xeroxalto.computerhistory.org/_cd8_/pup/.gatewayinformation.press!1.pdf
Misc Services:
http://xeroxalto.computerhistory.org/_cd8_/pup/.miscservices.press!1.pdf
8.0 Packet-Level Protocol
=========================
IFS (and ContrAlto) use a very simple encapsulation for transmitting 3mbit
Ethernet packets over modern transports. An encapsulated packet consists of
two fields:
- Packet Length (2 bytes): Length (in 16-bit words) of the 3mbit Packet
Data field (see below)
- Packet Data (N bytes): The 3mbit packet, including 3mbit Ethernet header
but excluding the checksum word.
All words are stored in big-endian format.
The Packet Length field is necessary to allow proper transport over Raw
Ethernet packets -- modern Ethernet defines a minimum length for a packet
whereas the Experimental 3mbit Ethernet (as implemented on the Alto) does not.
Short packets are therefore padded by the modern transport, so a separate field
is necessary in order to ascertain the intended packet length.
As discussed in Section 5.0, all packets are broadcast. The technical reasons
for this are documented in the source code; see Transport\UDP.cs for details.
9.0 Thanks
==========
This project would not have been possible without the conservation efforts of
the CHM and Bitsavers.