Merge from amd64-branch:
[reactos.git] / reactos / lib / drivers / ip / network / ports.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS TCP/IP protocol driver
4 * FILE: tcpip/ports.c
5 * PURPOSE: Port allocation
6 * PROGRAMMERS: arty (ayerkes@speakeasy.net)
7 * REVISIONS:
8 * arty 20041114 Created
9 */
10
11 #include "precomp.h"
12
13 NTSTATUS PortsStartup( PPORT_SET PortSet,
14 UINT StartingPort,
15 UINT PortsToManage ) {
16 PortSet->StartingPort = StartingPort;
17 PortSet->PortsToOversee = PortsToManage;
18
19 PortSet->ProtoBitBuffer =
20 ExAllocatePoolWithTag( NonPagedPool, (PortSet->PortsToOversee + 7) / 8,
21 PORT_SET_TAG );
22 if(!PortSet->ProtoBitBuffer) return STATUS_INSUFFICIENT_RESOURCES;
23 RtlInitializeBitMap( &PortSet->ProtoBitmap,
24 PortSet->ProtoBitBuffer,
25 PortSet->PortsToOversee );
26 RtlClearAllBits( &PortSet->ProtoBitmap );
27 KeInitializeSpinLock( &PortSet->Lock );
28 return STATUS_SUCCESS;
29 }
30
31 VOID PortsShutdown( PPORT_SET PortSet ) {
32 ExFreePoolWithTag( PortSet->ProtoBitBuffer, PORT_SET_TAG );
33 }
34
35 VOID DeallocatePort( PPORT_SET PortSet, ULONG Port ) {
36 KIRQL OldIrql;
37
38 Port = htons(Port);
39 ASSERT(Port >= PortSet->StartingPort);
40 ASSERT(Port < PortSet->StartingPort + PortSet->PortsToOversee);
41
42 KeAcquireSpinLock( &PortSet->Lock, &OldIrql );
43 RtlClearBits( &PortSet->ProtoBitmap, Port - PortSet->StartingPort, 1 );
44 KeReleaseSpinLock( &PortSet->Lock, OldIrql );
45 }
46
47 BOOLEAN AllocatePort( PPORT_SET PortSet, ULONG Port ) {
48 BOOLEAN Clear;
49 KIRQL OldIrql;
50
51 Port = htons(Port);
52
53 if ((Port < PortSet->StartingPort) ||
54 (Port >= PortSet->StartingPort + PortSet->PortsToOversee))
55 {
56 return FALSE;
57 }
58
59 Port -= PortSet->StartingPort;
60
61 KeAcquireSpinLock( &PortSet->Lock, &OldIrql );
62 Clear = RtlAreBitsClear( &PortSet->ProtoBitmap, Port, 1 );
63 if( Clear ) RtlSetBits( &PortSet->ProtoBitmap, Port, 1 );
64 KeReleaseSpinLock( &PortSet->Lock, OldIrql );
65
66 return Clear;
67 }
68
69 ULONG AllocateAnyPort( PPORT_SET PortSet ) {
70 ULONG AllocatedPort;
71 KIRQL OldIrql;
72
73 KeAcquireSpinLock( &PortSet->Lock, &OldIrql );
74 AllocatedPort = RtlFindClearBits( &PortSet->ProtoBitmap, 1, 0 );
75 if( AllocatedPort != (ULONG)-1 ) {
76 RtlSetBit( &PortSet->ProtoBitmap, AllocatedPort );
77 AllocatedPort += PortSet->StartingPort;
78 KeReleaseSpinLock( &PortSet->Lock, OldIrql );
79 return htons(AllocatedPort);
80 }
81 KeReleaseSpinLock( &PortSet->Lock, OldIrql );
82
83 return -1;
84 }
85
86 ULONG AllocatePortFromRange( PPORT_SET PortSet, ULONG Lowest, ULONG Highest ) {
87 ULONG AllocatedPort;
88 KIRQL OldIrql;
89
90 if ((Lowest < PortSet->StartingPort) ||
91 (Highest >= PortSet->StartingPort + PortSet->PortsToOversee))
92 {
93 return -1;
94 }
95
96 Lowest -= PortSet->StartingPort;
97 Highest -= PortSet->StartingPort;
98
99 KeAcquireSpinLock( &PortSet->Lock, &OldIrql );
100 AllocatedPort = RtlFindClearBits( &PortSet->ProtoBitmap, 1, Lowest );
101 if( AllocatedPort != (ULONG)-1 && AllocatedPort <= Highest) {
102 RtlSetBit( &PortSet->ProtoBitmap, AllocatedPort );
103 AllocatedPort += PortSet->StartingPort;
104 KeReleaseSpinLock( &PortSet->Lock, OldIrql );
105 return htons(AllocatedPort);
106 }
107 KeReleaseSpinLock( &PortSet->Lock, OldIrql );
108
109 return -1;
110 }