📄 dhcpc_subr.c
字号:
/* dhcpc_subr.c - DHCP client general subroutines *//* Copyright 1984 - 1999 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history____________________01n,01mar99,spm eliminated creation of invalid route (SPR #24266)01m,04dec97,spm added code review modifications01l,04dec97,spm replaced muxDevExists call with test of predefined flag; enabled ARP test of intended IP address01k,06oct97,spm removed reference to deleted endDriver global; replaced with support for dynamic driver type detection01j,26aug97,spm major overhaul: reorganized code and changed user interface to support multiple leases at runtime01i,06aug97,spm renamed class field of dhcp_reqspec structure to prevent C++ compilation errors (SPR #9079)01h,15jul97,spm set sa_len and reordered ioctl calls in configuration routine, changed to raw sockets to avoid memPartFree error (SPR #8650); replaced floating point to prevent ss5 exception (SPR #8738)01g,10jun97,spm corrected load exception (SPR #8724) and memalign() parameter; isolated incoming messages in state machine from input hooks01f,02jun97,spm changed DHCP option tags to prevent name conflicts (SPR #8667) and updated man pages01e,09may97,spm changed memory access to align IP header on four byte boundary01d,18apr97,spm added conditional include DHCPC_DEBUG for displayed output, shut down interface when changing address/netmask01c,07apr97,spm corrected bugs extracting options, added safety checks and memory cleanup code, rewrote documentation01b,27jan97,spm added little-endian support and modified to coding standards 01a,03oct96,spm created by modifying WIDE Project DHCP Implementation*//*DESCRIPTIONThis library contains subroutines which implement several utilities for the Wide project DHCP client, modified for vxWorks compatibility.INTERNALThe routines in this module are called by both portions of the runtime state machine, in the dhcpcState1 and dhcpcState2 modules, which execute before and after a lease is established, as well as the boot-time (partial) state machinein the dhcpcBoot module.INCLUDE_FILES: dhcpcLib.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 <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <fcntl.h>#include <sys/types.h>#include <time.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <net/if.h>#include <net/route.h>#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/if_ether.h>#include <netinet/ip.h>#include <netinet/udp.h>#include <arpa/inet.h>#include <inetLib.h>#include <etherLib.h>#include <sysLib.h>#include <logLib.h>#include <sockLib.h>#include <ioLib.h>#include <semLib.h>#include <vxLib.h>#include "muxLib.h"#include "dhcp/dhcp.h"#include "dhcp/dhcpcStateLib.h"#include "dhcp/dhcpcCommonLib.h"#include "dhcp/dhcpcInternal.h"#define CHKOFF(LEN) (offopt + 2 + (LEN) < DFLTOPTLEN) /* test option offset *//* globals */IMPORT SEM_ID dhcpcArpEventSem;IMPORT u_char dhcpArpSpa[4];IMPORT BOOL dhcpArpInputHook (struct ifnet*, char*, int);IMPORT int flushroutes (void);IMPORT char * pDhcpcRecvBuf; /* Message buffer for state machine. */struct msg dhcpcMsgOut;struct msg dhcpcMsgIn;struct ps_udph spudph;/* forward declarations */int config_if();void set_route();void make_decline (char *, struct dhcp_reqspec *, struct if_info *);void make_release (struct dhcp *, struct dhcp_reqspec *, struct if_info *);long generate_xid (struct if_info *);/********************************************************************************* generate_xid - generate a transaction identifier ** This routine forms a transaction identifier which is used by the lease * for transmissions over the interface described by <pIfData>. The routine * is called from multiple locations after the initialization routines have * retrieved the network interface hardware address.** RETURNS: 32-bit transaction identifier in host byte order. ** ERRNO: N/A** NOMANUAL*/long generate_xid ( struct if_info * pIfData /* interface used by lease */ ) { time_t current = 0; u_short result1 = 0; u_short result2 = 0; u_short result3 = 0; u_short tmp[6]; bcopy (pIfData->haddr.haddr, (char *)tmp, 6); time (¤t); result1 = checksum (tmp, 6); result2 = checksum ( (u_short *)¤t, 2); /* * Although unlikely, it is possible that separate leases which are using * the same network interface calculate a checksum at the same time. To * guarantee uniqueness, include the value of the lease-specific pointer * to the interface descriptor. */ tmp [0] = ((long)pIfData) >> 16; tmp [1] = ((long)pIfData) & 0xffff; result3 = checksum (tmp, 4); return ( (result1 << 16) + result2 + result3); }/********************************************************************************* arp_check - use ARP to check if given address is in use** This routine broadcasts an ARP request and waits for a reply to determine if* an IP address offered by a DHCP server is already in use.** RETURNS: ERROR if ARP indicates client in use, or OK otherwise.** ERRNO: N/A** NOMANUAL*/int arp_check ( struct in_addr *target, struct if_info *pIfData /* interface used by lease */ ) { int i = 0; long tmp; char inbuf [ETHERHL + sizeof (struct ether_arp)]; struct ether_header *sether = NULL; struct ether_arp *sarp = NULL; STATUS result; bzero (inbuf, ETHERHL + sizeof (struct ether_arp)); sether = (struct ether_header *) inbuf; sarp = (struct ether_arp *) &inbuf [ETHERHL]; sarp->arp_hrd = htons (ARPHRD_ETHER); sarp->arp_pro = htons (ETHERTYPE_IP); sarp->arp_hln = 6; sarp->arp_pln = 4; sarp->arp_op = htons (ARPOP_REQUEST); /* Set sender H/W address to your address for ARP requests. (RFC 1541). */ for (i = 0; i < 6; i++) { sarp->arp_sha[i] = sether->ether_shost[i] = pIfData->haddr.haddr[i]; sarp->arp_tha[i] = 0; sether->ether_dhost[i] = 0xff; } /* Set sender IP address to 0 for ARP requests as per RFC 1541. */ tmp = 0; bcopy ( (char *)&tmp, (char *)sarp->arp_spa, sarp->arp_pln); bcopy ( (char *)&target->s_addr, (char *)sarp->arp_tpa, sarp->arp_pln); sether->ether_type = ETHERTYPE_ARP; if (etherOutput (pIfData->iface, sether, (char *)sarp, sizeof (struct ether_arp)) == ERROR) { return (OK); /* it is harmless to return 0 */ } /* Set sender address to our address for checking by etherHook. */ bcopy ( (char *)&target->s_addr, (char *)dhcpArpSpa, sarp->arp_pln); /* Create signalling semaphore. */ dhcpcArpEventSem = semBCreate (SEM_Q_FIFO, SEM_EMPTY); if (dhcpcArpEventSem == NULL) {#ifdef DHCPC_DEBUG logMsg ("Error creating ARP semaphore.\n", 0, 0, 0, 0, 0, 0);#endif return (OK); } /* Wait up to one-half a second for a reply. If none received, return 0. */ if (pIfData->endDrvFlag) etherInputHookAdd (dhcpArpInputHook, pIfData->name, pIfData->unit); else etherInputHookAdd (dhcpArpInputHook, NULL, pIfData->unit); result = semTake (dhcpcArpEventSem, sysClkRateGet() / 2); semDelete (dhcpcArpEventSem); if (pIfData->endDrvFlag) etherInputHookDelete (dhcpArpInputHook, pIfData->name, pIfData->unit); else etherInputHookDelete (dhcpArpInputHook, NULL, pIfData->unit); if (result == ERROR) /* Error indicates timeout occurred. */ return (OK); else /* ARP reply received - duplicate IP address. */ return (ERROR); }/********************************************************************************* arp_reply - use ARP to notify other hosts of new address in use** This routine broadcasts an ARP reply when the DHCP client changes addresses* to a new value retrieved from a DHCP server.** RETURNS: -1 if ARP indicates client in use, or 0 otherwise.** ERRNO: N/A** NOMANUAL*/int arp_reply ( struct in_addr *ipaddr, struct if_info *pIfData /* interface used by lease */ ) { int i = 0; char inbuf [ETHERHL + sizeof (struct ether_arp) ]; struct ether_header *sether = NULL; struct ether_arp *sarp = NULL; bzero (inbuf, ETHERHL + sizeof (struct ether_arp)); sether = (struct ether_header *)inbuf; sarp = (struct ether_arp *)&inbuf [ETHERHL]; sarp->arp_hrd = htons (ARPHRD_ETHER); sarp->arp_pro = htons (ETHERTYPE_IP); sarp->arp_hln = 6; sarp->arp_pln = 4; sarp->arp_op = htons (ARPOP_REPLY); for (i = 0; i < 6; i++) { sarp->arp_tha[i] = sarp->arp_sha[i] = sether->ether_shost[i] = pIfData->haddr.haddr[i]; sether->ether_dhost[i] = 0xff; } bcopy ( (char *)&ipaddr->s_addr, (char *)sarp->arp_spa, sarp->arp_pln); bcopy ( (char *)&ipaddr->s_addr, (char *)sarp->arp_tpa, sarp->arp_pln); sether->ether_type = ETHERTYPE_ARP; if (etherOutput (pIfData->iface, sether, (char *)sarp, sizeof (struct ether_arp)) == ERROR) return (-1); return (0); }/********************************************************************************* nvttostr - convert NVT ASCII to strings** This routine implements a limited NVT conversion which removes any embedded* NULL characters from the input string.** RETURNS: N/A** ERRNO: N/A** NOMANUAL*/int nvttostr ( char * nvt, char * str, int length ) { FAST int i = 0; FAST char *tmp = NULL; tmp = str; for (i = 0; i < length; i++) { if (nvt[i] != NULL) { *tmp = nvt[i]; tmp++; } } str [length] = '\0'; return (0); }/********************************************************************************* align_msg - set the buffer pointers to access message components** This routine sets the pointers in the given message descriptor* structure to access the various components of a received DHCP* message. It is used internally by the Ethernet input hook and* the state machine.** RETURNS: N/A** ERRNO: N/A** NOMANUAL*/void align_msg ( struct msg * rmsg, /* Components of received message */ char * rbuf /* Received Ethernet packet */ ) { rmsg->ether = (struct ether_header *) rbuf; rmsg->ip = (struct ip *) &rbuf[ETHERHL]; if ( (ntohs (rmsg->ip->ip_off) & 0x1fff) == 0 && ntohs (rmsg->ip->ip_len) >= DFLTBOOTPLEN + UDPHL + IPHL) {#if BSD<44 rmsg->udp = (struct udphdr *)&rbuf [ETHERHL + (rmsg->ip->ip_v_hl & 0xf) * WORD]; rmsg->dhcp = (struct dhcp *)&rbuf [ETHERHL + (rmsg->ip->ip_v_hl & 0xf) * WORD + UDPHL];#else rmsg->udp = (struct udphdr *) &rbuf [ETHERHL + rmsg->ip->ip_hl * WORD]; rmsg->dhcp = (struct dhcp *) &rbuf [ETHERHL + rmsg->ip->ip_hl * WORD + UDPHL];#endif } else { rmsg->udp = NULL; rmsg->dhcp = NULL; } return; }/********************************************************************************* dhcp_msgtoparam - expand DHCP message into data structure*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -