Annotation of embedaddon/dhcp/minires/res_init.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (c) 1985, 1989, 1993
        !             3:  *    The Regents of the University of California.  All rights reserved.
        !             4:  * 
        !             5:  * Redistribution and use in source and binary forms, with or without
        !             6:  * modification, are permitted provided that the following conditions
        !             7:  * are met:
        !             8:  * 1. Redistributions of source code must retain the above copyright
        !             9:  *    notice, this list of conditions and the following disclaimer.
        !            10:  * 2. Redistributions in binary form must reproduce the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer in the
        !            12:  *    documentation and/or other materials provided with the distribution.
        !            13:  * 3. All advertising materials mentioning features or use of this software
        !            14:  *    must display the following acknowledgement:
        !            15:  *     This product includes software developed by the University of
        !            16:  *     California, Berkeley and its contributors.
        !            17:  * 4. Neither the name of the University nor the names of its contributors
        !            18:  *    may be used to endorse or promote products derived from this software
        !            19:  *    without specific prior written permission.
        !            20:  * 
        !            21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            31:  * SUCH DAMAGE.
        !            32:  */
        !            33: 
        !            34: /*
        !            35:  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
        !            36:  * 
        !            37:  * Permission to use, copy, modify, and distribute this software for any
        !            38:  * purpose with or without fee is hereby granted, provided that the above
        !            39:  * copyright notice and this permission notice appear in all copies, and that
        !            40:  * the name of Digital Equipment Corporation not be used in advertising or
        !            41:  * publicity pertaining to distribution of the document or software without
        !            42:  * specific, written prior permission.
        !            43:  * 
        !            44:  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
        !            45:  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
        !            46:  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
        !            47:  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
        !            48:  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
        !            49:  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
        !            50:  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
        !            51:  * SOFTWARE.
        !            52:  */
        !            53: 
        !            54: /*
        !            55:  * Portions Copyright (c) 2004,2007,2009 by Internet Systems Consortium, Inc. ("ISC")
        !            56:  * Portions Copyright (c) 1995-2003 by Internet Software Consortium
        !            57:  *
        !            58:  * Permission to use, copy, modify, and distribute this software for any
        !            59:  * purpose with or without fee is hereby granted, provided that the above
        !            60:  * copyright notice and this permission notice appear in all copies.
        !            61:  *
        !            62:  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
        !            63:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            64:  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
        !            65:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            66:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            67:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
        !            68:  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            69:  *
        !            70:  *   Internet Systems Consortium, Inc.
        !            71:  *   950 Charter Street
        !            72:  *   Redwood City, CA 94063
        !            73:  *   <info@isc.org>
        !            74:  *   https://www.isc.org/
        !            75:  */
        !            76: 
        !            77: #if defined(LIBC_SCCS) && !defined(lint)
        !            78: static const char sccsid[] = "@(#)res_init.c   8.1 (Berkeley) 6/7/93";
        !            79: static const char rcsid[] = "$Id: res_init.c,v 1.11.74.2 2009-07-24 22:04:52 sar Exp $";
        !            80: #endif /* LIBC_SCCS and not lint */
        !            81: 
        !            82: #include <sys/types.h>
        !            83: #include <sys/param.h>
        !            84: #include <sys/socket.h>
        !            85: #include <sys/time.h>
        !            86: 
        !            87: #include <netinet/in.h>
        !            88: #include <arpa/inet.h>
        !            89: 
        !            90: #include <ctype.h>
        !            91: #include <stdio.h>
        !            92: #include <stdlib.h>
        !            93: #include <string.h>
        !            94: #include <unistd.h>
        !            95: 
        !            96: #include "minires/minires.h"
        !            97: #include "arpa/nameser.h"
        !            98: 
        !            99: /* Options.  Should all be left alone. */
        !           100: #define RESOLVSORT
        !           101: #define RFC1535
        !           102: 
        !           103: static void res_setoptions (res_state, const char *, const char *);
        !           104: 
        !           105: #ifdef RESOLVSORT
        !           106: static const char sort_mask[] = "/&";
        !           107: #define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL)
        !           108: static u_int32_t net_mask (struct in_addr);
        !           109: #endif
        !           110: 
        !           111: #if !defined(isascii)  /* XXX - could be a function */
        !           112: # define isascii(c) (!(c & 0200))
        !           113: #endif
        !           114: 
        !           115: /*
        !           116:  * Resolver state default settings.
        !           117:  */
        !           118: 
        !           119: /*
        !           120:  * Set up default settings.  If the configuration file exist, the values
        !           121:  * there will have precedence.  Otherwise, the server address is set to
        !           122:  * INADDR_ANY and the default domain name comes from the gethostname().
        !           123:  *
        !           124:  * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
        !           125:  * rather than INADDR_ANY ("0.0.0.0") as the default name server address
        !           126:  * since it was noted that INADDR_ANY actually meant ``the first interface
        !           127:  * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
        !           128:  * it had to be "up" in order for you to reach your own name server.  It
        !           129:  * was later decided that since the recommended practice is to always 
        !           130:  * install local static routes through 127.0.0.1 for all your network
        !           131:  * interfaces, that we could solve this problem without a code change.
        !           132:  *
        !           133:  * The configuration file should always be used, since it is the only way
        !           134:  * to specify a default domain.  If you are running a server on your local
        !           135:  * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
        !           136:  * in the configuration file.
        !           137:  *
        !           138:  * Return 0 if completes successfully, -1 on error
        !           139:  */
        !           140: extern int minires_vinit(res_state, int);
        !           141: 
        !           142: #if defined (TRACING)
        !           143: u_int trace_mr_res_randomid(u_int);
        !           144: #endif
        !           145: 
        !           146: int
        !           147: res_ninit(res_state statp) {
        !           148: 
        !           149:        return (minires_vinit(statp, 0));
        !           150: }
        !           151: 
        !           152: /* This function has to be reachable by res_data.c but not publically. */
        !           153: int
        !           154: minires_vinit(res_state statp, int preinit) {
        !           155:        register FILE *fp;
        !           156:        char *cp;
        !           157:        register char **pp;
        !           158:        register int n;
        !           159:        char buf[BUFSIZ];
        !           160:        int nserv = 0;    /* number of nameserver records read from file */
        !           161:        int haveenv = 0;
        !           162:        int havesearch = 0;
        !           163: #ifdef RESOLVSORT
        !           164:        int nsort = 0;
        !           165:        char *net;
        !           166: #endif
        !           167: #ifndef RFC1535
        !           168:        int dots;
        !           169: #endif
        !           170: 
        !           171:        if (!preinit) {
        !           172:                statp->retrans = RES_TIMEOUT;
        !           173:                statp->retry = RES_DFLRETRY;
        !           174:                statp->options = RES_DEFAULT;
        !           175:                statp->id = res_randomid();
        !           176: #if defined (TRACING)
        !           177:                statp->id = trace_mr_res_randomid (statp -> id);
        !           178: #endif
        !           179:        }
        !           180: 
        !           181: #ifdef USELOOPBACK
        !           182:        statp->nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
        !           183: #else
        !           184:        statp->nsaddr.sin_addr.s_addr = INADDR_ANY;
        !           185: #endif
        !           186:        statp->nsaddr.sin_family = AF_INET;
        !           187:        statp->nsaddr.sin_port = htons(NAMESERVER_PORT);
        !           188:        statp->nscount = 1;
        !           189:        statp->ndots = 1;
        !           190:        statp->pfcode = 0;
        !           191:        statp->_sock = -1;
        !           192:        statp->_flags = 0;
        !           193:        statp->qhook = NULL;
        !           194:        statp->rhook = NULL;
        !           195: 
        !           196:        /* Allow user to override the local domain definition */
        !           197:        if ((cp = getenv("LOCALDOMAIN")) != NULL) {
        !           198:                (void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
        !           199:                statp->defdname[sizeof(statp->defdname) - 1] = '\0';
        !           200:                haveenv++;
        !           201: 
        !           202:                /*
        !           203:                 * Set search list to be blank-separated strings
        !           204:                 * from rest of env value.  Permits users of LOCALDOMAIN
        !           205:                 * to still have a search list, and anyone to set the
        !           206:                 * one that they want to use as an individual (even more
        !           207:                 * important now that the rfc1535 stuff restricts searches)
        !           208:                 */
        !           209:                cp = statp->defdname;
        !           210:                pp = statp->dnsrch;
        !           211:                *pp++ = cp;
        !           212:                for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
        !           213:                        if (*cp == '\n')        /* silly backwards compat */
        !           214:                                break;
        !           215:                        else if (*cp == ' ' || *cp == '\t') {
        !           216:                                *cp = 0;
        !           217:                                n = 1;
        !           218:                        } else if (n) {
        !           219:                                *pp++ = cp;
        !           220:                                n = 0;
        !           221:                                havesearch = 1;
        !           222:                        }
        !           223:                }
        !           224:                /* null terminate last domain if there are excess */
        !           225:                while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n')
        !           226:                        cp++;
        !           227:                *cp = '\0';
        !           228:                *pp++ = 0;
        !           229:        }
        !           230: 
        !           231: #define        MATCH(line, name) \
        !           232:        (!strncmp(line, name, sizeof(name) - 1) && \
        !           233:        (line[sizeof(name) - 1] == ' ' || \
        !           234:         line[sizeof(name) - 1] == '\t'))
        !           235: 
        !           236:        if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
        !           237:            /* read the config file */
        !           238:            while (fgets(buf, sizeof(buf), fp) != NULL) {
        !           239:                /* skip comments */
        !           240:                if (*buf == ';' || *buf == '#')
        !           241:                        continue;
        !           242:                /* read default domain name */
        !           243:                if (MATCH(buf, "domain")) {
        !           244:                    if (haveenv)        /* skip if have from environ */
        !           245:                            continue;
        !           246:                    cp = buf + sizeof("domain") - 1;
        !           247:                    while (*cp == ' ' || *cp == '\t')
        !           248:                            cp++;
        !           249:                    if ((*cp == '\0') || (*cp == '\n'))
        !           250:                            continue;
        !           251:                    strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
        !           252:                    statp->defdname[sizeof(statp->defdname) - 1] = '\0';
        !           253:                    if ((cp = strpbrk(statp->defdname, " \t\n")) != NULL)
        !           254:                            *cp = '\0';
        !           255:                    havesearch = 0;
        !           256:                    continue;
        !           257:                }
        !           258:                /* set search list */
        !           259:                if (MATCH(buf, "search")) {
        !           260:                    if (haveenv)        /* skip if have from environ */
        !           261:                            continue;
        !           262:                    cp = buf + sizeof("search") - 1;
        !           263:                    while (*cp == ' ' || *cp == '\t')
        !           264:                            cp++;
        !           265:                    if ((*cp == '\0') || (*cp == '\n'))
        !           266:                            continue;
        !           267:                    strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
        !           268:                    statp->defdname[sizeof(statp->defdname) - 1] = '\0';
        !           269:                    if ((cp = strchr(statp->defdname, '\n')) != NULL)
        !           270:                            *cp = '\0';
        !           271:                    /*
        !           272:                     * Set search list to be blank-separated strings
        !           273:                     * on rest of line.
        !           274:                     */
        !           275:                    cp = statp->defdname;
        !           276:                    pp = statp->dnsrch;
        !           277:                    *pp++ = cp;
        !           278:                    for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
        !           279:                            if (*cp == ' ' || *cp == '\t') {
        !           280:                                    *cp = 0;
        !           281:                                    n = 1;
        !           282:                            } else if (n) {
        !           283:                                    *pp++ = cp;
        !           284:                                    n = 0;
        !           285:                            }
        !           286:                    }
        !           287:                    /* null terminate last domain if there are excess */
        !           288:                    while (*cp != '\0' && *cp != ' ' && *cp != '\t')
        !           289:                            cp++;
        !           290:                    *cp = '\0';
        !           291:                    *pp++ = 0;
        !           292:                    havesearch = 1;
        !           293:                    continue;
        !           294:                }
        !           295:                /* read nameservers to query */
        !           296:                if (MATCH(buf, "nameserver") && nserv < MAXNS) {
        !           297:                    struct in_addr a;
        !           298: 
        !           299:                    cp = buf + sizeof("nameserver") - 1;
        !           300:                    while (*cp == ' ' || *cp == '\t')
        !           301:                        cp++;
        !           302:                    if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) {
        !           303:                        statp->nsaddr_list[nserv].sin_addr = a;
        !           304:                        statp->nsaddr_list[nserv].sin_family = AF_INET;
        !           305:                        statp->nsaddr_list[nserv].sin_port =
        !           306:                                htons(NAMESERVER_PORT);
        !           307:                        nserv++;
        !           308:                    }
        !           309:                    continue;
        !           310:                }
        !           311: #ifdef RESOLVSORT
        !           312:                if (MATCH(buf, "sortlist")) {
        !           313:                    struct in_addr a;
        !           314: 
        !           315:                    cp = buf + sizeof("sortlist") - 1;
        !           316:                    while (nsort < MAXRESOLVSORT) {
        !           317:                        while (*cp == ' ' || *cp == '\t')
        !           318:                            cp++;
        !           319:                        if (*cp == '\0' || *cp == '\n' || *cp == ';')
        !           320:                            break;
        !           321:                        net = cp;
        !           322:                        while (*cp && !ISSORTMASK(*cp) && *cp != ';' &&
        !           323:                               isascii((int)*cp) && !isspace((int)*cp))
        !           324:                                cp++;
        !           325:                        n = *cp;
        !           326:                        *cp = 0;
        !           327:                        if (inet_aton(net, &a)) {
        !           328:                            statp->sort_list[nsort].addr = a;
        !           329:                            if (ISSORTMASK(n)) {
        !           330:                                *cp++ = n;
        !           331:                                net = cp;
        !           332:                                while (*cp && *cp != ';' &&
        !           333:                                        isascii((int)*cp) && !isspace((int)*cp))
        !           334:                                    cp++;
        !           335:                                n = *cp;
        !           336:                                *cp = 0;
        !           337:                                if (inet_aton(net, &a)) {
        !           338:                                    statp->sort_list[nsort].mask = a.s_addr;
        !           339:                                } else {
        !           340:                                    statp->sort_list[nsort].mask = 
        !           341:                                        net_mask(statp->sort_list[nsort].addr);
        !           342:                                }
        !           343:                            } else {
        !           344:                                statp->sort_list[nsort].mask = 
        !           345:                                    net_mask(statp->sort_list[nsort].addr);
        !           346:                            }
        !           347:                            nsort++;
        !           348:                        }
        !           349:                        *cp = n;
        !           350:                    }
        !           351:                    continue;
        !           352:                }
        !           353: #endif
        !           354:                if (MATCH(buf, "options")) {
        !           355:                    res_setoptions(statp, buf + sizeof("options") - 1, "conf");
        !           356:                    continue;
        !           357:                }
        !           358:            }
        !           359:            if (nserv > 1) 
        !           360:                statp->nscount = nserv;
        !           361: #ifdef RESOLVSORT
        !           362:            statp->nsort = nsort;
        !           363: #endif
        !           364:            (void) fclose(fp);
        !           365:        }
        !           366:        if (statp->defdname[0] == 0 &&
        !           367:            gethostname(buf, sizeof(statp->defdname) - 1) == 0 &&
        !           368:            (cp = strchr(buf, '.')) != NULL)
        !           369:                strcpy(statp->defdname, cp + 1);
        !           370: 
        !           371:        /* find components of local domain that might be searched */
        !           372:        if (havesearch == 0) {
        !           373:                pp = statp->dnsrch;
        !           374:                *pp++ = statp->defdname;
        !           375:                *pp = NULL;
        !           376: 
        !           377: #ifndef RFC1535
        !           378:                dots = 0;
        !           379:                for (cp = statp->defdname; *cp; cp++)
        !           380:                        dots += (*cp == '.');
        !           381: 
        !           382:                cp = statp->defdname;
        !           383:                while (pp < statp->dnsrch + MAXDFLSRCH) {
        !           384:                        if (dots < LOCALDOMAINPARTS)
        !           385:                                break;
        !           386:                        cp = strchr(cp, '.') + 1;    /* we know there is one */
        !           387:                        *pp++ = cp;
        !           388:                        dots--;
        !           389:                }
        !           390:                *pp = NULL;
        !           391:                if (statp->options & RES_DEBUG) {
        !           392:                        printf(";; res_init()... default dnsrch list:\n");
        !           393:                        for (pp = statp->dnsrch; *pp; pp++)
        !           394:                                printf(";;\t%s\n", *pp);
        !           395:                        printf(";;\t..END..\n");
        !           396:                }
        !           397: #endif /* !RFC1535 */
        !           398:        }
        !           399: 
        !           400:        if ((cp = getenv("RES_OPTIONS")) != NULL)
        !           401:                res_setoptions(statp, cp, "env");
        !           402:        statp->options |= RES_INIT;
        !           403:        return (0);
        !           404: }
        !           405: 
        !           406: static void
        !           407: res_setoptions(res_state statp, const char *options, const char *source) {
        !           408:        const char *cp = options;
        !           409:        int i;
        !           410: 
        !           411:        if (statp->options & RES_DEBUG)
        !           412:                printf(";; res_setoptions(\"%s\", \"%s\")...\n",
        !           413:                       options, source);
        !           414:        while (*cp) {
        !           415:                /* skip leading and inner runs of spaces */
        !           416:                while (*cp == ' ' || *cp == '\t')
        !           417:                        cp++;
        !           418:                /* search for and process individual options */
        !           419:                if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
        !           420:                        i = atoi(cp + sizeof("ndots:") - 1);
        !           421:                        if (i <= RES_MAXNDOTS)
        !           422:                                statp->ndots = i;
        !           423:                        else
        !           424:                                statp->ndots = RES_MAXNDOTS;
        !           425:                        if (statp->options & RES_DEBUG)
        !           426:                                printf(";;\tndots=%d\n", statp->ndots);
        !           427:                } else if (!strncmp(cp, "timeout:", sizeof("timeout:") - 1)) {
        !           428:                        i = atoi(cp + sizeof("timeout:") - 1);
        !           429:                        if (i <= RES_MAXRETRANS)
        !           430:                                statp->retrans = i;
        !           431:                        else
        !           432:                                statp->retrans = RES_MAXRETRANS;
        !           433:                } else if (!strncmp(cp, "attempts:", sizeof("attempts:") - 1)){
        !           434:                        i = atoi(cp + sizeof("attempts:") - 1);
        !           435:                        if (i <= RES_MAXRETRY)
        !           436:                                statp->retry = i;
        !           437:                        else
        !           438:                                statp->retry = RES_MAXRETRY;
        !           439:                } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
        !           440:                        if (!(statp->options & RES_DEBUG)) {
        !           441:                                printf(";; res_setoptions(\"%s\", \"%s\")..\n",
        !           442:                                       options, source);
        !           443:                                statp->options |= RES_DEBUG;
        !           444:                        }
        !           445:                        printf(";;\tdebug\n");
        !           446:                } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
        !           447:                        statp->options |= RES_USE_INET6;
        !           448:                } else if (!strncmp(cp, "rotate", sizeof("rotate") - 1)) {
        !           449:                        statp->options |= RES_ROTATE;
        !           450:                } else if (!strncmp(cp, "no-check-names",
        !           451:                                    sizeof("no-check-names") - 1)) {
        !           452:                        statp->options |= RES_NOCHECKNAME;
        !           453:                } else {
        !           454:                        /* XXX - print a warning here? */
        !           455:                }
        !           456:                /* skip to next run of spaces */
        !           457:                while (*cp && *cp != ' ' && *cp != '\t')
        !           458:                        cp++;
        !           459:        }
        !           460: }
        !           461: 
        !           462: #ifdef RESOLVSORT
        !           463: /* XXX - should really support CIDR which means explicit masks always. */
        !           464: static u_int32_t
        !           465: net_mask(in)           /* XXX - should really use system's version of this */
        !           466:        struct in_addr in;
        !           467: {
        !           468:        register u_int32_t i = ntohl(in.s_addr);
        !           469: 
        !           470:        if (IN_CLASSA(i))
        !           471:                return (htonl(IN_CLASSA_NET));
        !           472:        else if (IN_CLASSB(i))
        !           473:                return (htonl(IN_CLASSB_NET));
        !           474:        return (htonl(IN_CLASSC_NET));
        !           475: }
        !           476: #endif
        !           477: 
        !           478: u_int
        !           479: res_randomid(void) {
        !           480:        struct timeval now;
        !           481: 
        !           482:        gettimeofday(&now, NULL);
        !           483:        return (0xffff & (now.tv_sec ^ now.tv_usec ^ getpid()));
        !           484: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>