📄 dhcpcboot.c
字号:
/* dhcpcBoot.c - DHCP client finite state machine definition (boot time)*//* Copyright 1984 - 1997 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history____________________01g,04dec97,spm added code review modifications01f,06oct97,spm removed reference to deleted endDriver global; replaced with support for dynamic driver type detection01e,02sep97,spm removed name conflicts with runtime DHCP client (SPR #9241)01d,26aug97,spm major overhaul: included version 01h of dhcpcState1.c and version 01i of dhcpc_subr.c to retain single-lease library for boot time use01c,06aug97,spm removed parameters linked list to reduce memory required01b,07apr97,spm rewrote documentation01a,29jan97,spm created by modifying dhcpc.c module*//*DESCRIPTIONThis library contains the boot-time DHCP client implementation. The librarycontains routines to obtain a set of boot parameters using DHCP. Because the bootstrap loader handles all the system configuration, the boot-time client will not apply any configuration parameters received to the underlying networkinterface.INTERNAL This module contains a modified version of the DHCP client finite statemachine which eliminates all states from BOUND onwards. Provided that the obtained lease exceeds the download time for the runtime image, these routinesare not needed by the ROM-resident bootstrap loader. Their removal reduces the size of the boot ROM image so that the DHCP client can be used with targets like the MV147 which have limited ROM capacity. The code size is further reduced by eliminating the routines which change the network interface settingsand maintain the correct routing table entries. Although necessary to prevent access to an unconfigured interface during runtime, it is overkill at boot time, since the system will not start if an error occurs. Finally, the runtime DHCP client supports the retrieval and maintenance of multiple leases. That capability is not necessary at boot time.INCLUDE_FILES: dhcpcBootLib.h*//* * WIDE Project DHCP Implementation * Copyright (c) 1995 Akihiro Tominaga * Copyright (c) 1995 WIDE Project * All rights reserved. * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided only with the following * conditions are satisfied: * * 1. Both the copyright notice and this permission notice appear in * all copies of the software, derivative works or modified versions, * and any portions thereof, and that both notices appear in * supporting documentation. * 2. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by WIDE Project and * its contributors. * 3. Neither the name of WIDE Project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND WIDE * PROJECT DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ALSO, THERE * IS NO WARRANTY IMPLIED OR OTHERWISE, NOR IS SUPPORT PROVIDED. * * Feedback of the results generated from any improvements or * extensions made to this software would be much appreciated. * Any such feedback should be sent to: * * Akihiro Tominaga * WIDE Project * Keio University, Endo 5322, Kanagawa, Japan * (E-mail: dhcp-dist@wide.ad.jp) * * WIDE project has the rights to redistribute these changes. *//* includes */#include "vxWorks.h"#include "vxLib.h" /* checksum() declaration. */#include "netLib.h"#include "inetLib.h"#include "etherLib.h"#include "taskLib.h"#include "sysLib.h"#include "ioLib.h"#include "sockLib.h"#include "wdLib.h"#include "rngLib.h"#include "logLib.h"#include "muxLib.h"#include "stdio.h"#include "stdlib.h"#include "sys/ioctl.h"#include "time.h"#include "netinet/in.h"#include "netinet/ip.h"#include "netinet/udp.h"#include "dhcpcBootLib.h"/* defines */#define MAX_BOOT_STATES REQUESTING + 1#define SLEEP_RANDOM(timer) ( (timer - 1) + (rand () % 2) )#define REQUEST_RETRANS 4 /* Number of retries, maximum of 5. (RFC 1541). *//* globals */int dhcpcSPort; /* configAll.h #define value */int dhcpcCPort; /* configAll.h #define value */int dhcpcBootMinLease; /* configAll.h #define value */struct dhcp_reqspec dhcpcBootReqSpec;struct dhcp_param * dhcpcBootParam; /* Configuration parameters */IMPORT WDOG_ID dhcpcBootEventTimer; /* Timeout for server response */IMPORT RING_ID dhcpcBootEventRing; /* Buffer for external events */IMPORT SEM_ID dhcpcBootRingSem; /* Protection for event buffer. */IMPORT RING_ID dhcpcBootMsgRing; /* Buffer for incoming DHCP messages */IMPORT struct msg dhcpcRbufMsg; /* Incoming DHCP message components. */IMPORT char * pDhcpcRbuf; /* Buffer for input hooks. */IMPORT SEM_ID dhcpcBootEventSem; /* Signal for external events */IMPORT SEM_ID dhcpcBootArpEventSem;IMPORT u_char dhcpcBootArpSpa[4];IMPORT BOOL dhcpcBootArpInputHook (struct ifnet*, char*, int);IMPORT int dhcpcBindType; /* DHCP or BOOTP reply selected? */IMPORT struct if_info dhcpcDevice; /* Interface descriptor. *//* locals */LOCAL int dhcpcCurrState; /* Current state */LOCAL int dhcpcPrevState; /* Previous state */LOCAL unsigned long dhcpcInitEpoch; /* Transmission timestamp. */LOCAL struct if_info dhcpcIntface; /* Network interface */LOCAL struct buffer rbuf; /* Buffer for incoming messages */LOCAL struct buffer sbuf; /* Buffer for outgoing messages */LOCAL struct msg dhcpcMsgIn; /* Incoming message components */LOCAL struct msg dhcpcMsgOut; /* Outgoing message components */LOCAL unsigned char dhcpCookie [MAGIC_LEN] = RFC1048_MAGIC;LOCAL struct ps_udph spudph;LOCAL int (*dhcpcBootStates [MAX_BOOT_STATES]) ();LOCAL int handle_ip();LOCAL int handle_num();LOCAL int handle_ips();LOCAL int handle_str();LOCAL int handle_bool();LOCAL int handle_ippairs();LOCAL int handle_nums();LOCAL int handle_list();LOCAL int (*handle_param [MAXTAGNUM]) () = { NULL, /* PAD */ handle_ip, /* SUBNET_MASK */ handle_num, /* TIME_OFFSET */ handle_ips, /* ROUTER */ handle_ips, /* TIME_SERVER */ handle_ips, /* NAME_SERVER */ handle_ips, /* DNS_SERVER */ handle_ips, /* LOG_SERVER */ handle_ips, /* COOKIE_SERVER */ handle_ips, /* LPR_SERVER */ handle_ips, /* IMPRESS_SERVER */ handle_ips, /* RLS_SERVER */ handle_str, /* HOSTNAME */ handle_num, /* BOOTSIZE */ handle_str, /* MERIT_DUMP */ handle_str, /* DNS_DOMAIN */ handle_ip, /* SWAP_SERVER */ handle_str, /* ROOT_PATH */ handle_str, /* EXTENSIONS_PATH */ handle_bool, /* IP_FORWARD */ handle_bool, /* NONLOCAL_SRCROUTE */ handle_ippairs, /* POLICY_FILTER */ handle_num, /* MAX_DGRAM_SIZE */ handle_num, /* DEFAULT_IP_TTL */ handle_num, /* MTU_AGING_TIMEOUT */ handle_nums, /* MTU_PLATEAU_TABLE */ handle_num, /* IF_MTU */ handle_bool, /* ALL_SUBNET_LOCAL */ handle_ip, /* BRDCAST_ADDR */ handle_bool, /* MASK_DISCOVER */ handle_bool, /* MASK_SUPPLIER */ handle_bool, /* ROUTER_DISCOVER */ handle_ip, /* ROUTER_SOLICIT */ handle_ippairs, /* STATIC_ROUTE */ handle_bool, /* TRAILER */ handle_num, /* ARP_CACHE_TIMEOUT */ handle_bool, /* ETHER_ENCAP */ handle_num, /* DEFAULT_TCP_TTL */ handle_num, /* KEEPALIVE_INTER */ handle_bool, /* KEEPALIVE_GARBA */ handle_str, /* NIS_DOMAIN */ handle_ips, /* NIS_SERVER */ handle_ips, /* NTP_SERVER */ handle_list, /* VENDOR_SPEC */ handle_ips, /* NBN_SERVER */ handle_ips, /* NBDD_SERVER */ handle_num, /* NB_NODETYPE */ handle_str, /* NB_SCOPE */ handle_ips, /* XFONT_SERVER */ handle_ips, /* XDISPLAY_MANAGER */ NULL, /* REQUEST_IPADDR */ handle_num, /* LEASE_TIME */ NULL, /* OPT_OVERLOAD */ NULL, /* DHCP_MSGTYPE */ handle_ip, /* SERVER_ID */ NULL, /* REQ_LIST */ handle_str, /* DHCP_ERRMSG */ NULL, /* DHCP_MAXMSGSIZE */ handle_num, /* DHCP_T1 */ handle_num, /* DHCP_T2 */ NULL, /* CLASS_ID */ NULL, /* CLIENT_ID */ NULL, NULL, handle_str, /* NISP_DOMAIN */ handle_ips, /* NISP_SERVER */ handle_str, /* TFTP_SERVERNAME */ handle_str, /* BOOTFILE */ handle_ips, /* MOBILEIP_HA */ handle_ips, /* SMTP_SERVER */ handle_ips, /* POP3_SERVER */ handle_ips, /* NNTP_SERVER */ handle_ips, /* DFLT_WWW_SERVER */ handle_ips, /* DFLT_FINGER_SERVER */ handle_ips, /* DFLT_IRC_SERVER */ handle_ips, /* STREETTALK_SERVER */ handle_ips /* STDA_SERVER */ };/* forward declarations */int dhcp_boot_client (struct if_info *);int check_wait_offer (void);int check_requesting (void);void msgAlign (struct msg *, char *);LOCAL int initialize (void);LOCAL int arp_check (struct in_addr *);LOCAL void set_declinfo (struct dhcp_reqspec *, char *, int);LOCAL void make_discover (void);LOCAL int make_request (struct dhcp_param *, int);LOCAL int dhcp_decline (struct dhcp_reqspec *);LOCAL char * pickup_opt (struct dhcp *, int, char);LOCAL u_short udp_cksum (struct ps_udph *, char *, int n);LOCAL int dhcp_msgtoparam (struct dhcp *, int, struct dhcp_param *);LOCAL int merge_param (struct dhcp_param *, struct dhcp_param *);LOCAL long generate_xid ();LOCAL int clean_param (struct dhcp_param *);LOCAL int dhcpcBootInitState();LOCAL int dhcpcBootWaitOffer();LOCAL int dhcpcBootSelecting();LOCAL int dhcpcBootRequesting();#ifdef DHCPC_DEBUGLOCAL int nvttostr (char *, char *, int);#endif/********************************************************************************* dhcp_boot_client - Exercise client finite state machine** This routine executes the finite state machine up until the BOUND state when* a dhcpcBootBind() call is issued from the ROM-resident bootstrap loader.* The states from BOUND onward are omitted to reduce the size of the boot ROM* images. The boot file downloaded by the bootstrap loader must spawn a task* containing the full state machine defined in the DHCP client runtime library* to monitor the established lease. ** RETURNS: OK if BOUND state reached, or value of failed state on error.** ERRNO: N/A** SEE ALSO: dhcpcLib** NOMANUAL*/int dhcp_boot_client ( struct if_info *ifp ) { int next_state = 0; int retval = 0; dhcpcBootStates [INIT] = dhcpcBootInitState; dhcpcBootStates [WAIT_OFFER] = dhcpcBootWaitOffer; dhcpcBootStates [SELECTING] = dhcpcBootSelecting; dhcpcBootStates [REQUESTING] = dhcpcBootRequesting; dhcpcIntface = *ifp; /* Reset the network device and initialize the data structures. */ if ( (retval = initialize ()) < 0) return (retval); /* Use the state machine to obtain configuration parameters. */ dhcpcPrevState = dhcpcCurrState = INIT; while (next_state != BOUND) { if ( (next_state = (*dhcpcBootStates [dhcpcCurrState]) ()) < 0) {#ifdef DHCPC_DEBUG logMsg ("Error in finite state machine.\n", 0, 0, 0, 0, 0, 0);#endif if (dhcpcBootParam != NULL) { clean_param (dhcpcBootParam); free (dhcpcBootParam); dhcpcBootParam = NULL; } free (rbuf.buf); free (sbuf.buf); return (ERROR); } dhcpcPrevState = dhcpcCurrState; dhcpcCurrState = next_state;#ifdef DHCPC_DEBUG logMsg ("next state= %d\n", next_state, 0, 0, 0, 0, 0);#endif } free (rbuf.buf); free (sbuf.buf); return (OK); /* Bind successful. */ } /********************************************************************************* check_wait_offer - verify that a received packet is a DHCP lease offer** This routine examines an IP message received at the DHCP client port to* determine if it is a DHCP lease offer or a BOOTP reply. It is used * internally by the Ethernet input hook while in the WAIT_OFFER state.** RETURNS: 0 if message unrecognized, 1 for DHCP, 2 for BOOTP.** ERRNO: N/A* * NOMANUAL*/int check_wait_offer ( void ) { char *option = NULL; u_short ripcksum = 0; u_short rudpcksum = 0; struct ps_udph rpudph; /* Check if UDP and DHCP portions are present (set by msgAlign). */ if (dhcpcRbufMsg.udp == NULL || dhcpcRbufMsg.dhcp == NULL) return (0); /* Construct a UDP pseudo-header. */ bzero ( (char *)&rpudph, sizeof(rpudph)); ripcksum = dhcpcRbufMsg.ip->ip_sum; dhcpcRbufMsg.ip->ip_sum = 0; rudpcksum = dhcpcRbufMsg.udp->uh_sum; dhcpcRbufMsg.udp->uh_sum = 0; rpudph.zero = 0; rpudph.prto = IPPROTO_UDP; rpudph.srcip.s_addr = dhcpcRbufMsg.ip->ip_src.s_addr; rpudph.dstip.s_addr = dhcpcRbufMsg.ip->ip_dst.s_addr; rpudph.ulen = dhcpcRbufMsg.udp->uh_ulen; /* Check lengths of each portion of message. */ if (ntohs (dhcpcRbufMsg.ip->ip_len) < DFLTBOOTPLEN + UDPHL + IPHL) return (0); if (ntohs (dhcpcRbufMsg.udp->uh_ulen) < DFLTBOOTPLEN + UDPHL) return (0); /* Verify message received at client port. */ if (dhcpcRbufMsg.udp->uh_dport != dhcpc_port) return (0); /* Check message IP checksum. */#if BSD<44 if (ripcksum != checksum ( (u_short *)dhcpcRbufMsg.ip, (dhcpcRbufMsg.ip->ip_v_hl & 0xf) << 2))#else if (ripcksum != checksum ( (u_short *) dhcpcRbufMsg.ip, dhcpcRbufMsg.ip->ip_hl << 2))#endif return (0); /* Check message UDP checksum. */ if (dhcpcRbufMsg.udp->uh_sum != 0 && rudpcksum != udp_cksum (&rpudph, (char *)dhcpcRbufMsg.udp, ntohs (rpudph.ulen))) return (0); /* Check DHCP message opcode, transaction ID and magic cookie. */ if (dhcpcRbufMsg.dhcp->op != BOOTREPLY || dhcpcRbufMsg.dhcp->xid != dhcpcMsgOut.dhcp->xid) return (0); if (bcmp (dhcpcRbufMsg.dhcp->options, (char *)dhcpCookie, MAGIC_LEN) != 0) return (0); /* Verify type of message. If 0 returned, message is discarded. */ option = (char *)pickup_opt (dhcpcRbufMsg.dhcp, DHCPLEN (dhcpcRbufMsg.udp), _DHCP_MSGTYPE_TAG); if (option == NULL) { /* Discard untyped DHCP messages. BOOTP replies are OK. */ if (DHCPLEN (dhcpcRbufMsg.udp) < DFLTDHCPLEN) return (2); else return (0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -