All about the DHCP server callout API functions.


Ah now for the best part. I had always wanted to test this callout API thing. This is perhaps the most powerful way to leverage your Windows DHCP server. With the DHCP server callout, in a way, the whole DHCP server source code is before you for you to change and fine tune to your specific needs. In reality you really don’t get the source code access but you do get all the power you would get had you really had the source code access. This is perhaps the best way to encourage people to build upon and extend your software’s capability while still staying in the commercial realm and without throwing open the product’s source code. I won’t discuss the nitty-gritties of this callout technique as it has been properly documented here: DHCP Server callout API.

Possiblities unlimited:

Some of the exciting things that are possible with the DHCP Callout DLL:
1) Create a parallel lease database in your favorite DB say SQLServer. With this you get the power to monitor the leasing process in a very flexible way (say using SQL, you can run a query to list all those machines which got an IP address in the last 2 hours).
2) Create customized extensions to the DHCP server: This is a pretty loaded sentence. What this fact implies is that with the callout DLL, you can prevent giving IP address unless the client satifies some policy: like membership to a given user class or a given vendor class. This is pretty usefull if you want to enforce minimum security to your enterprise, just ensure that only the authenticaled users are let known the user class say ‘xyz’. Now prevent leasing out IP address unless the client belongs to this user class. This can be done when you implement the function DhcpNewPktHook and set the ProcessIt flag to FALSE when you don’t see the right user class in the Packet. For this you need to parse the packet which is a BYTE *. 🙁

Now for the hard part: Even though this callout DLL support has been there for a while, I really don’t see people using this. (Prove me wrong!) Even though the online documentation has clearly explained the technology in some good detail, there is no sample code which people can readily use. So here I am to give you exactly these: A sample implementation of the callout DLL and the registry settings to enable the callout DLL’s functioning.

Sample Code:

//Mind you this is a very simple implementation of the callout DLL.

//Our callout function just logs the various states into a file (and that too incompletely..)

//But I guess you people should take it from here……

#include <windows.h>
#include <stdio.h>
#include “dhcpssdk.h”

FILE * CalloutFile;

DWORD CALLBACK DhcpAddressDelHook
 (LPBYTE Packet,DWORD PacketSize,DWORD ControlCode,DWORD IpAddress,DWORD AltAddress,LPVOID Reserved,LPVOID PktContext)
{
 return ERROR_SUCCESS;
}

DWORD CALLBACK DhcpAddressOfferHook
 (LPBYTE Packet,DWORD PacketSize,DWORD ControlCode, DWORD IpAddress,DWORD AltAddress,DWORD AddrType,DWORD LeaseTime,LPVOID Reserved,LPVOID PktContext)
{
 char PacketBuff[4096];
 if(ControlCode==DHCP_GIVE_ADDRESS_NEW)
 {
  fprintf(CalloutFile,”Offering new address %x %d on interface %x for %d seconds\n”,AltAddress,AltAddress,IpAddress,LeaseTime);
 }
 else if(ControlCode==DHCP_GIVE_ADDRESS_OLD)
 {
  fprintf(CalloutFile,”Offering old address %x %d on interface %x for %d seconds\n”,AltAddress,AltAddress,IpAddress,LeaseTime);
 }
 if(PacketSize<4096)
 {
  memcpy(PacketBuff,Packet,PacketSize);
  PacketBuff[PacketSize]=’\0′;
  fprintf(CalloutFile,”Packet: %s\n”,PacketBuff);
 }
 return ERROR_SUCCESS;
}

DWORD CALLBACK DhcpControlHook(DWORD dwControlCode,LPVOID lpReserved)
{
 switch (dwControlCode)
 {
 case DHCP_CONTROL_START:
  {
   CalloutFile=fopen(“callout.txt”,”w”);
   fprintf(CalloutFile,”The DHCP server has successfully started.\n”);
   break;
  }
 case DHCP_CONTROL_STOP:
  {
   fprintf(CalloutFile,”The DHCP server has successfully stoped.\n”);
   fclose(CalloutFile);
   break;
  }
 case DHCP_CONTROL_PAUSE:
  {
   fprintf(CalloutFile,”The DHCP server has been paused.\n”);
   break;
  }
 case DHCP_CONTROL_CONTINUE:
  {
   fprintf(CalloutFile,”The DHCP server has been continued.\n”);
   break;
  }   
 }
 return ERROR_SUCCESS;
}

DWORD CALLBACK DhcpDeleteClientHook(DWORD IpAddress, LPBYTE HwAddress,ULONG HwAddressLength, DWORD Reserved,DWORD ClientType)
{
 return ERROR_SUCCESS;
}

DWORD CALLBACK DhcpNewPktHook(LPBYTE* Packet,DWORD* PacketSize,DWORD IpAddress,LPVOID Reserved,LPVOID* PktContext,LPBOOL ProcessIt)
{
 return ERROR_SUCCESS;
}

DWORD CALLBACK DhcpPktDropHook(LPBYTE* Packet,DWORD* PacketSize,DWORD ControlCode, DWORD IpAddress,LPVOID Reserved,LPVOID PktContext)
{
 return ERROR_SUCCESS;
}

DWORD CALLBACK DhcpPktSendHook(LPBYTE* Packet,DWORD* PacketSize,DWORD ControlCode,DWORD IpAddress,LPVOID Reserved,LPVOID PktContext)
{
 return ERROR_SUCCESS;
}

DWORD CALLBACK DhcpServerCalloutEntry(LPWSTR ChainDlls,DWORD CalloutVersion,LPDHCP_CALLOUT_TABLE CalloutTbl)
{
 CalloutTbl->DhcpAddressDelHook=DhcpAddressDelHook;
 CalloutTbl->DhcpControlHook=DhcpControlHook;
 CalloutTbl->DhcpDeleteClientHook=DhcpDeleteClientHook;
 CalloutTbl->DhcpPktDropHook=DhcpPktDropHook;
 CalloutTbl->DhcpAddressDelHook=DhcpAddressDelHook;
 CalloutTbl->DhcpNewPktHook=DhcpNewPktHook;
 CalloutTbl->DhcpPktSendHook=DhcpPktSendHook;
 return ERROR_SUCCESS;
}

The DHCP callout Cookbook:
1) After writing your program for creating the callout DLL, make sure that your DLL exports the functions DhcpServerCalloutEntry, DhcpAddressDelHook, DhcpControlHook, DhcpPktDropHook, DhcpAddressDelHook, DhcpNewPktHook and DhcpPktSendHook. These functions should be GetProcAddress’able once the DHCP Server LoadLibrary’s your DLL. Otherwise you would be seeing the event 1034 logged on to your system event log.
2)One more thing, to compile this code you should be needing the Platform SDK. This is required as the header file which contains all the relevant callout data structures, dhcpssdk.h comes along with the Platform SDK. Don’t forget to set your compiler’s include path to the place where dhcpssdk.h is copied.
3) Last but not the least once you have created the DLL, you can copy it to any place (say c:\callout\callout.dll) in your Windows server (Windows Server 2003 or Windows 2000 Server.)
4) Now comes the registry nibbling part. As usual backup your registry. The following are the two registry entries which should be created and which are located within:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\DHCPServer\Parameters
1)
Name :  CalloutDlls
Value : list of path/filenames for the dlls to be loaded. In our case it is c:\callout\callout.dll
Type : REG_MULTI_SZ
2)
Name : CalloutEnabled
Value :
 0 = DHCP Server does not attempt load of callout.dlls
 1 = DHCP Server attempts to load callout.dlls
Type : DWORD

 BTW, This information is not available in the MSDN.

Now restart the DHCP service. If everything went well you should see the event 1033 logged on in your system event log: “The DHCP service has successfully loaded one or more callout DLLs.” Congrats!


Comments (33)

  1. Anonymous says:

    I have looked for this before, I just didn’t know what to search for.

    I have looked for scripting dhcp, loading dhcp as a ActiveX control, and commandline access. And I never found what I was looking for.

    I was wanting to track DHCP requests and limit who is to receive them. This is exactly what I needed.

    other questions. How would this work with VB.NET? I probably shouldn’t write DHCP dll’s in managed code, but VB is our standard language. Would it be easyer to write a wrapper in C++ to let me do the work in VB.NET? Any thoughts?

    What about running 2 DHCP Servers on the same box and loading custom DLL’s. I want one group of computers to get one ip range and another to get a different range. Would that be possible, or am I dreaming.

  2. Anonymous says:

    I have looked for this before, I just didn’t know what to search for.

    I have looked for scripting dhcp, loading dhcp as a ActiveX control, and commandline access. And I never found what I was looking for.

    I was wanting to track DHCP requests and limit who is to receive them. This is exactly what I needed.

    other questions. How would this work with VB.NET? I probably shouldn’t write DHCP dll’s in managed code, but VB is our standard language. Would it be easyer to write a wrapper in C++ to let me do the work in VB.NET? Any thoughts?

    What about running 2 DHCP Servers on the same box and loading custom DLL’s. I want one group of computers to get one ip range and another to get a different range. Would that be possible, or am I dreaming.

  3. Anonymous says:

    I guess you can write C++ wrapper arround the managed code. This should be possible.

    Other than that, I don’t know why you should be running two DHCP servers on the same box. If all you wanted to acheive was to make sure that computers belonging to two distinct groups are allocated an IP address from two distinct ranges (scopes in DHCP terminology), I am afraid that this is not possible today. The reason why this is not possible today is that the DHCP server chooses a scope from which it doles out an IP address based only on the subnet where the client is existing. This is done so that the machine gets an address that is appropriate to the link.

  4. Anonymous says:

    I have an idea that should work in theory.

    I want to give a scope to all authorized computers and a private scope to all others.

    The computers will exist on the same physical network, but on different subnets.

    I do have a reason for my madness

  5. Anonymous says:

    I guess you can do that. But for this you must sort of hack the packet pointer variable ‘Packet’ got in the the function DhcpNewPktHook. You can overwrite the giaddr field in the packet buffer to the subnet address of the scope from which you want to assign the IP address. Say for unauthenticated computers you might want to allocate addresses from scope 192.168.200.0 then you might want to overwrite the giaddr field to 192.168.200.1 to fool the server that this packet had come from the segment 192.168.200.0 and hence we must allocate the address from that scope. This is in accordance with the RFC 2131. This is fine but this involves parsing the packet which is a BYTE *. I really don’t know if this will work. Have not tried it myself. The possible issues that might arise is that: if the packet origanally comes from the local network on which the DHCP server is attached then the DHCP server might send the resonse in a different way than when the packet orignates from the remote network as we are feingning it.

  6. Anonymous says:

    Hi,

    I’ve just read your article http://weblogs.asp.net/anto_rocks/archive/2005/02/25/380510.aspx, I built the dll from your source code and installed it on my server, sure enough up popped the event number 1033, it seemed that everything went well. Now I paused, and resumed my server, to check it was working correctly, but the text file callout.txt remained blank. I’ve also been playing with DhcpEnumSubnetClients, with equally low success rates. Both your dll and the code I wrote to make use of the DhcpEnumSubnetClients function look like they should work, but both are returning nothing.

    Is there something that I need to install on my server? (it’s a windows 2003 server, if that makes any difference) Is there a redistributable or some such that I need to install?

    Any help would be gratefully received.

    Regards,

    Rob

  7. Anonymous says:

    You do not need anything further than a Win2K3 server. I assume the file was created by the DHCP server but you don’t see anything there. I don’t get understand why this should be happening. Maybe we are missing something. Did u change the registry? Maybe there is someone else in the blogosphere who can help Rob??

  8. Anonymous says:

    This is what I obtained. Can you explain this?

    Value obtained from file system volume descriptor pointer: 0x347cb00

    The old setting was THU JAN 01 00:00:00 1970

    Accepted system dates are greater than THU DEC 27 00:00:00 1990

    ramdrv:/ – Volume is OK

    tffsdrv: DOS mounting Complete

    tffsdrv:/ – Volume is OK

    nvdrv: DOS mounting Complete

    nvdrv:/ – Volume is OK

    0x34b97c8 (tStartup): WARNING: RAM db is deleted

  9. Anonymous says:

    Does anyone know how to dissect the lpbyte packet parameter and get the hostname requesting the IP address?

    Thanks.

  10. Anonymous says:

    Wow, I have finally found someone doing something with the callout.

    I have had the callout running for sometime now on a Windows 2K3 server in the lab pumping out all kinds of good stuff.

    My plan is to set up a parameter and reject those machines that dont pass the various test such as minimum patch level and virus pattern files.

    The DLL was easy, the hard part has been the "back end" stuff.

  11. Anonymous says:

    Hello,

    I’m lucky to find the article and the web site. It is very useful for me to develop an external dll of a DHCP server.

    I am planing to reject to offer address to some machine. How can I do it?

    Thanks

  12. Anonymous says:

    well, DhcpNewPktHook may fit your needs,

    set the (LPBOOL ProcessIt) flag with FALSE, DHCP will drop the packet, you can add your own judgement to process it. be care LPBOOL. it is a point;

  13. Anonymous says:

    I want to assign IPs from a different pools depending on the network card.

    I have a W2K3 server with 4 network cards and I want a range of IPs for every card. I conect a group of clients to every card and I can know what group of clients belong with the IP of the client in a proxy application.

    I can make the DLL in VS2005 C#?

    GREAT!!!

  14. ratna says:

    I ave included the callout.dll in windows2003 server.everthing sems to be fine but the dll is not able to log the messages when a new client request for an ipaddress from DHCP server.

    please help

  15. Anonymous says:

    Hi

    Dear

    I want to use your method that is a very good

    way to have an extention to DHCP

    But when I make this DLL in VC++.Net 2003 and make regitery changes I have a very bad Error

    1034 : The sepscified procedure could not bE found

    My server Is Win 2003

    and i dont know exactly where i should paste your code sample

    I make an Class Lib in VC++.Net 2003 and paste the sample code in cpp file what is wrong

    Please Help Me?

    Please

    Best regards

    Meenavee

  16. Anonymous says:

    I have taken a looka t using the DHCP call out but I need some assistants in tryin to determine how to manipulate the response. I understan I need to modify the packet contents before being sent. Again I think I need to use the call out DhcpNewPktHook. I can not figure out how to refrenece the portion of the packet?

    Any quick sample on how to make this call? or perhaps does someone know who might help. All I want is help on changing various response fields such as gateway & mask values. Please help I am my witts end.

    Cheers,

    Scrappy

  17. Anonymous says:

    I work at an ISP and I am trying to use these API functions to migrate our DSL Customers from Static IP’s to DHCP. In order for me to sell this the transition must be seamless. Our Router will append Option 82 which contains the ATM Virtual Circuit that is assigned to the customer. I have a working DLL that will disect the packet and get the Virtual Circuit information out, and then it will Query our MySQL database to reference ther Virtual Circuit to there old Static IP. Now all I need to do is send the IP that I get from the Database, how can I do this, should I use DHCPPacketSendHook?

  18. Anonymous says:

    Hi, this is certainly the most useful BLOG on the subject. Thanks Anton.

    Is it possible to hook into the server callout functions using c#.net or vb.net? Is so , how do I call it?

    phil

  19. Anonymous says:

    Hi,

    the "restrict clients" feature was one thing that bugged me back in 2003, so I wrote a Delphi callout DLL for the MS DHCP server back then. Although it performed quite well, I decided to port it to C at some point and enhance it a little. The result is MACkerer2 and you can read about it here:

    http://blog.assarbad.info/20060814/mackerer_en/

    The whole idea is to limit the clients by their MAC addresses, which are stored in an Apache-like configuration file. There are advanced logging features that will blow your mind if you would like to give a certain context to the IP/MAC (i.e. lease) that was given out on 3rd of May 2004, for example. If you have given the respective information in the configuration file, it will be contained in the log file. Logging features can be turned on and off …

    The tool (i.e. the DLL) is OpenSource under the BSD license which allows anyone to use it even in ClosedSource projects as long as the conditions of the license are met.

    The DLL as it is provided for download from

    http://assarbad.info/stuff/MACkerer2.rar

    was running for more than 2 years in its current form on Windows 2000 Server and Windows 2003 Server and has proven its reliability. The method was, as I pointed out, implemented earlier in a Delphi DLL and is approx. 1 year older than the version of the DLL offered.

    Have fun with MACkerer2 … and spread the word!

    // Oliver

  20. Anonymous says:

    Ah now for the best part. I had always wanted to test this callout API thing. This is perhaps the most powerful way to leverage your Windows DHCP server. With the DHCP server callout, in a way, the whole DHCP server source code is before you for you to change and fine tune to your specific needs. In reality you really don’t get the source code access but you do get all the power you would get had you really had the source code access. This is perhaps the best way to encourage people to build upon and extend your software’s capability while still staying in the commercial&nbsp;realm and without throwing open the product’s source code.&nbsp;I won’t discuss the&nbsp;nitty-gritties of this callout technique as it has been properly documented&nbsp;here: DHCP Server callout API.

    I do not agree. Go to http://www.hotelsmall.info/laurel_Italy/abstruse_Lombardia/gimp_Milan_1.html

  21. Anonymous says:

    Ah now for the best part. I had always wanted to test this callout API thing. This is perhaps the most powerful way to leverage your Windows DHCP server. With the DHCP server callout, in a way, the whole DHCP server source code is before you for you to change and fine tune to your specific needs. In reality you really don’t get the source code access but you do get all the power you would get had you really had the source code access. This is perhaps the best way to encourage people to build upon and extend your software’s capability while still staying in the commercial&nbsp;realm and without throwing open the product’s source code.&nbsp;I won’t discuss the&nbsp;nitty-gritties of this callout technique as it has been properly documented&nbsp;here: DHCP Server callout API.

    I do not agree. Go to http://www.myromehotel.info/toll_France/caisson_Pays%20de%20la%20Loire/crayon_La%20Baule_1.html

  22. Anonymous says:

    Great post. The MSDN documentation on this stuff is ok, but it contains a flaw in not telling us that the registry value required is "CalloutDlls". Without that info no-one is going to be able to use this stuff, and this is the only place I was able to find it.

  23. Anonymous says:

    Has anyone managed to use DHCPPacketSendHook or DhcpNewPktHook to modify the packet and add more options for example. I understand the API reasonably well, however it isn’t obvious how to handle memory allocation/freeing etc when extending the packet. Has anyone done this?

  24. Anonymous says:

    Ah now for the best part. I had always wanted to test this callout API thing. This is perhaps the most powerful way to leverage your Windows DHCP server. With the DHCP server callout, in a way, the whole DHCP server source code is before you for you to change and fine tune to your specific needs. In reality you really don’t get the source code access but you do get all the power you would get had you really had the source code access. This is perhaps the best way to encourage people to build upon and extend your software’s capability while still staying in the commercial&nbsp;realm and without throwing open the product’s source code.&nbsp;I won’t discuss the&nbsp;nitty-gritties of this callout technique as it has been properly documented&nbsp;here: DHCP Server callout API.

    I do not agree. Go to http://apartments.waw.pl/

  25. Anonymous says:

    Hi,

    The good work. I am researching DHCP for detect new computer when plug in LAN, so You could share your code to me .

    Thanks very much

    Regards,

  26. Anonymous says:

    Is there a way not to allow the dhcp server to assign an IP to a machine until you make a reservation for the machine, without using the call out api?

    for example, on a Linux machine, you can configure the Linux DHCP server with option "ignore unknown-clients" to forbid the server assign IPs to unknown machines.

    Thank

    Dave

  27. Anonymous says:

    the asp.net C# code for the code you written in C

  28. Anonymous says:

    A.J.Anto: The log file is fopen'ed using buffering, so the contents don't get written until the buffer is full or the service is stopped. Change the fopen mode from "w" to "wc" and call fflush to see each line as it's written.

    Also, the code that sets the CalloutTable sets DhcpAddressDelHook twice, but doesn't set DhcpAddressOfferHook once – simple fix.

    Finally, if you compile a 32-bit DLL but install in x64 Windows, you get an error "%1 is not a valid Win32 application" – which might make you think that you did the right thing and it should be a win32 dll – but in fact it must be an x64 DLL.

    It's unfortunate that the DHCP server doesn't report the underlying error code, and the %1 is not substituted for the name of the DLL file being loaded.