bootpd.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 794 行 · 第 1/2 页

C
794
字号
#ifndef lintstatic	char	*sccsid = "@(#)bootpd.c	4.1	ULTRIX	7/2/90 - 1.1 (Stanford) 1/22/86";#endif lint/************************************************************************ *									* *			Copyright (c) 1984 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//* * BOOTP (bootstrap protocol) server daemon. * * Answers BOOTP request packets from booting client machines. * See [SRI-NIC]<RFC>RFC951.TXT for a description of the protocol. *//* * history * 01/22/86	Croft	created. * * 07/30/86     Kovar modified to work at CMU. * 07/24/87	Drew D. Perkins at Carnegie Mellon University *		    Modified to use syslog instead of Kovar's *		    routines.  Add debugging dumps.  Many other fixups. * 01/28/88	Jeffrey Mogul/DECWRL *			removed CMU-specific stuff but kept improvements *			and restored much of the Stanford code for *			figuring out the bootfile because the CMU code *			was quite broken. * 03/01/88	Jeffrey Mogul/DECWRL *			Modified for use with /etc/inetd; use * bootp dgram udp wait /etc/bootpd bootpd -i */#include <sys/types.h>#include <sys/stat.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <sys/file.h>#include <net/if.h>#include <netinet/in.h>#include <signal.h>#include <stdio.h>#include <strings.h>#include <errno.h>#include <ctype.h>#include <netdb.h>#include <setjmp.h>#include <syslog.h>#include <protocols/bootp.h>#define	DALLYTIME	60	/* seconds to wait for additional requests */#define SYSLOGint debug = 0;			/* Debugging flag */int inetd = 0;			/* Running under inetd */int s;				/* Socket file descriptor */struct sockaddr_in sin;struct sockaddr_in from;	/* Packet source */u_char buf[1024];		/* Receive packet buffer */struct ifreq ifreq[10];		/* Holds interface configuration */struct ifconf ifconf;		/* Int. config ioctl block (pnts to ifreq) */struct arpreq arpreq;		/* Arp request ioctl block *//* * Globals below are associated with the bootp database file (bootptab). */char *bootptab = "/etc/bootptab";#ifdef DEBUGchar * bootpd_dump = "/tmp/bootpd.dump";#endifFILE *fp = NULL;		/* Boot FILE */char line[256];			/* Line buffer for reading bootptab */char *linep;			/* Pointer to 'line' */int linenum;			/* Current line number in bootptab */char homedir[64];		/* Bootfile homedirectory */char defaultboot[64];		/* Default file to boot */struct hosts {	struct hosts *next;	/* Next in list */	char host[31];		/* Host name (and suffix) */	u_char htype;		/* Hardware type */	u_char haddr[6];	/* Hardware address */	struct in_addr iaddr;	/* Internet address */	char bootfile[32];	/* Default boot file name */} *hosts = NULL;int nhosts;			/* Current number of hosts */long modtime = 0;		/* Last modification time of bootptab */char *haddrtoa();		/* Convert haddr to ascii */main(argc, argv)	int argc;	char *argv[];{	struct bootp *bp = (struct bootp *) buf;	int n, fromlen;	void readtab();#ifdef DEBUG	void dumptab();#endif	/*	 * Read switches.	 */	for (argc--, argv++; argc > 0; argc--, argv++) {		if (argv[0][0] == '-') {			switch (argv[0][1]) {			    case 'd':				debug++;				break;			    case 'i':				inetd++;				break;			}		}	}	/*	 * Go into background and disassociate from controlling terminal.	 */	if ((debug < 2) && (inetd == 0)) {		if (fork())			exit(0);		for (n = 0; n < 10; n++)			(void) close(n);		(void) open("/", 0);		(void) dup2(0, 1);		(void) dup2(0, 2);		n = open("/dev/tty", 2);		if (n >= 0) {			ioctl(n, TIOCNOTTY, (char *) 0);			(void) close(n);		}	}#ifdef SYSLOG	/*	 * Initialize logging.	 */#ifdef	LOG_DAEMON	/* 4.3-style syslog */	openlog("bootpd", LOG_PID | LOG_CONS, LOG_DAEMON);#else	openlog("bootpd", LOG_PID);#endif	LOG_DAEMON	syslog(LOG_INFO, "startup");#endif	if (inetd == 0) {	    /*	     * Get us a socket.	     */	    if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {#ifdef SYSLOG		    syslog(LOG_ERR, "socket: %m");#endif		    perror("bootpd: socket");		    exit(1);	    }	    /*	     * Bind socket to BOOTPS port.	     */	    sin.sin_family = AF_INET;	    sin.sin_addr.s_addr = INADDR_ANY;	    sin.sin_port = htons(IPPORT_BOOTPS);	    if (bind(s, &sin, sizeof(sin)) < 0) {#ifdef SYSLOG		syslog(LOG_ERR, "bind: %m");#endif		perror("bootpd: bind");		exit(1);	    }	} else {	    /*	     * Running under inetd	     */	    s = 0;	/* inetd gives us socket as stdin */	}	/* end "if (inetd)" */	/*	 * Determine network configuration.	 */	ifconf.ifc_len = sizeof(ifreq);	ifconf.ifc_req = ifreq;	if ((ioctl(s, SIOCGIFCONF, (caddr_t) &ifconf) < 0) ||	    (ifconf.ifc_len <= 0)) {#ifdef SYSLOG		syslog(LOG_ERR, "ioctl: %m");#endif		perror("bootpd: ioctl");		exit(1);	}		/*	 * Read the bootptab file once immediately upon startup.	 */	readtab();	/*	 * Set up signals to read or dump the table.	 */	if ((int) signal(SIGHUP, readtab) == -1) {#ifdef SYSLOG		syslog(LOG_ERR, "signal: %m");#endif	    perror("bootpd: signal");	    exit(1);	}#ifdef DEBUG	if ((int) signal(SIGTERM, dumptab) == -1) {#ifdef SYSLOG		syslog(LOG_ERR, "signal: %m");#endif	    perror("bootpd: signal");	    exit(1);	}#endif	/*	 * Process incoming requests.	 */	for (;;) {		if (inetd)		    alarm(DALLYTIME);		fromlen = sizeof(from);		n = recvfrom(s, buf, sizeof(buf), 0, &from, &fromlen);		if (n <= 0)			continue;		if (n < sizeof(struct bootp)) {			if (debug) {#ifdef SYSLOG				syslog(LOG_INFO, "received short packet");#endif			}			continue;		}		readtab();	/* maybe re-read bootptab */		switch (bp->bp_op) {		    case BOOTREQUEST:			request();			break;		    case BOOTREPLY:			reply();			break;		}	}}/* * Process BOOTREQUEST packet. * * (Note, this version of the bootp.c server never forwards  * the request to another server.  In our environment the  * stand-alone gateways perform that function.) * * (Also this version does not interpret the hostname field of * the request packet;  it COULD do a name->address lookup and * forward the request there.) */request(){	register struct bootp *bp = (struct bootp *) buf;	register struct hosts *hp;	register n;	char path[64], file[64];		bp->bp_op = BOOTREPLY;	if (bp->bp_ciaddr.s_addr == 0) { 		/*		 * client doesnt know his IP address, 		 * search by hardware address.		 */		if (debug) {#ifdef SYSLOG			syslog(LOG_INFO,			    "Processing boot request from hw addr %s",			    haddrtoa(bp->bp_chaddr));#endif		}		for (hp = hosts, n = 0; n < nhosts && hp; n++, hp = hp->next) {		    if ((bp->bp_htype == hp->htype) &&			(bcmp(bp->bp_chaddr, hp->haddr, 6) == 0))			break;		}		if ((n == nhosts) || hp == NULL) {#ifdef SYSLOG		    syslog(LOG_NOTICE, "hw addr not found: %s",			    haddrtoa(bp->bp_chaddr));#endif		    return;	/* not found */		}		if (debug) {#ifdef SYSLOG			syslog(LOG_INFO, "Found %s", inet_ntoa(hp->iaddr));#endif		}		bp->bp_yiaddr = hp->iaddr;	} else {		/*		 * search by IP address.		 */		if (debug) {#ifdef SYSLOG			syslog(LOG_INFO,			    "Processing boot request from IP addr %s",			    inet_ntoa(bp->bp_ciaddr));#endif		}		for (hp = hosts, n = 0; n < nhosts && hp; n++, hp = hp->next)		    if (bp->bp_ciaddr.s_addr == hp->iaddr.s_addr)			break;		if ((n == nhosts) || hp == NULL) {#ifdef SYSLOG		    syslog(LOG_NOTICE,			"IP addr not found: %s", inet_ntoa(bp->bp_ciaddr));#endif		    return;		}	}	if (strcmp(bp->bp_file, "sunboot14") == 0)	/* OBSOLETE? */		bp->bp_file[0] = 0;	/* pretend it's null */	if (bp->bp_file[0] == 0) { /* if client did not specify file */		if (hp->bootfile[0] == 0)			strcpy(file, defaultboot);		else			strcpy(file, hp->bootfile);	} else {		/* client did specify file */		strcpy(file, bp->bp_file);	}	if (file[0] == '/')	/* if absolute pathname */		strcpy(path, file);	else {		strcpy(path, homedir);		strcat(path, "/");		strcat(path, file);	}	/* try first to find the file with a ".host" suffix */	n = strlen(path);	strcat(path, ".");	strcat(path, hp->host);	if (access(path, R_OK) < 0) {		path[n] = 0;	/* try it without the suffix */		if (access(path, R_OK) < 0) {		    if (bp->bp_file[0]) {			/*			 * Client wanted specific file			 * and we didnt have it.			 */#ifdef SYSLOG			syslog(LOG_NOTICE,			    "requested file not found: %s", path);#endif			return;		    }		}	}	

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?