bootpd.c

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

C
794
字号
	/* Ok, we know the filename and the file exists */	strcpy(bp->bp_file, path);#ifdef	SYSLOG	if (debug)		syslog(LOG_INFO, "bootfile is %s\n", path);#endif	SYSLOG	SetVendorInfo(bp, hp);	sendreply(0);}SetVendorInfo(bp, hp)register struct bootp *bp;register struct hosts *hp;{	/* For now, nothing */	bzero(bp->bp_vend, sizeof(bp->bp_vend));}/* * Process BOOTREPLY packet (something is using us as a gateway). */reply(){	if (debug) {#ifdef SYSLOG		syslog(LOG_INFO, "Processing boot reply");#endif	}	sendreply(1);}/* * Send a reply packet to the client.  'forward' flag is set if we are * not the originator of this reply packet. */sendreply(forward){	register struct bootp *bp = (struct bootp *) buf;	struct in_addr dst;	struct sockaddr_in to;	to.sin_family = AF_INET;	to.sin_addr.s_addr = INADDR_ANY;	to.sin_port = htons(IPPORT_BOOTPC);	/*	 * If the client IP address is specified, use that	 * else if gateway IP address is specified, use that	 * else make a temporary arp cache entry for the client's NEW 	 * IP/hardware address and use that.	 */	if (bp->bp_ciaddr.s_addr) {		dst = bp->bp_ciaddr;	} else if (bp->bp_giaddr.s_addr && forward == 0) {		dst = bp->bp_giaddr;		to.sin_port = htons(IPPORT_BOOTPS);	} else {		dst = bp->bp_yiaddr;		setarp(&dst, bp->bp_chaddr, bp->bp_hlen);	}	if (forward == 0) {		/*		 * If we are originating this reply, we		 * need to find our own interface address to		 * put in the bp_siaddr field of the reply.		 * If this server is multi-homed, pick the		 * 'best' interface (the one on the same net		 * as the client).		 */		int maxmatch = 0;		int len, m;		register struct ifreq *ifrq, *ifrmax;		ifrmax = ifrq = &ifreq[0];		len = ifconf.ifc_len;		for (; len > 0; len -= sizeof(ifreq[0]), ifrq++) {			m = nmatch(&dst, &((struct sockaddr_in *)					  (&ifrq->ifr_addr))->sin_addr);			if (m > maxmatch) {				maxmatch = m;				ifrmax = ifrq;			}		}		if (bp->bp_giaddr.s_addr == 0) {			if (maxmatch == 0) {				return;			}			bp->bp_giaddr = ((struct sockaddr_in *)				(&ifrmax->ifr_addr))->sin_addr;		}		bp->bp_siaddr = ((struct sockaddr_in *)			(&ifrmax->ifr_addr))->sin_addr;	}	to.sin_addr = dst; 	if (sendto(s, bp, sizeof(struct bootp), 0, &to, sizeof(to)) < 0) {#ifdef SYSLOG	    syslog(LOG_ERR, "sendto: %m");#endif	    perror("bootpd: sendto");	}}/* * Return the number of leading bytes matching in the * internet addresses supplied. */nmatch(ca,cb)	register char *ca, *cb;{	register n,m;	for (m = n = 0 ; n < 4 ; n++) {		if (*ca++ != *cb++)			return(m);		m++;	}	return(m);}/* * Setup the arp cache so that IP address 'ia' will be temporarily * bound to hardware address 'ha' of length 'len'. */setarp(ia, ha, len)	struct in_addr *ia;	u_char *ha;	int len;{	struct sockaddr_in *si;		bzero((caddr_t)&arpreq, sizeof(arpreq));		arpreq.arp_pa.sa_family = AF_INET;	si = (struct sockaddr_in *) &arpreq.arp_pa;	si->sin_addr = *ia;	arpreq.arp_flags = ATF_INUSE | ATF_COM;		bcopy(ha, arpreq.arp_ha.sa_data, len);	if (ioctl(s, SIOCSARP, (caddr_t)&arpreq) < 0) {#ifdef SYSLOG	    syslog(LOG_ERR, "ioctl(SIOCSARP): %m");#endif	    perror("bootpd: ioctl(SIOCSARP)");	}}/* * Read bootptab database file.  Avoid rereading the file if the * write date hasn't changed since the last time we read it. */voidreadtab(){	struct stat st;	register char *cp;	int v;	register int i;	char temp[64];	register struct hosts *hp, **hpp;	int skiptopercent;	/*	 * If the file is open already check last modification time.	 */	if (fp != 0) {		fstat(fileno(fp), &st);		if (st.st_mtime == modtime && st.st_nlink)			/*			 * hasnt been modified or deleted yet.			 */			return;		/*		 * Close and reopen it.		 */		fclose(fp);#ifdef SYSLOG		syslog(LOG_INFO, "found new bootptab");#endif	}	/*	 * Open bootptab file.	 */	if ((fp = fopen(bootptab, "r")) == NULL) {#ifdef SYSLOG		syslog(LOG_ERR, "error opening %s: %m", bootptab);#endif		perror("bootpd: opening bootptab");		exit(1);	}	/*	 * Record file modification time.	 */	fstat(fileno(fp), &st);	modtime = st.st_mtime;	homedir[0] = defaultboot[0] = 0;	nhosts = 0;	hp = hosts;	hpp = &hosts;	linenum = 0;	skiptopercent = 1;	/* 	 * read and parse each line in the file.	 */	for (;;) {		if (fgets(line, sizeof(line), fp) == NULL)			break;		/* done */		if ((i = strlen(line)))			line[i - 1] = 0; /* remove trailing newline */		linep = line;		linenum++;		if (line[0] == '#' || line[0] == 0 || line[0] == ' ')			continue;	/* skip comment lines */		if (skiptopercent) {	/* allow for leading fields */			if (line[0] != '%') {			    readhdr();			    continue;			}			skiptopercent = 0;			continue;		}		if (hp == NULL) {			if (!(*hpp = hp = (struct hosts *) calloc(1, sizeof(struct hosts)))) {#ifdef SYSLOG				syslog(LOG_ERR, "malloc failure");#endif				fprintf(stderr, "bootpd: malloc failure\n");				exit(1);			}			hp->next = NULL;		}		/* fill in host table */		getfield(hp->host, sizeof(hp->host));		getfield(temp, sizeof(temp));		sscanf(temp, "%d", &v);		hp->htype = v;		getfield(temp, sizeof(temp));		cp = temp;		/* parse hardware address */		for (i = 0; i < sizeof(hp->haddr); i++) {			if (*cp == '.' || *cp == ':' || *cp == '-')				cp++;			if (!isxdigit(cp[0]) || !isxdigit(cp[1]))				goto badentry;			if (sscanf(cp, "%2x", &v) != 1)				goto badentry;			cp += 2; 			hp->haddr[i] = v;		}		getfield(temp, sizeof(temp));		if ((i = inet_addr(temp)) == -1 || i == 0) {			goto badentry;		}		hp->iaddr.s_addr = i;		getfield(hp->bootfile, sizeof(hp->bootfile));goodentry:		++nhosts;		hpp = &(hp->next);		hp = hp->next;badentry: 		continue;	}#ifdef SYSLOG	syslog(LOG_INFO, "read %d entries from bootptab", nhosts);#endif}/* * Parse header lines of bootptab. */readhdr(){	u_long i;	char temp[64];	/* fill in fixed leading fields */	if (homedir[0] == 0) {		getfield(homedir, sizeof(homedir));		return;	}	if (defaultboot[0] == 0) {		getfield(defaultboot, sizeof(defaultboot));		return;	}}/* * Get next field from 'line' buffer into 'str'.  'linep' is the  * pointer to current position. */getfield(str, len)	char *str;{	register char *cp = str;	for ( ; *linep && (*linep == ' ' || *linep == '\t') ; linep++)		;	/* skip spaces/tabs */	if (*linep == 0) {		*cp = 0;		return;	}	len--;	/* save a spot for a null */	for (; *linep && *linep != ' ' & *linep != '\t'; linep++) {		*cp++ = *linep;		if (--len <= 0) {			*cp = 0;			return;		}	}	*cp = 0;}#ifdef DEBUG/* * Dump bootptab to bootpd_dump. */voiddumptab(){	register FILE *fp;	register struct hosts *hp;	register int n;	long t;	/*	 * Open bootpd.dump file.	 */	if ((fp = fopen(bootpd_dump, "w")) == NULL) {#ifdef SYSLOG		syslog(LOG_ERR, "error opening %s: %m", bootpd_dump);#endif		perror("bootpd: opening bootpd.dump");		exit(1);	}	t = time(NULL);	fprintf(fp,"#\n# %s: dump of bootp server database.\n#\n# dump taken %s\n#\n\# home directory\n\%s\n\n# default bootfile\n%s\n\n",		bootpd_dump, ctime(&t), homedir, defaultboot);	fprintf(fp,	    "%%%%\n# host htype haddr iaddr bootfile\n");	for (hp = hosts, n = 0; n < nhosts && hp; n++, hp = hp->next) {	    fprintf(fp, "%-16s %d %s %-15s %8s\n",		hp->host, hp->htype, haddrtoa(hp->haddr),		inet_ntoa(hp->iaddr), hp->bootfile);	}	fclose(fp);#ifdef SYSLOG	syslog(LOG_INFO, "dumped %d entries to %s", n, bootpd_dump);#endif}#endif/* * Convert a hardware address to an ascii string. */char *haddrtoa(h)unsigned char *h;{	static char haddrbuf[18];	sprintf(haddrbuf, "%02x:%02x:%02x:%02x:%02x:%02x",	    h[0], h[1], h[2], h[3], h[4], h[5]);	return (haddrbuf);}

⌨️ 快捷键说明

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