issues and solutions for dhcp - vxdev.com · issues and solutions for dhcp appnote-212 ... you will...

42
AppNote-212 Issues and Solutions for DHCP Copyright © 1984-2002 Wind River Systems Inc. ALL RIGHTS RESERVED. Abstract There are three DHCP components provided in VxWorks: the DHCP Client, Relay Agent and Server. The VxWorks Networking Programmer’s Guide covers the basic operation of these components. This release note includes configuration details, answers to common questions and troubleshooting suggestions. The majority of the note applies to Tornado 2.0 and 2.02. If you are using Tornado 2.2 and cannot find information that answers your questions here, please contact Technical Support. DHCP in VxWorks

Upload: duongbao

Post on 16-May-2018

214 views

Category:

Documents


1 download

TRANSCRIPT

AppNote-212

Issues and Solutions for DHCP Copyright © 1984-2002 Wind River Systems Inc. ALL RIGHTS RESERVED. Abstract

There are three DHCP components provided in VxWorks: the DHCP Client, Relay Agent and Server. The VxWorks Networking Programmer’s Guide covers the basic operation of these components. This release note includes configuration details, answers to common questions and troubleshooting suggestions. The majority of the note applies to Tornado 2.0 and 2.02. If you are using Tornado 2.2 and cannot find information that answers your questions here, please contact Technical Support.

DHCP in VxWorks

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

2

DHCP Configuration Files The DHCP components are configurable both at the command line and within the Project Facility. If you are using the Project Facility, you will edit the VxWorks configlette files. The DHCP configlette files are in the following locations: /comps/src/net/usrNetDhcpcCfg.c /comps/src/net/usrNetDhcpcBootSetup.c /comps/src/net/usrDhcpcCfg.c /comps/src/net/usrNetDhcprCfg.c /comps/src/net/usrNetDhcpsCfg.c

If you are building from the command line, you will edit one file: /target/src/config/usrNetwork.c

The DHCP Client You can build the runtime DHCP client into a VxWorks image from the command line or from the Project Facility.

Command Line Build Include the following line in the config.h file: #define INCLUDE_DHCPC #define configAll.h

Rebuild the image. To verify inclusion of DHCP, use the nm utility. For example:

nmppc --numeric-sort vxWorks | grep -i DHCP

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

3

Project Facility Build Include the DHCP Client in the networking applications section of the Project Facility. In the Project Facility, select:

network components -> network protocols -> network applications

??DHCPv4 runtime client

You will notice a configuration error when you include the DHCP client in the Project Facility. This is a known issue (SPR is #27224), and is not under revision. The workaround is to remove the component named “DHCP client timestamp removal” in the bootline processing components. To find this components, go down the Project Facility tree: network components -> basic network initialization

-> bootline processing components -> DHCP device address initialization

??DHCP client timestamp removal

DHCP State Machine

DHCP Lease Negotiation The DHCP Client State Machine describes the progression of a DHCP negotiation. The VxWorks client follows the DHCP Client State Machine as it is described in RFC 2131. The process of acquiring a DHCP lease is straightforward: the DHCP client sends a DISCOVER message (a broadcast). DHCP servers respond to the message with DHCP OFFER messages. Once the OFFERS are collected, the client makes a decision as to which lease to select and sends a REQUEST message. The server acknowledges the REQUEST with an ACK message and sends a lease. DHCP Client Lease Selection The DHCP client will always choose the lease offer with the longest lease time, regardless of the options that are set on the client side. If the offered leases have the same times, then the lease offer that arrived first will be selected. The dhcpcBind(<interface>, <syncFlag>) call fails if no server is available. If dhcpcBind has the <syncFlag> parameter set to TRUE (synchronous), the call waits until the timeout occurs, then returns ERROR. If the <syncFlag is set to FALSE, the status is reported to an event hook that the user must install. Without an event hook, the call will succeed or fail silently. For more information about Event Hooks, see the section entitled DHCP Event Hook. The timeout algorithm is specified in RFCs 1541 and 2131. The formula is an exponential backoff, which is roughly 1 minute. DHCP Client Lease Renewal The lease renewal routine contains the fifth state of the client state machine. When the renewing routine is executed, a DHCP lease is already active on the client. The lease renewal begins when the first DHCP timer expires (T1). The renewal sends a REQUEST message to the issuing server, which decides whether or not it will allow the same lease to be used. If the server does accept the renewal, the renewing routine returns and the client enters the next state.

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

4

If the renewal does not succeed, the client goes back to the first state, INIT. If a timeout occurs before the second timer (T2) expires, the DHCP client retransmits the REQUEST message and waits for a reply. If the timer does expire, the client enters a rebinding routine, which sends a broadcast REQUEST to all servers. In this case, a different server may respond to the client. In the VxWorks DHCP client, the period of time the client waits for offers after receiving the first offer from a server. The time that elapses is the value for offerTimeout in the function arguments. Adjusting Retransmission Times A common question is that of reducing the time the DHCP client spends waiting for a response from the server. It is possible to reduce the number of DHCP DISCOVER retransmissions. This will not change the time interval, but it will reduce the overall wait time. The value, DISCOVER_RETRANS is an internal state machine setting and is defined in dhcpcCommonState.h. If you wish to change the number of retransmissions, you will require DHCP source code. How Do I Change the DHCP Lease Interval? The client sends requests at the intervals specified in the protocol, which can’t be changed directly. The best way to alter renewal times is to adjust the lease interval. For an established lease, the client sends a request message to renew it after half the duration, so providing a 10 minute lease would cause the first renewal attempts to occur at 5 minute intervals. Alternatively, the server can use different lease durations and specify a specific percentage value with the T1 and T2 options for the lease. In any case, there isn’t any method that absolutely guarantees a fixed interval between requests, since those messages will arrive more frequently if the server does not reply to the first renewal attempt. There isn’t any method for altering the interval of request messages during the negotiation process, except for rewriting the source code to use different values than those outlined in the RFC specification.

Boot Time DHCP To use the DHCP client at boot time, include the DHCP client in the boot ROM image.

Edit /target/config/<BSP directory>/config.h:

#define INCLUDE_DHCPC #include "configAll.h" #include "pc.h"

After adding that line, change the default boot line so that it will use DHCP. #define DEFAULT_BOOT_LINE \ "fei(0,0)ala-raritan:D:/Tornado/target/config/pcPentium/default/vxWorks h=147.11.38.89 f=0x40"

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

5

The 0x40 flag is the DHCP flag. If you did not include the DHCP client in the boot image, the BOOTP client will execute at startup.

Rebuild the image.

Why Does the DHCP Runtime Client Immediately Renew the Lease Acquired at Boot Time? This behavior occurs because the system resets before starting the runtime image. As a result, it is impossible to track the elapsed time since the boot image obtained the lease. The size of the downloaded runtime image and the type of connection contribute to this variation. The renewal verifies the assigned address in case the lease expired. Why Can’t I Acquire an Address Dynamically When Booting Over a Non-Networked Device? Those wishing to boot using DHCP over a boot device other than the network card may have difficulty. Tornado 2.02 and 2.0 are deficient in providing DHCP functionality (SPR #73762) for non-networked boot devices. A workaround exists for Tornado 2.02 users, but upgrading to Tornado 2.2 is recommended, as it provides the best solution.

Why is the DHCP Address Changing to a 10.0.x.x Address? When a lease is in the process of being acquired, the interface is temporarily shut down and restarted. The routine to reset the interface sets its address to 10.x.x.x, resets the broadcast address, subnet mask, and flushes the routing tables. The routine is called before initiating a lease negotiation if no event notification hook is present. Specifying an IP Address at Lease Request Time To assign a specific IP address to a requesting interface, configure the DHCP client id (clid) option. This is applicable to Tornado 2.0 and 2.2. There are some difficulties when using this option in Tornado 2.02. Please see Application Note #81 for more information. The clid member is a pointer to another struct into which dhcpcOptionSet() copies the arguments passed. dhcpcOptionAdd(pCookie, _DHCP_CLIENT_ID_TAG, 6, etherAddress)

If you are using a VxWorks DHCP Server, the correct way to make this call is: dhcpcOptionAdd(pCookie, _DHCP_CLIENT_ID_TAG, 7, etherAddress)

dhcpcOptionAdd() calls calloc to allocate space for the client_id struct, assigns the address to clid and then copies the identifier from pData to the clid->id member. See Application Note #81 for implementation details. Incorporating Gateway Retrieval for DHCP for the boot ROM image Users often wish to retrieve the gateway address through which their DHCP offer arrived. To do this, modify bootConfig.c. First, in the function dhcpGet():

1. Declare router structures: STATUS result; struct ifnet *pIf; /* pointer to network interface data*/ char serverAddr [INET_ADDR_LEN]; /* DHCP server address*/ char bootFile [BOOT_FILE_LEN]; /* name of boot file*/

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

6

int subnetMask; /* subnet mask */ void * pCookie; struct dhcp_param bootParams; struct in_addrs routerStruct; <-- add struct in_addr routerAddress; <-- add

2. Add the following lines for the router structure setup: bzero ( (char *) &routerAddress, sizeof (struct in_addr));

routerStruct.num = 1; routerStruct.addr = &routerAddress; bootParams.router = &routerStruct; /* Need target IP address to boot over the backplane */

3. Set the router option tag:

dhcpcOptionSet (pCookie, _DHCP_ROUTER_TAG); if (pBootDevAddr[0] == EOS) { /* Attempt to retrieve address information from a DHCP server. */

4. Fill in the host address. Find this line: /* * Fill in the target's IP address, if needed. The status * variable indicates the source of the IP address as follows:

Add the following above it:

/* fill in gateway address */ if(pGateway [0] == EOS && routerAddress.s_addr != 0)

{ inet_ntoa_b (routerAddress, pGateway); printf ("Gateway: %s\n", pGateway); }

5. To add a default route, change the line in bootLoad() in bootConfig.c: /* if a gateway was specified, extract the network part

* of the host's address and add a route to this network

*/

printf("Will try to add default route.\n");

if (params.gad[0] != EOS)

{

if(routeAdd("0.0.0.0", params.gad) == ERROR)

printf("Error adding gateway as default route.\n");

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

7

else

printf("Router's address: %s\n", params.gad); Why Does the boot ROM Have Its Own Version of DHCP? The boot ROM code uses a trimmed down version of the DHCP code because when the code was developed, there was a limitation in boot ROM size. The boot ROM version of DHCP is limited to obtaining a lease and does not permit renewal or rebinding of leases. Replace DHCP boot library API calls with standard DHCP library API calls. To change the boot code, modify target/config/all/bootConfig.c. What are the ARP Messages That I See Being Sent Out During Negotiation? When a DHCP lease negotiation is performed, each client performs an ARP probe to verify that the offered address from the server is not in use by another machine. This ARP probe occurs when a DHCP server sends an OFFER message to the DHCP client. The client sends the ARP broadcast across the network.

The boot sequence also includes the target sending of a gratuitous ARP message for its boot address. This will happen whether or not DHCP was used to obtain an address. If more than one client sends back a reply to this ARP message, it indicates an address conflict on the network. The gratuitious ARP message is sent out only after an ACK is received from the DHCP server. The ARP message sent to check the OFFER message IP address is not required according to the DHCP RFC. However, it is a common feature implemented in DHCP clients. The gratutious ARP message is a feature of the IP stack. If you wish to remove it, you will have to make changes to the source code. The DHCP Boot Client Does Not Process Incoming OFFER Packets When Using BSD Drivers SPR #79330 existed in Tornado 2.02 + SPR #68322 within the Berkeley Packet Filter (BPF). The BPF is responsible for capturing packets and sending them to the DHCP client application. A symptom of this bug is that of the client sending a DHCP DISCOVER message, the server replying with an OFFER, and the client then ignoring the OFFER. This SPR was fixed in Tornado 2.2 DHCP Event Hook The DHCP Event Hook serves as a way to handle changes in the configuration parameters. The hook is invoked by using the dhcpcEventHookAdd() routine. As stated in the documentation, the hook itself provides an alternate configuration method for DHCP leases using the dhcpcEventHookRtn() interface. Two events may occur: DHCPC_LEASE_NEW and DHCPC_LEASE_INVALID. The DHCPC_LEASE_NEW event occurs whenever a new lease is successfully established. The DHCPC_LEASE_INVALID event indicates that the parameters for the corresponding lease may no longer be used. The DHCP hook design prevents access to DHCP option processing in an effort to minimize time spent on tasks unrelated to event processing. This is the reason the error occurs. The source code that invokes the hook follows: status = use_parameter (pLeaseData->dhcpcParam, pLeaseData); semTake (dhcpcMutexSem, WAIT_FOREVER);

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

8

if (status != 0) { #ifdef DHCPC_DEBUG logMsg ("Error configuring network. Shutting down.\n", 0, 0, 0, 0, 0, 0); #endif pLeaseData->leaseGood = FALSE; } else { pLeaseData->leaseGood = TRUE; } semGive (dhcpcMutexSem);

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

9

If you attempt to access DHCP API functions from within the DHCP Event Hook, an error is returned: S_dhcpcLib_NOT_BOUND

Avoiding the S_dhcpcLib_NOT_BOUND Error The hook executes before the end of the use_parameter() routine. Any handler code that executes at a

priority lower than that of the DHCP client will receive the correct configuration information. All routines that retrieve DHCP lease parameters also obtain the above mutex semaphore. The operating system scheduler will guarantee the handler executes in the correct relative order without any explicit delay, avoiding the possibility of race conditions.

A way to get around the error condition mentioned above is to spawn a new task in advance, then use semGive() within the hook to trigger the lease handling in the new thread. As long as the new task ha a lower priority, it will retrieve the new information correctly.

Miscellaneous DHCP Issues

What Happens to Sockets that are Already Open When a DHCP Lease Expires or Renews? Open sockets are affected, depending on how the socket is configured. Sockets configured to use a specific IP address will not be accessible if a new IP address is assigned.

If the sockets were configured to use INADDR_ANY, then a new IP address will not affect the socket connections, except for possible send or receive failures. The calling application would have to handle such failures.

Why Does DHCP Begin a Full DHCP Negotiation Instead of Renewing the Lease? In Tornado 2.0 and 2.02, DHCP renewals fail if the system clock is changed after the DHCP client is initialized (SPR#68900). This problem occured because the DHCP client called the time() function, which returned the system

clock time relative to the time of booting, not to the actual time of day. If an application reset the system clock to the actual time of day, it was possible that the difference between the original system clock time and the actual time of day would far exceed the lease time. Therefore, the DHCP client behaved as though the lease had expired, and reinitialized the lease. This problem occurs only in Tornado 2.0, Tornado 2.02. It has been repaired in Tornado 2.2. If you have Tornado 2.0 or 2.02, contact WindRiver and refer to SPR #68900. The DHCP Client is not Detecting Renewals when the Lease is in RENEW or REBIND The DHCP Client had a bug in version T2.02 that kept it from detecting ACK messages sent after a renewal or a rebinding request. This problem has been fixed in Tornado 2.2. The repair is available from WindRiver. Refer to SPR #73243. Restrictions on DHCP Packet Lengths (SPR #65264) Resulting in Dropped DHCP Offers

SPR #65264 addresses the problem of DHCP OFFER packets that are not processed by the DHCP client. A symptom of this bug is the successful send of a DISCOVER, followed by a successful send of an OFFER from the DHCP server. However, the DHCP client does not pick up the OFFER packet. The problem is attributable to the DHCP client’s BPF filter not filtering packets shorter than 328 bytes. If this is the case in your system, contact WindRiver for a repair. The official fix for this problem has been released in Tornado 2.2.

Why is the DHCP Client Sending INFORM Messages?

The DHCP Client sends INFORM messages when the client interface is already configured, but requires additional parameters for local configuration. When a server receives a DHCPINFORM message, it will construct a DHCPACK

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

10

message with any local configuration parameters appropriate for the client. The DHCP Server will send a DHCPACK response directly to the address in the ‘ciaddr’ field of the DHCPINFORM message.

DHCP Client Code Samples Code samples are provided in the Appendix. These samples are unsupported. They are intended to be examples of how to use the API. Contact WindRiver if you have difficulty using the DHCP API’s.

dhcpcRuntime.c - an example of how to use dhcpcBind() to obtain a lease. Also includes an example of how to stop the DHCP lease.

dhcpLoop.c - continually sends DISCOVER packets until a server responds. Also contains event hook usage.

dhcpsSampleHook.c - example of a DHCP lease storage hook routine

Note: Sample Code is unsupported

BOOTP in VxWorks The Bootstrap Protocol (BOOTP) was a precursor of DHCP. A BOOTP client requests information from a BOOTP server. The BOOTP server keeps client information in two databases. One database stores the MAC addresses of clients and the other maps a filename to the client address. The filename is in the ‘file’ field, and will specify which file to load. The BOOTP client can be invoked at boot time or at runtime. To send a BOOTP message, use the bootpMsgSend()routine. It is documented in the API Reference. The bootConfig.c file is the system configuration module for boot ROMs. The bootConfig.c file is in D:\TornadoInstall\target \config\all Incorporating Gateway Retreival for BOOTP for boot ROM and Runtime Images

Like DHCP, BOOTP does not automatically get the gateway address through which a DHCP request occurred.

Detailed procedures:

Change code so that the gateway will be entered as the default route (0.0.0.0) a) Edit bootConfig.c to retrieve the gateway for the boot ROM image.

b) If you are building from the command line, edit /target/src/config/usrNetwork.c

c) If you are building with the Project Facility, edit /target/config/comps/src/net/usrNetRemoteCfg.c

/* if a gateway was specified, extract the network part of * the host's * address and add a route to this network */

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

11

if (params.gad[0] != EOS) { inet_netof_string (params.had, nad); routeAdd (nad, params.gad); } For example: target ethernet address = 147.11.41.198:ffffff00 host address = 147.11.48.28 then a gateway is needed = 147.11.41.254 This code would add a route to reach the host. ROUTE NET TABLE Destination Gateway 147.11.48.0 147.11.41.254 147.11.41.0 147.11.41.198

If the user needs to have the gateway as a default router then code, the following additions are necessary:

if (params.gad[0] != EOS) { /* Extract the network address in dot notation */ inet_netof_string (params.had, nad); /* for host address */ inet_netof_string (params.gad, ngad);

/* for gateway address */ /* gateway and host are on same subnet */ if (strcmp(nad, ngad) == 0) { /* Add default route */ if (routeAdd ("0.0.0.0", params.gad) == ERROR) printf("Error adding default route: "); } else { /* Add network route */ if (routeAdd (nad, params.gad) == ERROR) printf("Error setting route to host "); } }

where char ngad [20] has been added to the automatic variables

Change bootConfig.c to retrieve gateway parameter and store it so that it will be retrieved by the runtime image.

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

12

a. Change prototype for bootpGet() to include the gateway parameter:

LOCAL STATUS bootpGet (char *netDev, char *pBootDevAddr, char *pBootFile, char *pHostAddr, int *pMask, char *pGateway);

b. Pass params.gad so that the gateway parameter will be stored /* Get boot parameters over the network if requested. */ if (sysFlags & SYSFLG_AUTOCONFIG) { if (bootpGet (netDev, pBootAddr, params.bootFile, params.had, &netmask, params.gad ) == ERROR) return (ERROR);

c. Add the following to bootpGet(): /************************************************************************ * * bootpGet - get network parameters via BOOTP. * * RETURNS: OK if successful otherwise ERROR */ LOCAL STATUS bootpGet ( char *netDev, /* boot device */

char *pBootDevAddr, /* device address */ char *pBootFile, /* file name */ char *pHostAddr, /* host address */ int *pMask, /* mask */ char *pGateway /* subnet gateway */ ) ... struct in_addr_list routerlist; struct in_addr gateway; ... bzero ( (char *)&gateway, sizeof (struct in_addr)); ... /* Set pointers to retrieve needed boot parameters. */ ... routerlist.addr = &gateway; routerlist.num = 1; bootParams.routers = &routerlist; ...

AFTER

printf ("Getting boot parameters via network interface %s", pNetDev); if (bootpParamsGet (pNetDev, 0, 0, &bootParams) == ERROR) return (ERROR);

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

13

...

ADD: if (pGateway [0] == EOS) /* fill in subnet gateway */ { inet_ntoa_b(gateway, pGateway); printf (" Subnet gateway: %s ", pGateway); } Known Bugs: BOOTP A bug preventing successful negotiation with BOOTP exists in Tornado 2.02. The bug is addressed in SPR #67304. The recommended fix is to upgrade to Tornado 2.2. If you are unable to perform an upgrade, contact WindRiver for an unofficial patch. For more information about BOOTP, see the VxWorks Reference Manual entry for bootpLib.c

DHCP Server Configuration and Build Like the DHCP Client, the DHCP Server can be configured either at the command line or with the project facility. 1. PROJECT FACILITY BUILD Include the DHCP Server in the Project Facility tree: network components -> network applcations -> DHCP Server Below is a description of how to add lease entries to the DHCP server. You can add entries either dynamically with an API or in the configlette To add entries in the configlette, edit usrNetDhcpsCfg.c: DHCPS_LEASE_DESC dhcpsLeaseTbl [] = { /* Name Start IP End IP Parameters ---- ---------- ------ ----------- see man pages (timers, bootfile, etc.) */ /* * Host requirements defaults needed for RFC compliance - DO NOT REMOVE!! */ {"dflt", NULL, NULL, DHCPS_DEFAULT_ENTRY}, /* Sample database entries. */ /* {"ent1", "90.11.42.24", "90.11.42.24", clid=\"1:0x08003D21FE90\":maxl=90:dfll=60"}, */

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

14

/* {"ent2", "90.11.42.25", "90.11.42.26","snmk=255.255.255.0:maxl=90:dfll=70:file= /vxWorks"}, */ /* {"ent3", "90.11.42.27", "90.11.42.27", “maxl=0xffffffff:file=/vxWorks”}, */ /* {"entry4", "90.11.42.28", "90.11.42.29", "albp=true:file=/vxWorks"} */ }; /* {"entry5", "90.11.42.28", "90.11.42.29", "dnsd=205.214.51.16"} */

2. COMMAND LINE BUILD To include the DHCP Server when building from the command line, include the following component in the config.h file within the BSP directory: #define INCLUDE_DHCPS

Configure the DHCP lease entries in usrNetwork.c. The table is the same as the one mentioned on page 15. If you wish to add more DHCP table entries after the runtime image starts, use: dhcpsLeaseEntryAdd() How Do I Specify a List of DNS Servers in the DHCP Lease Entry?

You can specify the name of a DNS server or a list of IP addresses separated by white space.

At the target command prompt:

Use this entry for multiple DNS servers: -> dhcpsLeaseEntryAdd (<...lease entry...>, "dnsd=205.214.51.16 dnsd=192.169.33.3")

Use this entry for a single DNS server:

-> dhcpsLeaseEntryAdd (<...lease entry...>, "dnsv=205.214.51.16")

The option associated with the DNS server, is option 15.

Configuring the DHCP Server as a BOOTP Server Entries that you put in the DHCP server can be specified only to reply to BOOTP replies. When the VxWorks DHCP server receives requests from a BOOTP client, it will reply if the correct flag is set in the DHCP server entry. The flag is ‘albp’ /* {"entry4", "90.11.42.28", "90.11.42.29", "albp=true:file=/vxWorks"}

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

15

DHCP Server Features The DHCP Server can store leases if the server is shutdown then restarted. The hook helps to store active lease configurations. Configuring Lease Hooks To configure lease hooks, follow the instructions below.

1) If you are using the Project Facility, Define the following macro in target/config/comps/src/net/usrNetDhcpsCfg.c IMPORT STATUS DHCPS_LEASE_HOOK(int, char *, int); If you are building from the command line rather than the Project Facility, see /target/config/all/configAll.h and define the following: #define DHCPS_LEASE_HOOK

(2) Edit dhcpsLeaseTbl[] according to your needs. This table contains the DHCP server entries that you intend to use.

(3) Write a Lease Hook. Guidelines are provided at the end of this document.

When the VxWorks DHCP client has obtained a lease from the vxWorks Server, there is a garbage collection routine that runs every 10 minutes that will call the Lease Hook routine. The hook notes that a valid lease is loaned out and will call the write routine of the lease hook. You can also manually call the undocumented dump_bind_db() routine that will write out a new lease file, if it detects that any valid leases exist.

Configuring Address Hooks The DHCP Server Address Hook usage is documented in the Network Programmer’s Manual.

(1) Write a storage hook routine.

(2) Using a VxWorks image containing the DHCP server and the object file produced when compiling the attached source code, edit the startup sequence to install the test routine as follows before the DHCP server initialization:

dhcpsAddressHookAdd (sampleAddressStorageHook)

The DHCP Server Address Hook will not work with statically configured entries. Use dhcpsEntryAdd() for entries that the hook will access.

Changing the DHCP Configuration Will Not Appear on the DHCP Client Until a New Lease Is Negotiated. The DHCP client applies the local IP address and subnet mask automatically if the value of the <autoConfig> flag permits that behavior. It will never make any other changes involving the values in the DHCP options field, including the default gateway address. Therefore, the DHCP client will not detect changes made on the server even if they are sent in the DHCP offer packet.

The DHCP Relay Agent The DHCP relay agent sends DISCOVER messages from a DHCP client on one subnet that lacks a DHCP server to specific DHCP servers on a different subnet. While some routers on the network may be capable of relaying messages, they do not forward DISCOVER packets (because they are broadcast messages). This is the reason relay agents

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

16

should be implemented on the far side of the router. Configuring and building the VxWorks DHCP Relay Agent

The following instructions describe how to configure a VxWorks DHCP relay agent and server. Figure 1 illustrates the configuration that the instructions describe.

Figure 1: DHCP Relay Agent Configuration

147.11.41.50 147.11.41.150 10.1.1.20 any address

---------------------------------------------------------------------------------------------------------------------------

DHCP Server | DHCP Relay Agent | DHCP Client These instructions apply to Tornado versions 2.02 and 2.2. If you have an earlier version, you must upgrade to Tornado 2.02 for a functioning DHCP Relay Agent.

1. PROJECT FACILITY BUILD

Create a new usrNetDhcprCfg.c file. Rename the old configlette, usrNetDhcprCfg.c and copy it to a new file, usrNetDhcprCfg.c

a. Note: this step applies only to Tornado 2.02. Make changes to the new file:

/* IMPORT void dhcprLibInit (); */ IMPORT void dhcprLibInit (int);

/* dhcprLibInit (); */ dhcprLibInit (DHCPS_MAX_MSGSIZE);

Adjust the DHCP relay agent table in usrNetDhcprCfg.c:

If you leave this table empty, the relay agent will not start.

DHCP_TARGET_DESC dhcpTargetTbl [] = { /* IP address of DHCP target servers --------------------------------- */ /* {"90.11.42.2"}, */ {"147.11.38.50"} /* DHCP Server address */ };

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

17

Initialize all interfaces you intend to use on the relay agent. There are two ways to initialize the Relay Agent. Each is outlined below.

METHOD 1

In the file../target/comps/src/net/usrNetEndBoot.c, add a function that initializes the interface. For example:

void addInterface ( void ) { ipAttach(1, “fei”); usrNetIfConfig(“fei”, 1, “10.1.1.20”, “private”, 0xffffff00); }

Call addInterface()at the end of usrNetEndDevStart()

Example: . . . netAttachFlag = TRUE; printf ("Attached TCP/IP interface to %s unit %d\n", pDevName, unitNum); addInterface(); #endif /* INCLUDE_END */ return;

Add a line to ../target/comps/src/net/usrNetDhcprCfg.c: Search for:

dhcprInit()

Add: devlist[1] = ifunit ("fei1");

If the VxWorks target will be serving as relay agent and router, change the number of devices that the relay agent initializes. If you are working one a single subnet, the relay agent will send and receive messages on a single interface.

The example shows two interfaces instead of one:

dhcprResult = dhcprInit (devlist, 2, dhcpTargetTbl, dhcpTargetTblSize);

Include the DHCP Relay Agent component with the Project Facility:

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

18

network components -> network applications -> DHCP relay agent This also holds true for METHOD 2 METHOD 2

Make all the changes in usrNetDhcprCfg.c:

/* struct ifnet *devlist[1]; */ <---- original line struct ifnet *devlist[2]; <---- two devices ipAttach(1, "fei"); usrNetIfConfig("fei", 1, "10.1.1.20", "private", 0xffffff00); devlist[1] = ifunit ("fei1");

Change the number of initialized devices from one to two. /* dhcprResult=dhcprInit (devlist, 1, dhcpTargetTbl, dhcpTargetTblSize);*/ dhcprResult = dhcprInit (devlist, 2, dhcpTargetTbl, dhcpTargetTblSize);

Create a new cdf file based 00network.cdf. Name the file 50network.cdf. Change the 50network.cdf file for the relay agent. In ../target/comps/src/net/50network.cdf

Add DHCPS_MAX_MSGSIZE to the CFG_PARAMS

Call this file 60network.cdf Component INCLUDE_DHCPR { NAME DHCP relay agent . CFG_PARAMS DHCPS_SPORT DHCPS_CPORT \ DHCP_MAX_HOPS DHCPS_MAX_MSGSIZE REQUIRES INCLUDE_NET_SETUP HDR_FILES ioLib.h }

Make sure that the following parameter is defined.

Parameter DHCPS_MAX_MSGSIZE { NAME DHCP Server/Relay Agent Maximum Message DEFAULT 590 TYPE uint }

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

19

2. COMMAND LINE BUILD: If you are using the command line, Make changes to usrNetwork.c

In usrNetwork.c, add the following information to account for multiple devices on the relay agent. /* struct ifnet *devlist[1]; */ <---- original line struct ifnet *devlist[2]; <---- add this line for two devices ipAttach(1, "fei"); usrNetIfConfig("fei", 1, "10.1.1.20", "private", 0xffffff00); devlist[1] = ifunit ("fei1");

Change the number of initialized devices from one to two. /* dhcprResult=dhcprInit (devlist, 1, dhcpTargetTbl, dhcpTargetTblSize); */ dhcprResult = dhcprInit (devlist, 2, dhcpTargetTbl, dhcpTargetTblSize);

This step applies to Tornado 2.02 only.

Adjust the library initialization in usrNetwork.c as follows: /* IMPORT void dhcprLibInit (); */ IMPORT void dhcprLibInit (int);

/* dhcprLibInit (); */ dhcprLibInit (DHCPS_MAX_MSGSIZE);

Now populate the relay target table, dhcpTargetTbl[]. The dhcpTargetTbl[] will contain DHCP server IP addresses of the servers that will receive relayed messages via the relay agent. The DHCP Relay Target Table is in usrNetwork.c

If you leave this table empty, the relay agent will not start.

DHCP_TARGET_DESC dhcpTargetTbl [] = { /* IP address of DHCP target servers --------------------------------- */ /* {"90.11.42.2"}, */ {"147.11.38.50"} /* DHCP Server address */ };

Add the number of listening interfaces for the relay agent. /* struct ifnet *devlist[1]; */ struct ifnet *devlist[2]; <-- array for two interfaces

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

20

Change the number of devices that dhcprInit() initializes dhcprResult = dhcprInit (devlist, 2, dhcpTargetTbl,dhcpTargetTblSize);

Add an entry to dhcpRelayTbl[]. The table is in usrNetwork.c

DHCPS_RELAY_DESC dhcpsRelayTbl [] = { /* IP address of agent Subnet Number -------------------- ------------- */ {"10.1.1.20", “10.1.1.0"} };

The IP address of the agent is the interface that messages are sent out from once the agent receives a message from a DHCP server. The subnet number should match the network number of the agent IP address. Configure dhcpTargetTbl[] in usrNetwork.c with the IP address of the DHCP server. DHCP_TARGET_DESC dhcpTargetTbl [] = { /* IP address of DHCP target servers --------------------------------- */ {"147.11.41.50"} };

Configure the DHCP server with the addresses you wish to distribute: DHCPS_LEASE_DESC dhcpsLeaseTbl [] = { /* Name Start IP End IP Parameters ---- ---------- ------ ----------- * see man pages * (timers, bootfile, etc.) */ /* Host requirements defaults needed for RFC compliance - DO NOT REMOVE!! */ {"dflt", NULL, NULL, DHCPS_DEFAULT_ENTRY}, /* Sample database entries. */ {"ent1", "10.1.1.1", "10.1.1.1", "snmk=255.255.255.0"} };

When you start the DHCP server, add the appropriate route(s): routeAdd (“10.1.1.20”, “147.11.41.150”);

The above adds a host route to 10.1.1.20 (the DHCP relay agents IP address on the 10.1.1.0 network) with the

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

21

147.11.41.150 as the gateway. The output of dhcpcParamsShow on the client after the lease was obtained:

->dhcpcParamsShow Router discovery enabled. RFC 894 Ethernet encapsulation enabled. Maximum datagram size: 576 Default IP Time-to-live: 64 Interface MTU: 576 ARP cache timeout: 60 Default TCP Time-to-live: 64 TCP keepalive interval: 7200 Client lease origin: 212 Client lease duration: 3600 Client renewal (T1) time value: 1800 Client rebinding (T2) time value: 3150 DHCP server: 147.11.41.176 Assigned IP address: 10.1.1.1 Relay agent IP address: 10.1.1.20 Client subnet mask: 255.255.255.0 Client broadcast address: 255.255.255.255 Client router solicitation address: 255.255.255.25

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

22

DHCP Source Code Policy WindRiver will not provide source code to customers who do not have a source code license. Occasionally, exceptions are made for customers who are seeing bugs that have known fixes or workarounds. Such exceptions are determined at the discretion of the support engineer or the account manager.

Source Code Listing The following is a list and description of the DHCP source code modules.

/netwrs

dhcpcBootLib.c interface for client side DHCP used during system boot dhcpcCommonLib.c contains common library routines

dhcpcLib.c run-time access to the DHCP client dhcpcShow.c DHCP show routines dhcprLib.c DHCP relay agent routines

dhcpsLib.c DHCP server routines /dhcp

dhcpRelay.c routines sending packets in and out of the relay agent dhcpc.c state machine configuration code

dhcpcBoot.c dhcp boot library code dhcpcState1.c client state machine routines prior to the BOUND state dhcpcState2.c client state during and after BOUND state

dhcpc_subr.c contains internal routines dhcpr.c relay agent routine that processes incoming messages dhcps.c starts the DHCP server

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

23

Debugging Techniques for DHCP PACKET TRACES

The Core Networking support staff debugs the DHCP client through two methods: sniffer traces and debug messages within the source code. Obtain a packet trace of the problem. If you are unfamiliar with sniffer traces, see: http://www.robertgraham.com/pubs/sniffing-faq.html WindRiver staff prefers one of the following trace formats: snoop – Common trace utility for Sun Solaris machines http://www.cis.ohio-state.edu/cgi-bin/rfc/rfc1761.html The support staff prefers receiving traces in binary format. This is because both short and verbose forms are available. You must be root or have root privilege in order to run snoop. Here’s an example:

%snoop -o outputFile 147.11.38.89

A file, outputFile, is generated. That file is not readable as -is. For a short output:

%snoop -i outputFile > outputFile.txt

For a verbose output, including packet information:

%snoop -i outputFile -v > outputFileVerbose.txt

tcpdump - The oldest and most common wiretap program. First verify that you have tcpdump on your machine. You can specify traffic based on the ethernet MAC addresses for the DHCP client and server. If you don’t know if you have tcpdump available or not, check with your system administrator. Ethereal – This program is based on tcpdump, but is a GUI version. http://www.ethereal.com/. You may use ethereal on both Unix and Windows machines. Alternative packet trace utilities are: WildPackets EtherPeek or SMS Network Monitor, which comes with the Microsoft System Management Server.

Save the traces in the available binary format, rather than sending large text files.

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

24

DEBUGGING WITH SOURCE CODE The ideal way to spot problems in the DHCP client, server and relay agent is to acquire the source code and turn on debugging messages. If you have the source code, incorporate the code into your image, and define the following flags in the dhcp.h file: DHCPC_DEBUG 1 /* Client debugging flag DHCPS_DEBUG 1 /* Server debugging flag */ DHCPR_DEBUG 1 /* Relay Agent debugging flag */

After defining the flags, you will see debug output as the negotiation proceeds. If you would like to see the debugging messages, but don’t have the source code, contact WindRiver to request pre-compiled object code that includes debugging messages. After defining the flags, you will see log messages that follow the DHCP state machine. DHCP Runtime Client Sample Code /* dhcpcRuntime.c - Get lease after boot time */ /**************************************************************************** * * THIS CODE IS NOT SUPPORTED CODE. IT IS PROVIDED ON AN AS-IS BASIS. * ***************************************************************************** */ /* Copyright 1992 - 1998 Wind River Systems, Inc. */ /* modification history -------------------- 01a,06jul00,ijm based on dhcpcConfigSet */ /* DESCRIPTION This file contains routine to get a DHCP lease after booting with a static IP address NOMANUAL */ #include “vxWorks.h” #include <ioctl.h> #include <inetLib.h> #include “dhcp/dhcpcInit.h” #include “dhcp/dhcpcCommonLib.h” #include “dhcpcLib.h” #include “bootLib.h” #include “stdio.h” #include “netinet/if_ether.h”

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

25

#include “ifLib.h” #define MAX_LEASES 10 #define SERVER_PORT 67 #define CLIENT_PORT 68 #define OFFER_TIMEOUT 5 /* #define OFFER_TIMEOUT 5 change to test */ #define DEFAULT_LEASE 3600 #define MINIMUM_LEASE 30 #define MAX_SIZE 576 /* prototypes */ void dhcpStop( LEASE_DATA *, char *, int, char *); /* IMPORT BOOL dhcpcInputHook(struct ifnet *pIf, char * ifName, int unit); */ /* global */ void *pDhcpcRuntimeCookie; LEASE_DATA *pLeaseData; /**************************************************************************** * * ifEtherPrint - print Ethernet address in “:” notation * * RETURNS: N/A. */ LOCAL void ifEtherAddressPrint ( u_char enaddr[6] /* ethernet address */ ) { unsigned char *en = (unsigned char *)enaddr; printf(“ Ethernet address is %02x:%02x:%02x:%02x:%02x:%02x\n”, en [0], en [1], en [2], en [3], en [4], en [5]); } /************************************************************************* * * getDhcpLease - get IP address from DHCP server. Configure interface * * This routine gets IP address at runtime after the target has booted * (perhaps with a static IP addresss). It shows how to use tags like the * ROUTER_TAG and CLIENT_ID_TAG. If this function is called for an * additional interface, dhcpcInit() call in this routine will setup the * necessary data structures and create a cookie identifying the * boot lease. The cookie is stored in the pDhcpcBootCookie global to * provide users with access to the boot-time lease. This routine is called * when initializing the network from usrNetInit() in usrNetwork.c and will * not function correctly if executed in any other context.

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

26

* * RETURNS: OK if configuration completed, or ERROR otherwise.

AppNote-212

* * ERRNO: N/A * * NOMANUAL */ STATUS getDhcpLease ( char * netDev ) { struct dhcp_param dhcpParameters; struct ifnet * pIf; char tempString[30]; /* LEASE_DATA * pLeaseData; */ struct in_addrs routerStruct; /* gateway address */ struct in_addr routerAddress; struct in_addr dnsAddress; char dhcpServerAddr[INET_ADDR_LEN]; char dnsServerAddr[INET_ADDR_LEN]; char targetAddr[INET_ADDR_LEN]; char gatewayAddr[INET_ADDR_LEN]; int netMask = 0; struct in_addrs dnsServerStruct; u_char etherAddress[7]; etherAddress[0] = 0x1; /* DHCP Client Library initialization. Function returns TRUE if it has * been initialized previously. This assumes that the runtime image * was configured with DHCP client support. */ if ((dhcpcLibInit(SERVER_PORT, CLIENT_PORT, \ MAX_LEASES, MAX_SIZE, OFFER_TIMEOUT, \ DEFAULT_LEASE, MINIMUM_LEASE) == ERROR)) { printf(“\ndhcpLibInit failed!”); return ERROR; } /* if ((dhcpcLibInit(SERVER_PORT, CLIENT_PORT, MAX_LEASES, OFFER_TIMEOUT, DEFAULT_LEASE, MINIMUM_LEASE) == ERROR)) { printf(“\ndhcpLibInit failed!”); return ERROR; }

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

3

*/

/* Must bzero structures! dhcpcParamsGet copies parameters for non-blank * fields. Exceptions may occur if memory has not been allocated.

AppNote-212

*/ bzero ( (char *)&dhcpParameters, sizeof (struct dhcp_param)); bzero ((char *) &routerAddress, sizeof (struct in_addr)); bzero ((char *) &dnsAddress, sizeof (struct in_addr)); /* Get interfaces IP control structure */ pIf = ifunit (netDev); if (pIf == NULL) { printf (“Invalid device: %s\n”, netDev); return (ERROR); } /* If dhcpcLibInit was called at boot time, dhcpcInputHook was added to boot device. If this code is run for additional interfaces, dhcpcInputHook must be added to that device as well. etherInputHookAdd checks for duplicate hook routines. */ /* if (muxDevExists (pIf->if_name, pIf->if_unit)) etherInputHookAdd(dhcpcInputHook, pIf->if_name, pIf->if_unit); else etherInputHookAdd(dhcpcInputHook, NULL, pIf->if_unit); */ /* * Initialize required variables and get the lease identifier. * The resulting lease will always apply the address information * to the specified network interface. */ pDhcpcRuntimeCookie = dhcpcInit (pIf, TRUE); if (pDhcpcRuntimeCookie == NULL) { printf (“Error initializing DHCP runtime lease.\n”); return (ERROR); } /* Use the cookie to access the lease-specific data structures. */ pLeaseData = (LEASE_DATA *)pDhcpcRuntimeCookie; /* Set the lease descriptor. Interface will be initialized with lease values. */ pLeaseData->leaseType = DHCP_AUTOMATIC; /* If you want a manual lease, set the lease type to DHCP_MANUAL */ /* pLeaseData->leaseType = DHCP_MANUAL;*/ /* Set some options, dhcpcInit gets subnet mask by default */ dhcpParameters.subnet_mask = (struct in_addr *) &netMask;

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

3

/* Set DNS server tag */ dnsServerStruct.num = 1; dnsServerStruct.addr = &dnsAddress; dhcpParameters.dns_server = &dnsServerStruct; dhcpcOptionAdd (pDhcpcRuntimeCookie,_DHCP_DNS_SERVER_TAG, 0, NULL); /* dhcpcOptionSet (pDhcpcRuntimeCookie, _DHCP_LEASE_TIME_TAG); */ /* Set ROUTER_TAG */ routerStruct.num = 1; routerStruct.addr = &routerAddress; dhcpParameters.router = &routerStruct; dhcpcOptionAdd (pDhcpcRuntimeCookie,_DHCP_ROUTER_TAG, 0, NULL); dhcpcOptionAdd (pDhcpcRuntimeCookie,_DHCP_SUBNET_MASK_TAG, 0, NULL); */ bcopy ((char *) ((struct arpcom *)pIf)->ac_enaddr, etherAddress + 1, 6); ifEtherAddressPrint(etherAddress); /* To make this call, set up the etherAddress array above as the MAC address*/ printf(“Adding CLIENT_ID tag.\n”); if (dhcpcOptionAdd (pDhcpcRuntimeCookie,_DHCP_CLIENT_ID_TAG, \ 7, etherAddress) == ERROR) perror(“CLIENT_ID_TAG”); */ /* Execute the bind call synchronously */ if (dhcpcBind (pDhcpcRuntimeCookie, TRUE) != OK) { printf (“Can’t establish a DHCP runtime lease.\n”); return (ERROR); } /* Get Parameters from runtime cookie */ if (dhcpcParamsGet (pDhcpcRuntimeCookie, &dhcpParameters) == ERROR) { printf (“Can’t get network data from DHCP runtime lease.\n”); return (ERROR); } /* Fill in server addresses. */ if (dhcpParameters.server_id.s_addr != 0) { inet_ntoa_b (dhcpParameters.server_id, dhcpServerAddr); printf(“DHCP Server’s address = %s\n”, dhcpServerAddr); } if (dnsAddress.s_addr != 0) { inet_ntoa_b (dnsAddress, dnsServerAddr);

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

4

printf(“DNS Server’s address = %s\n”, dnsServerAddr); } /* Fill in router’s information */ if (routerAddress.s_addr != NULL) { inet_ntoa_b (routerAddress, gatewayAddr); printf(“Router’s address = %s\n”, gatewayAddr); } /* Fill in target address */ if (dhcpParameters.yiaddr.s_addr != 0) { inet_ntoa_b (dhcpParameters.yiaddr, targetAddr); printf(“%s IP address %s \n”, netDev, targetAddr); } /* Display DHCP information */ printf(“\nUse dhcpcParamsShow to show all available parameters: \n\n”); dhcpcParamsShow(pDhcpcRuntimeCookie); dhcpcTimersShow(pDhcpcRuntimeCookie); return (OK); } /* Function to stop the DHCP lease. Uses dhcpcRelease function. */ void dhcpStop( LEASE_DATA *pLeaseData, char *newIpAddress, int newSubnetMask, char *defaultRoute ) { struct if_info ifi; int isAuto; int sockfd; struct ifreq ridreq; char *bcastAddr; memcpy( &ifi, &pLeaseData->ifData, sizeof( struct if_info ) ); /* Auto flag will cause the interface to go down after the lease is * relinquished, so wait for that to happen.... */ isAuto = pLeaseData->autoConfig | ( pLeaseData->leaseType == DHCP_AUTOMATIC ? 1 : 0 ); dhcpcRelease(pLeaseData); bzero ( (char *)&ridreq, sizeof (struct ifreq)); sprintf (ridreq.ifr_name, “%s%d”, ifi.name, ifi.unit); ridreq.ifr_addr.sa_len = sizeof (struct sockaddr_in); if ( (sockfd = socket (AF_INET, SOCK_RAW, 0)) < 0) return; if ( isAuto )

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

5

{ /* wait for interface to shut down */ do { taskDelay( 1 ); ioctl (sockfd, SIOCGIFFLAGS, (int) (caddr_t) &ridreq); } while( ridreq.ifr_flags & IFF_UP); } mRouteShow(); routeDelete( “10.0.0.0”, newIpAddress ); ifMaskSet( ridreq.ifr_name, newSubnetMask ); ifAddrSet( ridreq.ifr_name, newIpAddress ); mRouteShow(); /* bcastAddr = inet_ntoa( ( inet_addr(newIpAddress) & newSubnetMask ) | ~newSubnetMask ); ifBroadcastSet( ridreq.ifr_name, bcastAddr ); */ ioctl (sockfd, SIOCGIFFLAGS, (int) (caddr_t) &ridreq); if ( ! (ridreq.ifr_flags & IFF_UP ) ) { ridreq.ifr_flags |= IFF_UP; ioctl (sockfd, SIOCSIFFLAGS, (int) (caddr_t) &ridreq); } close (sockfd); if ( !isAuto ) { flushroutes (); } routeAdd( “0.0.0.0”, defaultRoute ); } /* calls the dhcpStop routine */ void callStop(void) { dhcpStop(pLeaseData, “10.6.31.226”, 0xffffff00, “10.6.31.1”); routeAdd( “0.0.0.0”, defaultRoute );*/ } /* dhcp event hook : install the hook: -> dhcpcHook */ void hook(int event, void *cookie) { switch (event) { case 0: printf(“got lease new!\n”); break; case 1: printf(“got lease invalid!\n”); break;

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

6

default: printf(“got unknown!\n”); break; } } void dhcpcHook() { dhcpcEventHookAdd(pDhcpcRuntimeCookie, (FUNCPTR) hook); } DHCP Loop Sample Code /* dhcpLoop.c - A DHCP example to send continuous DHCP messages */ /**************************************************************************** * * THIS CODE IS NOT SUPPORTED CODE. IT IS PROVIDED ON AN AS-IS BASIS. * ***************************************************************************** */ /* modification history -------------------- 01a,06jul01, ds routine to repeatedly send DHCP packets */ /* DESCRIPTION This file contains three routines: 1. sysDhcpIpConfig(): a routine that initializes DHCP, then calls getIP() 2. getIP(): A routine that sends DHCP discover packets until a server replies. 3. dhcpEventHookRoutine(): A callback routine to notify users when a DHCP event occurs. */ #include <vxWorks.h> #include “dhcp/dhcpc.h” #include “dhcpcLib.h” #include “dhcp/dhcpcCommonLib.h” #include “dhcp/dhcpcInit.h” /* Define values for the DHCP*/ #define DHCPC_MAX_LEASES 10 #define MAX_SIZE 576 #define DHCPC_SPORT 67 #define DHCPC_CPORT 68 #define DHCPC_OFFER_TIMEOUT 5 #define DHCPC_DEFAULT_LEASE 3600 #define DHCPC_MIN_LEASE 30 /* Global variable */ struct ifnet * pIf; /* Function prototype for hook */ void dhcpEventHookRoutine( int, void * );

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

7

STATUS sysDhcpIpConfig() { char ipAddr[20]; char ifName[10]; struct dhcp_param dhcpcParams; strcpy(ifName, “fei0”); if (dhcpcLibInit (DHCPC_SPORT, DHCPC_CPORT, DHCPC_MAX_LEASES, MAX_SIZE, DHCPC_OFFER_TIMEOUT, DHCPC_DEFAULT_LEASE, DHCPC_MIN_LEASE) == ERROR) { printf(“sysDhcpIpConfig: dhcpcLibInit\n”); return ERROR; } pIf = ifunit(ifName); if (pIf == NULL) { printf(“sysDhcpIpConfig: incorrect boot device\n”); return ERROR; pDhcpcBootCookie = dhcpcInit(pIf,TRUE); if(dhcpcEventHookAdd(pDhcpcBootCookie, (FUNCPTR)dhcpEventHookRoutine) \ != OK) { printf(“Unable to add hook.\n”); return ERROR; } if(pDhcpcBootCookie == NULL){ printf(“sysDhcpIpConfig: unable to setup lease\n”); return ERROR; } if(getIP() != OK) { printf(“Unable to start DHCP process.\n”); return ERROR; } return OK; } STATUS getIP(void) { int i; char ipAddr[20]; struct dhcp_param dhcpcResult; bzero ( (char *)&dhcpcResult, sizeof (struct dhcp_param))

{ pIf = ifunit(“fei0”); i = ERROR; printf(“Starting DHCP process...\n”);

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

8

/* Start DHCP process */ while(i != OK) if((i = dhcpcBind(pDhcpcBootCookie, TRUE))!=OK) printf(“sysDhcpIpConfig: Unable to bind to the dhcp server.\n”); printf(“Bind was successful.\n”);

if(dhcpcParamsGet(pDhcpcBootCookie, &dhcpcResult)== ERROR){ printf(“Unable to get device parameters from DHCP\n”); return ERROR ; } inet_ntoa_b (dhcpcResult.yiaddr, &ipAddr[0]); printf(“ipAddress of the device = %s\n”,ipAddr); /* Show current DHCP parameters */ dhcpcParamsShow(); return OK; } /* end while */ void dhcpEventHookRoutine( int leaseEvent, void *pCookie ) { switch (leaseEvent ) { case DHCPC_LEASE_NEW : /* this case gets called when a new lease is established */ printf(“ DHCPC_LEASE_NEW \n “); break; case DHCPC_LEASE_INVALID : /* this case gets called when the client gives up... */ printf(“ DHCPC_LEASE_INVALID \n “); break; default: printf(“ leaseEvent = %d \n “, leaseEvent ); break; } } DHCP Lease Storage Hook Sample Code /* dhcpsSampleHook.c - Sample DHCP server storage routine */ /**************************************************************************** * * THIS CODE IS NOT SUPPORTED CODE. IT IS PROVIDED ON AN AS-IS BASIS. * ***************************************************************************** */ /* Copyright 1984 - 1997 Wind River Systems, Inc. */ #include “copyright_wrs.h”

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

9

/* modification history ____________________

AppNote-212

01c,16jan02,ds minor edits 01b,29apr97,spm written. */ /* DESCRIPTION This code demonstrates one possible method of implementing the permanent storage needed by the DHCP server. It uses an ATA device and a DOS file system which spans the full device. */ #include “vxWorks.h” #include “dosFsLib.h” #include “ioLib.h” #include <drv/hdisk/ataDrv.h> #include “stdio.h” /* for sprintf() */ #include “stdlib.h” /* for atoi() */ extern usrFdiskPartRead; extern ataDiskInit(void *); /* DHCP include files */ #include “dhcp/dhcp.h” #include “dhcp/common.h” #include “dhcpsLib.h” BOOL myFsInit = FALSE; BOOL myFileInit = FALSE; BOOL endOfData = FALSE; BLK_DEV *pBlkDev0; void *blk_device, *pCbio, *cbio1; /* *scsi related code SCSI_PHYS_DEV * pPhysDev; BLK_DEV * pBlkDev; DOS_VOL_DESC * pVolDesc; DOS_VOL_CONFIG configStruct; */ int myWriteDesc; int myReadDesc; STATUS sampleLeaseStorageHook ( int op, /* lease operation */ char *recData, /* record of active lease */ int dataLen /* length of record data */ ) {

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

3

int result; int offset; int length; char delim; char buffer [10]; switch (op) { case DHCPS_STORAGE_START: /* Prepare to store and retrieve records of active leases. */ printf (“START message\n”); if (myFsInit == FALSE) { /* Set up the BLK_DEV structure to access the ATA device. printf(“Calling cbioLibInit()\n”); cbioLibInit(); printf(“Calling dosFsLibInit()\n”); dosFsLibInit(20); printf(“Calling dosFsFatInit()\n”); dosFsFatInit(); printf(“Calling dosFsFmtLibInit()\n”); dosFsFmtLibInit(); printf(“Calling dosVDirLibInit()\n”); dosVDirLibInit(); printf(“Calling dosChkLibInit()\n”); dosChkLibInit(); printf(“Calling ataDevCreate()\n”); blk_device = ataDevCreate(0,0,0,0); printf(“Calling dcacheDevCreate()\n”); pCbio = dcacheDevCreate(blk_device, 0, 0, “/ata0/”); printf(“Calling dpartDevCreate()\n”); cbio1 = dpartDevCreate( pCbio, 1, usrFdiskPartRead ); printf(“Calling dosFsDevCreate(a)\n”); dosFsDevCreate(“/sd0a”, dpartPartGet(cbio1,0), 0, 0 ); */ pBlkDev0 = ataDevCreate(0,0,0,0); ataDiskInit(pBlkDev0); dosFsConfigShow(); /* Access an existing DOS file system. */

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

4

/* pVolDesc = dosFsDevInit (“/sd0a”, pBlkDev, &configStruct); if (pVolDesc == NULL) return (ERROR); */ myFsInit = TRUE; } if (myFileInit == FALSE)

AppNote-212

{ myWriteDesc = open (“/sd0a/leases.dat”, O_WRONLY, 0); if (myWriteDesc == ERROR) /* Try to create file. */ { myWriteDesc = creat (“/sd0a/leases.dat”,O_WRONLY); endOfData = TRUE; } if (myWriteDesc == ERROR) return (ERROR); myReadDesc = open (“/sd0a/leases.dat”, O_RDONLY, 0); if (myReadDesc == ERROR) return (ERROR); myFileInit = TRUE; } break; case DHCPS_STORAGE_WRITE: printf (“WRITE message\n”); /* Store active leases. Return ERROR if START operation failed. */ if (myFsInit == FALSE || myFileInit == FALSE) return (ERROR); /* Store the length for later retrieval by READ operation. */ sprintf (buffer, “%d:”, dataLen); result = write (myWriteDesc, buffer, strlen (buffer)); if (result != strlen (buffer)) return (ERROR); /* Store the record of the lease. */ result = write (myWriteDesc, recData, dataLen); if (result != dataLen) return (ERROR); /* * Force write to file - each operation must be independent, * so can’t rely on close() call in the DHCPS_STORAGE_STOP code. */ result = ioctl (myWriteDesc, FIOFLUSH, 0); if (result == ERROR) return (ERROR); endOfData = FALSE; /* Data available. */ break; result = read (myReadDesc, recData, length);

Issues and Solutions for DHCP AppNote-212

Version 1.0 October 2002

3

if (result == 0) /* Unexpected end-of-file. */ { endOfData = TRUE;

AppNote-212

return (ERROR); } if (result == ERROR) return (ERROR); if (result != length) return (ERROR); break; case DHCPS_STORAGE_CLEAR: printf (“CLEAR message\n”); myFileInit = FALSE; endOfData = TRUE; /* Remove and recreate underlying file. */ close (myWriteDesc); close (myReadDesc); result = remove (“/sd0a/leases.dat”); if (result == ERROR) return (ERROR); myWriteDesc = creat (“/sd0a/leases.dat”, O_WRONLY); if (myWriteDesc == ERROR) return (ERROR); myReadDesc = open (“/sd0a/leases.dat”, O_RDONLY, 0); if (myReadDesc == ERROR) return (ERROR); myFileInit = TRUE; break; case DHCPS_STORAGE_STOP: printf (“STOP message\n”); myFileInit = FALSE; endOfData = FALSE; close (myWriteDesc); close (myReadDesc); break; default: printf (“bogus message\n”); break; } return (OK); }