📄 dhcps.c
字号:
/* dhcps.c - WIDE project DHCP server routines *//* Copyright 1984 - 1999 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history____________________01h,01mar99,spm corrected checksum calculation for ICMP requests (SPR #24745)01g,06oct97,spm removed reference to deleted endDriver global; replaced with support for dynamic driver type detection; split interface name into device name and unit number01f,26aug97,spm rearranged functions to consolidate lease selection routines01e,02jun97,spm changed DHCP option tags to prevent name conflicts (SPR #8667) and updated man pages01d,06may97,spm changed memory access to align IP header on four byte boundary and corrected format of lease record01c,28apr97,spm allowed user to change DHCP_MAX_HOPS setting01b,18apr97,spm added conditional include DHCPS_DEBUG for displayed output01a,07apr97,spm created by modifying WIDE project DHCP implementation*//*DESCRIPTIONThis library implements the server side of the Dynamic Host ConfigurationProtocol (DHCP). DHCP is an extension of BOOTP. Like BOOTP, it allows atarget to configure itself dynamically by obtaining its IP address, aboot file name, and the DHCP server's address over the network. Additionally,DHCP provides for automatic reuse of network addresses by specifyingindividual leases as well as many additional options. The compatiblemessage format allows DHCP participants to interoperate with BOOTPparticipants.INCLUDE FILES: dhcpsLib.hSEE ALSO: RFC 1541, RFC 1533*//* includes */#include "dhcp/copyright_dhcp.h"#include "vxWorks.h"#include "vxLib.h" /* checksum() declaration. */#include "etherLib.h"#include "logLib.h"#include "inetLib.h"#include "sockLib.h"#include "ioLib.h"#include "wdLib.h"#include "taskLib.h"#include "sysLib.h"#include "muxLib.h"#include "netinet/ip.h"#include "netinet/in_systm.h"#include "netinet/ip_icmp.h" #include <time.h>#include <stdio.h>#include <stdlib.h>#include "dhcp/dhcp.h"#include "dhcp/common.h"#include "dhcp/hash.h"#include "dhcp/dhcps.h"#include "dhcpsLib.h"#include "dhcp/common_subr.h"/* defines */#define MEMORIZE 90 /* Seconds of delay before re-using offered lease. */#define E_NOMORE -2 /* Error code: no more space in options field. *//* globals */int nbind; /* Number of active or pending lease records. */struct msg dhcpsMsgIn; /* Pointers to components of incoming message. */struct msg dhcpsMsgOut; /* Pointers to outgoing message parts. */char *dhcpsSendBuf; /* Transmit buffer for outgoing messages. */char dhcpsOverflowBuf [ETHERMTU - DFLTOPTLEN]; /* Extra space for options. */IMPORT struct if_info *dhcpsIntfaceList; /* Interfaces to monitor. */IMPORT int dhcpMaxHops; /* Maximum number of hops before message discard. */struct iovec sbufvec[2]; /* Socket access to outgoing message. * sbufvec[0] is standard message. * sbufvec[1] contains message extensions if * client accepts longer messages. *//* locals */LOCAL char *rbufp = NULL; /* Pointer to incoming message. */LOCAL unsigned char dhcpCookie[] = RFC1048_MAGIC; /* DHCP message indicator. */LOCAL int rdhcplen; /* Size of received DHCP message. */LOCAL int overload; /* Options in sname or file fields? */LOCAL int off_options; /* Index into options field. */LOCAL int off_extopt; /* Index into any options in sbufvec[1]. */LOCAL int maxoptlen; /* Space available for options. */LOCAL int off_file; /* Index into any options within file field. */LOCAL int off_sname; /* Index into any options in sname field. */LOCAL int timeoutflag; /* Shows time limit reached for ICMP reply. *//* forward declarations */LOCAL int icmp_check (int, struct in_addr *);LOCAL void timeout (int);IMPORT void dhcpServerRelay (struct if_info *);IMPORT void dhcpClientRelay (struct if_info *, int);IMPORT void delarp (struct in_addr *, int);/********************************************************************************* dhcpsStart - execute the DHCP server** This routine receives DHCP requests from clients and generates replies. If* configured to do so, it may also act as a relay agent and forward these * requests to other servers or transfer replies to clients. It is the entry * point for the DHCP server task and should only be called internally.** RETURNS: N/A** ERRNO: N/A** NOMANUAL*/void dhcpsStart (void) { struct if_info *ifp; /* pointer to receiving interface descriptor */ int n = 0; /* number of bytes received */ char msgtype; /* DHCP message type, or BOOTP indicator */ char *option = NULL; /* pointer to access message options */ BOOL bsdDrvFlag = TRUE; /* Add hook for BSD 4.4 drivers? */ /* * Begin receiving appropriate Ethernet frames from every interface. * Currently, the same input hook routine must be added once for all BSD * driver, if any, and once for each END-style driver. Eventually, DHCP * will be registered as a protocol and the input hooks will be * removed. */ ifp = dhcpsIntfaceList; while (ifp != NULL) { if (muxDevExists (ifp->name, ifp->unit)) etherInputHookAdd (dhcpsInputHook, ifp->name, ifp->unit); else if (bsdDrvFlag) { /* Add the input hook once for all BSD 4.4 drivers. */ etherInputHookAdd (dhcpsInputHook, NULL, ifp->unit); bsdDrvFlag = FALSE; } ifp = ifp->next; } /* Main loop - read and process incoming messages. */ FOREVER { garbage_collect (); /* remove expired leases from hash table. */ /* select and read from interfaces */ if ( (ifp = read_interfaces (dhcpsIntfaceList, &n)) == NULL) continue; /* * Access at offset to provide 4-byte alignment for IP header * needed by Sun BSP's. */ rbufp = &ifp->buf [DHCPS_OFF]; /* Set pointers to access message components. */ dhcpsMsgIn.ether = (struct ether_header *)rbufp; dhcpsMsgIn.ip = (struct ip *)&rbufp [ETHERHL]; if ( (ntohs (dhcpsMsgIn.ip->ip_off) & 0x1fff) == 0 && ntohs (dhcpsMsgIn.ip->ip_len) >= DFLTBOOTPLEN + UDPHL + IPHL && (dhcpsMsgIn.ip->ip_dst.s_addr == 0xffffffff || dhcpsMsgIn.ip->ip_dst.s_addr == ifp->ipaddr.s_addr) && check_ipsum(dhcpsMsgIn.ip)) dhcpsMsgIn.udp = (struct udphdr *)&rbufp [ETHERHL + dhcpsMsgIn.ip->ip_hl * WORD]; else continue; /* Invalid IP header: ignore. */ if (ntohs (dhcpsMsgIn.udp->uh_ulen) >= DFLTBOOTPLEN + UDPHL && dhcpsMsgIn.udp->uh_dport == dhcps_port && check_udpsum (dhcpsMsgIn.ip, dhcpsMsgIn.udp)) dhcpsMsgIn.dhcp = (struct dhcp *) &rbufp [ETHERHL + dhcpsMsgIn.ip->ip_hl * WORD + UDPHL]; else continue; /* Invalid UDP header: ignore. */ /* final packet check */ if (bcmp (dhcpsMsgIn.dhcp->options, (char *)dhcpCookie, MAGIC_LEN) != 0) continue; /* * Perform function of relay agent for received client messages. * (Changes contents of input message Ethernet, IP, and UDP headers). */ dhcpMsgIn.ether = dhcpsMsgIn.ether; dhcpMsgIn.ip = dhcpsMsgIn.ip; dhcpMsgIn.udp = dhcpsMsgIn.udp; dhcpMsgIn.dhcp = dhcpsMsgIn.dhcp; if (dhcpMsgIn.dhcp->op == BOOTREPLY && dhcpMsgIn.dhcp->hops <= dhcpMaxHops) dhcpClientRelay (dhcpsIntfaceList, DHCPLEN (dhcpsMsgIn.udp)); if (dhcpsMsgIn.dhcp->op != BOOTREQUEST) continue; /* Process DHCP client message received at server port. */ rdhcplen = DHCPLEN (dhcpsMsgIn.udp); msgtype = BOOTP; option = pickup_opt (dhcpsMsgIn.dhcp, rdhcplen, _DHCP_MSGTYPE_TAG); if (option != NULL) msgtype = *OPTBODY(option);#ifdef DHCPS_DEBUG if (msgtype < BOOTP || msgtype > DHCPRELEASE) logMsg ("dhcps: unknown message received.\n", 0, 0, 0, 0, 0, 0);#endif if (msgtype >= BOOTP && msgtype <= DHCPRELEASE) if (process_msg [ (int)msgtype] != NULL) (*process_msg [ (int)msgtype]) (ifp); /* * Relay received server messages if target addresses available. * (Changes contents of input DHCP message - must process first). */ dhcpMsgIn.udp = dhcpsMsgIn.udp; dhcpMsgIn.dhcp = dhcpsMsgIn.dhcp; if (pDhcpTargetList != NULL && dhcpMsgIn.dhcp->hops <= dhcpMaxHops) dhcpServerRelay (ifp); } }/********************************************************************************* haddrtos - convert hardware address to cache format** This routine converts the given hardware address to the <type>:<value> pair* used when adding lease record entries to permanent storage.** RETURNS: Pointer to converted string** ERRNO: N/A** NOMANUAL*/char * haddrtos ( struct chaddr *haddr /* pointer to parsed hardware address */ ) { int i; int fin; char tmp[3]; static char result [MAX_HLEN * 2 + 8]; /* it seems enough */ bzero (result, sizeof (result)); fin = haddr->hlen; if (fin > MAX_HLEN) fin = MAX_HLEN; sprintf (result, "%d:0x", haddr->htype); for (i = 0; i < fin; i++) { sprintf(tmp, "%.2x", haddr->haddr[i] & 0xff); strcat(result, tmp); } return (result); }/********************************************************************************* cidtos - convert client identifier to cache format** This routine converts the given client identifier to the <type>:<value> pair* used when adding lease record entries to permanent storage. It also* adds the current subnet number so that the server can deny inaccurate * leases caused by a client changing subnets. When used for user output, the* subnet is not included in the converted string.** RETURNS: Pointer to converted string** ERRNO: N/A** NOMANUAL*/char * cidtos ( struct client_id *cid, /* pointer to parsed client ID */ int withsubnet /* flag for adding subnet to output string */ ) { int i = 0; static char result [MAXOPT * 2 + sizeof ("255.255.255.255") + 3]; char tmp [sizeof ("255.255.255.255") + 1]; sprintf (result, "%d:0x", cid->idtype); for (i = 0; i < cid->idlen; i++) { sprintf (tmp, "%.2x", cid->id[i] & 0xff); strcat (result, tmp); } if (withsubnet) { inet_ntoa_b (cid->subnet, tmp); strcat (result, ":"); strcat (result, tmp); } return (result); }/********************************************************************************* get_reqlease - Retrieve requested lease value ** This routine extracts the desired lease duration from the options field of * the DHCP client request and converts it to host byte order.** RETURNS: Requested lease duration, or 0 if none.** ERRNO: N/A** NOMANUAL*/ static u_long get_reqlease ( struct dhcp *msg, /* pointer to incoming message */ int length /* length of incoming message */ ) { char *option = NULL; u_long retval = 0; if ( (option = pickup_opt (msg, length, _DHCP_LEASE_TIME_TAG)) != NULL) retval = GETHL (OPTBODY (option)); return (retval); }/********************************************************************************* get_cid - Retrieve client identifier** This routine extracts the client identifier from the options field of the* DHCP client request and stores the <type>:<value> pair in the given * structure. If no explicit client ID is given, the routine uses the hardware* address, as specified by RFC 1541.** RETURNS: N/A** ERRNO: N/A** NOMANUAL*/static void get_cid ( struct dhcp *msg, /* pointer to incoming message */ int length, /* length of incoming message */ struct client_id *cid /* pointer to storage for parsed data */ ) { char *option = NULL; option = pickup_opt (msg, length, _DHCP_CLIENT_ID_TAG); if (option != NULL) { cid->idlen = ( (int)DHCPOPTLEN (option)) - 1; /* -1 for ID type */ bcopy (OPTBODY (option) + 1, cid->id, cid->idlen); cid->idtype = *OPTBODY (option); } else { /* haddr is used to substitute for client identifier */ cid->idlen = msg->hlen; cid->idtype = msg->htype; bcopy (msg->chaddr, cid->id, msg->hlen); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -