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 + -
显示快捷键?