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