From owner-freebsd-audit Sun Mar 31 21:26:28 2002 Delivered-To: freebsd-audit@freebsd.org Received: from yello.shallow.net (yello.shallow.net [203.18.243.120]) by hub.freebsd.org (Postfix) with ESMTP id 3FB8737B421 for ; Sun, 31 Mar 2002 21:26:26 -0800 (PST) Received: by yello.shallow.net (Postfix, from userid 1001) id 35FD62A73; Mon, 1 Apr 2002 15:26:25 +1000 (EST) Date: Mon, 1 Apr 2002 15:26:25 +1000 From: Joshua Goodall To: audit@freebsd.org Subject: request code review: kern/29355 lchflags syscall and supporting userland Message-ID: <20020401052625.GD30787@roughtrade.net> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.3.28i Sender: owner-freebsd-audit@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG This PR has been open for some time, and was on the verge of bitrotting, so I've updated the diff. I'd appreciate a review, since this is my first public attempt at kernel hacking. http://www.FreeBSD.org/cgi/query-pr.cgi?pr=29355 Joshua To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-audit" in the body of the message From owner-freebsd-audit Mon Apr 1 23:15: 9 2002 Delivered-To: freebsd-audit@freebsd.org Received: from mail.rpi.edu (mail.rpi.edu [128.113.22.40]) by hub.freebsd.org (Postfix) with ESMTP id F202D37B41D for ; Mon, 1 Apr 2002 23:14:36 -0800 (PST) Received: from [128.113.24.47] (gilead.acs.rpi.edu [128.113.24.47]) by mail.rpi.edu (8.12.1/8.12.1) with ESMTP id g327EZp5472514; Tue, 2 Apr 2002 02:14:35 -0500 Mime-Version: 1.0 X-Sender: drosih@mail.rpi.edu Message-Id: Date: Tue, 2 Apr 2002 02:14:33 -0500 To: freebsd-print@bostonradio.org, freebsd-audit@freebsd.org From: Garance A Drosihn Subject: A patch to cleanup sendfile() routine in lpd/printjob.c Content-Type: text/plain; charset="us-ascii" ; format="flowed" X-Scanned-By: MIMEDefang 2.3 (www dot roaringpenguin dot com slash mimedefang) Sender: owner-freebsd-audit@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG In a previous message to freebsd-print@bostonradio.org, I talked about adding a new 'resend_copies' aka 'rc' option for printcap entries. To do that "right" requires moving some code around in sendfile(), and the more I tried to do that the more I realized that the code which was there is too complicated, mainly in the way it tries to handle output filters for remote jobs. It is trying to use the same output-filter processing as is used when printing a job to a local device, and it does not get it quite right. This does a pretty major restructuring of the code for sendfile(), which paves the way for a number of other updates. It should work exactly the same for remote queues which have no filter defined, or which have an input filter defined. It will behave slightly different for a queue which has an output filter defined, but since I couldn't really figure out *all* the code paths thru the old code I can't say what exactly will be different. I am much more confident that what this does will be correct. I intend to put this in later this week, but I probably won't be around at all for Tuesday, and maybe not for Wednesday, so I wanted to send this off tonight. Index: lpd/printjob.c =================================================================== RCS file: /home/ncvs/src/usr.sbin/lpr/lpd/printjob.c,v retrieving revision 1.44 diff -u -r1.44 printjob.c --- lpd/printjob.c 27 Nov 2001 01:32:25 -0000 1.44 +++ lpd/printjob.c 2 Apr 2002 06:43:33 -0000 @@ -130,6 +130,8 @@ static void banner(struct printer *_pp, char *_name1, char *_name2); static int dofork(const struct printer *_pp, int _action); static int dropit(int _c); +static int execfilter(struct printer *_pp, char *_f_cmd, char **_f_av, + int _infd, int _outfd); static void init(struct printer *_pp); static void openpr(const struct printer *_pp); static void opennet(const struct printer *_pp); @@ -971,9 +973,9 @@ { register int f, i, amt; struct stat stb; - FILE *fp; - char buf[BUFSIZ]; - int closedpr, resp, sizerr, statrc; + char *av[15], *filtcmd; + char buf[BUFSIZ], opt_c[4], opt_h[4], opt_n[4]; + int filtstat, narg, resp, sizerr, statrc; statrc = lstat(file, &stb); if (statrc < 0) { @@ -996,146 +998,104 @@ (stb.st_dev != fdev || stb.st_ino != fino)) return(ACCESS); - job_dfcnt++; /* increment datafile counter for this job */ - - /* everything seems OK, start it up */ + /* Everything seems OK for reading the file, now to send it */ + filtcmd = NULL; sizerr = 0; - closedpr = 0; + tfd = -1; if (type == '\3') { + /* + * Type == 3 means this is a datafile, not a control file. + * Increment the counter of data-files in this job, and + * then check for input or output filters (which are only + * applied to datafiles, not control files). + */ + job_dfcnt++; + + /* + * Note that here we are filtering datafiles, one at a time, + * as they are sent to the remote machine. Here, the *only* + * difference between an input filter (`if=') and an output + * filter (`of=') is the argument list that the filter is + * started up with. Here, the output filter is executed + * for each individual file as it is sent. This is not the + * same as local print queues, where the output filter is + * started up once, and then all jobs are passed thru that + * single invocation of the output filter. + * + * Also note that a queue for a remote-machine can have an + * input filter or an output filter, but not both. + */ if (pp->filters[LPF_INPUT]) { - /* - * We're sending something with an ifilter. We have to - * run the ifilter and store the output as a temporary - * spool file (tfile...), because the protocol requires - * us to send the file size before we start sending any - * of the data. - */ - char *av[15]; - int n; - int ifilter; - union wait status; /* XXX */ - - strcpy(tfile,TFILENAME); - if ((tfd = mkstemp(tfile)) == -1) { - syslog(LOG_ERR, "mkstemp: %m"); - return(ERROR); - } - if ((av[0] = strrchr(pp->filters[LPF_INPUT], '/')) == NULL) - av[0] = pp->filters[LPF_INPUT]; - else - av[0]++; + filtcmd = pp->filters[LPF_INPUT]; + av[0] = filtcmd; + narg = 0; + strcpy(opt_c, "-c"); + strcpy(opt_h, "-h"); + strcpy(opt_n, "-n"); if (format == 'l') - av[n=1] = "-c"; - else - n = 0; - av[++n] = width; - av[++n] = length; - av[++n] = indent; - av[++n] = "-n"; - av[++n] = logname; - av[++n] = "-h"; - av[++n] = origin_host; - av[++n] = pp->acct_file; - av[++n] = 0; - if ((ifilter = dofork(pp, DORETURN)) == 0) { /* child */ - dup2(f, 0); - dup2(tfd, 1); - /* setup stderr for the filter (child process) - * so it goes to our temporary errors file */ - n = open(tempstderr, O_WRONLY|O_TRUNC, 0664); - if (n >= 0) - dup2(n, 2); - closelog(); - closeallfds(3); - execv(pp->filters[LPF_INPUT], av); - syslog(LOG_ERR, "cannot execv %s", - pp->filters[LPF_INPUT]); - exit(2); - } - (void) close(f); - if (ifilter < 0) - status.w_retcode = 100; - else { - while ((pid = wait((int *)&status)) > 0 && - pid != ifilter) - ; - if (pid < 0) { - status.w_retcode = 100; - syslog(LOG_WARNING, "%s: after execv(%s), wait() returned: %m", - pp->printer, pp->filters[LPF_INPUT]); - } - } - /* Copy the filter's output to "lf" logfile */ - if ((fp = fopen(tempstderr, "r"))) { - while (fgets(buf, sizeof(buf), fp)) - fputs(buf, stderr); - fclose(fp); - } - /* process the return-code from the filter */ - switch (status.w_retcode) { - case 0: - break; - case 1: - unlink(tfile); - return(REPRINT); - case 2: - unlink(tfile); - return(ERROR); - default: - syslog(LOG_WARNING, "%s: filter '%c' exited" - " (retcode=%d)", - pp->printer, format, status.w_retcode); - unlink(tfile); - return(FILTERERR); - } - statrc = fstat(tfd, &stb); /* to find size of tfile */ - if (statrc < 0) { - syslog(LOG_ERR, "%s: error processing 'if', fstat(%s): %m", - pp->printer, tfile); - return(ERROR); - } - f = tfd; - lseek(f,0,SEEK_SET); - } else if (ofilter) { - /* - * We're sending something with an ofilter, we have to - * store the output as a temporary file (tfile)... the - * protocol requires us to send the file size - */ - int i; - for (i = 0; i < stb.st_size; i += BUFSIZ) { - amt = BUFSIZ; - if (i + amt > stb.st_size) - amt = stb.st_size - i; - if (sizerr == 0 && read(f, buf, amt) != amt) { - sizerr = 1; - break; - } - if (write(ofd, buf, amt) != amt) { - (void) close(f); - return(REPRINT); - } - } - close(ofd); - close(f); - while ((i = wait(NULL)) > 0 && i != ofilter) - ; - if (i < 0) - syslog(LOG_WARNING, "%s: after closing 'of', wait() returned: %m", - pp->printer); - ofilter = 0; - statrc = fstat(tfd, &stb); /* to find size of tfile */ - if (statrc < 0) { - syslog(LOG_ERR, "%s: error processing 'of', fstat(%s): %m", - pp->printer, tfile); - openpr(pp); - return(ERROR); - } - f = tfd; - lseek(f,0,SEEK_SET); - closedpr = 1; + av[++narg] = opt_c; + av[++narg] = width; + av[++narg] = length; + av[++narg] = indent; + av[++narg] = opt_n; + av[++narg] = logname; + av[++narg] = opt_h; + av[++narg] = origin_host; + av[++narg] = pp->acct_file; + av[++narg] = NULL; + } else if (pp->filters[LPF_OUTPUT]) { + filtcmd = pp->filters[LPF_OUTPUT]; + av[0] = filtcmd; + narg = 0; + av[++narg] = width; + av[++narg] = length; + av[++narg] = NULL; } } + if (filtcmd) { + /* + * If there is an input or output filter, we have to run + * the datafile thru that filter and store the result as + * a temporary spool file, because the protocol requires + * that we send the remote host the file-size before we + * start to send any of the data. + */ + strcpy(tfile, TFILENAME); + tfd = mkstemp(tfile); + if (tfd == -1) { + syslog(LOG_ERR, "%s: mkstemp(%s): %m", pp->printer, + TFILENAME); + return (ERROR); + } + filtstat = execfilter(pp, filtcmd, av, f, tfd); + + /* process the return-code from the filter */ + switch (filtstat) { + case 0: + break; + case 1: + unlink(tfile); + return (REPRINT); + case 2: + unlink(tfile); + return (ERROR); + default: + syslog(LOG_WARNING, + "%s: filter '%c' exited (retcode=%d)", + pp->printer, format, filtstat); + unlink(tfile); + return (FILTERERR); + } + statrc = fstat(tfd, &stb); /* to find size of tfile */ + if (statrc < 0) { + syslog(LOG_ERR, + "%s: error processing 'if', fstat(%s): %m", + pp->printer, tfile); + return (ERROR); + } + f = tfd; + lseek(f,0,SEEK_SET); + } (void) sprintf(buf, "%c%qd %s\n", type, stb.st_size, file); amt = strlen(buf); @@ -1146,8 +1106,6 @@ if (tfd != -1 && type == '\3') { tfd = -1; unlink(tfile); - if (closedpr) - openpr(pp); } return(REPRINT); } else if (resp == '\0') @@ -1175,8 +1133,6 @@ if (tfd != -1 && type == '\3') { tfd = -1; unlink(tfile); - if (closedpr) - openpr(pp); } return(REPRINT); } @@ -1191,23 +1147,92 @@ syslog(LOG_INFO, "%s: %s: changed size", pp->printer, file); /* tell recvjob to ignore this file */ (void) write(pfd, "\1", 1); - if (closedpr) - openpr(pp); return(ERROR); } if (write(pfd, "", 1) != 1 || response(pp)) { - if (closedpr) - openpr(pp); return(REPRINT); } - if (closedpr) - openpr(pp); if (type == '\3') trstat_write(pp, TR_SENDING, stb.st_size, logname, pp->remote_host, origin_host); return(OK); } +static int +execfilter(struct printer *pp, char *f_cmd, char *f_av[], int infd, int outfd) +{ + int errfd, fpid, wpid; + FILE *errfp; + union wait status; /* XXX */ + char buf[BUFSIZ], *slash; + + fpid = dofork(pp, DORETURN); + if (fpid == 0) { + /* + * This is the child process, which is the one that + * executes the given filter. + */ + /* + * If the first parameter has any slashes in it, then + * change it to point to the first character after + * the last slash. + */ + slash = strrchr(f_av[0], '/'); + if (slash != NULL) + f_av[0] = slash + 1; + /* + * XXX - in the future, this should setup an explicit + * list of environ variables and use execve! + */ + + /* + * Setup stdin, stdout, and stderr as we want them when + * the filter is running. Point stderr at a temporary + * errors file, which will then be copied to the real + * logfile when the filter completes. + */ + dup2(infd, 0); + dup2(outfd, 1); + errfd = open(tempstderr, O_WRONLY|O_TRUNC, 0664); + if (errfd >= 0) + dup2(errfd, 2); + closelog(); + closeallfds(3); + execv(f_cmd, f_av); + syslog(LOG_ERR, "%s: cannot execv %s", pp->printer, f_cmd); + exit(2); + /* NOTREACHED */ + } + + /* This is the parent process, which waits for the child to complete */ + (void) close(infd); + if (fpid < 0) + status.w_retcode = 100; + else { + while ((wpid = wait((int *)&status)) > 0 && wpid != fpid) + ; + if (wpid < 0) { + status.w_retcode = 100; + syslog(LOG_WARNING, + "%s: after execv(%s), wait() returned: %m", + pp->printer, f_cmd); + } + } + + /* + * Copy everything the filter wrote to stderr from our temporary + * errors file to the "lf=" logfile. + */ + errfp = fopen(tempstderr, "r"); + if (errfp) { + while (fgets(buf, sizeof(buf), errfp)) + fputs(buf, stderr); + fclose(errfp); + } + + return (status.w_retcode); +} + /* * Check to make sure there have been no errors and that both programs * are in sync with eachother. @@ -1559,6 +1584,17 @@ if (pp->remote) { openrem(pp); + /* + * Lpd does support the setting of 'of=' filters for + * jobs going to remote machines, but that does not + * have the same meaning as 'of=' does when handling + * local print queues. For remote machines, all 'of=' + * filter processing is handled in sendfile(), and that + * does not use these global "output filter" variables. + */ + ofd = -1; + ofilter = 0; + return; } else if (*pp->lp) { if ((cp = strchr(pp->lp, '@')) != NULL) opennet(pp); -- Garance Alistair Drosehn = gad@eclipse.acs.rpi.edu Senior Systems Programmer or gad@freebsd.org Rensselaer Polytechnic Institute or drosih@rpi.edu To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-audit" in the body of the message From owner-freebsd-audit Tue Apr 2 1:11:48 2002 Delivered-To: freebsd-audit@freebsd.org Received: from relay1.macomnet.ru (relay1.macomnet.ru [195.128.64.10]) by hub.freebsd.org (Postfix) with ESMTP id 25BDF37B41A for ; Tue, 2 Apr 2002 01:11:33 -0800 (PST) Received: from news1.macomnet.ru (maxim@news1.macomnet.ru [195.128.64.14]) by relay1.macomnet.ru (8.11.6/8.11.6) with ESMTP id g329BVT9778948 for ; Tue, 2 Apr 2002 13:11:31 +0400 (MSD) Date: Tue, 2 Apr 2002 13:11:31 +0400 (MSD) From: Maxim Konovalov To: freebsd-audit@freebsd.org Subject: a couple of ping(8) patches for review Message-ID: <20020402114845.U76561-100000@news1.macomnet.ru> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: owner-freebsd-audit@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG Hello -audit, I am going to commit two patches below. Bruce Evans has already reviewed them and now I would like to ask -audit. The first patch is based on Kris's code. #1 o correct a maximum payload size, o replace serveral magic numbers by constants, o allow zero payload, o increase an input buffer size. Index: ping.c =================================================================== RCS file: /home/ncvs/src/sbin/ping/ping.c,v retrieving revision 1.64 diff -u -r1.64 ping.c --- ping.c 23 Mar 2002 18:10:59 -0000 1.64 +++ ping.c 2 Apr 2002 08:23:42 -0000 @@ -100,12 +100,12 @@ #define DEFDATALEN (64 - PHDR_LEN) /* default data length */ #define FLOOD_BACKOFF 20000 /* usecs to back off if F_FLOOD mode */ /* runs out of buffer space */ -#define MAXIPLEN 60 -#define MAXICMPLEN 76 -#define MAXPACKET (65536 - 60 - 8)/* max packet size */ +#define MAXIPLEN (sizeof(struct ip) + MAX_IPOPTLEN) +#define MAXICMPLEN (ICMP_ADVLENMIN + MAX_IPOPTLEN) +#define MINICMPLEN ICMP_MINLEN +#define MAXPAYLOAD (IP_MAXPACKET - MAXIPLEN - MINICMPLEN) #define MAXWAIT 10 /* max seconds to wait for response */ #define MAXALARM (60 * 60) /* max seconds for alarm timeout */ -#define NROUTES 9 /* number of record route slots */ #define A(bit) rcvd_tbl[(bit)>>3] /* identify byte in array */ #define B(bit) (1 << ((bit) & 0x07)) /* identify bit in byte */ @@ -149,7 +149,7 @@ struct sockaddr_in whereto; /* who to ping */ int datalen = DEFDATALEN; int s; /* socket file descriptor */ -u_char outpack[MAXPACKET]; +u_char outpack[MINICMPLEN + MAXPAYLOAD]; char BSPACE = '\b'; /* characters written for flood */ char BBELL = '\a'; /* characters written for MISSED and AUDIBLE */ char DOT = '.'; @@ -206,7 +206,7 @@ struct timeval last, intvl; struct hostent *hp; struct sockaddr_in *to; - u_char *datap, *packet; + u_char *datap, packet[IP_MAXPACKET]; char *ep, *source, *target; #ifdef IPSEC_POLICY_IPSEC char *policy_in, *policy_out; @@ -216,7 +216,7 @@ char ctrl[CMSG_SPACE(sizeof(struct timeval))]; char hnamebuf[MAXHOSTNAMELEN], snamebuf[MAXHOSTNAMELEN]; #ifdef IP_OPTIONS - char rspace[3 + 4 * NROUTES + 1]; /* record route space */ + char rspace[MAX_IPOPTLEN]; /* record route space */ #endif unsigned char mttl, loop; @@ -238,7 +238,7 @@ alarmtimeout = preload = 0; - datap = &outpack[8 + PHDR_LEN]; + datap = &outpack[MINICMPLEN + PHDR_LEN]; while ((ch = getopt(argc, argv, "AI:LQRS:T:c:adfi:l:m:np:qrs:t:v" #ifdef IPSEC @@ -348,10 +348,11 @@ err(EX_NOPERM, "-s flag"); } ultmp = strtoul(optarg, &ep, 0); - if (ultmp > MAXPACKET) - errx(EX_USAGE, "packet size too large: %lu", - ultmp); - if (*ep || ep == optarg || !ultmp) + if (ultmp > MAXPAYLOAD) + errx(EX_USAGE, + "packet size too large: %lu > %u", + ultmp, MAXPAYLOAD); + if (*ep || ep == optarg) errx(EX_USAGE, "invalid packet size: `%s'", optarg); datalen = ultmp; @@ -414,7 +415,8 @@ source, hstrerror(h_errno)); sin.sin_len = sizeof sin; - if (hp->h_length > sizeof(sin.sin_addr)) + if (hp->h_length > sizeof(sin.sin_addr) || + hp->h_length < 0) errx(1,"gethostbyname2: illegal address"); memcpy(&sin.sin_addr, hp->h_addr_list[0], sizeof (sin.sin_addr)); @@ -460,9 +462,8 @@ if (datalen >= PHDR_LEN) /* can we time transfer */ timing = 1; - packlen = datalen + MAXIPLEN + MAXICMPLEN; - if (!(packet = (u_char *)malloc((size_t)packlen))) - err(EX_UNAVAILABLE, "malloc"); + packlen = MAXIPLEN + MAXICMPLEN + datalen; + packlen = packlen > IP_MAXPACKET ? IP_MAXPACKET : packlen; if (!(options & F_PINGFILLED)) for (i = PHDR_LEN; i < datalen; ++i) @@ -563,7 +564,12 @@ * /etc/ethers. But beware: RFC 1122 allows hosts to ignore broadcast * or multicast pings if they wish. */ - hold = 48 * 1024; + + /* + * XXX receive buffer needs undetermined space for mbuf overhead + * as well. + */ + hold = IP_MAXPACKET + 128; (void)setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&hold, sizeof(hold)); @@ -742,9 +748,9 @@ * pinger -- * Compose and transmit an ICMP ECHO REQUEST packet. The IP packet * will be added on by the kernel. The ID field is our UNIX process ID, - * and the sequence number is an ascending integer. The first 8 bytes - * of the data portion are used to hold a UNIX "timeval" struct in host - * byte-order, to compute the round-trip time. + * and the sequence number is an ascending integer. The first PHDR_LEN + * bytes of the data portion are used to hold a UNIX "timeval" struct in + * host byte-order, to compute the round-trip time. */ static void pinger(void) @@ -762,10 +768,10 @@ CLR(ntransmitted % mx_dup_ck); if (timing) - (void)gettimeofday((struct timeval *)&outpack[8], + (void)gettimeofday((struct timeval *)&outpack[MINICMPLEN], (struct timezone *)NULL); - cc = datalen + PHDR_LEN; /* skips ICMP portion */ + cc = MINICMPLEN + datalen; /* compute ICMP checksum here */ icp->icmp_cksum = in_cksum((u_short *)icp, cc); @@ -881,7 +887,7 @@ (void)write(STDOUT_FILENO, &BBELL, 1); /* check the data */ cp = (u_char*)&icp->icmp_data[PHDR_LEN]; - dp = &outpack[8 + PHDR_LEN]; + dp = &outpack[MINICMPLEN + PHDR_LEN]; for (i = PHDR_LEN; i < datalen; ++i, ++cp, ++dp) { if (*cp != *dp) { (void)printf("\nwrong data byte #%d should be 0x%x but was 0x%x", @@ -894,7 +900,7 @@ (void)printf("%x ", *cp); } printf("\ndp:"); - cp = &outpack[8]; + cp = &outpack[MINICMPLEN]; for (i = 0; i < datalen; ++i, ++cp) { if ((i % 32) == 8) (void)printf("\n\t"); @@ -1416,7 +1422,7 @@ { char *cp; int pat[16]; - int ii, jj, kk; + u_int ii, jj, kk; for (cp = patp; *cp; cp++) { if (!isxdigit(*cp)) @@ -1431,9 +1437,7 @@ &pat[13], &pat[14], &pat[15]); if (ii > 0) - for (kk = 0; - kk <= MAXPACKET - (8 + PHDR_LEN + ii); - kk += ii) + for (kk = 0; kk <= MAXPAYLOAD - (PHDR_LEN + ii); kk += ii) for (jj = 0; jj < ii; ++jj) bp[jj + kk] = pat[jj]; if (!(options & F_QUIET)) { %%% #2 Rewrote IP options parsing: o more strict boundary checks, o replace magic numbers by constants. The diff is practically unreadable, sorry. Index: ping.c =================================================================== RCS file: /home/ncvs/src/sbin/ping/ping.c,v retrieving revision 1.64 diff -u -r1.64 ping.c --- ping.c 23 Mar 2002 18:10:59 -0000 1.64 +++ ping.c 2 Apr 2002 08:20:16 -0000 @@ -96,6 +96,7 @@ #include #endif /*IPSEC*/ +#define INADDR_LEN ((int)sizeof(in_addr_t)) #define PHDR_LEN sizeof(struct timeval) #define DEFDATALEN (64 - PHDR_LEN) /* default data length */ #define FLOOD_BACKOFF 20000 /* usecs to back off if F_FLOOD mode */ @@ -806,10 +807,10 @@ { struct icmp *icp; struct ip *ip; + struct in_addr ina; struct timeval *tp; u_char *cp, *dp; double triptime; - u_long l; int dupflag, hlen, i, j, seq; static int old_rrlen; static char old_rr[MAX_IPOPTLEN]; @@ -945,79 +946,68 @@ break; case IPOPT_LSRR: (void)printf("\nLSRR: "); + j = cp[IPOPT_OLEN] - IPOPT_MINOFF + 1; hlen -= 2; - j = *++cp; - ++cp; - if (j > IPOPT_MINOFF) + cp += 2; + if (j >= INADDR_LEN && j <= hlen - INADDR_LEN) { for (;;) { - l = *++cp; - l = (l<<8) + *++cp; - l = (l<<8) + *++cp; - l = (l<<8) + *++cp; - if (l == 0) { + bcopy(++cp, &ina.s_addr, INADDR_LEN); + if (ina.s_addr == 0) printf("\t0.0.0.0"); - } else { - struct in_addr ina; - ina.s_addr = ntohl(l); + else printf("\t%s", pr_addr(ina)); - } - hlen -= 4; - j -= 4; - if (j <= IPOPT_MINOFF) - break; - (void)putchar('\n'); - } + hlen -= INADDR_LEN; + cp += INADDR_LEN - 1; + j -= INADDR_LEN; + if (j < INADDR_LEN) + break; + (void)putchar('\n'); + } + } else + (void)printf("\t(truncated route)\n"); break; case IPOPT_RR: - j = *++cp; /* get length */ - i = *++cp; /* and pointer */ + j = cp[IPOPT_OLEN]; /* get length */ + i = cp[IPOPT_OFFSET]; /* and pointer */ hlen -= 2; + cp += 2; if (i > j) i = j; - i -= IPOPT_MINOFF; - if (i <= 0) + i = i - IPOPT_MINOFF + 1; + if (i < 0 || i > (hlen - (int)sizeof(struct ip))) { + old_rrlen = 0; continue; + } if (i == old_rrlen - && cp == (u_char *)buf + sizeof(struct ip) + 2 && !bcmp((char *)cp, old_rr, i) && !(options & F_FLOOD)) { (void)printf("\t(same route)"); - i = ((i + 3) / 4) * 4; hlen -= i; cp += i; break; } - if (i < MAX_IPOPTLEN) { - old_rrlen = i; - bcopy((char *)cp, old_rr, i); - } else - old_rrlen = 0; + old_rrlen = i; + bcopy((char *)cp, old_rr, i); (void)printf("\nRR: "); - j = 0; - for (;;) { - l = *++cp; - l = (l<<8) + *++cp; - l = (l<<8) + *++cp; - l = (l<<8) + *++cp; - if (l == 0) { - printf("\t0.0.0.0"); - } else { - struct in_addr ina; - ina.s_addr = ntohl(l); - printf("\t%s", pr_addr(ina)); - } - hlen -= 4; - i -= 4; - j += 4; - if (i <= 0) - break; - if (j >= MAX_IPOPTLEN) { - (void) printf("\t(truncated route)"); - break; + + if (i >= INADDR_LEN && + i <= hlen - (int)sizeof(struct ip)) { + for (;;) { + bcopy(++cp, &ina.s_addr, INADDR_LEN); + if (ina.s_addr == 0) + printf("\t0.0.0.0"); + else + printf("\t%s", pr_addr(ina)); + hlen -= INADDR_LEN; + cp += INADDR_LEN - 1; + i -= INADDR_LEN; + if (i < INADDR_LEN) + break; + (void)putchar('\n'); } - (void)putchar('\n'); - } + } else + (void)printf("\t(truncated route)"); break; case IPOPT_NOP: (void)printf("\nNOP"); %%% Thanks, Maxim. To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-audit" in the body of the message From owner-freebsd-audit Tue Apr 2 12:40:49 2002 Delivered-To: freebsd-audit@freebsd.org Received: from smtp-1.enteract.com (smtp-1.enteract.com [207.229.143.33]) by hub.freebsd.org (Postfix) with ESMTP id D590A37B41D for ; Tue, 2 Apr 2002 12:40:40 -0800 (PST) Received: from bjorn.goddamnbastard.org (bjorn.goddamnbastard.org [216.80.6.225]) by smtp-1.enteract.com (Postfix) with SMTP id 06DD363C9 for ; Tue, 2 Apr 2002 14:40:40 -0600 (CST) Received: (qmail 38152 invoked by uid 1000); 2 Apr 2002 20:40:39 -0000 Date: Tue, 2 Apr 2002 14:40:39 -0600 From: ryan beasley To: freebsd-audit@FreeBSD.Org Subject: [patch] mtree(8) inode number tracking support Message-ID: <20020402204039.GE34680@bjorn.goddamnbastard.org> Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="BZaMRJmqxGScZ8Mx" Content-Disposition: inline User-Agent: Mutt/1.3.25i Sender: owner-freebsd-audit@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG --BZaMRJmqxGScZ8Mx Content-Type: multipart/mixed; boundary="SO98HVl1bnMOfKZd" Content-Disposition: inline --SO98HVl1bnMOfKZd Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Hi! The following patch adds support for tracking inode number changes to mtree(8). It seems like a good idea for those using mtree as the poor-man's Tripwire. (Forgot who coined that phrase. :/) (Patch made against mid-February RELENG_4. Also attached is an excerpt of a mtree "session" to show output for differing inodes.) Thoughts? --=20 ryan beasley professional fat bastard http://www.goddamnbastard.org GPG ID 0x36321D13 --SO98HVl1bnMOfKZd Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="mtree.inode.patch" Content-Transfer-Encoding: quoted-printable Common subdirectories: src/usr.sbin/mtree.orig/CVS and src/usr.sbin/mtree/C= VS diff -u src/usr.sbin/mtree.orig/compare.c src/usr.sbin/mtree/compare.c --- src/usr.sbin/mtree.orig/compare.c Fri Jan 12 13:17:18 2001 +++ src/usr.sbin/mtree/compare.c Fri Mar 29 08:28:16 2002 @@ -178,6 +178,12 @@ tab, s->st_size, p->fts_statp->st_size); tab =3D "\t"; } + if (s->flags & F_INUM && s->st_ino !=3D p->fts_statp->st_ino) { + LABEL; + (void)printf("%sinode expected %u found %u\n", + tab, s->st_ino, p->fts_statp->st_ino); + tab =3D "\t"; + } /* * XXX * Catches nano-second differences, but doesn't display them. diff -u src/usr.sbin/mtree.orig/create.c src/usr.sbin/mtree/create.c --- src/usr.sbin/mtree.orig/create.c Fri Jan 12 13:17:18 2001 +++ src/usr.sbin/mtree/create.c Fri Mar 29 08:31:24 2002 @@ -218,6 +218,8 @@ (void)close(fd); output(indent, &offset, "cksum=3D%lu", val); } + if (keys & F_INUM) + output(indent, &offset, "inum=3D%u", p->fts_statp->st_ino); #ifdef MD5 if (keys & F_MD5 && S_ISREG(p->fts_statp->st_mode)) { char *digest, buf[33]; diff -u src/usr.sbin/mtree.orig/misc.c src/usr.sbin/mtree/misc.c --- src/usr.sbin/mtree.orig/misc.c Tue Jun 27 21:33:17 2000 +++ src/usr.sbin/mtree/misc.c Fri Mar 29 08:42:56 2002 @@ -65,6 +65,7 @@ {"gid", F_GID, NEEDVALUE}, {"gname", F_GNAME, NEEDVALUE}, {"ignore", F_IGN, 0}, + {"inum", F_INUM, NEEDVALUE}, {"link", F_SLINK, NEEDVALUE}, #ifdef MD5 {"md5digest", F_MD5, NEEDVALUE}, diff -u src/usr.sbin/mtree.orig/mtree.8 src/usr.sbin/mtree/mtree.8 --- src/usr.sbin/mtree.orig/mtree.8 Thu Aug 16 10:56:08 2001 +++ src/usr.sbin/mtree/mtree.8 Fri Mar 29 10:38:42 2002 @@ -226,6 +226,8 @@ .It Cm socket socket .El +.It Cm inum +The inode number of the file. .El .Pp The default set of keywords are diff -u src/usr.sbin/mtree.orig/mtree.h src/usr.sbin/mtree/mtree.h --- src/usr.sbin/mtree.orig/mtree.h Thu Dec 9 14:38:35 1999 +++ src/usr.sbin/mtree/mtree.h Mon Apr 1 16:07:21 2002 @@ -58,6 +58,7 @@ mode_t st_mode; /* mode */ u_long st_flags; /* flags */ nlink_t st_nlink; /* link count */ + ino_t st_ino; /* inode number */ =20 #define F_CKSUM 0x0001 /* check sum */ #define F_DONE 0x0002 /* directory done */ @@ -81,6 +82,7 @@ #define F_RMD160 0x40000 /* RIPEMD160 digest */ #define F_FLAGS 0x80000 /* file flags */ u_int flags; /* items set */ +#define F_INUM 0x100000 /* inode number */ =20 #define F_BLOCK 0x001 /* block special */ #define F_CHAR 0x002 /* char special */ diff -u src/usr.sbin/mtree.orig/spec.c src/usr.sbin/mtree/spec.c --- src/usr.sbin/mtree.orig/spec.c Tue Jun 27 21:33:17 2000 +++ src/usr.sbin/mtree/spec.c Fri Mar 29 08:34:27 2002 @@ -307,6 +307,12 @@ errx(1, "line %d: unknown user %s", lineno, val); ip->st_uid =3D pw->pw_uid; break; + case F_INUM: + ip->st_ino =3D strtoul(val, &ep, 10); + if (*ep) + errx(1, "line %d: invalid inode number %s", + lineno, val); + break; } } } --SO98HVl1bnMOfKZd Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="mtree.excerpt.txt" Content-Transfer-Encoding: quoted-printable [ryanb@m1 ~] $ date Fri Mar 29 16:54:37 CST 2002 [ryanb@m1 ~] $ mtree -c -x -p . -k flags,uid,gid,nlink,mode,sha1digest,size= ,link,time,type,inum > /tmp/myhome.mtree=20 [ryanb@m1 ~] $ ls -i mtree.inode.patch=20 8076 mtree.inode.patch [ryanb@m1 ~] $ cp -p mtree.inode.patch mtree.inode.patch.blargh [ryanb@m1 ~] $ ls -i mtree.inode.patch* 8076 mtree.inode.patch 8078 mtree.inode.patch.blargh [ryanb@m1 ~] $ rm mtree.inode.patch [ryanb@m1 ~] $ mv mtree.inode.patch.blargh mtree.inode.patch =20 [ryanb@m1 ~] $ ls -i mtree.inode.patch=20 8078 mtree.inode.patch [ryanb@m1 ~] $ mtree -x -p . -k flags,uid,gid,nlink,mode,sha1digest,size,li= nk,time,type,inum < /tmp/myhome.mtree =2E changed modification time expected Fri Mar 29 16:48:04 2002 found Fri Mar 2= 9 16:57:04 2002 mtree.inode.patch changed inode expected 8076 found 8078 --SO98HVl1bnMOfKZd-- --BZaMRJmqxGScZ8Mx Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.0.6 (FreeBSD) Comment: For info see http://www.gnupg.org iD8DBQE8qhdGCbo22TYyHRMRAs1KAJ0deEjnybwopjP4jfd/3+oAnBKG4wCaAjWM XD0g6GNHm0cobiygZJjdPJk= =3l7n -----END PGP SIGNATURE----- --BZaMRJmqxGScZ8Mx-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-audit" in the body of the message