Skip to content
This repository has been archived by the owner on Sep 9, 2021. It is now read-only.

Lab2 /70201, Казанджи Михаил. Ntp server & Snmp client #145

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions Lab2/Lab2.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@

Microsoft Visual Studio Solution File, Format Version 12.00
#
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NtpServer", "NtpServer\NtpServer.csproj", "{B5B6FA59-0FCF-4894-AB47-62EA69934381}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SnmpClient", "SnmpClient\SnmpClient.csproj", "{C6EC7EA8-5892-4033-AFED-D97E2EBB8C01}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B5B6FA59-0FCF-4894-AB47-62EA69934381}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B5B6FA59-0FCF-4894-AB47-62EA69934381}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B5B6FA59-0FCF-4894-AB47-62EA69934381}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B5B6FA59-0FCF-4894-AB47-62EA69934381}.Release|Any CPU.Build.0 = Release|Any CPU
{C6EC7EA8-5892-4033-AFED-D97E2EBB8C01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C6EC7EA8-5892-4033-AFED-D97E2EBB8C01}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C6EC7EA8-5892-4033-AFED-D97E2EBB8C01}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C6EC7EA8-5892-4033-AFED-D97E2EBB8C01}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
8 changes: 8 additions & 0 deletions Lab2/NtpServer/NtpServer.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>

</Project>
108 changes: 108 additions & 0 deletions Lab2/NtpServer/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace NtpServer
{
internal class Packet
{
public readonly byte Head = 0x1C;
public byte Layer;
public byte Interval;
public byte Precisions;
public byte[] Delay;
public byte[] Disp;
public byte[] Id = Encoding.ASCII.GetBytes("ZHMR");
public byte[] TimeUpdate;
public byte[] TimeStart;
public byte[] TimeIncome;
public byte[] TimeSend;

public byte[] GetBytes() => new[] {Head, Layer, Interval, Precisions}
.Concat(Delay).Concat(Disp).Concat(Id).Concat(TimeUpdate)
.Concat(TimeStart).Concat(TimeIncome).Concat(TimeSend).ToArray();
}

internal static class Program
{
private static readonly DateTime Century =
new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc);

private static byte[] GetTimestamp(DateTime? timestamp) {
if (timestamp == null) { return new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }; }

DateTime time = timestamp.Value;
if (time.Kind == DateTimeKind.Local) { time = time.ToUniversalTime(); }

var eraTime = Century;
var n1 = (UInt32)(time - eraTime).TotalSeconds;
var buffer1LE = BitConverter.GetBytes(n1);

var n2 = (UInt32)Math.Min(Math.Max((time.Ticks - eraTime.AddSeconds(n1).Ticks) / 10_000_000.0 * 0x100000000, 0), 0x100000000);
var buffer2LE = BitConverter.GetBytes(n2);

return buffer1LE.Reverse().Concat(buffer2LE.Reverse()).ToArray();
}

private static DateTime? GetTimestamp(byte[] bytes, int offset) {
long n1 = BitConverter.ToUInt32(bytes.Skip(offset).Take(4).Reverse().ToArray(), 0);
long n2 = BitConverter.ToUInt32(bytes.Skip(offset + 4).Take(4).Reverse().ToArray(), 0);

if (n1 == 0 && n2 == 0) { return null; }

var time = Century;
time = time.AddTicks(n1 * 10_000_000);
time = time.AddTicks((long)(n2 / 4294967296.0 * 10_000_000));
return time;
}

private static void Main(string[] args)
{
var buffer = new byte[48];
buffer[0] = 0x1B; //LI = 0 (no warning), VN = 3 (IPv4 only), Mode = 3 (Client Mode)
var ipEndPoint = new IPEndPoint(Dns.GetHostEntry("pool.ntp.org").AddressList[0], 123);
// ReSharper disable once ConvertToUsingDeclaration
using (var socket =
new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp) {ReceiveTimeout = 3000})
{
socket.Connect(ipEndPoint);
socket.Send(buffer);
socket.Receive(buffer);
}
var time = GetTimestamp(buffer, 40);
Console.WriteLine("Server online");
Console.WriteLine("Global time: {0}", time);
Console.WriteLine("Server time: {0}", GetTimestamp(DateTime.UtcNow));
Debug.Assert(time != null, nameof(time) + " != null");
Console.WriteLine(DateTime.UtcNow.Subtract((DateTime) time).Seconds <= 1
? "Server time correct"
: "Server time need to correction");
var template = new Packet {Layer = (byte) (buffer[1] + 1), Interval = buffer[2],
Precisions = buffer[3], Delay = buffer.Skip(4).Take(4).ToArray(),
Disp = buffer.Skip(8).Take(4).ToArray(), TimeUpdate = GetTimestamp(time)};
using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
{
Console.CancelKeyPress += (sender, eventArgs) => { socket.Shutdown(SocketShutdown.Both); Environment.Exit(0); };
socket.Bind(new IPEndPoint(IPAddress.Any, 123));
while (true)
{
var package = template;
EndPoint ip = new IPEndPoint(IPAddress.Any, 0);
var buf = new byte[49];
var i = socket.ReceiveFrom(buf, ref ip);
package.TimeIncome = GetTimestamp(DateTime.UtcNow);
if (i != 48) return;
package.TimeStart = buffer.Skip(24).Take(8).ToArray();
package.TimeSend = GetTimestamp(DateTime.UtcNow);
Console.WriteLine("{0}", ip);
socket.SendTo(package.GetBytes(), ip);
}
}
}
}
}
18 changes: 18 additions & 0 deletions Lab2/NtpServer/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
## Лабораторная №2 - NTP Сервер

### Сборка

Для сборки необходим .NET Core v3.10+. По команде `dotnet run` программа будет запущена без создания исполняемого файла.
Для полной сборки проекта команда `dotnet build`.

### Запуск

Необходим запускать с правами администратора, так как 123 порт находится в зарезервированных системой.

### Ntp Сервер

Сервер реализует протокол NTPv3. Со следующей структурой протокола

![Структура пакета NTP](packet.png)

Сервер тестировался с помощью пакета ntpd.
Binary file added Lab2/NtpServer/packet.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
155 changes: 155 additions & 0 deletions Lab2/SnmpClient/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace SnmpClient
{
internal static class Program
{
public static void Main(string[] args)
{
Console.Write("Manager ip> ");
var ip = Console.ReadLine();
Debug.Assert(ip != null, nameof(ip) + " != null");
if (ip.Trim().Length == 0)
{
Console.WriteLine("Wrong ip");
return;
}
var sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
ProtocolType.Udp);
sock.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReceiveTimeout, 5000);

var iep = new IPEndPoint(IPAddress.Parse(ip!), 161);
var ep = (EndPoint)iep;
uint rid = 0;
Console.Write("Your community tag> ");
var com = Console.ReadLine()?.Trim();
while (true)
{
Console.Write(">");
string oib;
int offset;
byte[] packet;
switch (Console.ReadLine()?.Trim())
{
case "get":
Console.Write("oib>");
oib = Console.ReadLine()?.Trim();
packet = Snmp.GenGetPacket(com, oib, ref rid);
sock.SendTo(packet, packet.Length, SocketFlags.None, iep);
try
{
var recv = sock.ReceiveFrom(packet, ref ep);
}
catch (SocketException)
{
Console.WriteLine("Receive error. Maybe wrong ip?");
break;
}

offset = 6 + packet[6] + 1;
if (packet[offset] == 0xa2) //not Response
{
offset += 4;
var arid = (uint) BitConverter.ToInt32(packet, offset);
if (arid != rid || packet[offset + 6] != 0 || packet[offset + 9] != 0)
{
Console.WriteLine("Wrong answer");
break;
}

offset += 16 + packet[offset + 15];
switch (packet[offset])
{
case 2:
Console.WriteLine("Integer type [{0}]", packet[offset + 1]);
Console.WriteLine(BitConverter.ToInt32(packet, offset + 2));
break;
case 4:
Console.WriteLine("String type [{0}]", packet[offset + 1]);
Console.WriteLine(Encoding.ASCII.GetString(packet.Skip(offset + 2).ToArray()));
break;
case 5:
Console.WriteLine("Null type");
break;
}
}
else
{
Console.WriteLine("Not RESPONSE was received");
}
break;
case "set":
Console.Write("oib> ");
oib = Console.ReadLine()?.Trim();
Console.Write("type(1 - int, 2 - string, 3 - null)> ");
var type = Console.ReadLine()?.Trim();
Console.Write("val> ");
var val = Console.ReadLine()?.Trim();
var data = type switch
{
"1" => new byte[] {2, (byte) BitConverter
.GetBytes(Convert.ToInt32(val)).Count(i => i > 0)}
.Concat(BitConverter.GetBytes(Convert.ToInt32(val))
.Where(i => i > 0)).ToArray(),
"2" => new byte[] {4, (byte) (val.Length % 128)}.Concat(Encoding.ASCII.GetBytes(val)).ToArray(),
"3" => new byte[] {5, 0}
};
packet = Snmp.GenSetPacket(com, oib, data, ref rid);
sock.SendTo(packet, packet.Length, SocketFlags.None, iep);
try
{
var recv = sock.ReceiveFrom(packet, ref ep);
}
catch (SocketException)
{
Console.WriteLine("Receive error. Maybe wrong ip?");
break;
}

offset = 6 + packet[6] + 1;
if (packet[offset] == 0xa2) //not Response
{
offset += 4;
var arid = (uint) BitConverter.ToInt32(packet, offset);
if (arid != rid || packet[offset + 6] != 0 || packet[offset + 9] != 0)
{
Console.WriteLine("Wrong answer");
break;
}

offset += 16 + packet[offset + 15];
switch (packet[offset])
{
case 2:
Console.WriteLine("Integer type [{0}]", packet[offset + 1]);
Console.WriteLine(BitConverter.ToInt32(packet, offset + 2));
break;
case 4:
Console.WriteLine("String type [{0}]", packet[offset + 1]);
Console.WriteLine(Encoding.ASCII.GetString(packet.Skip(offset + 2).ToArray()));
break;
case 5:
Console.WriteLine("Null type");
break;
}
}
else
{
Console.WriteLine("Not RESPONSE was received");
}
break;
default:
Console.WriteLine("Only get and set implemented");
break;
}
}
}
}
}
16 changes: 16 additions & 0 deletions Lab2/SnmpClient/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
## Лабораторная №2 - SNMP клиент

### Сборка

Для сборки необходим .NET Core v3.10+. По команде `dotnet run` программа будет запущена без создания исполняемого файла.
Для полной сборки проекта команда `dotnet build`.

### Запуск

Необходим запускать с правами администратора, так как 123 порт находится в зарезервированных системой.

### Snmp клиент

Клиент работает с SNMP v2c. Реализованы только простые команды set и get для типов Integer и OctetString.

Клиент тестировался подключением к старому роутеру tp-link, откопанном в шкафу.
Loading