xref: /reactos/drivers/network/tcpip/ip/network/ports.c (revision 1734f297)
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 
PortsStartup(PPORT_SET PortSet,UINT StartingPort,UINT PortsToManage)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 
PortsShutdown(PPORT_SET PortSet)31 VOID PortsShutdown( PPORT_SET PortSet ) {
32     ExFreePoolWithTag( PortSet->ProtoBitBuffer, PORT_SET_TAG );
33 }
34 
DeallocatePort(PPORT_SET PortSet,ULONG Port)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 
AllocatePort(PPORT_SET PortSet,ULONG Port)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 
AllocateAnyPort(PPORT_SET PortSet)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 
AllocatePortFromRange(PPORT_SET PortSet,ULONG Lowest,ULONG Highest)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 }
111