Re: crontab: support random offsets for steps

2023-05-05 Thread Todd C . Miller
There appears to be a strong preference for a syntax like "~/10"
instead of "*/~10".  The following diff implements that instead and
also supports random ranges like "1~58/10".  When a high and/or low
value is used with a random range, the initial offset is a random
value less than eiter the step value or the difference of the high
and low values (whichever is smaller).

 - todd

Index: usr.sbin/cron/crontab.5
===
RCS file: /cvs/src/usr.sbin/cron/crontab.5,v
retrieving revision 1.41
diff -u -p -u -r1.41 crontab.5
--- usr.sbin/cron/crontab.5 18 Apr 2020 17:11:40 -  1.41
+++ usr.sbin/cron/crontab.5 6 May 2023 02:19:40 -
@@ -157,8 +157,7 @@ If either (or both) of the numbers on ei
 .Ql ~
 are omitted, the appropriate limit (low or high) for the field will be used.
 .Pp
-Step values can be used in conjunction with ranges (but not random ranges
-which represent a single number).
+Step values can be used in conjunction with ranges.
 Following a range with
 .No / Ns Ar number
 specifies skips of
@@ -173,6 +172,18 @@ Steps are also permitted after an asteri
 .Dq every two hours ,
 just use
 .Dq */2 .
+A step value after a random range will execute the command at a random
+offset less than the step size.
+For example, to avoid a thundering herd at the top and bottom of the hour,
+.Dq 0~59/30
+.Po
+or simply
+.Dq ~/30
+.Pc
+can be used in the
+.Ar minute
+field to specify that command execution happen twice an hour at
+consistent intervals.
 .Pp
 An asterisk
 .Pq Ql *
Index: usr.sbin/cron/entry.c
===
RCS file: /cvs/src/usr.sbin/cron/entry.c,v
retrieving revision 1.53
diff -u -p -u -r1.53 entry.c
--- usr.sbin/cron/entry.c   21 May 2022 01:21:29 -  1.53
+++ usr.sbin/cron/entry.c   5 May 2023 21:39:30 -
@@ -456,10 +456,11 @@ get_range(bitstr_t *bits, int low, int h
/* range = number | number* "~" number* | number "-" number ["/" number]
 */
 
-   int i, num1, num2, num3;
+   int i, num1, num2, num3, rndstep;
 
num1 = low;
num2 = high;
+   rndstep = 0;
 
if (ch == '*') {
/* '*' means [low, high] but can still be modified by /step
@@ -497,7 +498,7 @@ get_range(bitstr_t *bits, int low, int h
 
/* get the (optional) number following the tilde
 */
-   ch = get_number(&num2, low, names, ch, file, ", \t\n");
+   ch = get_number(&num2, low, names, ch, file, "/, \t\n");
if (ch == EOF)
ch = get_char(file);
if (ch == EOF || num1 > num2) {
@@ -505,6 +506,13 @@ get_range(bitstr_t *bits, int low, int h
return (EOF);
}
 
+   if (ch == '/') {
+   /* randomize the step value instead of num1
+*/
+   rndstep = 1;
+   break;
+   }
+
/* get a random number in the interval [num1, num2]
 */
num3 = num1;
@@ -538,6 +546,13 @@ get_range(bitstr_t *bits, int low, int h
ch = get_number(&num3, 0, NULL, ch, file, ", \t\n");
if (ch == EOF || num3 == 0)
return (EOF);
+   if (rndstep) {
+   /*
+* use a random offset smaller than the step size
+* and the difference between high and low values.
+*/
+   num1 += arc4random_uniform(MINIMUM(num3, num2 - num1));
+   }
} else {
/* no step.  default==1.
 */
Index: usr.sbin/cron/macros.h
===
RCS file: /cvs/src/usr.sbin/cron/macros.h,v
retrieving revision 1.15
diff -u -p -u -r1.15 macros.h
--- usr.sbin/cron/macros.h  12 Nov 2015 21:12:05 -  1.15
+++ usr.sbin/cron/macros.h  5 May 2023 21:38:19 -
@@ -29,6 +29,8 @@
 #defineMAX_TEMPSTR 100 /* obvious */
 #defineMAX_UNAME   (_PW_NAME_LEN+1)/* max length of 
username, should be overkill */
 
+#defineMINIMUM(a, b)   (((a) < (b)) ? (a) : (b))
+
 #defineSkip_Blanks(c, f) \
while (c == '\t' || c == ' ') \
c = get_char(f);



Re: cron: better error checking of random values

2023-05-05 Thread Mark Jamsek
On 23-05-05 10:41AM, Todd C. Miller wrote:
> On Fri, 05 May 2023 16:13:01 +1000, Mark Jamsek wrote:
> 
> > I found kn's attempted syntax intuitive though; it feels like a natural
> > extension of the existing random and step syntax. I also assumed ~/15
> > would run every 15 minutes starting with a random minute, and since
> > discovering it didn't work like that, I've been carrying a simple patch
> > that allows kn's syntax:
> >
> >   ~/15  random 15 minute intervals in [0, 59]
> >   1~9/10random 10 minute intervals in [1,59]
> 
> It does seem like people prefer the ~/step syntax over my own, which
> is fine.
> 
> However, I'm unsure about the x~y/step syntax.  Personally, I think
> it would be more natural to treat x~y/step like x-y/step and just
> use a random offset in the interval [0,step-1].  Do you have a
> use-case for the way your diff handles this or did it just follow
> naturally from the random value being in num1?
> 
> Also, using the % operator with the random value results in modulo
> bias, which we would like to avoid.  If we use a random offset based
> on the step interval instead there is no need for the modulus.

Both tbh. I primarily wanted to get intervals that would not fall on
common times where I already had jobs running; namely, 0th minutes
(e.g., 0, 30). And I described the second example wrong, so this was
most likely lost in my first response:

> >   1~9/10random 10 minute intervals in [1,59]

The "intervals in [1,59]" is not correct in this example. Rather, this
will result in an initial random value 1 <= n <= 9, so each interval in
this step /10 case will also fall in [N1,N9] (e.g., 7, 17, 27, ...) and
avoid said common times. And the modulo is used to get the first point
in [low,high] from which to start the step loop that fit this
constraint. In other words, I wanted some control over where the random
intervals landed such that being able to avoid ranges was as much
a requirement, in my use case, as random steps.

But I also didn't want to change the code too much so it just followed
naturally. This could be done other ways, too, and I'm not presuming
such a requirement is as important to anyone else.

-- 
Mark Jamsek 
GPG: F2FF 13DE 6A06 C471 CA80  E6E2 2930 DC66 86EE CF68


fragment code cleanup for tso

2023-05-05 Thread Alexander Bluhm
Hi,

I preparation for my TSO in software diff, I would like to cleanup
the fragment code.  Both are very simmilar and I like consistency.

- Use if_output_ml() to send mbuf lists to interfaces.  This can
  be used for TSO, fragments, ARP and ND6.
- Rename variable fml to ml.  It will soon be used for TCP segments,
  no need to have the f for fragment in the name.
- In pf_route6() split the if else block, then tcp_chopper() can
  be easily put in there in the next diff.
- In ip_fragment() the if (hlen + firstlen < tlen) is a new safety
  check.  It makes the code correct for the case where the packet
  was to short to be fragmented.  This should not happen, but the
  other functions also have this logic.

No functional change intended.

ok?

bluhm

Index: net/if.c
===
RCS file: /data/mirror/openbsd/cvs/src/sys/net/if.c,v
retrieving revision 1.694
diff -u -p -r1.694 if.c
--- net/if.c26 Apr 2023 19:54:35 -  1.694
+++ net/if.c5 May 2023 20:27:06 -
@@ -762,27 +762,6 @@ if_enqueue_ifq(struct ifnet *ifp, struct
 }
 
 void
-if_mqoutput(struct ifnet *ifp, struct mbuf_queue *mq, unsigned int *total,
-struct sockaddr *dst, struct rtentry *rt)
-{
-   struct mbuf_list ml;
-   struct mbuf *m;
-   unsigned int len;
-
-   mq_delist(mq, &ml);
-   len = ml_len(&ml);
-   while ((m = ml_dequeue(&ml)) != NULL)
-   ifp->if_output(ifp, m, rt_key(rt), rt);
-
-   /* XXXSMP we also discard if other CPU enqueues */
-   if (mq_len(mq) > 0) {
-   /* mbuf is back in queue. Discard. */
-   atomic_sub_int(total, len + mq_purge(mq));
-   } else
-   atomic_sub_int(total, len);
-}
-
-void
 if_input(struct ifnet *ifp, struct mbuf_list *ml)
 {
ifiq_input(&ifp->if_rcv, ml);
@@ -841,6 +820,46 @@ if_input_local(struct ifnet *ifp, struct
}
 
return (0);
+}
+
+int
+if_output_ml(struct ifnet *ifp, struct mbuf_list *ml,
+struct sockaddr *dst, struct rtentry *rt)
+{
+   struct mbuf *m;
+   int error = 0;
+
+   while ((m = ml_dequeue(ml)) != NULL) {
+   error = ifp->if_output(ifp, m, dst, rt);
+   if (error)
+   break;
+   }
+   if (error)
+   ml_purge(ml);
+
+   return error;
+}
+
+int
+if_output_mq(struct ifnet *ifp, struct mbuf_queue *mq, unsigned int *total,
+struct sockaddr *dst, struct rtentry *rt)
+{
+   struct mbuf_list ml;
+   unsigned int len;
+   int error;
+
+   mq_delist(mq, &ml);
+   len = ml_len(&ml);
+   error = if_output_ml(ifp, &ml, dst, rt);
+
+   /* XXXSMP we also discard if other CPU enqueues */
+   if (mq_len(mq) > 0) {
+   /* mbuf is back in queue. Discard. */
+   atomic_sub_int(total, len + mq_purge(mq));
+   } else
+   atomic_sub_int(total, len);
+
+   return error;
 }
 
 int
Index: net/if_bridge.c
===
RCS file: /data/mirror/openbsd/cvs/src/sys/net/if_bridge.c,v
retrieving revision 1.365
diff -u -p -r1.365 if_bridge.c
--- net/if_bridge.c 27 Feb 2023 09:35:32 -  1.365
+++ net/if_bridge.c 5 May 2023 20:38:22 -
@@ -1826,7 +1826,7 @@ bridge_fragment(struct ifnet *brifp, str
 struct mbuf *m)
 {
struct llc llc;
-   struct mbuf_list fml;
+   struct mbuf_list ml;
int error = 0;
int hassnap = 0;
u_int16_t etype;
@@ -1884,11 +1884,11 @@ bridge_fragment(struct ifnet *brifp, str
return;
}
 
-   error = ip_fragment(m, &fml, ifp, ifp->if_mtu);
+   error = ip_fragment(m, &ml, ifp, ifp->if_mtu);
if (error)
return;
 
-   while ((m = ml_dequeue(&fml)) != NULL) {
+   while ((m = ml_dequeue(&ml)) != NULL) {
if (hassnap) {
M_PREPEND(m, LLC_SNAPFRAMELEN, M_DONTWAIT);
if (m == NULL) {
@@ -1908,7 +1908,7 @@ bridge_fragment(struct ifnet *brifp, str
break;
}
if (error)
-   ml_purge(&fml);
+   ml_purge(&ml);
else
ipstat_inc(ips_fragmented);
 
Index: net/if_var.h
===
RCS file: /data/mirror/openbsd/cvs/src/sys/net/if_var.h,v
retrieving revision 1.125
diff -u -p -r1.125 if_var.h
--- net/if_var.h18 Apr 2023 22:01:24 -  1.125
+++ net/if_var.h5 May 2023 21:07:16 -
@@ -321,12 +321,14 @@ extern struct ifnet_head ifnetlist;
 void   if_start(struct ifnet *);
 intif_enqueue(struct ifnet *, struct mbuf *);
 intif_enqueue_ifq(struct ifnet *, struct mbuf *);
-void   if_mqoutput(struct ifnet *, struct mbuf_queue *, unsigned int *,
-   struct sockaddr *, struct rtentry *);
 void   if_input(struct ifnet *, struct mbuf_list *);
 void   if_vinput(struct ifnet *, struct mbuf 

Re: passwd: fix error paths and undefined behaviour

2023-05-05 Thread Tobias Stoeckmann
On Fri, May 05, 2023 at 11:00:12AM -0600, Todd C. Miller wrote:
> This looks OK but I'd like to see an error message if waitpid()
> really does fail.  How about something like this, which also avoid
> needing the extra variable?

Yes, looks much better!


Index: local_passwd.c
===
RCS file: /cvs/src/usr.bin/passwd/local_passwd.c,v
retrieving revision 1.63
diff -u -p -u -p -r1.63 local_passwd.c
--- local_passwd.c  10 Feb 2022 13:06:46 -  1.63
+++ local_passwd.c  5 May 2023 17:03:43 -
@@ -217,7 +217,7 @@ getnewpasswd(struct passwd *pw, login_ca
continue;
}
 
-   if ((tries++ < pwd_tries || pwd_tries == 0) &&
+   if ((pwd_tries == 0 || tries++ < pwd_tries) &&
pwd_check(lc, p) == 0)
continue;
p = readpassphrase("Retype new password:", repeat, 
sizeof(repeat),
Index: pwd_check.c
===
RCS file: /cvs/src/usr.bin/passwd/pwd_check.c,v
retrieving revision 1.17
diff -u -p -u -p -r1.17 pwd_check.c
--- pwd_check.c 28 Aug 2021 06:46:49 -  1.17
+++ pwd_check.c 5 May 2023 17:03:43 -
@@ -114,6 +114,8 @@ pwd_check(login_cap_t *lc, char *passwor
switch (child = fork()) {
case -1:
warn("fork");
+   close(pipefds[0]);
+   close(pipefds[1]);
goto out;
case 0:
(void)signal(SIGINT, SIG_DFL);
@@ -184,8 +186,10 @@ pwd_check(login_cap_t *lc, char *passwor
 
/* get the return value from the child */
while (waitpid(child, &res, 0) == -1) {
-   if (errno != EINTR)
-   break;
+   if (errno != EINTR) {
+   warn("waitpid");
+   goto out;
+   }
}
if (WIFEXITED(res) && WEXITSTATUS(res) == 0) {
free(checker);



Re: passwd: fix error paths and undefined behaviour

2023-05-05 Thread Todd C . Miller
On Fri, 05 May 2023 17:05:05 -, Tobias Stoeckmann wrote:

> On Fri, May 05, 2023 at 11:00:12AM -0600, Todd C. Miller wrote:
> > This looks OK but I'd like to see an error message if waitpid()
> > really does fail.  How about something like this, which also avoid
> > needing the extra variable?
>
> Yes, looks much better!

OK millert@

 - todd



Re: passwd: fix error paths and undefined behaviour

2023-05-05 Thread Todd C . Miller
On Fri, 05 May 2023 16:46:51 -, Tobias Stoeckmann wrote:

> In getnewpasswd we increment "tries" every time we try to enter a new
> password. The code allows this to be repeated endlessly by defining
> passwordtries to be 0 in /etc/login.conf. But unfortunately we even
> increment the int "tries" if pwd_tries is 0, which eventually would lead
> to a signed integer overflow (and we would stop asking for passwords
> after billion times).
>
> In pwd_check we should close pipe file descriptors if fork fails. Also
> it might be possible that waitpid fails if the root user tries to
> sabotage the own passwd call. Let's just handle the error case here
> as well to avoid accessing undefined content of "res".

This looks OK but I'd like to see an error message if waitpid()
really does fail.  How about something like this, which also avoid
needing the extra variable?

 - todd

Index: /usr/src/usr.bin/passwd/pwd_check.c
===
RCS file: /cvs/src/usr.bin/passwd/pwd_check.c,v
retrieving revision 1.17
diff -u -p -u -r1.17 pwd_check.c
--- /usr/src/usr.bin/passwd/pwd_check.c 28 Aug 2021 06:46:49 -  1.17
+++ /usr/src/usr.bin/passwd/pwd_check.c 5 May 2023 16:59:20 -
@@ -184,8 +184,10 @@ pwd_check(login_cap_t *lc, char *passwor
 
/* get the return value from the child */
while (waitpid(child, &res, 0) == -1) {
-   if (errno != EINTR)
-   break;
+   if (errno != EINTR) {
+   warn("waitpid");
+   goto out;
+   }
}
if (WIFEXITED(res) && WEXITSTATUS(res) == 0) {
free(checker);



passwd: fix error paths and undefined behaviour

2023-05-05 Thread Tobias Stoeckmann
Hi,

this patch fixes error paths and an undefined behaviour:

In getnewpasswd we increment "tries" every time we try to enter a new
password. The code allows this to be repeated endlessly by defining
passwordtries to be 0 in /etc/login.conf. But unfortunately we even
increment the int "tries" if pwd_tries is 0, which eventually would lead
to a signed integer overflow (and we would stop asking for passwords
after billion times).

In pwd_check we should close pipe file descriptors if fork fails. Also
it might be possible that waitpid fails if the root user tries to
sabotage the own passwd call. Let's just handle the error case here
as well to avoid accessing undefined content of "res".

Okay?


Tobias

Index: local_passwd.c
===
RCS file: /cvs/src/usr.bin/passwd/local_passwd.c,v
retrieving revision 1.63
diff -u -p -u -p -r1.63 local_passwd.c
--- local_passwd.c  10 Feb 2022 13:06:46 -  1.63
+++ local_passwd.c  5 May 2023 16:35:58 -
@@ -217,7 +217,7 @@ getnewpasswd(struct passwd *pw, login_ca
continue;
}
 
-   if ((tries++ < pwd_tries || pwd_tries == 0) &&
+   if ((pwd_tries == 0 || tries++ < pwd_tries) &&
pwd_check(lc, p) == 0)
continue;
p = readpassphrase("Retype new password:", repeat, 
sizeof(repeat),
Index: pwd_check.c
===
RCS file: /cvs/src/usr.bin/passwd/pwd_check.c,v
retrieving revision 1.17
diff -u -p -u -p -r1.17 pwd_check.c
--- pwd_check.c 28 Aug 2021 06:46:49 -  1.17
+++ pwd_check.c 5 May 2023 16:35:58 -
@@ -91,7 +91,7 @@ pwd_check(login_cap_t *lc, char *passwor
char *checker;
char *argp[] = { "sh", "-c", NULL, NULL};
int pipefds[2];
-   pid_t child;
+   pid_t child, c;
uid_t uid;
gid_t gid;
 
@@ -114,6 +114,8 @@ pwd_check(login_cap_t *lc, char *passwor
switch (child = fork()) {
case -1:
warn("fork");
+   close(pipefds[0]);
+   close(pipefds[1]);
goto out;
case 0:
(void)signal(SIGINT, SIG_DFL);
@@ -183,11 +185,11 @@ pwd_check(login_cap_t *lc, char *passwor
}
 
/* get the return value from the child */
-   while (waitpid(child, &res, 0) == -1) {
+   while ((c = waitpid(child, &res, 0)) == -1) {
if (errno != EINTR)
break;
}
-   if (WIFEXITED(res) && WEXITSTATUS(res) == 0) {
+   if (c == child && WIFEXITED(res) && WEXITSTATUS(res) == 0) {
free(checker);
return (1);
}



Re: cron: better error checking of random values

2023-05-05 Thread Todd C . Miller
On Fri, 05 May 2023 16:13:01 +1000, Mark Jamsek wrote:

> I found kn's attempted syntax intuitive though; it feels like a natural
> extension of the existing random and step syntax. I also assumed ~/15
> would run every 15 minutes starting with a random minute, and since
> discovering it didn't work like that, I've been carrying a simple patch
> that allows kn's syntax:
>
>   ~/15random 15 minute intervals in [0, 59]
>   1~9/10  random 10 minute intervals in [1,59]

It does seem like people prefer the ~/step syntax over my own, which
is fine.

However, I'm unsure about the x~y/step syntax.  Personally, I think
it would be more natural to treat x~y/step like x-y/step and just
use a random offset in the interval [0,step-1].  Do you have a
use-case for the way your diff handles this or did it just follow
naturally from the random value being in num1?

Also, using the % operator with the random value results in modulo
bias, which we would like to avoid.  If we use a random offset based
on the step interval instead there is no need for the modulus.

 - todd



Fix makefs(8) for creating ffs2 filesystem images

2023-05-05 Thread Jihyun Yu
Hi,

makefs(8) creates an ffs1 filesystem by default, and the generated
filesystem image passes fsck checks. However, when creating an ffs2
filesystem using the -o version=2 option, the generated filesystem image
fails fsck checks.

This patch resolves the issue by ensuring that the superblock parameters
for the ffs2 filesystem match those set by newfs.

---

diff --git a/usr.sbin/makefs/ffs/mkfs.c b/usr.sbin/makefs/ffs/mkfs.c
index a4d57c008a2..6369af6ba4a 100644
--- a/usr.sbin/makefs/ffs/mkfs.c
+++ b/usr.sbin/makefs/ffs/mkfs.c
@@ -222,13 +222,9 @@ ffs_mkfs(const char *fsys, const fsinfo_t
*fsopts, time_t tstamp)
sblock.fs_fmask = ~(sblock.fs_fsize - 1);
sblock.fs_qbmask = ~sblock.fs_bmask;
sblock.fs_qfmask = ~sblock.fs_fmask;
-   for (sblock.fs_bshift = 0, i = sblock.fs_bsize; i > 1; i >>= 1)
-   sblock.fs_bshift++;
-   for (sblock.fs_fshift = 0, i = sblock.fs_fsize; i > 1; i >>= 1)
-   sblock.fs_fshift++;
+   sblock.fs_bshift = ilog2(sblock.fs_bsize);
+   sblock.fs_fshift = ilog2(sblock.fs_fsize);
sblock.fs_frag = numfrags(&sblock, sblock.fs_bsize);
-   for (sblock.fs_fragshift = 0, i = sblock.fs_frag; i > 1; i >>= 1)
-   sblock.fs_fragshift++;
if (sblock.fs_frag > MAXFRAG) {
printf("fragment size %d is too small, "
"minimum with block size %d is %d\n",
@@ -236,8 +232,12 @@ ffs_mkfs(const char *fsys, const fsinfo_t
*fsopts, time_t tstamp)
sblock.fs_bsize / MAXFRAG);
exit(21);
}
+   sblock.fs_fragshift = ilog2(sblock.fs_frag);
sblock.fs_fsbtodb = ilog2(sblock.fs_fsize / sectorsize);
sblock.fs_size = fssize = dbtofsb(&sblock, fssize);
+   sblock.fs_nspf = sblock.fs_fsize / sectorsize;
+   sblock.fs_nrpos = 1;
+   sblock.fs_cpg = 1;

if (Oflag <= 1) {
sblock.fs_magic = FS_UFS1_MAGIC;
@@ -251,13 +251,10 @@ ffs_mkfs(const char *fsys, const fsinfo_t
*fsopts, time_t tstamp)
sblock.fs_ffs1_size = sblock.fs_size;
sblock.fs_rotdelay = 0;
sblock.fs_rps = 60;
-   sblock.fs_nspf = sblock.fs_fsize / sectorsize;
-   sblock.fs_cpg = 1;
sblock.fs_interleave = 1;
sblock.fs_trackskew = 0;
sblock.fs_cpc = 0;
sblock.fs_postblformat = 1;
-   sblock.fs_nrpos = 1;
} else {
sblock.fs_magic = FS_UFS2_MAGIC;
 #if 0 /* XXX makefs is used for small filesystems. */



software tcp send offloading

2023-05-05 Thread Alexander Bluhm
Hi,

Claudio suggested to implement TCP send offloading in software as
a fallback if hardware cannot do it.  So I took Jan's diff, ripped
that part out and polished it.

Result is that software TSO can be a bit faster than regular TCP.

http://bluhm.genua.de/perform/results/2023-05-04T07%3A05%3A11Z/perform.html

Left column is OpenBSD-current, middle is with this diff, but TSO
disabled, and right is software TSO enabled.  So comparing middle
and right shows the effect.

http://bluhm.genua.de/perform/results/2023-05-04T07%3A05%3A11Z/patch-sys-tso-soft-disable.0/btrace/tcpbench_-S100_-t10_10.3.45.35-btrace-kstack.0.svg
http://bluhm.genua.de/perform/results/2023-05-04T07%3A05%3A11Z/patch-sys-tso-soft.0/btrace/tcpbench_-S100_-t10_10.3.45.35-btrace-kstack.0.svg

When looking at kstack you see that m_copym() load moves from
tcp_output() to ip_output() where the large packet is chopped.  So
pf_test() needs less CPU cycles what explains the increased througput.

I round the large TCP packet to a multiple of the maximum segment
size with at least two segments.  So I avoid residual small packets.

Implementation in pf_route() is still missing.  Also IP option
handling has to be fixed and TCP output size decisions have to be
rechecked.

I just wanted to show where this is heading.  When software TSO is
done, it should be easy to use network interface hardware to speed
things up.

bluhm

Index: netinet/in.h
===
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/in.h,v
retrieving revision 1.142
diff -u -p -r1.142 in.h
--- netinet/in.h11 Apr 2023 00:45:09 -  1.142
+++ netinet/in.h5 May 2023 15:02:12 -
@@ -780,6 +780,7 @@ intin_canforward(struct in_addr);
 int   in_cksum(struct mbuf *, int);
 int   in4_cksum(struct mbuf *, u_int8_t, int, int);
 void  in_proto_cksum_out(struct mbuf *, struct ifnet *);
+int   in_ifcap_cksum(struct mbuf *, struct ifnet *, int);
 void  in_ifdetach(struct ifnet *);
 int   in_mask2len(struct in_addr *);
 void  in_len2mask(struct in_addr *, int);
Index: netinet/ip_output.c
===
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_output.c,v
retrieving revision 1.382
diff -u -p -r1.382 ip_output.c
--- netinet/ip_output.c 12 Aug 2022 17:04:16 -  1.382
+++ netinet/ip_output.c 5 May 2023 15:02:12 -
@@ -84,7 +84,6 @@ void ip_mloopback(struct ifnet *, struct
 static __inline u_int16_t __attribute__((__unused__))
 in_cksum_phdr(u_int32_t, u_int32_t, u_int32_t);
 void in_delayed_cksum(struct mbuf *);
-int in_ifcap_cksum(struct mbuf *, struct ifnet *, int);
 
 int ip_output_ipsec_lookup(struct mbuf *m, int hlen, struct inpcb *inp,
 struct tdb **, int ipsecflowinfo);
@@ -104,7 +103,7 @@ ip_output(struct mbuf *m, struct mbuf *o
 {
struct ip *ip;
struct ifnet *ifp = NULL;
-   struct mbuf_list fml;
+   struct mbuf_list ml;
int hlen = sizeof (struct ip);
int error = 0;
struct route iproute;
@@ -469,6 +468,24 @@ sendit:
goto done;
}
 
+   if (ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO) &&
+   m->m_pkthdr.ph_mss <= mtu) {
+   error = tcp_chopper(m, &ml, ifp, m->m_pkthdr.ph_mss);
+   if (error)
+   goto done;
+
+   while ((m = ml_dequeue(&ml)) != NULL) {
+   error = ifp->if_output(ifp, m, sintosa(dst), ro->ro_rt);
+   if (error)
+   break;
+   }
+   if (error)
+   ml_purge(&ml);
+   else
+   tcpstat_inc(tcps_outswtso);
+   goto done;
+   }
+
/*
 * Too large for interface; fragment if possible.
 * Must be able to put at least 8 bytes per fragment.
@@ -505,17 +522,17 @@ sendit:
goto bad;
}
 
-   error = ip_fragment(m, &fml, ifp, mtu);
+   error = ip_fragment(m, &ml, ifp, mtu);
if (error)
goto done;
 
-   while ((m = ml_dequeue(&fml)) != NULL) {
+   while ((m = ml_dequeue(&ml)) != NULL) {
error = ifp->if_output(ifp, m, sintosa(dst), ro->ro_rt);
if (error)
break;
}
if (error)
-   ml_purge(&fml);
+   ml_purge(&ml);
else
ipstat_inc(ips_fragmented);
 
@@ -677,16 +694,15 @@ ip_output_ipsec_send(struct tdb *tdb, st
 #endif /* IPSEC */
 
 int
-ip_fragment(struct mbuf *m0, struct mbuf_list *fml, struct ifnet *ifp,
+ip_fragment(struct mbuf *m0, struct mbuf_list *ml, struct ifnet *ifp,
 u_long mtu)
 {
-   struct mbuf *m;
struct ip *ip;
int firstlen, hlen, tlen, len, off;
int error;
 
-   ml_init(fml);
-   ml_enqueue(fml, m0);
+   ml_init(ml);
+   ml_enqueue(ml, m0);
 
 

Re: cron: better error checking of random values

2023-05-05 Thread Peter Hessler
On 2023 May 05 (Fri) at 16:13:01 +1000 (+1000), Mark Jamsek wrote:
:On 23-05-04 05:40PM, Todd C. Miller wrote:
:> On Thu, 04 May 2023 21:41:26 -, Klemens Nanni wrote:
:> 
:> > On Thu, May 04, 2023 at 03:30:30PM -0600, Todd C. Miller wrote:
:> > > This fixes two issues with the parsing of random values:
:> > > 
:> > > 1) A random value with a step is now rejected.  For example:
:> > > 
:> > > ~/10* * * * echo invalid
:> >
:> > I've ben using ~/10 to randomly distribute four similar tasks so that
:> > they don't start at the same time.
:> >
:> > Is that wrong?
:> 
:> I'm fairly certain that doesn't do what you think it does.  When I
:> tested it "~/10" behaved the same as "~".  The step value is not
:> even parsed.
:

I really dislike "previously accepted (even if behaved differently)"
configs being rejected ...


:todd is correct in that the step value is not parsed with "~/10". We
:recently discovered this when setting up Got mirrors to sync every 15
:minutes. IIRC, Lucas (or op?) asked about syncing each mirror at
:a different 15 minute interval by using the same syntax kn is using.
:
:I found kn's attempted syntax intuitive though; it feels like a natural
:extension of the existing random and step syntax. I also assumed ~/15
:would run every 15 minutes starting with a random minute, and since
:discovering it didn't work like that, I've been carrying a simple patch
:that allows kn's syntax:
:
:  ~/15 random 15 minute intervals in [0, 59]
:  1~9/10   random 10 minute intervals in [1,59]
:

... but I really like this syntax and behaviour.

I haven't had a chance to review the code, but I think this would be a
better direction for us to go.

-peter


:8<
:diff refs/remotes/origin/master refs/heads/master
:commit - e253a7cc21de530da6fcf49c1279258fecade8f4
:commit + 761b09ae46431344766330cc14c958ffca5a3a0a
:blob - ab683b8476a8c862aabc53101b4080959820835a
:blob + 030ab599dcf07eb3e94efe90c118e4e9bea8f6c4
:--- usr.sbin/cron/entry.c
:+++ usr.sbin/cron/entry.c
:@@ -456,10 +456,11 @@ get_range(bitstr_t *bits, int low, int high, const cha
:   /* range = number | number* "~" number* | number "-" number ["/" number]
:*/
: 
:-  int i, num1, num2, num3;
:+  int i, num1, num2, num3, rndstep;
: 
:   num1 = low;
:   num2 = high;
:+  rndstep = 0;
: 
:   if (ch == '*') {
:   /* '*' means [low, high] but can still be modified by /step
:@@ -497,7 +498,7 @@ get_range(bitstr_t *bits, int low, int high, const cha
: 
:   /* get the (optional) number following the tilde
:*/
:-  ch = get_number(&num2, low, names, ch, file, ", \t\n");
:+  ch = get_number(&num2, low, names, ch, file, "/, \t\n");
:   if (ch == EOF)
:   ch = get_char(file);
:   if (ch == EOF || num1 > num2) {
:@@ -509,6 +510,10 @@ get_range(bitstr_t *bits, int low, int high, const cha
:*/
:   num3 = num1;
:   num1 = arc4random_uniform(num2 - num3 + 1) + num3;
:+  if (ch == '/') {
:+  rndstep = 1;
:+  break;
:+  }
:   /* FALLTHROUGH */
:   default:
:   /* not a range, it's a single number.
:@@ -538,6 +543,10 @@ get_range(bitstr_t *bits, int low, int high, const cha
:   ch = get_number(&num3, 0, NULL, ch, file, ", \t\n");
:   if (ch == EOF || num3 == 0)
:   return (EOF);
:+  if (rndstep) {
:+  num1 %= num3;
:+  num2 = high;
:+  }
:   } else {
:   /* no step.  default==1.
:*/
:>8
:
:> It sounds like what you want is the proposed syntax "*/~10"
:> to use a random offset.
:
:But this would be nice too! Anything that enables regular intervals from
:a random offset would satisfy a common enough use case.
:
:-- 
:Mark Jamsek 
:GPG: F2FF 13DE 6A06 C471 CA80  E6E2 2930 DC66 86EE CF68

-- 
Time flies like an arrow, but fruit flies like a banana.



Re: cron: better error checking of random values

2023-05-05 Thread Klemens Nanni
On Thu, May 04, 2023 at 05:40:10PM -0600, Todd C. Miller wrote:
> I'm fairly certain that doesn't do what you think it does.  When I
> tested it "~/10" behaved the same as "~".  The step value is not
> even parsed.

Oh I see, it is actually picking a random minute and ignores steps,
so entries run once an hour:

~/10 * * * *-qs touch /tmp/cron-foo.$(date +\%s)
~/10 * * * *-qs touch /tmp/cron-bar.$(date +\%s)
~/10 * * * *-qs touch /tmp/cron-lol.$(date +\%s)

from earlier gave me:

-rw-r--r--  1 kn  wheel  0 May  5 18:08 /tmp/cron-bar.1683295681
-rw-r--r--  1 kn  wheel  0 May  5 19:08 /tmp/cron-bar.1683299281
-rw-r--r--  1 kn  wheel  0 May  5 18:34 /tmp/cron-foo.1683297241
-rw-r--r--  1 kn  wheel  0 May  5 18:11 /tmp/cron-lol.1683295861
-rw-r--r--  1 kn  wheel  0 May  5 19:11 /tmp/cron-lol.1683299461

> 
> It sounds like what you want is the proposed syntax "*/~10"
> to use a random offset.

Indeed, thanks.