📄 dhcps.c
字号:
/* dhcps.c - WIDE project DHCP server routines *//* Copyright 1984 - 2001 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01n,23apr02,wap use dhcpTime() instead of time() (SPR #68900), also use BPF_WORDALIGN() when traversing multiple packets in BPF buffers (SPR #74215)01m,08mar02,wap Return sane lease renewal times for clients that request leases without specifying their own lease times (SPR #73243)01l,31oct01,vvv allow low-priority tasks to run while server waits for ICMP reply (SPR #33132)01k,12oct01,rae merge from truestack ver 01s, base 01h SPRs 70184, 69547, 34799, 6680801j,24oct00,spm fixed modification history after tor3_x merge; fixed invalid socket reference (SPR #27246)01i,23oct00,niq merged from version 01j of tor3_x branch (base version 01h)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 "net/bpf.h"#include "logLib.h"#include "vxLib.h" /* checksum() declaration */#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. */#ifndef VIRTUAL_STACK/* 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; /* Extra space (for larger messages) starts here. */IMPORT struct if_info *dhcpsIntfaceList; /* Interfaces to monitor. */struct iovec sbufvec[2]; /* Socket access to outgoing message. * sbufvec[0] is standard message. * sbufvec[1] contains message extensions if * client accepts longer messages. */IMPORT int dhcpsMaxSize; /* Size of transmit buffer. */IMPORT int dhcpsBufSize; /* Size of receive buffer. */IMPORT u_short dhcps_port;IMPORT u_short dhcpc_port;/* locals */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. */#else#include "netinet/vsLib.h"#include "netinet/vsDhcps.h"#endif /* VIRTUAL_STACK *//* forward declarations */LOCAL int icmp_check (int, struct in_addr *);IMPORT STATUS dhcpsSend (struct ifnet *, char *, int, struct sockaddr_in *, char *, int, BOOL);IMPORT void dhcpServerRelay (struct if_info *);IMPORT void dhcpClientRelay (struct if_info *, int, char *);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*/int dhcpsStart (#ifndef VIRTUAL_STACK void#else int stackNum#endif /* VIRTUAL_STACK */ ) { struct if_info *ifp; /* pointer to receiving interface descriptor */ int n = 0; /* number of bytes received */ int msgtype; /* DHCP message type, or BOOTP indicator */ char *option = NULL; /* pointer to access message options */ struct bpf_hdr * pMsgHdr; char * pMsgData; int msglen; int curlen; int totlen; /* Amount of data in BPF buffer. */#ifdef VIRTUAL_STACK if (virtualStackNumTaskIdSet (stackNum) == ERROR) return (ERROR);#endif /* VIRTUAL_STACK */ /* Main loop - read and process incoming messages. */ FOREVER { garbage_collect (); /* remove expired leases from hash table. */ /* select and read from interfaces */ ifp = read_interfaces (dhcpsIntfaceList, &n, dhcpsBufSize); if (ifp == NULL) continue; /* Divide each DHCP message in buffer into protocol sections. */ msglen = curlen = 0; totlen = n; pMsgHdr = (struct bpf_hdr *)ifp->buf; pMsgData = ifp->buf; while (curlen < totlen) { msglen = BPF_WORDALIGN(pMsgHdr->bh_hdrlen + pMsgHdr->bh_caplen); curlen += msglen; /* Set the IP pointer to skip the BPF and link level headers. */ dhcpsMsgIn.ip = (struct ip *) (pMsgData + pMsgHdr->bh_hdrlen + pMsgHdr->bh_linklen); if ( (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 *)( (UCHAR *)dhcpsMsgIn.ip + dhcpsMsgIn.ip->ip_hl * WORD); else { /* Invalid IP header: ignore. */ pMsgData = pMsgData + msglen; pMsgHdr = (struct bpf_hdr *)pMsgData; continue; } if (check_udpsum (dhcpsMsgIn.ip, dhcpsMsgIn.udp)) dhcpsMsgIn.dhcp = (struct dhcp *)( (UCHAR *)dhcpsMsgIn.udp + UDPHL); else { /* Invalid UDP header: ignore. */ pMsgData = pMsgData + msglen; pMsgHdr = (struct bpf_hdr *)pMsgData; continue; } /* * Perform function of relay agent for received server replies. * (Changes contents of input message IP and UDP headers while * sending to client). */ dhcpMsgIn.ip = dhcpsMsgIn.ip; dhcpMsgIn.udp = dhcpsMsgIn.udp; dhcpMsgIn.dhcp = dhcpsMsgIn.dhcp; if (dhcpMsgIn.dhcp->op == BOOTREPLY) dhcpClientRelay (dhcpsIntfaceList, DHCPLEN (dhcpsMsgIn.udp), dhcpsSendBuf); if (dhcpsMsgIn.dhcp->op != BOOTREQUEST) { pMsgData = pMsgData + msglen; pMsgHdr = (struct bpf_hdr *)pMsgData; 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 = (int) *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 [msgtype]) != NULL) (*process_msg [msgtype]) (ifp); /* * Relay received client messages if target addresses available. * (Changes contents of input DHCP message when sending to * server or relay agent - must process first). */ dhcpMsgIn.udp = dhcpsMsgIn.udp; dhcpMsgIn.dhcp = dhcpsMsgIn.dhcp; if (pDhcpTargetList != NULL) dhcpServerRelay (ifp); pMsgData = pMsgData + msglen; pMsgHdr = (struct bpf_hdr *)pMsgData; } } }/********************************************************************************* 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*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -