snmpd - improve trap handle documentation
When moving the traphandler code to snpme I overlooked some text in the "trap handle" section. This diff tries to rectify that. While here, try to be a little more clear in the "listen on" segment as well. OK? martijn@ Index: snmpd.conf.5 === RCS file: /cvs/src/usr.sbin/snmpd/snmpd.conf.5,v retrieving revision 1.46 diff -u -p -r1.46 snmpd.conf.5 --- snmpd.conf.522 Jan 2021 06:33:26 - 1.46 +++ snmpd.conf.53 Mar 2021 16:02:16 - @@ -116,9 +116,12 @@ The default protocol is .Ic udp. The default .Ar port -is 161, unless the only listen flags contains +is 161, unless .Ic notify -which sets it to 162. +is the only listen flags +which sets the +.Ar port +to 162. If no flags are specified it defaults to .Dq Ic read Ic write , or @@ -126,6 +129,11 @@ or when .Ar port is 162. +Having +.Ic notify +set requires at least one +.Ic trap handle +statement. .It Ic read-only community Ar string Specify the name of the read-only community. The default value is @@ -217,9 +225,12 @@ the resolved hostname of the host sendin the IP address of the host sending the trap, and any variable bindings contained in the trap (the OID followed by the value, separated by a single space). -Traps will be accepted on all +This option requires at least one .Ic listen on -UDP addresses. +statement with a +.Ic notify +flag set. +Traps over SNMPv3 are currently unsupported. .It Xo .Ic trap receiver Ar string .Op Ic oid Ar oid-string
snmp(1) Fix some ranges and types
Live and learn. While working on a regress test I found that I misunderstood some types when I wrote this code. According to RFC2578: - timeticks is a 32 bit unsigned int - counter32 is a 32 bit unsigned int - unsigned is "indistinguishable from Gauge32" - integer is a 32 bit integer OK? martijn@ Index: snmp.1 === RCS file: /cvs/src/usr.bin/snmp/snmp.1,v retrieving revision 1.15 diff -u -p -r1.15 snmp.1 --- snmp.1 14 Sep 2020 15:12:27 - 1.15 +++ snmp.1 2 Mar 2021 21:48:35 - @@ -524,7 +524,6 @@ A regular string. Timeticks in centiseconds. .It Cm u Unsigned integer. -Actually a normal integer for compatibility with netsnmp. .It Cm x A hex string. Similar to a decimal string, but in hexadecimal format. Index: snmpc.c === RCS file: /cvs/src/usr.bin/snmp/snmpc.c,v retrieving revision 1.31 diff -u -p -r1.31 snmpc.c --- snmpc.c 2 Dec 2020 15:45:51 - 1.31 +++ snmpc.c 2 Mar 2021 21:48:35 - @@ -801,7 +801,7 @@ snmpc_trap(int argc, char *argv[]) if (clock_gettime(CLOCK_UPTIME, ) == -1) err(1, "clock_gettime"); } else { - lval = strtonum(argv[1], 0, LLONG_MAX, ); + lval = strtonum(argv[1], 0, UINT32_MAX, ); if (errstr != NULL) errx(1, "Bad value notation (%s)", argv[1]); ts.tv_sec = lval / 100; @@ -1439,7 +1439,7 @@ snmpc_varbindparse(int argc, char *argv[ */ goto pastestring; case 'c': - lval = strtonum(argv[i + 2], INT32_MIN, INT32_MAX, + lval = strtonum(argv[i + 2], 0, UINT32_MAX, ); if (errstr != NULL) errx(1, "%s: Bad value notation (%s)", argv[i], @@ -1472,9 +1472,8 @@ snmpc_varbindparse(int argc, char *argv[ tmpstr = endstr + 1; } while (endstr[0] != '\0'); goto pastestring; - case 'u': case 'i': - lval = strtonum(argv[i + 2], LLONG_MIN, LLONG_MAX, + lval = strtonum(argv[i + 2], INT32_MIN, INT32_MAX, ); if (errstr != NULL) errx(1, "%s: Bad value notation (%s)", argv[i], @@ -1508,7 +1507,7 @@ pastestring: free(str); break; case 't': - lval = strtonum(argv[i + 2], LLONG_MIN, LLONG_MAX, + lval = strtonum(argv[i + 2], 0, UINT32_MAX, ); if (errstr != NULL) errx(1, "%s: Bad value notation (%s)", argv[i], @@ -1516,6 +1515,17 @@ pastestring: if ((varbind = ober_printf_elements(varbind, "{Oit}", , lval, BER_CLASS_APPLICATION, SNMP_T_TIMETICKS)) == NULL) + err(1, "ober_printf_elements"); + break; + case 'u': + lval = strtonum(argv[i + 2], 0, UINT32_MAX, + ); + if (errstr != NULL) + errx(1, "%s: Bad value notation (%s)", argv[i], + argv[i + 2]); + if ((varbind = ober_printf_elements(varbind, "{Oit}", + , lval, BER_CLASS_APPLICATION, + SNMP_T_GAUGE32)) == NULL) err(1, "ober_printf_elements"); break; case 'x':
Re: systat(1) sticky help
On Sun, 2021-02-28 at 23:03 -0800, Anindya Mukherjee wrote: > Hi, > > Thanks for the feedback. I see your point. Perhaps it would be better to > have a separate "stickiness" toggle and not tie it to the help or the > view name display functions. For example, pressing 't' could toggle it > on and then pressing 'h' or Ctrl-G would make the display stick. > Pressing 't' again would toggle it off, and then the display would get > cleared normally. Something like that seems better, but keep in mind that the single key bindings within systat is a mess: 't' might already be allocated by one of the views. When submitting your followup, try to make sure that you considered all possible issues, including the keybindings, and show how you came to your conclusion. > > Regards, > Anindya > > On Mon, Mar 01, 2021 at 07:49:49AM +0100, Martijn van Duren wrote: > > Although the feature *might* be useful (just woken up, so haven't given > > it too much thought), the bindings have some problems and need to be > > reworked if we decide to get this in. Problems that I see from just a > > few short tests (so there might be others): > > - Entering sticky: H, which also enters help, which is annoying if I > > want sticky ^G. > > - Clearing sticky: h, which also displays help, which if I come from > > ^G is not what I want and if I'm in help is confusing, because I want > > to get rid of it. > > > > martijn@ > > > > On Sun, 2021-02-28 at 19:40 -0800, Anindya Mukherjee wrote: > > > Hi, > > > > > > I tend to keep systat(1) running in interactive mode, and find it very > > > useful to have the help line displayed permanently, i.e., not disappear > > > if a key is pressed or after a command is executed. The same goes for > > > the Ctrl-G display. For example, it tells me what modes are adjacent to > > > the currently active one when pressing left or right arrow keys. > > > > > > The attached diff adds this feature. It is off by default. I noticed > > > that the 'h' key was not documented in the man page, so I took the > > > liberty of adding a line describing it. > > > > > > Hope it is useful. Please have a look, thanks! > > > > > > Regards, > > > Anindya > > > > > > Index: engine.c > > > === > > > RCS file: /cvs/src/usr.bin/systat/engine.c,v > > > retrieving revision 1.27 > > > diff -u -p -r1.27 engine.c > > > --- engine.c6 Feb 2021 06:19:28 - 1.27 > > > +++ engine.c1 Mar 2021 03:20:41 - > > > @@ -70,6 +70,8 @@ volatile sig_atomic_t gotsig_alarm = 0; > > > int need_update = 0; > > > int need_sort = 0; > > > int separate_thousands = 0; > > > +int viewmode = 0; > > > +int sticky = 0; > > > > > > SCREEN *screen; > > > > > > @@ -1139,7 +1141,9 @@ command_set(struct command *cmd, const c > > > cmdbuf[0] = 0; > > > } > > > } > > > - message_set(NULL); > > > + > > > + if (!sticky) > > > + message_set(NULL); > > > curr_cmd = cmd; > > > need_update = 1; > > > return prev; > > > @@ -1234,7 +1238,7 @@ keyboard(void) > > > return; > > > > > > if (curr_message != NULL) { > > > - if (ch > 0) { > > > + if (ch > 0 && !sticky) { > > > message_set(NULL); > > > need_update = 1; > > > } > > > @@ -1359,8 +1363,15 @@ engine_loop(int countmax) > > > if (need_update) { > > > erase(); > > > if (!averageonly || > > > - (averageonly && count == countmax - 1)) > > > + (averageonly && count == countmax - 1)) { > > > disp_update(); > > > + if (interactive && sticky) { > > > + if (viewmode) > > > + show_view(); > > > + else > > > + show_help(); > > > + } > > > + } > > &g
Re: systat(1) sticky help
Although the feature *might* be useful (just woken up, so haven't given it too much thought), the bindings have some problems and need to be reworked if we decide to get this in. Problems that I see from just a few short tests (so there might be others): - Entering sticky: H, which also enters help, which is annoying if I want sticky ^G. - Clearing sticky: h, which also displays help, which if I come from ^G is not what I want and if I'm in help is confusing, because I want to get rid of it. martijn@ On Sun, 2021-02-28 at 19:40 -0800, Anindya Mukherjee wrote: > Hi, > > I tend to keep systat(1) running in interactive mode, and find it very > useful to have the help line displayed permanently, i.e., not disappear > if a key is pressed or after a command is executed. The same goes for > the Ctrl-G display. For example, it tells me what modes are adjacent to > the currently active one when pressing left or right arrow keys. > > The attached diff adds this feature. It is off by default. I noticed > that the 'h' key was not documented in the man page, so I took the > liberty of adding a line describing it. > > Hope it is useful. Please have a look, thanks! > > Regards, > Anindya > > Index: engine.c > === > RCS file: /cvs/src/usr.bin/systat/engine.c,v > retrieving revision 1.27 > diff -u -p -r1.27 engine.c > --- engine.c6 Feb 2021 06:19:28 - 1.27 > +++ engine.c1 Mar 2021 03:20:41 - > @@ -70,6 +70,8 @@ volatile sig_atomic_t gotsig_alarm = 0; > int need_update = 0; > int need_sort = 0; > int separate_thousands = 0; > +int viewmode = 0; > +int sticky = 0; > > SCREEN *screen; > > @@ -1139,7 +1141,9 @@ command_set(struct command *cmd, const c > cmdbuf[0] = 0; > } > } > - message_set(NULL); > + > + if (!sticky) > + message_set(NULL); > curr_cmd = cmd; > need_update = 1; > return prev; > @@ -1234,7 +1238,7 @@ keyboard(void) > return; > > if (curr_message != NULL) { > - if (ch > 0) { > + if (ch > 0 && !sticky) { > message_set(NULL); > need_update = 1; > } > @@ -1359,8 +1363,15 @@ engine_loop(int countmax) > if (need_update) { > erase(); > if (!averageonly || > - (averageonly && count == countmax - 1)) > + (averageonly && count == countmax - 1)) { > disp_update(); > + if (interactive && sticky) { > + if (viewmode) > + show_view(); > + else > + show_help(); > + } > + } > end_page(); > need_update = 0; > if (countmax && ++count >= countmax) > Index: engine.h > === > RCS file: /cvs/src/usr.bin/systat/engine.h,v > retrieving revision 1.12 > diff -u -p -r1.12 engine.h > --- engine.h12 Jan 2020 20:51:08 - 1.12 > +++ engine.h1 Mar 2021 03:20:41 - > @@ -144,6 +144,8 @@ struct command *command_set(struct comma > const char *message_set(const char *msg); > > void foreach_view(void (*callback)(field_view *)); > +void show_help(void); > +void show_view(void); > > extern int sortdir; > extern useconds_t udelay; > @@ -160,6 +162,8 @@ extern int columns, lines; > extern int need_update; > extern int need_sort; > extern int separate_thousands; > +extern int viewmode; > +extern int sticky; > > extern volatile sig_atomic_t gotsig_close; > extern volatile sig_atomic_t gotsig_resize; > Index: main.c > === > RCS file: /cvs/src/usr.bin/systat/main.c,v > retrieving revision 1.73 > diff -u -p -r1.73 main.c > --- main.c 30 Jan 2021 08:44:42 - 1.73 > +++ main.c 1 Mar 2021 03:20:41 - > @@ -285,6 +285,14 @@ cmd_compat(const char *buf) > > if (strcasecmp(buf, "help") == 0) { > show_help(); > + sticky = 0; > + need_update = 1; > + return; > + } > + if (strcasecmp(buf, "stickyhelp") == 0) { > + show_help(); > + sticky = 1; > + viewmode = 0; > need_update = 1; > return; > } > @@ -359,10 +367,18 @@ keyboard_callback(int ch) > /* FALLTHROUGH */ > case 'h': > show_help(); > + sticky = 0; > + need_update = 1; > + break; > + case 'H':
ober_get_string.3: s/byte/character
As pointed out by claudio@, it makes more sense to talk about characters for fmt instead of bytes. The .Bl line already was >80 columns, but I don't know how to remedy this situation, so this diff makes that a little worse. martijn@ Index: ober_get_string.3 === RCS file: /cvs/src/lib/libutil/ober_get_string.3,v retrieving revision 1.4 diff -u -p -r1.4 ober_get_string.3 --- ober_get_string.3 22 Feb 2021 17:15:02 - 1.4 +++ ober_get_string.3 22 Feb 2021 22:08:32 - @@ -87,15 +87,15 @@ to return a valid .Fn ober_scanf_elements retrieves the values from zero or more elements starting at .Fa root . -For each byte in +For each character in .Fa fmt , arguments of the types given in the following table are consumed and passed to the function listed, processing one .Vt ber_element -per byte. -The following bytes are valid: -.Bl -column -offset indent bytes ober_get_enumerated() "1: struct ber_element **" -.It Sy byte Ta Sy function Ta Sy arguments +per character. +The following characters are valid: +.Bl -column -offset indent characters ober_get_enumerated() "1: struct ber_element **" +.It Sy character Ta Sy function Ta Sy arguments .It $ Ta see below Ta 0 .It B Ta Fn ober_get_bitstring Ta 2: Vt void ** , size_t * .It b Ta Fn ober_get_booleanTa 1: Vt int *
Re: snmpd: Add end of sequence tests
On Fri, 2021-02-12 at 11:02 +0100, Claudio Jeker wrote: > On Fri, Feb 12, 2021 at 10:03:21AM +0100, Martijn van Duren wrote: > > ping > > > > On Sun, 2021-01-31 at 11:57 +0100, Martijn van Duren wrote: > > > Now that ober_scanf_elements supports '$' lets use it. > > > > > > Here's a first stab by adding it to snmpd. > > > Passing regress and a few manual checks. > > > > > > 'e' still doesn't consume the element, but I've talked it over with > > > rob@, who said that shouldn't get in the way of using this new feature. > > > > > > OK? > > Looks reasonable and I guess you verified the layout of all those ASN.1 > messages to ensure the $ is at the right place. To the best of my knowledge in both reading and testing. If I somehow did screw it up, it should be easy enough to fix and loud enough to notice. > > Side note: I wonder why does } not imply the $? At least now with S it > would be possible to enforce this. } does nothing more then dropping down from the current sequence level. This comes in handy if for instance when parsing a PDU. The varbindlist is of undefined length, so I wouldn't know how many Ss I'd need. See line snmpe.c:380. The parsing and verifying of the varbindlist happens on snmpe.c:439. > I like that you closed a lot of open { format strings. What about these: > > > > - if (ober_scanf_elements(usm, "{xiixpxx", , , > > > + if (ober_scanf_elements(usm, "{xiixpxx$", , , > > Wouldn't it be better to use "{xiixpxx$}" here? > I treat } as dropping down from the current sequence level. In that case it doesn't matter. It might be more estatically pleasing. I can add it if you want, but doesn't add anything. Updated diff, since I just now noticed how mangled that thing was. Index: snmpe.c === RCS file: /cvs/src/usr.sbin/snmpd/snmpe.c,v retrieving revision 1.69 diff -u -p -r1.69 snmpe.c --- snmpe.c 5 Feb 2021 10:30:45 - 1.69 +++ snmpe.c 12 Feb 2021 10:34:32 - @@ -227,7 +227,7 @@ snmpe_parse(struct snmp_message *msg) case SNMP_V2: if (env->sc_min_seclevel != 0) goto badversion; - if (ober_scanf_elements(a, "se", , >sm_pdu) != 0) + if (ober_scanf_elements(a, "seS$", , >sm_pdu) != 0) goto parsefail; if (strlcpy(msg->sm_community, comn, sizeof(msg->sm_community)) >= sizeof(msg->sm_community)) { @@ -237,7 +237,7 @@ snmpe_parse(struct snmp_message *msg) } break; case SNMP_V3: - if (ober_scanf_elements(a, "{iisi}e", + if (ober_scanf_elements(a, "{iisi$}e", >sm_msgid, >sm_max_msg_size, , >sm_secmodel, ) != 0) goto parsefail; @@ -255,7 +255,7 @@ snmpe_parse(struct snmp_message *msg) goto parsefail; } - if (ober_scanf_elements(a, "{xxe", + if (ober_scanf_elements(a, "{xxeS$}$", >sm_ctxengineid, >sm_ctxengineid_len, , , >sm_pdu) != 0) goto parsefail; @@ -377,7 +377,7 @@ snmpe_parse(struct snmp_message *msg) } /* SNMP PDU */ - if (ober_scanf_elements(a, "iiie{et", + if (ober_scanf_elements(a, "iiie{et}$", , , , >sm_pduend, >sm_varbind, , ) != 0) { stats->snmp_silentdrops++; @@ -436,7 +436,7 @@ snmpe_parsevarbinds(struct snmp_message for (i = 1; varbind != NULL && i < SNMPD_MAXVARBIND; varbind = varbind->be_next, i++) { - if (ober_scanf_elements(varbind, "{oe}", , ) == -1) { + if (ober_scanf_elements(varbind, "{oeS$}", , ) == -1) { stats->snmp_inasnparseerrs++; msg->sm_errstr = "invalid varbind"; goto varfail; Index: traphandler.c === RCS file: /cvs/src/usr.sbin/snmpd/traphandler.c,v retrieving revision 1.20 diff -u -p -r1.20 traphandler.c --- traphandler.c 22 Jan 2021 06:33:27 - 1.20 +++ traphandler.c 12 Feb 2021 10:34:32 - @@ -67,7 +67,7 @@ traphandler_parse(struct snmp_message *m struct privsep *ps = _env->sc_ps; struct snmp_stats *stats = _env->sc_stats; struct ber ber = {0}; - struct ber_element *vblist = NULL, *elm, *elm2; + struct ber_element *vblist = NULL, *elm;
Re: snmpd: Add end of sequence tests
ping On Sun, 2021-01-31 at 11:57 +0100, Martijn van Duren wrote: > Now that ober_scanf_elements supports '$' lets use it. > > Here's a first stab by adding it to snmpd. > Passing regress and a few manual checks. > > 'e' still doesn't consume the element, but I've talked it over with > rob@, who said that shouldn't get in the way of using this new feature. > > OK? > > martijn@ > > Index: snmpe.c > === > RCS file: /cvs/src/usr.sbin/snmpd/snmpe.c,v > retrieving revision 1.68 > diff -u -p -r1.68 snmpe.c > --- snmpe.c 22 Jan 2021 06:33:27 - 1.68 > +++ snmpe.c 31 Jan 2021 10:55:49 - > @@ -220,7 +220,7 @@ snmpe_parse(struct snmp_message *msg) > case SNMP_V2: > if (env->sc_min_seclevel != 0) > goto badversion; > - if (ober_scanf_elements(a, "se", , >sm_pdu) != 0) > + if (ober_scanf_elements(a, "seS$", , >sm_pdu) != 0) > goto parsefail; > if (strlcpy(msg->sm_community, comn, > sizeof(msg->sm_community)) >= sizeof(msg->sm_community)) { > @@ -230,7 +230,7 @@ snmpe_parse(st? tm_udp.c > Index: snmpe.c > === > RCS file: /cvs/src/usr.sbin/snmpd/snmpe.c,v > retrieving revision 1.68 > diff -u -p -r1.68 snmpe.c > --- snmpe.c 22 Jan 2021 06:33:27 - 1.68 > +++ snmpe.c 31 Jan 2021 10:55:49 - > @@ -220,7 +220,7 @@ snmpe_parse(struct snmp_message *msg) > case SNMP_V2: > if (env->sc_min_seclevel != 0) > goto badversion; > - if (ober_scanf_elements(a, "se", , >sm_pdu) != 0) > + if (ober_scanf_elements(a, "seS$", , >sm_pdu) != 0) > goto parsefail; > if (strlcpy(msg->sm_community, comn, > sizeof(msg->sm_community)) >= sizeof(msg->sm_community)) { > @@ -230,7 +230,7 @@ snmpe_parse(struct snmp_message *msg) > } > break; > case SNMP_V3: > - if (ober_scanf_elements(a, "{iisi}e", > + if (ober_scanf_elements(a, "{iisi$}e", > >sm_msgid, >sm_max_msg_size, , > >sm_secmodel, ) != 0) > goto parsefail; > @@ -248,7 +248,7 @@ snmpe_parse(struct snmp_message *msg) > goto parsefail; > } > > - if (ober_scanf_elements(a, "{xxe", > + if (ober_scanf_elements(a, "{xxeS$}$", > >sm_ctxengineid, >sm_ctxengineid_len, > , , >sm_pdu) != 0) > goto parsefail; > @@ -370,7 +370,7 @@ snmpe_parse(struct snmp_message *msg) > } > > /* SNMP PDU */ > - if (ober_scanf_elements(a, "iiie{et", > + if (ober_scanf_elements(a, "iiie{etS$}$", > , , , >sm_pduend, > >sm_varbind, , ) != 0) { > stats->snmp_silentdrops++; > @@ -429,7 +429,7 @@ snmpe_parsevarbinds(struct snmp_message > > for (i = 1; varbind != NULL && i < SNMPD_MAXVARBIND; > varbind = varbind->be_next, i++) { > - if (ober_scanf_elements(varbind, "{oe}", , ) == -1) { > + if (ober_scanf_elements(varbind, "{oeS$}", , ) == -1) > { > stats->snmp_inasnparseerrs++; > msg->sm_errstr = "invalid varbind"; > goto varfail; > Index: traphandler.c > === > RCS file: /cvs/src/usr.sbin/snmpd/traphandler.c,v > retrieving revision 1.20 > diff -u -p -r1.20 traphandler.c > --- traphandler.c 22 Jan 2021 06:33:27 - 1.20 > +++ traphandler.c 31 Jan 2021 10:55:49 - > @@ -67,7 +67,7 @@ traphandler_parse(struct snmp_message *m > struct privsep *ps = _env->sc_ps; > struct snmp_stats *stats = _env->sc_stats; > struct ber ber = {0}; > - struct ber_element *vblist = NULL, *elm, *elm2; > + struct ber_element *vblist = NULL, *elm; > struct ber_oid o1, o2, snmpTrapOIDOID; > struct ber_oid snmpTrapOID, sysUpTimeOID; > int sysUpTime; > @@ -82,7 +82,7 @@ traphandler_parse(struct snmp_message *m >
snmpd: add transaction id to snmp_message
Carefully taking some first looks into readding agentx master support to snmpd. One of the things we're going to need is a transaction id as per RFC2741 section 6.1 subsection h.transactionID: The transaction ID uniquely identifies, for a given session, the single SNMP management request (and single SNMP PDU) with which an AgentX PDU is associated. If a single SNMP management request results in multiple AgentX PDUs being sent by the master agent with the same session ID, each of these AgentX PDUs must contain the same transaction ID; conversely, AgentX PDUs sent during a particular session, that result from distinct SNMP management requests, must have distinct transaction IDs within the limits of the 32- bit field). Note that the transaction ID is not the same as the SNMP PDU's request-id (as described in section 4.1 of RFC 1905 [13], nor is it the same as the SNMP Message's msgID (as described in section 6.2 of RFC 2572 [11]), nor can it be, since a master agent might receive SNMP requests with the same request-ids or msgIDs from different managers. The transaction ID has no significance and no defined value in AgentX administrative PDUs, i.e., AgentX PDUs that are not associated with an SNMP management request. Our previous implementation took the transaction id from the agentx context and incremented it by one for every request, which is just plain wrong. OK? martijn@ Index: snmpd.h === RCS file: /cvs/src/usr.sbin/snmpd/snmpd.h,v retrieving revision 1.93 diff -u -p -r1.93 snmpd.h --- snmpd.h 28 Jan 2021 20:45:14 - 1.93 +++ snmpd.h 2 Feb 2021 12:23:37 - @@ -399,6 +399,8 @@ struct snmp_message { u_int8_t sm_data[READ_BUF_SIZE]; size_t sm_datalen; + uint32_t sm_transactionid; + u_intsm_version; /* V1, V2c */ @@ -436,7 +438,11 @@ struct snmp_message { struct ber_element *sm_varbind; struct ber_element *sm_varbindresp; + + RB_ENTRY(snmp_message) sm_entry; }; +RB_HEAD(snmp_messages, snmp_message); +extern struct snmp_messages snmp_messages; /* Defined in SNMPv2-MIB.txt (RFC 3418) */ struct snmp_stats { @@ -642,6 +648,8 @@ struct kif_arp *karp_getaddr(struct sock voidsnmpe(struct privsep *, struct privsep_proc *); voidsnmpe_shutdown(void); voidsnmpe_dispatchmsg(struct snmp_message *); +int snmp_messagecmp(struct snmp_message *, struct snmp_message *); +RB_PROTOTYPE(snmp_messages, snmp_message, sm_entry, snmp_messagecmp) /* trap.c */ voidtrap_init(void); Index: snmpe.c === RCS file: /cvs/src/usr.sbin/snmpd/snmpe.c,v retrieving revision 1.68 diff -u -p -r1.68 snmpe.c --- snmpe.c 22 Jan 2021 06:33:27 - 1.68 +++ snmpe.c 2 Feb 2021 12:23:37 - @@ -58,6 +58,8 @@ void snmp_msgfree(struct snmp_message * struct imsgev *iev_parent; static const struct timevalsnmpe_tcp_timeout = { 10, 0 }; /* 10s */ +struct snmp_messages snmp_messages = RB_INITIALIZER(_messages); + static struct privsep_proc procs[] = { { "parent", PROC_PARENT } }; @@ -210,6 +212,11 @@ snmpe_parse(struct snmp_message *msg) msg->sm_errstr = "invalid message"; + do { + msg->sm_transactionid = arc4random(); + } while (msg->sm_transactionid == 0 || + RB_FIND(snmp_messages, _messages, msg) != NULL); + if (ober_scanf_elements(root, "{ie", , ) != 0) goto parsefail; @@ -834,6 +841,8 @@ snmpe_response(struct snmp_message *msg) void snmp_msgfree(struct snmp_message *msg) { + if (msg->sm_transactionid != 0) + RB_REMOVE(snmp_messages, _messages, msg); event_del(>sm_sockev); ober_free(>sm_ber); if (msg->sm_req != NULL) @@ -896,3 +905,12 @@ snmpe_encode(struct snmp_message *msg) #endif return 0; } + +int +snmp_messagecmp(struct snmp_message *m1, struct snmp_message *m2) +{ + return (m1->sm_transactionid < m2->sm_transactionid ? -1 : + m1->sm_transactionid > m2->sm_transactionid); +} + +RB_GENERATE(snmp_messages, snmp_message, sm_entry, snmp_messagecmp)
snmpd: Add end of sequence tests
Now that ober_scanf_elements supports '$' lets use it. Here's a first stab by adding it to snmpd. Passing regress and a few manual checks. 'e' still doesn't consume the element, but I've talked it over with rob@, who said that shouldn't get in the way of using this new feature. OK? martijn@ Index: snmpe.c === RCS file: /cvs/src/usr.sbin/snmpd/snmpe.c,v retrieving revision 1.68 diff -u -p -r1.68 snmpe.c --- snmpe.c 22 Jan 2021 06:33:27 - 1.68 +++ snmpe.c 31 Jan 2021 10:55:49 - @@ -220,7 +220,7 @@ snmpe_parse(struct snmp_message *msg) case SNMP_V2: if (env->sc_min_seclevel != 0) goto badversion; - if (ober_scanf_elements(a, "se", , >sm_pdu) != 0) + if (ober_scanf_elements(a, "seS$", , >sm_pdu) != 0) goto parsefail; if (strlcpy(msg->sm_community, comn, sizeof(msg->sm_community)) >= sizeof(msg->sm_community)) { @@ -230,7 +230,7 @@ snmpe_parse(st? tm_udp.c Index: snmpe.c === RCS file: /cvs/src/usr.sbin/snmpd/snmpe.c,v retrieving revision 1.68 diff -u -p -r1.68 snmpe.c --- snmpe.c 22 Jan 2021 06:33:27 - 1.68 +++ snmpe.c 31 Jan 2021 10:55:49 - @@ -220,7 +220,7 @@ snmpe_parse(struct snmp_message *msg) case SNMP_V2: if (env->sc_min_seclevel != 0) goto badversion; - if (ober_scanf_elements(a, "se", , >sm_pdu) != 0) + if (ober_scanf_elements(a, "seS$", , >sm_pdu) != 0) goto parsefail; if (strlcpy(msg->sm_community, comn, sizeof(msg->sm_community)) >= sizeof(msg->sm_community)) { @@ -230,7 +230,7 @@ snmpe_parse(struct snmp_message *msg) } break; case SNMP_V3: - if (ober_scanf_elements(a, "{iisi}e", + if (ober_scanf_elements(a, "{iisi$}e", >sm_msgid, >sm_max_msg_size, , >sm_secmodel, ) != 0) goto parsefail; @@ -248,7 +248,7 @@ snmpe_parse(struct snmp_message *msg) goto parsefail; } - if (ober_scanf_elements(a, "{xxe", + if (ober_scanf_elements(a, "{xxeS$}$", >sm_ctxengineid, >sm_ctxengineid_len, , , >sm_pdu) != 0) goto parsefail; @@ -370,7 +370,7 @@ snmpe_parse(struct snmp_message *msg) } /* SNMP PDU */ - if (ober_scanf_elements(a, "iiie{et", + if (ober_scanf_elements(a, "iiie{etS$}$", , , , >sm_pduend, >sm_varbind, , ) != 0) { stats->snmp_silentdrops++; @@ -429,7 +429,7 @@ snmpe_parsevarbinds(struct snmp_message for (i = 1; varbind != NULL && i < SNMPD_MAXVARBIND; varbind = varbind->be_next, i++) { - if (ober_scanf_elements(varbind, "{oe}", , ) == -1) { + if (ober_scanf_elements(varbind, "{oeS$}", , ) == -1) { stats->snmp_inasnparseerrs++; msg->sm_errstr = "invalid varbind"; goto varfail; Index: traphandler.c === RCS file: /cvs/src/usr.sbin/snmpd/traphandler.c,v retrieving revision 1.20 diff -u -p -r1.20 traphandler.c --- traphandler.c 22 Jan 2021 06:33:27 - 1.20 +++ traphandler.c 31 Jan 2021 10:55:49 - @@ -67,7 +67,7 @@ traphandler_parse(struct snmp_message *m struct privsep *ps = _env->sc_ps; struct snmp_stats *stats = _env->sc_stats; struct ber ber = {0}; - struct ber_element *vblist = NULL, *elm, *elm2; + struct ber_element *vblist = NULL, *elm; struct ber_oid o1, o2, snmpTrapOIDOID; struct ber_oid snmpTrapOID, sysUpTimeOID; int sysUpTime; @@ -82,7 +82,7 @@ traphandler_parse(struct snmp_message *m goto done; break; case SNMP_C_TRAPV2: - if (ober_scanf_elements(msg->sm_pdu, "{SSe}", ) == -1) { + if (ober_scanf_elements(msg->sm_pdu, "{SSe}$", ) == -1) { stats->snmp_inasnparseerrs++; goto done; } @@ -98,7 +98,7 @@ traphandler_parse(struct snmp_message *m (void)ober_string2oid("1.3.6.1.2.1.1.3.0", ); (void)ober_string2oid("1.3.6.1.6.3.1.1.4.1.0", ); - if (ober_scanf_elements(vblist, "{{od}{oo}", , , , + if (ober_scanf_elements(vblist, "{{od$}{oo$}", , , , ) == -1 || ober_oid_cmp(, ) != 0 || ober_oid_cmp(, ) != 0) { @@ -107,8 +107,7 @@ traphandler_parse(struct snmp_message *m }
Re: snmpd: remove print_{verbose,debug}
ping On Sun, 2021-01-24 at 14:48 +0100, Martijn van Duren wrote: > Nothing seems to use them and I see no reason in the forseeable future > to start using them. > > OK? > > martijn@ > > Index: snmpd.h > === > RCS file: /cvs/src/usr.sbin/snmpd/snmpd.h,v > retrieving revision 1.91 > diff -u -p -r1.91 snmpd.h > --- snmpd.h 22 Jan 2021 06:33:26 - 1.91 > +++ snmpd.h 24 Jan 2021 13:48:15 - > @@ -780,8 +780,6 @@ ssize_t sendtofrom(int, void *, size_t, > socklen_t, struct sockaddr *, socklen_t); > ssize_t recvfromto(int, void *, size_t, int, struct sockaddr *, > socklen_t *, struct sockaddr *, socklen_t *); > -void print_debug(const char *, ...); > -void print_verbose(const char *, ...); > const char *log_in6addr(const struct in6_addr *); > const char *print_host(struct sockaddr_storage *, char *, size_t); > > Index: util.c > === > RCS file: /cvs/src/usr.sbin/snmpd/util.c,v > retrieving revision 1.10 > diff -u -p -r1.10 util.c > --- util.c 30 Jun 2020 17:11:49 - 1.10 > +++ util.c 24 Jan 2021 13:48:15 - > @@ -152,30 +152,6 @@ recvfromto(int s, void *buf, size_t len, > return (ret); > } > > -void > -print_debug(const char *emsg, ...) > -{ > - va_list ap; > - > - if (log_getverbose() > 2) { > - va_start(ap, emsg); > - vfprintf(stderr, emsg, ap); > - va_end(ap); > - } > -} > - > -void > -print_verbose(const char *emsg, ...) > -{ > - va_list ap; > - > - if (log_getverbose()) { > - va_start(ap, emsg); > - vfprintf(stderr, emsg, ap); > - va_end(ap); > - } > -} > - > const char * > log_in6addr(const struct in6_addr *addr) > { > >
Re: systat(1): improve parsing of delay value
On Tue, 2021-01-26 at 16:40 +0100, Alexander Bluhm wrote: > On Mon, Jan 25, 2021 at 11:17:04AM +0100, Martijn van Duren wrote: > > if (argc == 1) { > > - double del = atof(argv[0]); > > - if (del == 0) > > + delay = strtodnum(argv[0], 0, UINT32_MAX / 100, > > ); > > + if (errstr != NULL) > > viewstr = argv[0]; > > - else > > - delay = del; > > You need the else. delay should only be changed if parsing was successful. > > > } else if (argc == 2) { > > viewstr = argv[0]; > > - delay = atof(argv[1]); > > - if (delay <= 0) > > - delay = 5; > > + delay = strtodnum(optarg, 0, UINT32_MAX / 100, ); > > This should be argv[1] instead of optarg. > > > + if (errstr != NULL) > > + errx(1, "-s \"%s\": delay value is %s", optarg, > > errstr); > > } > > The -s in the error message is wrong. Here delay was passed as argument. > > bluhm > Thanks for checking. Should be fixed below. Index: main.c === RCS file: /cvs/src/usr.bin/systat/main.c,v retrieving revision 1.72 diff -u -p -r1.72 main.c --- main.c 12 Jan 2020 20:51:08 - 1.72 +++ main.c 28 Jan 2021 20:05:30 - @@ -40,9 +40,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -73,6 +75,7 @@ char uloadbuf[TIMEPOS]; int ucount(void); void usage(void); +double strtodnum(const char *, double, double, const char **); /* command prompt */ @@ -323,9 +326,14 @@ void cmd_delay(const char *buf) { double del; - del = atof(buf); + const char *errstr; - if (del > 0) { + if (buf[0] == '\0') + return; + del = strtodnum(buf, 0, UINT32_MAX / 100, ); + if (errstr != NULL) + error("s: \"%s\": delay value is %s", buf, errstr); + else { udelay = (useconds_t)(del * 100); gotsig_alarm = 1; naptime = del; @@ -414,6 +422,48 @@ gethz(void) hz = cinf.hz; } +#defineINVALID 1 +#defineTOOSMALL2 +#defineTOOLARGE3 + +double +strtodnum(const char *nptr, double minval, double maxval, const char **errstrp) +{ + double d = 0; + int error = 0; + char *ep; + struct errval { + const char *errstr; + int err; + } ev[4] = { + { NULL, 0 }, + { "invalid",EINVAL }, + { "too small", ERANGE }, + { "too large", ERANGE }, + }; + + ev[0].err = errno; + errno = 0; + if (minval > maxval) { + error = INVALID; + } else { + d = strtod(nptr, ); + if (nptr == ep || *ep != '\0') + error = INVALID; + else if ((d == -HUGE_VAL && errno == ERANGE) || d < minval) + error = TOOSMALL; + else if ((d == HUGE_VAL && errno == ERANGE) || d > maxval) + error = TOOLARGE; + } + if (errstrp != NULL) + *errstrp = ev[error].errstr; + errno = ev[error].err; + if (error) + d = 0; + + return (d); +} + int main(int argc, char *argv[]) { @@ -421,7 +471,7 @@ main(int argc, char *argv[]) const char *errstr; extern char *optarg; extern int optind; - double delay = 5; + double delay = 5, del; char *viewstr = NULL; @@ -475,9 +525,11 @@ main(int argc, char *argv[]) nflag = 1; break; case 's': - delay = atof(optarg); - if (delay <= 0) - delay = 5; + delay = strtodnum(optarg, 0, UINT32_MAX / 100, + ); + if (errstr != NULL) + errx(1, "-s \"%s\": delay value is %s", optarg, + errstr); break; case 'w': rawwidth = strtonum(optarg, 1, MAX_LINE_BUF-1, ); @@ -497,16 +549,16 @@ main(int argc, char *argv[]) argv += optind; if (argc == 1) { - double del = atof(argv[0]); - if (del == 0) + del = strtodnum(argv[0], 0, UINT32_MAX / 100, ); + if (errstr != NULL
Re: systat(1): improve parsing of delay value
On Mon, 2021-01-25 at 10:50 +0100, Martijn van Duren wrote: > On Mon, 2021-01-25 at 08:15 +, Nick Gasson wrote: > > Hi, > > > > I incorrectly ran "systat netstat -N" instead of "systat -N netstat" and > > got confused why it wasn't resolving host names. The -N gets parsed with > > atof to a 0s delay that is then clamped to 5s. The patch below instead > > prints an error if the delay cannot be parsed. I think the <= 0 case > > should also produce an error but I left the existing behaviour of > > setting it to 5s. > > Your diff fails for the simple case of "systat", because of your added > else case. It's also not completely clear to the end user why things > fail. > > I agree that failing loud on unparseable strings and just defaulting > back to the 5s is just stupid. So here's an updated diff that just > blatantly steals^Wborrows from strtonum. > > OK? > > martijn@ > That one was a little too rushed... It overlooked the internal "s" command and some minor additional testing shows that currently large delays are accepted and completely broken because of useconds_t overflow. I couldn't find something like USECONDS_MAX, so I took the next best thing: UINT32_MAX, where useconds_t is based on. This change limits delays to 4294 seconds, which already is the only reasonable value that would work for systat. martijn@ Index: main.c === RCS file: /cvs/src/usr.bin/systat/main.c,v retrieving revision 1.72 diff -u -p -r1.72 main.c --- main.c 12 Jan 2020 20:51:08 - 1.72 +++ main.c 25 Jan 2021 10:16:34 - @@ -40,9 +40,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -73,6 +75,7 @@ char uloadbuf[TIMEPOS]; int ucount(void); void usage(void); +double strtodnum(const char *, double, double, const char **); /* command prompt */ @@ -323,9 +326,14 @@ void cmd_delay(const char *buf) { double del; - del = atof(buf); + const char *errstr; - if (del > 0) { + if (buf[0] == '\0') + return; + del = strtodnum(buf, 0, UINT32_MAX / 100, ); + if (errstr != NULL) + error("s: \"%s\": delay value is %s", buf, errstr); + else { udelay = (useconds_t)(del * 100); gotsig_alarm = 1; naptime = del; @@ -414,6 +422,48 @@ gethz(void) hz = cinf.hz; } +#defineINVALID 1 +#defineTOOSMALL2 +#defineTOOLARGE3 + +double +strtodnum(const char *nptr, double minval, double maxval, const char **errstrp) +{ + double d = 0; + int error = 0; + char *ep; + struct errval { + const char *errstr; + int err; + } ev[4] = { + { NULL, 0 }, + { "invalid",EINVAL }, + { "too small", ERANGE }, + { "too large", ERANGE }, + }; + + ev[0].err = errno; + errno = 0; + if (minval > maxval) { + error = INVALID; + } else { + d = strtod(nptr, ); + if (nptr == ep || *ep != '\0') + error = INVALID; + else if ((d == -HUGE_VAL && errno == ERANGE) || d < minval) + error = TOOSMALL; + else if ((d == HUGE_VAL && errno == ERANGE) || d > maxval) + error = TOOLARGE; + } + if (errstrp != NULL) + *errstrp = ev[error].errstr; + errno = ev[error].err; + if (error) + d = 0; + + return (d); +} + int main(int argc, char *argv[]) { @@ -475,9 +525,11 @@ main(int argc, char *argv[]) nflag = 1; break; case 's': - delay = atof(optarg); - if (delay <= 0) - delay = 5; + delay = strtodnum(optarg, 0, UINT32_MAX / 100, + ); + if (errstr != NULL) + errx(1, "-s \"%s\": delay value is %s", optarg, + errstr); break; case 'w': rawwidth = strtonum(optarg, 1, MAX_LINE_BUF-1, ); @@ -497,16 +549,14 @@ main(int argc, char *argv[]) argv += optind; if (argc == 1) { - double del = atof(argv[0]); - if (del == 0) + delay = strtodnum(argv[0], 0, UINT32_MAX / 100, ); + if (errstr != NULL) viewstr = argv[0]; - else -
Re: systat(1): improve parsing of delay value
On Mon, 2021-01-25 at 08:15 +, Nick Gasson wrote: > Hi, > > I incorrectly ran "systat netstat -N" instead of "systat -N netstat" and > got confused why it wasn't resolving host names. The -N gets parsed with > atof to a 0s delay that is then clamped to 5s. The patch below instead > prints an error if the delay cannot be parsed. I think the <= 0 case > should also produce an error but I left the existing behaviour of > setting it to 5s. Your diff fails for the simple case of "systat", because of your added else case. It's also not completely clear to the end user why things fail. I agree that failing loud on unparseable strings and just defaulting back to the 5s is just stupid. So here's an updated diff that just blatantly steals^Wborrows from strtonum. OK? martijn@ Index: main.c === RCS file: /cvs/src/usr.bin/systat/main.c,v retrieving revision 1.72 diff -u -p -r1.72 main.c --- main.c 12 Jan 2020 20:51:08 - 1.72 +++ main.c 25 Jan 2021 09:48:44 - @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -414,6 +415,48 @@ gethz(void) hz = cinf.hz; } +#defineINVALID 1 +#defineTOOSMALL2 +#defineTOOLARGE3 + +double +strtodnum(const char *nptr, double minval, double maxval, const char **errstrp) +{ + double d = 0; + int error = 0; + char *ep; + struct errval { + const char *errstr; + int err; + } ev[4] = { + { NULL, 0 }, + { "invalid",EINVAL }, + { "too small", ERANGE }, + { "too large", ERANGE }, + }; + + ev[0].err = errno; + errno = 0; + if (minval > maxval) { + error = INVALID; + } else { + d = strtod(nptr, ); + if (nptr == ep || *ep != '\0') + error = INVALID; + else if ((d == -HUGE_VAL && errno == ERANGE) || d < minval) + error = TOOSMALL; + else if ((d == HUGE_VAL && errno == ERANGE) || d > maxval) + error = TOOLARGE; + } + if (errstrp != NULL) + *errstrp = ev[error].errstr; + errno = ev[error].err; + if (error) + d = 0; + + return (d); +} + int main(int argc, char *argv[]) { @@ -475,9 +518,9 @@ main(int argc, char *argv[]) nflag = 1; break; case 's': - delay = atof(optarg); - if (delay <= 0) - delay = 5; + delay = strtodnum(optarg, 0, HUGE_VAL, ); + if (errstr != NULL) + errx(1, "-s %s: delay value is %s", optarg, errstr); break; case 'w': rawwidth = strtonum(optarg, 1, MAX_LINE_BUF-1, ); @@ -497,16 +540,14 @@ main(int argc, char *argv[]) argv += optind; if (argc == 1) { - double del = atof(argv[0]); - if (del == 0) + delay = strtodnum(argv[0], 0, HUGE_VAL, ); + if (errstr != NULL) viewstr = argv[0]; - else - delay = del; } else if (argc == 2) { viewstr = argv[0]; - delay = atof(argv[1]); - if (delay <= 0) - delay = 5; + delay = strtodnum(optarg, 0, HUGE_VAL, ); + if (errstr != NULL) + errx(1, "-s %s: delay value is %s", optarg, errstr); } udelay = (useconds_t)(delay * 100.0);
snmpd: remove print_{verbose,debug}
Nothing seems to use them and I see no reason in the forseeable future to start using them. OK? martijn@ Index: snmpd.h === RCS file: /cvs/src/usr.sbin/snmpd/snmpd.h,v retrieving revision 1.91 diff -u -p -r1.91 snmpd.h --- snmpd.h 22 Jan 2021 06:33:26 - 1.91 +++ snmpd.h 24 Jan 2021 13:48:15 - @@ -780,8 +780,6 @@ ssize_t sendtofrom(int, void *, size_t, socklen_t, struct sockaddr *, socklen_t); ssize_t recvfromto(int, void *, size_t, int, struct sockaddr *, socklen_t *, struct sockaddr *, socklen_t *); -voidprint_debug(const char *, ...); -voidprint_verbose(const char *, ...); const char *log_in6addr(const struct in6_addr *); const char *print_host(struct sockaddr_storage *, char *, size_t); Index: util.c === RCS file: /cvs/src/usr.sbin/snmpd/util.c,v retrieving revision 1.10 diff -u -p -r1.10 util.c --- util.c 30 Jun 2020 17:11:49 - 1.10 +++ util.c 24 Jan 2021 13:48:15 - @@ -152,30 +152,6 @@ recvfromto(int s, void *buf, size_t len, return (ret); } -void -print_debug(const char *emsg, ...) -{ - va_list ap; - - if (log_getverbose() > 2) { - va_start(ap, emsg); - vfprintf(stderr, emsg, ap); - va_end(ap); - } -} - -void -print_verbose(const char *emsg, ...) -{ - va_list ap; - - if (log_getverbose()) { - va_start(ap, emsg); - vfprintf(stderr, emsg, ap); - va_end(ap); - } -} - const char * log_in6addr(const struct in6_addr *addr) {
Re: snmpd(8): Remove traphandler process attempt 2
ping On Tue, 2021-01-05 at 22:24 +0100, Martijn van Duren wrote: > With the traphandler code beaten into submission I was able to keep the > traphandler process removal diff more manageable. This diff does a > couple things. > - "listen on" now accepts any combination of read, write and notify. > This combination removes the traphandler dependency on the generic > listen on statement, which allows an admin to run snmpd in > traphandler-only mode. This will break existing traphandler setups, > but considering the benefit of not having the two functionalities > mixed is worth it to me and is fully intentional. > The names are choosen based on viewType names from RFC 3415 (VACM) > - The traphandler process is gone, resulting in a single dispatcher > responsible for the initial parsing of the packets, which allows for > better msg checking in the future. The current traphandler process > does nothing more then what snmpe already does, but a lot crappier: > the pledge was also too wide. > - We now check incoming trap packets against "trap community". The > current code does no community verification. > - trap parsing errors are now shown in a similar fashion to the read > and write requests. > - traphandler now support tcp!!! > - Minus 65 LoC > > With this change regress requires the following diff: > Index: snmpd.sh > === > RCS file: /cvs/src/regress/usr.sbin/snmpd/snmpd.sh,v > retrieving revision 1.12 > diff -u -p -r1.12 snmpd.sh > --- snmpd.sh8 Aug 2020 11:06:40 - 1.12 > +++ snmpd.sh5 Jan 2021 20:46:19 - > @@ -65,6 +65,7 @@ cat > ${OBJDIR}/snmpd.conf < # This is config template (1) for snmpd regression testing > # Restrict daemon to listen on localhost only > listen on 127.0.0.1 > +listen on 127.0.0.1 notify > listen on ::1 > > # Specify a number of trap receivers > > OK? > > martijn@ > > Index: parse.y > === > RCS file: /cvs/src/usr.sbin/snmpd/parse.y,v > retrieving revision 1.62 > diff -u -p -r1.62 parse.y > --- parse.y 30 Oct 2020 07:43:48 - 1.62 > +++ parse.y 5 Jan 2021 21:22:12 - > @@ -94,11 +94,10 @@ char*symget(const char *); > struct snmpd *conf = NULL; > static int errors = 0; > static struct usmuser *user = NULL; > -static char*snmpd_port = SNMPD_PORT; > > int host(const char *, const char *, int, > struct sockaddr_storage *, int); > -int listen_add(struct sockaddr_storage *, int); > +int listen_add(struct sockaddr_storage *, int, int); > > typedef struct { > union { > @@ -121,7 +120,7 @@ typedef struct { > %} > > %token INCLUDE > -%token LISTEN ON > +%token LISTEN ON READ WRITE NOTIFY > %token SYSTEM CONTACT DESCR LOCATION NAME OBJECTID SERVICES RTFILTER > %token READONLY READWRITE OCTETSTRING INTEGER COMMUNITY TRAP RECEIVER > %token SECLEVEL NONE AUTH ENC USER AUTHKEY ENCKEY ERROR DISABLED > @@ -130,7 +129,7 @@ typedef struct { > %token NUMBER > %typehostcmn > %typesrcaddr port > -%typeoptwrite yesno seclevel > +%typeoptwrite yesno seclevel listenopt listenopts > %type objtype cmd > %type oid hostoid trapoid > %type auth > @@ -281,54 +280,74 @@ listenproto : UDP listen_udp > | TCP listen_tcp > | listen_udp > > -listen_udp : STRING port { > +listenopts : /* empty */ { $$ = 0; } > + | listenopts listenopt { $$ |= $2; } > + ; > + > +listenopt : READ { $$ = ADDRESS_FLAG_READ; } > + | WRITE { $$ = ADDRESS_FLAG_WRITE; } > + | NOTIFY { $$ = ADDRESS_FLAG_NOTIFY; } > + ; > + > +listen_udp : STRING port listenopts{ > struct sockaddr_storage ss[16]; > int nhosts, i; > + char *port = $2; > + > + if (port == NULL) { > + if ($3 == ADDRESS_FLAG_NOTIFY) > + port = SNMPTRAP_PORT; > + else > + port = SNMP_PORT; > + } > > - nhosts = host($1, $2, SOCK_DGRAM, ss, nitems(ss)); > + nhosts = host($1, port, SOCK_DGRAM, ss, nitems(ss)); &
ber: mandate end of sequence/set
Right now we don't check for end of sequence or set in most ber places. This means that valid ber, but invalid ASN1 could be passed down the codepath. Since most of the parsing is done with ober_scanf_elements I think it would be a good idea to add a sequence limiter. rob@ likes the idea and suggested '$'. This allows for the following syntax (e.g. varbind parsing): for (; elm != NULL; elm = elm->be_next) { if (ober_scanf_elements(elm, "{oe$}", , ) == -1) goto fail; } OK? martijn@ Index: ber.c === RCS file: /cvs/src/lib/libutil/ber.c,v retrieving revision 1.17 diff -u -p -r1.17 ber.c --- ber.c 3 Sep 2020 19:09:57 - 1.17 +++ ber.c 8 Jan 2021 15:22:50 - @@ -684,9 +684,14 @@ ober_scanf_elements(struct ber_element * va_start(ap, fmt); while (*fmt) { - if (ber == NULL && *fmt != '}' && *fmt != ')') + if (ber == NULL && *fmt != '$' && *fmt != '}' && *fmt != ')') goto fail; switch (*fmt++) { + case '$': + if (ber != NULL) + goto fail; + ret++; + continue; case 'B': ptr = va_arg(ap, void **); len = va_arg(ap, size_t *); Index: ober_get_string.3 === RCS file: /cvs/src/lib/libutil/ober_get_string.3,v retrieving revision 1.2 diff -u -p -r1.2 ober_get_string.3 --- ober_get_string.3 25 Oct 2019 04:00:10 - 1.2 +++ ober_get_string.3 8 Jan 2021 15:22:50 - @@ -81,6 +81,7 @@ per byte. The following bytes are valid: .Bl -column -offset indent bytes ober_get_enumerated() "1: struct ber_element **" .It Sy byte Ta Sy function Ta Sy arguments +.It $ Ta see below Ta 0 .It B Ta Fn ober_get_bitstring Ta 2: Vt void ** , size_t * .It b Ta Fn ober_get_booleanTa 1: Vt int * .It d Ta Fn ober_get_integerTa 1: Vt int * @@ -121,6 +122,9 @@ For .Sq t , the class and type of the element are stored in the two corresponding variables, but if the element contains a value, that value is ignored. +A +.Sq $ +mandates the end of a sequence or set. .Pp For an opening parenthesis or brace, it is checked that the element is a sequence or a set, and parsing continues with its children.
snmpd(8): Remove traphandler process attempt 2
With the traphandler code beaten into submission I was able to keep the traphandler process removal diff more manageable. This diff does a couple things. - "listen on" now accepts any combination of read, write and notify. This combination removes the traphandler dependency on the generic listen on statement, which allows an admin to run snmpd in traphandler-only mode. This will break existing traphandler setups, but considering the benefit of not having the two functionalities mixed is worth it to me and is fully intentional. The names are choosen based on viewType names from RFC 3415 (VACM) - The traphandler process is gone, resulting in a single dispatcher responsible for the initial parsing of the packets, which allows for better msg checking in the future. The current traphandler process does nothing more then what snmpe already does, but a lot crappier: the pledge was also too wide. - We now check incoming trap packets against "trap community". The current code does no community verification. - trap parsing errors are now shown in a similar fashion to the read and write requests. - traphandler now support tcp!!! - Minus 65 LoC With this change regress requires the following diff: Index: snmpd.sh === RCS file: /cvs/src/regress/usr.sbin/snmpd/snmpd.sh,v retrieving revision 1.12 diff -u -p -r1.12 snmpd.sh --- snmpd.sh8 Aug 2020 11:06:40 - 1.12 +++ snmpd.sh5 Jan 2021 20:46:19 - @@ -65,6 +65,7 @@ cat > ${OBJDIR}/snmpd.conf < NUMBER %typehostcmn %typesrcaddr port -%typeoptwrite yesno seclevel +%typeoptwrite yesno seclevel listenopt listenopts %type objtype cmd %type oid hostoid trapoid %type auth @@ -281,54 +280,74 @@ listenproto : UDP listen_udp | TCP listen_tcp | listen_udp -listen_udp : STRING port { +listenopts : /* empty */ { $$ = 0; } + | listenopts listenopt { $$ |= $2; } + ; + +listenopt : READ { $$ = ADDRESS_FLAG_READ; } + | WRITE { $$ = ADDRESS_FLAG_WRITE; } + | NOTIFY { $$ = ADDRESS_FLAG_NOTIFY; } + ; + +listen_udp : STRING port listenopts{ struct sockaddr_storage ss[16]; int nhosts, i; + char *port = $2; + + if (port == NULL) { + if ($3 == ADDRESS_FLAG_NOTIFY) + port = SNMPTRAP_PORT; + else + port = SNMP_PORT; + } - nhosts = host($1, $2, SOCK_DGRAM, ss, nitems(ss)); + nhosts = host($1, port, SOCK_DGRAM, ss, nitems(ss)); if (nhosts < 1) { yyerror("invalid address: %s", $1); free($1); - if ($2 != snmpd_port) - free($2); + free($2); YYERROR; } if (nhosts > (int)nitems(ss)) log_warn("%s:%s resolves to more than %zu hosts", - $1, $2, nitems(ss)); + $1, port, nitems(ss)); free($1); - if ($2 != snmpd_port) - free($2); + free($2); for (i = 0; i < nhosts; i++) { - if (listen_add(&(ss[i]), SOCK_DGRAM) == -1) { + if (listen_add(&(ss[i]), SOCK_DGRAM, $3) == -1) { yyerror("calloc"); YYERROR; } } } -listen_tcp : STRING port { +listen_tcp : STRING port listenopts{ struct sockaddr_storage ss[16]; int nhosts, i; + char *port = $2; - nhosts = host($1, $2, SOCK_STREAM, ss, nitems(ss)); + if (port == NULL) { + if ($3 == ADDRESS_FLAG_NOTIFY) + port = SNMPTRAP_PORT; + else + port = SNMP_PORT; + } + nhosts = host($1, port, SOCK_STREAM, ss, nitems(ss)); if (nhosts < 1) { yyerror("invalid address: %s", $1); free($1); - if ($2 != snmpd_port) -
libagentx: Add notify (snmp trap) support
__VA_ARGS__ }, \ (sizeof((uint32_t []) { __VA_ARGS__ }) / sizeof(uint32_t)) @@ -147,3 +150,36 @@ void agentx_varbind_set_index_object(str struct agentx_index *, struct agentx_object *); void agentx_varbind_set_index_ipaddress(struct agentx_varbind *, struct agentx_index *, const struct in_addr *); + +struct agentx_notify *agentx_notify(struct agentx_context *, const uint32_t[], +size_t); +void agentx_notify_integer(struct agentx_notify *, const uint32_t[], size_t, +int32_t); +void agentx_notify_string(struct agentx_notify *, const uint32_t[], size_t, +const char *); +void agentx_notify_nstring(struct agentx_notify *, const uint32_t[], size_t, +const char *, size_t); +void agentx_notify_printf(struct agentx_notify *, const uint32_t[], size_t, +const char *, ...) __attribute__((__format__ (printf, 4, 5))); +void agentx_notify_null(struct agentx_notify *, const uint32_t[], size_t); +void agentx_notify_oid(struct agentx_notify *, const uint32_t[], size_t, +const uint32_t[], size_t); +void agentx_notify_object(struct agentx_notify *, const uint32_t[], size_t, +struct agentx_object *); +void agentx_notify_index(struct agentx_notify *, const uint32_t[], size_t, +struct agentx_index *); +void agentx_notify_ipaddress(struct agentx_notify *, const uint32_t[], size_t, +const struct in_addr *); +void agentx_notify_counter32(struct agentx_notify *, const uint32_t[], size_t, +uint32_t); +void agentx_notify_gauge32(struct agentx_notify *, const uint32_t[], size_t, +uint32_t); +void agentx_notify_unsigned32(struct agentx_notify *, const uint32_t[], size_t, +uint32_t); +void agentx_notify_timeticks(struct agentx_notify *, const uint32_t[], size_t, +uint32_t); +void agentx_notify_opaque(struct agentx_notify *, const uint32_t[], size_t, +const char *, size_t); +void agentx_notify_counter64(struct agentx_notify *, const uint32_t[], size_t, +uint64_t); +void agentx_notify_send(struct agentx_notify *); Index: agentx_internal.h === RCS file: /cvs/src/lib/libagentx/agentx_internal.h,v retrieving revision 1.2 diff -u -p -r1.2 agentx_internal.h --- agentx_internal.h 26 Oct 2020 16:02:16 - 1.2 +++ agentx_internal.h 4 Jan 2021 17:34:01 - @@ -67,6 +67,7 @@ struct agentx_context { enum agentx_dstate axc_dstate; TAILQ_HEAD(, agentx_agentcaps) axc_agentcaps; TAILQ_HEAD(, agentx_region) axc_regions; + TAILQ_HEAD(, agentx_notify) axc_notifications; RB_HEAD(axc_objects, agentx_object) axc_objects; TAILQ_ENTRY(agentx_context) axc_axs_contexts; }; Index: agentx_notify.3 === RCS file: agentx_notify.3 diff -N agentx_notify.3 --- /dev/null 1 Jan 1970 00:00:00 - +++ agentx_notify.3 4 Jan 2021 17:34:01 - @@ -0,0 +1,177 @@ +.\" $OpenBSD: agentx.3,v 1.5 2020/12/03 22:47:21 jmc Exp $ +.\" +.\" Copyright (c) 2020 Martijn van Duren +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.Dd $Mdocdate: December 3 2020 $ +.Dt AGENTX_NOTIFY 3 +.Os +.Sh NAME +.Nm agentx_notify +.Nm agentx_notify_integer +.Nm agentx_notify_string +.Nm agentx_notify_nstring +.Nm agentx_notify_printf +.Nm agentx_notify_null +.Nm agentx_notify_oid +.Nm agentx_notify_object +.Nm agentx_notify_index +.Nm agentx_notify_ipaddress +.Nm agentx_notify_counter32 +.Nm agentx_notify_gauge32 +.Nm agentx_notify_unsigned32 +.Nm agentx_notify_timeticks +.Nm agentx_notify_opaque +.Nm agentx_notify_counter64 +.Nm agentx_notify_send +.Sh SYNOPSIS +.In agentx.h +.Ft struct agentx_notify * +.Fo agentx_notify +.Fa "struct agentx_context *axc" "const uint32_t trapoid[]" "size_t oidlen" +.Fc +.Ft void +.Fo agentx_notify_integer +.Fa "struct agentx_notify *axn" "const uint32_t oid[]" "size_t oidlen" +.Fa "int32_t value" +.Fc +.Ft void +.Fo agentx_notify_string +.Fa "struct agentx_notify *axn" "const uint32_t oid[]" "size_t oidlen" +.Fa "const char *string" +.Fc +.Ft void +.Fo agentx_notify_nstring +.Fa "struct agentx_notify *ax
Re: snmp - remove BER_TYPE_BOOLEAN
On Mon, 2021-01-04 at 08:15 +0100, Rob Schmersel wrote: > On Sun, 03 Jan 2021 21:59:57 +0100 > Martijn van Duren wrote: > > > ping > > > > On Mon, 2020-12-14 at 12:13 +0100, Martijn van Duren wrote: > > > I can't find any reference in RFC2578 for a boolean type, nor have I > > > seen it in the wild and the TruthValue diff I just committed give > > > me a strong indication that this was added without any real reason. > > > > > > OK to remove? > > > > > > martijn@ > > > > > > Index: usr.bin/snmp/smi.c > > > === > > > RCS file: /cvs/src/usr.bin/snmp/smi.c,v > > > retrieving revision 1.13 > > > diff -u -p -r1.13 smi.c > > > --- usr.bin/snmp/smi.c 14 Dec 2020 07:44:26 - 1.13 > > > +++ usr.bin/snmp/smi.c 14 Dec 2020 11:12:29 - > > > @@ -95,9 +95,6 @@ smi_debug_elements(struct ber_element *r > > > case BER_TYPE_EOC: > > > fprintf(stderr, "end-of-content"); > > > break; > > > - case BER_TYPE_BOOLEAN: > > > - fprintf(stderr, "boolean"); > > > - break; > > > case BER_TYPE_INTEGER: > > > fprintf(stderr, "integer"); > > > break; > > > @@ -196,9 +193,6 @@ smi_debug_elements(struct ber_element *r > > > goto invalid; > > > > > > switch (root->be_encoding) { > > > - case BER_TYPE_BOOLEAN: > > > - fprintf(stderr, "%s", value); > > > - break; > > > case BER_TYPE_INTEGER: > > > case BER_TYPE_ENUMERATED: > > > fprintf(stderr, "value %s", value); > > > @@ -255,7 +249,6 @@ smi_print_element(struct ber_oid *oid, s > > > struct textconv tckey; > > > size_t len, i, slen; > > > long long v, ticks; > > > - int d; > > > int is_hex = 0, ret; > > > struct ber_oid o; > > > char strbuf[BUFSIZ]; > > > @@ -277,17 +270,6 @@ smi_print_element(struct ber_oid *oid, s > > > } > > > > > > switch (root->be_encoding) { > > > - case BER_TYPE_BOOLEAN: > > > - if (ober_get_boolean(root, ) == -1) > > > - goto fail; > > > - if (print_hint) { > > > - if (asprintf(, "INTEGER: %s(%d)", > > > - d ? "true" : "false", d) == -1) > > > - goto fail; > > > - } else > > > - if (asprintf(, "%s", d ? "true" : > > > "false") == -1) > > > - goto fail; > > > - break; > > > case BER_TYPE_INTEGER: > > > case BER_TYPE_ENUMERATED: > > > if (ober_get_integer(root, ) == -1) > > > Index: usr.sbin/snmpd/smi.c > > > === > > > RCS file: /cvs/src/usr.sbin/snmpd/smi.c,v > > > retrieving revision 1.27 > > > diff -u -p -r1.27 smi.c > > > --- usr.sbin/snmpd/smi.c24 Oct 2019 12:39:27 - 1.27 > > > +++ usr.sbin/snmpd/smi.c14 Dec 2020 11:12:29 - > > > @@ -317,9 +317,6 @@ smi_debug_elements(struct ber_element *r > > > case BER_TYPE_EOC: > > > fprintf(stderr, "end-of-content"); > > > break; > > > - case BER_TYPE_BOOLEAN: > > > - fprintf(stderr, "boolean"); > > > - break; > > > case BER_TYPE_INTEGER: > > > fprintf(stderr, "integer"); > > > break; > > > @@ -417,9 +414,6 @@ smi_debug_elements(struct ber_element *r > > > goto invalid; > > > > > > switch (root->be_encoding) { > > > - case BER_TYPE_BOOLEAN: > > > - fprintf(stderr, "%s", value); > > > - break; > > > case BE
Re: snmp - remove BER_TYPE_BOOLEAN
ping On Mon, 2020-12-14 at 12:13 +0100, Martijn van Duren wrote: > I can't find any reference in RFC2578 for a boolean type, nor have I > seen it in the wild and the TruthValue diff I just committed give me a > strong indication that this was added without any real reason. > > OK to remove? > > martijn@ > > Index: usr.bin/snmp/smi.c > === > RCS file: /cvs/src/usr.bin/snmp/smi.c,v > retrieving revision 1.13 > diff -u -p -r1.13 smi.c > --- usr.bin/snmp/smi.c 14 Dec 2020 07:44:26 - 1.13 > +++ usr.bin/snmp/smi.c 14 Dec 2020 11:12:29 - > @@ -95,9 +95,6 @@ smi_debug_elements(struct ber_element *r > case BER_TYPE_EOC: > fprintf(stderr, "end-of-content"); > break; > - case BER_TYPE_BOOLEAN: > - fprintf(stderr, "boolean"); > - break; > case BER_TYPE_INTEGER: > fprintf(stderr, "integer"); > break; > @@ -196,9 +193,6 @@ smi_debug_elements(struct ber_element *r > goto invalid; > > switch (root->be_encoding) { > - case BER_TYPE_BOOLEAN: > - fprintf(stderr, "%s", value); > - break; > case BER_TYPE_INTEGER: > case BER_TYPE_ENUMERATED: > fprintf(stderr, "value %s", value); > @@ -255,7 +249,6 @@ smi_print_element(struct ber_oid *oid, s > struct textconv tckey; > size_t len, i, slen; > long long v, ticks; > - int d; > int is_hex = 0, ret; > struct ber_oid o; > char strbuf[BUFSIZ]; > @@ -277,17 +270,6 @@ smi_print_element(struct ber_oid *oid, s > } > > switch (root->be_encoding) { > - case BER_TYPE_BOOLEAN: > - if (ober_get_boolean(root, ) == -1) > - goto fail; > - if (print_hint) { > - if (asprintf(, "INTEGER: %s(%d)", > - d ? "true" : "false", d) == -1) > - goto fail; > - } else > - if (asprintf(, "%s", d ? "true" : "false") == -1) > - goto fail; > - break; > case BER_TYPE_INTEGER: > case BER_TYPE_ENUMERATED: > if (ober_get_integer(root, ) == -1) > Index: usr.sbin/snmpd/smi.c > === > RCS file: /cvs/src/usr.sbin/snmpd/smi.c,v > retrieving revision 1.27 > diff -u -p -r1.27 smi.c > --- usr.sbin/snmpd/smi.c24 Oct 2019 12:39:27 - 1.27 > +++ usr.sbin/snmpd/smi.c14 Dec 2020 11:12:29 - > @@ -317,9 +317,6 @@ smi_debug_elements(struct ber_element *r > case BER_TYPE_EOC: > fprintf(stderr, "end-of-content"); > break; > - case BER_TYPE_BOOLEAN: > - fprintf(stderr, "boolean"); > - break; > case BER_TYPE_INTEGER: > fprintf(stderr, "integer"); > break; > @@ -417,9 +414,6 @@ smi_debug_elements(struct ber_element *r > goto invalid; > > switch (root->be_encoding) { > - case BER_TYPE_BOOLEAN: > - fprintf(stderr, "%s", value); > - break; > case BER_TYPE_INTEGER: > case BER_TYPE_ENUMERATED: > fprintf(stderr, "value %s", value); > @@ -473,17 +467,10 @@ smi_print_element(struct ber_element *ro > char*str = NULL, *buf, *p; > size_t len, i; > long long v; > - int d; > struct ber_oid o; > char strbuf[BUFSIZ]; > > switch (root->be_encoding) { > - case BER_TYPE_BOOLEAN: > - if (ober_get_boolean(root, ) == -1) > - goto fail; > - if (asprintf(, "%s(%d)", d ? "true" : "false", d) == -1) > - goto fail; > - break; > case BER_TYPE_INTEGER: > case BER_TYPE_ENUMERATED: > if (ober_get_integer(root, ) == -1) > >
snmpd(8) make traphandler more secure
Right now snmpd's traphandler_parse and traphandler_v1translate are just weird to me and do very little ASN1 checking. Since I want to remove the traphandler process anyway and the current code structue is in the way, this diff is a logical first step towards that goal. The new traphandler_v1translate should now be properly build around RFC3584 section 3.1 and I've choosen to disable the proxy addition, since we don't forward it to another host, but it does work for me and can be enabled for this scenario if people feel strong about it. Another major change people should be aware of is when running snmpd with -N the sysUpTime and snmpTrapOID parameters will now be numerical (where these were hardcode printed before). A minor thing people should be aware of is that the new code is a lot more strict on its ASN1 validation, so if you use it with crappy SNMP entities that send broken packets, you're out of luck. Also, traphandler_parse is now called only once, which should help in my next step in removing the traphandler process altogether. OK? martijn@ Index: traphandler.c === RCS file: /cvs/src/usr.sbin/snmpd/traphandler.c,v retrieving revision 1.18 diff -u -p -r1.18 traphandler.c --- traphandler.c 6 Sep 2020 15:51:28 - 1.18 +++ traphandler.c 3 Jan 2021 14:20:17 - @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -50,13 +51,12 @@ int traphandler_bind(struct address *); voidtraphandler_recvmsg(int, short, void *); int traphandler_priv_recvmsg(struct privsep_proc *, struct imsg *); int traphandler_fork_handler(struct privsep_proc *, struct imsg *); -int traphandler_parse(char *, size_t, struct ber_element **, - struct ber_element **, u_int *, struct ber_oid *); -voidtraphandler_v1translate(struct ber_oid *, u_int, u_int); - +int traphandler_parse(struct ber_element *, char *, struct sockaddr *); +struct ber_element * +traphandler_v1translate(struct ber_element *, char *, int); int trapcmd_cmp(struct trapcmd *, struct trapcmd *); voidtrapcmd_exec(struct trapcmd *, struct sockaddr *, - struct ber_element *, char *, u_int); + struct ber_element *); char *traphandler_hostname(struct sockaddr *, int); @@ -102,7 +102,7 @@ traphandler_init(struct privsep *ps, str /* listen for SNMP trap messages */ TAILQ_FOREACH(h, >sc_addresses, entry) { event_set(>ev, h->fd, EV_READ|EV_PERSIST, - traphandler_recvmsg, ps); + traphandler_recvmsg, NULL); event_add(>ev, NULL); } } @@ -180,104 +180,216 @@ snmpd_dispatch_traphandler(int fd, struc void traphandler_recvmsg(int fd, short events, void *arg) { - struct privsep *ps = arg; + struct ber ber = {0}; + struct ber_element *msg = NULL, *pdu; char buf[8196]; - struct iovec iov[2]; struct sockaddr_storage ss; socklen_tslen; ssize_t n; - struct ber_element *req, *iter; - struct ber_oid trapoid; - u_intuptime; + int vers; + char*community; slen = sizeof(ss); if ((n = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *), )) == -1) return; - if (traphandler_parse(buf, n, , , , ) == -1) - goto done; + ober_set_application(, smi_application); + ober_set_readbuf(, buf, n); - iov[0].iov_base = - iov[0].iov_len = ss.ss_len; - iov[1].iov_base = buf; - iov[1].iov_len = n; + if ((msg = ober_read_elements(, NULL)) == NULL) + goto parsefail; - /* Forward it to the parent process */ - if (proc_composev(ps, PROC_PARENT, IMSG_ALERT, iov, 2) == -1) - goto done; + if (ober_scanf_elements(msg, "{dse", , , ) == -1) + goto parsefail; - done: - if (req != NULL) - ober_free_elements(req); - return; + switch (vers) { + case SNMP_V1: + if (pdu->be_type != SNMP_C_TRAP) + goto parsefail; + break; + case SNMP_V2: + if (pdu->be_type != SNMP_C_TRAPV2) + goto parsefail; + break; + default: + goto parsefail; + } + + (void)traphandler_parse(pdu, community, (struct sockaddr *)); + +parsefail: + ober_free(); + if (msg != NULL) + ober_free_elements(msg); } /* * Validate received message */ int -traphandler_parse(char *buf, size_t n, struct ber_element **req, -struct ber_element **vbinds, u_int *uptime, struct ber_oid *trapoid) +traphandler_parse(struct ber_element *pdu, char
Re: [diff] src/usr.sbin/smtpd: change process names
On Tue, 2020-12-29 at 08:57 +0100, Giovanni Bechis wrote: > On 12/20/20 12:21 AM, gil...@poolp.org wrote: > > December 19, 2020 11:26 PM, "Martijn van Duren" > > wrote: > > > > > Personally I'd rather wait to keep the names in sync, especially since > > > it's an easy 2 line diff that can easily be incorperated in the bigger > > > thing. But it's not something I'm going to loose sleep over if others > > > thing it can go in right now. > > > > > > > Fair enough :-) > > > > Below is the diff that changes all references to pony into dispatcher. > > > > I didn't rename pony.c to dispatcher.c as this would break the diff, but if > > this gets > > committed I'll submit a diff for the rename + Makefile bit > > > I like it and it reads OK for me. > Giovanni > Here's the final diff that moves pony.c to dispatcher.c and (including in smtpd.h). OK? martijn@ Index: bounce.c === RCS file: /cvs/src/usr.sbin/smtpd/bounce.c,v retrieving revision 1.82 diff -u -p -r1.82 bounce.c --- bounce.c24 Apr 2020 11:34:07 - 1.82 +++ bounce.c30 Dec 2020 08:25:55 - @@ -290,7 +290,7 @@ bounce_drain() } log_debug("debug: bounce: requesting new enqueue socket..."); - m_compose(p_pony, IMSG_QUEUE_SMTP_SESSION, 0, 0, -1, NULL, 0); + m_compose(p_dispatcher, IMSG_QUEUE_SMTP_SESSION, 0, 0, -1, NULL, 0); running += 1; } Index: ca.c === RCS file: /cvs/src/usr.sbin/smtpd/ca.c,v retrieving revision 1.36 diff -u -p -r1.36 ca.c --- ca.c21 Sep 2019 07:46:53 - 1.36 +++ ca.c30 Dec 2020 08:25:55 - @@ -110,10 +110,10 @@ ca(void) config_peer(PROC_CONTROL); config_peer(PROC_PARENT); - config_peer(PROC_PONY); + config_peer(PROC_DISPATCHER); /* Ignore them until we get our config */ - mproc_disable(p_pony); + mproc_disable(p_dispatcher); if (pledge("stdio", NULL) == -1) err(1, "pledge"); @@ -246,7 +246,7 @@ ca_imsg(struct mproc *p, struct imsg *im ca_init(); /* Start fulfilling requests */ - mproc_enable(p_pony); + mproc_enable(p_dispatcher); return; case IMSG_CTL_VERBOSE: @@ -385,7 +385,7 @@ rsae_send_imsg(int flen, const unsigned if (n == 0) break; - log_imsg(PROC_PONY, PROC_CA, ); + log_imsg(PROC_DISPATCHER, PROC_CA, ); switch (imsg.hdr.type) { case IMSG_CA_RSA_PRIVENC: @@ -393,7 +393,7 @@ rsae_send_imsg(int flen, const unsigned break; default: /* Another imsg is queued up in the buffer */ - pony_imsg(p_ca, ); + dispatcher_imsg(p_ca, ); imsg_free(); continue; } @@ -569,14 +569,14 @@ ecdsae_send_enc_imsg(const unsigned char if (n == 0) break; - log_imsg(PROC_PONY, PROC_CA, ); + log_imsg(PROC_DISPATCHER, PROC_CA, ); switch (imsg.hdr.type) { case IMSG_CA_ECDSA_SIGN: break; default: /* Another imsg is queued up in the buffer */ - pony_imsg(p_ca, ); + dispatcher_imsg(p_ca, ); imsg_free(); continue; } Index: config.c === RCS file: /cvs/src/usr.sbin/smtpd/config.c,v retrieving revision 1.51 diff -u -p -r1.51 config.c --- config.c18 Dec 2019 10:00:39 - 1.51 +++ config.c30 Dec 2020 08:25:55 - @@ -325,8 +325,8 @@ config_peer(enum smtp_proc_type proc) p = p_queue; else if (proc == PROC_SCHEDULER) p = p_scheduler; - else if (proc == PROC_PONY) - p = p_pony; + else if (proc == PROC_DISPATCHER) + p = p_dispatcher; else if (proc == PROC_CA) p = p_ca; else Index: control.c === RCS file: /cvs/src/usr.sbin/smtpd/control.c,v retrieving revision 1.125 diff -u -p -r1.125 control.c --- control.c 23 Sep 2020 19:11:50 - 1.125 +++
Re: smtpd: trim down on filter processes
On Sun, 2020-12-27 at 11:18 -0700, Theo de Raadt wrote: > fork_filter_process() does not feel like the right name for > the function anymore. > Why not? Right now we do fork and call system system in the child. With my diff we move to fork -> exec The fork part is most definitely still there. Or do you object to some other part of the name? > Take note the exit value of the process (as seen by wait elsewhere) will > be subtly differe after this conversion from system() to execve(). > Upon failure, rather than being 127, it is now 1. parent_sig_handler() for the SIGCHLD case does: if (WEXITSTATUS(status) != 0) { A little further down we also do: mda_sysexit = WEXITSTATUS(status); But mda_sysexit is only used for CHILD_MDA. So I don't see a reason why this subtle difference matters here. > > Martijn van Duren wrote: > > > Because filters use system(3) after forking we get 2 processes for every > > filter: one for waiting for system(3) to return and one running the actual > > filter. > > > > Since the extra smtpd process does absolutely nothing we can just as easily > > copy over what system(3) does internally for execve and call the shell > > command directly. > > > > OK? > > > > martijn@ > > > > Index: smtpd.c > > === > > RCS file: /cvs/src/usr.sbin/smtpd/smtpd.c,v > > retrieving revision 1.335 > > diff -u -p -r1.335 smtpd.c > > --- smtpd.c 23 Sep 2020 19:11:50 - 1.335 > > +++ smtpd.c 27 Dec 2020 17:39:02 - > > @@ -1304,7 +1304,9 @@ fork_filter_process(const char *name, co > > struct passwd *pw; > > struct group*gr; > > char exec[_POSIX_ARG_MAX]; > > + char*argp[] = { "sh", "-c", exec, NULL }; > > int execr; > > + extern char **environ; > > > > if (user == NULL) > > user = SMTPD_USER; > > @@ -1387,11 +1389,8 @@ fork_filter_process(const char *name, co > > */ > > if (read(STDERR_FILENO, , 1) != 0) > > errx(1, "lka didn't properly close write end of error > > socket"); > > - if (system(exec) == -1) > > - err(1, NULL); > > - > > - /* there's no successful exit from a processor */ > > - _exit(1); > > + execve(_PATH_BSHELL, argp, environ); > > + err(1, "execve"); > > } > > > > static void > > > >
smtpd: trim down on filter processes
Because filters use system(3) after forking we get 2 processes for every filter: one for waiting for system(3) to return and one running the actual filter. Since the extra smtpd process does absolutely nothing we can just as easily copy over what system(3) does internally for execve and call the shell command directly. OK? martijn@ Index: smtpd.c === RCS file: /cvs/src/usr.sbin/smtpd/smtpd.c,v retrieving revision 1.335 diff -u -p -r1.335 smtpd.c --- smtpd.c 23 Sep 2020 19:11:50 - 1.335 +++ smtpd.c 27 Dec 2020 17:39:02 - @@ -1304,7 +1304,9 @@ fork_filter_process(const char *name, co struct passwd *pw; struct group*gr; char exec[_POSIX_ARG_MAX]; + char*argp[] = { "sh", "-c", exec, NULL }; int execr; + extern char **environ; if (user == NULL) user = SMTPD_USER; @@ -1387,11 +1389,8 @@ fork_filter_process(const char *name, co */ if (read(STDERR_FILENO, , 1) != 0) errx(1, "lka didn't properly close write end of error socket"); - if (system(exec) == -1) - err(1, NULL); - - /* there's no successful exit from a processor */ - _exit(1); + execve(_PATH_BSHELL, argp, environ); + err(1, "execve"); } static void
Re: [diff] src/usr.sbin/smtpd: change process names
In that case fine by me. Anyone else want to chime in? On Sun, 2020-12-27 at 17:04 +, gil...@poolp.org wrote: > it's slightly different: > > ca is for "crypto agent" unsure if there's really an interest in renaming > internally, > furthermore there's a separate crypto API for encrypted queue so not > distinguishing > between crypto api and crypto agent might be confusing. > > Gilles > > > December 27, 2020 5:43 PM, "Martijn van Duren" > wrote: > > > This one reads OK to me, with one minor bikeshed: > > You rename klondike to crypto, but the internals still refer to CA > > everywhere. Wouldn't it be cleaner to leave klondike in step one and do > > a s/CA/CRYPTO/ in a second step so everything is in concent? > > Personally I prefer the name crypto over ca. > > > > martijn@ > > > > On Sat, 2020-12-19 at 23:21 +, gil...@poolp.org wrote: > > > > > December 19, 2020 11:26 PM, "Martijn van Duren" > > > wrote: > > > > > > Personally I'd rather wait to keep the names in sync, especially since > > > it's an easy 2 line diff that can easily be incorperated in the bigger > > > thing. But it's not something I'm going to loose sleep over if others > > > thing it can go in right now. > > > > > > Fair enough :-) > > > > > > Below is the diff that changes all references to pony into dispatcher. > > > > > > I didn't rename pony.c to dispatcher.c as this would break the diff, but > > > if this gets > > > committed I'll submit a diff for the rename + Makefile bit > > > > > > diff --git a/usr.sbin/smtpd/bounce.c b/usr.sbin/smtpd/bounce.c > > > index e6fc55780a1..455da6ff8b1 100644 > > > --- a/usr.sbin/smtpd/bounce.c > > > +++ b/usr.sbin/smtpd/bounce.c > > > @@ -290,7 +290,7 @@ bounce_drain() > > > } > > > > > > log_debug("debug: bounce: requesting new enqueue socket..."); > > > - m_compose(p_pony, IMSG_QUEUE_SMTP_SESSION, 0, 0, -1, > > > NULL, 0); > > > + m_compose(p_dispatcher, IMSG_QUEUE_SMTP_SESSION, 0, 0, > > > -1, NULL, 0); > > > > > > running += 1; > > > } > > > diff --git a/usr.sbin/smtpd/ca.c b/usr.sbin/smtpd/ca.c > > > index fdc177e28b3..0299ee6cecc 100644 > > > --- a/usr.sbin/smtpd/ca.c > > > +++ b/usr.sbin/smtpd/ca.c > > > @@ -110,10 +110,10 @@ ca(void) > > > > > > config_peer(PROC_CONTROL); > > > config_peer(PROC_PARENT); > > > - config_peer(PROC_PONY); > > > + config_peer(PROC_DISPATCHER); > > > > > > /* Ignore them until we get our config */ > > > - mproc_disable(p_pony); > > > + mproc_disable(p_dispatcher); > > > > > > if (pledge("stdio", NULL) == -1) > > > err(1, "pledge"); > > > @@ -246,7 +246,7 @@ ca_imsg(struct mproc *p, struct imsg *imsg) > > > ca_init(); > > > > > > /* Start fulfilling requests */ > > > - mproc_enable(p_pony); > > > + mproc_enable(p_dispatcher); > > > return; > > > > > > case IMSG_CTL_VERBOSE: > > > @@ -385,7 +385,7 @@ rsae_send_imsg(int flen, const unsigned char *from, > > > unsigned char *to, > > > if (n == 0) > > > break; > > > > > > - log_imsg(PROC_PONY, PROC_CA, ); > > > + log_imsg(PROC_DISPATCHER, PROC_CA, ); > > > > > > switch (imsg.hdr.type) { > > > case IMSG_CA_RSA_PRIVENC: > > > @@ -393,7 +393,7 @@ rsae_send_imsg(int flen, const unsigned char *from, > > > unsigned char *to, > > > break; > > > default: > > > /* Another imsg is queued up in the buffer */ > > > - pony_imsg(p_ca, ); > > > + dispatcher_imsg(p_ca, ); > > > imsg_free(); > > > continue; > > > } > > > @@ -569,14 +569,14 @@ ecdsae_send_enc_imsg(const unsigned char *dgst, int > > > dgst_len, > > > if (n == 0) > > > break; > > > > > > - log_imsg(PROC_PONY, PROC_CA, ); > > > + log_imsg(PROC_DISPATCHER, PROC_CA, ); > > > > > > switch (imsg.hdr.type) { > > > case IMSG_CA_ECDSA_SIGN: > > > break; > > > default: > > > /* Another imsg is queued up in the buffer */ > > > -
Re: [diff] src/usr.sbin/smtpd: change process names
This one reads OK to me, with one minor bikeshed: You rename klondike to crypto, but the internals still refer to CA everywhere. Wouldn't it be cleaner to leave klondike in step one and do a s/CA/CRYPTO/ in a second step so everything is in concent? Personally I prefer the name crypto over ca. martijn@ On Sat, 2020-12-19 at 23:21 +, gil...@poolp.org wrote: > December 19, 2020 11:26 PM, "Martijn van Duren" > wrote: > > > Personally I'd rather wait to keep the names in sync, especially since > > it's an easy 2 line diff that can easily be incorperated in the bigger > > thing. But it's not something I'm going to loose sleep over if others > > thing it can go in right now. > > > > Fair enough :-) > > Below is the diff that changes all references to pony into dispatcher. > > I didn't rename pony.c to dispatcher.c as this would break the diff, but if > this gets > committed I'll submit a diff for the rename + Makefile bit > > > > diff --git a/usr.sbin/smtpd/bounce.c b/usr.sbin/smtpd/bounce.c > index e6fc55780a1..455da6ff8b1 100644 > --- a/usr.sbin/smtpd/bounce.c > +++ b/usr.sbin/smtpd/bounce.c > @@ -290,7 +290,7 @@ bounce_drain() > } > > log_debug("debug: bounce: requesting new enqueue socket..."); > - m_compose(p_pony, IMSG_QUEUE_SMTP_SESSION, 0, 0, -1, NULL, 0); > + m_compose(p_dispatcher, IMSG_QUEUE_SMTP_SESSION, 0, 0, -1, > NULL, 0); > > running += 1; > } > diff --git a/usr.sbin/smtpd/ca.c b/usr.sbin/smtpd/ca.c > index fdc177e28b3..0299ee6cecc 100644 > --- a/usr.sbin/smtpd/ca.c > +++ b/usr.sbin/smtpd/ca.c > @@ -110,10 +110,10 @@ ca(void) > > config_peer(PROC_CONTROL); > config_peer(PROC_PARENT); > - config_peer(PROC_PONY); > + config_peer(PROC_DISPATCHER); > > /* Ignore them until we get our config */ > - mproc_disable(p_pony); > + mproc_disable(p_dispatcher); > > if (pledge("stdio", NULL) == -1) > err(1, "pledge"); > @@ -246,7 +246,7 @@ ca_imsg(struct mproc *p, struct imsg *imsg) > ca_init(); > > /* Start fulfilling requests */ > - mproc_enable(p_pony); > + mproc_enable(p_dispatcher); > return; > > case IMSG_CTL_VERBOSE: > @@ -385,7 +385,7 @@ rsae_send_imsg(int flen, const unsigned char *from, > unsigned char *to, > if (n == 0) > break; > > - log_imsg(PROC_PONY, PROC_CA, ); > + log_imsg(PROC_DISPATCHER, PROC_CA, ); > > switch (imsg.hdr.type) { > case IMSG_CA_RSA_PRIVENC: > @@ -393,7 +393,7 @@ rsae_send_imsg(int flen, const unsigned char *from, > unsigned char *to, > break; > default: > /* Another imsg is queued up in the buffer */ > - pony_imsg(p_ca, ); > + dispatcher_imsg(p_ca, ); > imsg_free(); > continue; > } > @@ -569,14 +569,14 @@ ecdsae_send_enc_imsg(const unsigned char *dgst, int > dgst_len, > if (n == 0) > break; > > - log_imsg(PROC_PONY, PROC_CA, ); > + log_imsg(PROC_DISPATCHER, PROC_CA, ); > > switch (imsg.hdr.type) { > case IMSG_CA_ECDSA_SIGN: > break; > default: > /* Another imsg is queued up in the buffer */ > - pony_imsg(p_ca, ); > + dispatcher_imsg(p_ca, ); > imsg_free(); > continue; > } > diff --git a/usr.sbin/smtpd/config.c b/usr.sbin/smtpd/config.c > index 529420ac0f2..2882349ceba 100644 > --- a/usr.sbin/smtpd/config.c > +++ b/usr.sbin/smtpd/config.c > @@ -325,8 +325,8 @@ config_peer(enum smtp_proc_type proc) > p = p_queue; > else if (proc == PROC_SCHEDULER) > p = p_scheduler; > - else if (proc == PROC_PONY) > - p = p_pony; > + else if (proc == PROC_DISPATCHER) > + p = p_dispatcher; > else if (proc == PROC_CA) > p = p_ca; > else > diff --git a/usr.sbi
Re: extern int optreset not needed
OK martijn@ On Sat, 2020-12-26 at 23:24 +0100, Jan Stary wrote: > ftpd doesn't need to declare extern int optreset > as that is already done in the included unistd.h > > Jan > > Index: popen.c > === > RCS file: /cvs/src/libexec/ftpd/popen.c,v > retrieving revision 1.29 > diff -u -p -r1.29 popen.c > --- popen.c 15 Jan 2020 22:06:59 - 1.29 > +++ popen.c 26 Dec 2020 22:05:49 - > @@ -113,7 +113,6 @@ ftpd_ls(const char *path, pid_t *pidptr) > (void)close(pdes[0]); > closelog(); > > - extern int optreset; > extern int ls_main(int, char **); > > /* reset getopt for ls_main */ >
Re: [diff] src/usr.sbin/smtpd: plug a memory leak in regex lookups
Committed, thanks. On Wed, 2020-12-23 at 08:54 +0100, Gilles CHEHADE wrote: > Hello, > > The following diff plugs a memory leak in regex lookups. > > Cheers, > > > diff --git a/usr.sbin/smtpd/table.c b/usr.sbin/smtpd/table.c > index 4691..d1578403 100644 > --- a/usr.sbin/smtpd/table.c > +++ b/usr.sbin/smtpd/table.c > @@ -470,6 +470,7 @@ table_regex_match(const char *string, const char *pattern) > { > regex_t preg; > int cflags = REG_EXTENDED|REG_NOSUB; > + int ret; > > if (strncmp(pattern, "(?i)", 4) == 0) { > cflags |= REG_ICASE; > @@ -479,7 +480,11 @@ table_regex_match(const char *string, const char > *pattern) > if (regcomp(, pattern, cflags) != 0) > return (0); > > - if (regexec(, string, 0, NULL, 0) != 0) > + ret = regexec(, string, 0, NULL, 0); > + > + regfree(); > + > + if (ret != 0) > return (0); > > return (1); >
smtp(1) add authentication
Playing around with the filter API I want an easier way to send mail with authentication instead of doing the transaction manually via openssl or via bloated mailclients. Turns out we already have all the plumbing in place and just need to hook it up. OK? martijn@ Index: smtpc.c === RCS file: /cvs/src/usr.sbin/smtpd/smtpc.c,v retrieving revision 1.11 diff -u -p -r1.11 smtpc.c --- smtpc.c 14 Sep 2020 18:32:11 - 1.11 +++ smtpc.c 20 Dec 2020 18:57:13 - @@ -56,9 +56,8 @@ usage(void) { extern char *__progname; - fprintf(stderr, - "usage: %s [-Chnv] [-F from] [-H helo] [-s server] [-S name] rcpt ...\n", - __progname); + fprintf(stderr, "usage: %s [-Chnv] [-F from] [-H helo] [-a authfile] " + "[-s server] [-S name] rcpt ...\n", __progname); exit(1); } @@ -66,8 +65,12 @@ int main(int argc, char **argv) { char hostname[256]; + FILE *authfile; int ch, i; char *server = "localhost"; + char *authstr = NULL; + size_t alloc = 0; + ssize_t len; struct passwd *pw; log_init(1, 0); @@ -91,7 +94,7 @@ main(int argc, char **argv) memset(, 0, sizeof(mail)); mail.from = pw->pw_name; - while ((ch = getopt(argc, argv, "CF:H:S:hns:v")) != -1) { + while ((ch = getopt(argc, argv, "CF:H:S:a:hns:v")) != -1) { switch (ch) { case 'C': params.tls_verify = 0; @@ -107,6 +110,23 @@ main(int argc, char **argv) break; case 'h': usage(); + break; + case 'a': + if ((authfile = fopen(optarg, "r")) == NULL) + fatal("%s: open", optarg); + if ((len = getline(, , authfile)) == -1) + fatal("%s: Failed to read username", optarg); + if (authstr[len - 1] == '\n') + authstr[len - 1] = '\0'; + params.auth_user = authstr; + authstr = NULL; + len = 0; + if ((len = getline(, , authfile)) == -1) + fatal("%s: Failed to read password", optarg); + if (authstr[len - 1] == '\n') + authstr[len - 1] = '\0'; + params.auth_pass = authstr; + fclose(authfile); break; case 'n': noaction = 1; Index: smtp.1 === RCS file: /cvs/src/usr.sbin/smtpd/smtp.1,v retrieving revision 1.7 diff -u -p -r1.7 smtp.1 --- smtp.1 4 Jul 2018 08:23:43 - 1.7 +++ smtp.1 20 Dec 2020 18:57:13 - @@ -25,6 +25,7 @@ .Op Fl Chnv .Op Fl F Ar from .Op Fl H Ar helo +.Op Fl a Ar authfile .Op Fl s Ar server .Op Ar recipient ... .Sh DESCRIPTION @@ -49,6 +50,13 @@ Set the return-path (MAIL FROM) for the Default to the current username. .It Fl H Ar helo Define the hostname to advertise (HELO) when establishing the SMTP session. +.It Fl a Ar authfile +Perform a login before sending the message. +The username and password are read from +.Ar authfile +and need to be on the first and second line respectively. +This option requires a TLS or STARTTLS +.Ar server . .It Fl h Display version and usage. .It Fl n
Re: [diff] src/usr.sbin/smtpd: change process names
Personally I'd rather wait to keep the names in sync, especially since it's an easy 2 line diff that can easily be incorperated in the bigger thing. But it's not something I'm going to loose sleep over if others thing it can go in right now. On Sat, 2020-12-19 at 22:22 +, gil...@poolp.org wrote: > I agree but I thought this should be done in a second time as it is quite > invasive and not required for the change to be visible outside the daemon > > > December 19, 2020 11:13 PM, "Martijn van Duren" > wrote: > > > I'm in favour of this change, since I like proper nomenclature. > > But I think you should push this one to its logical conclusion and also > > rename the enum and potential other pony/klondike references, because > > with your diff the naming is inconsistent, which is even more confusing. > > > > martijn@ > > > > On Sat, 2020-12-19 at 22:06 +, gil...@poolp.org wrote: > > > > > Hello, > > > > > > A very long time ago, smtpd had several more processes which then got > > > factored > > > into a single one. We couldn't find a decent name back then but since a > > > hacker > > > had requested a pony from me I temporarily named the process "pony > > > express" as > > > it was in charge of delivering mail. Later, reyk improved the joke as he > > > named > > > the privsep crypto process klondike. > > > > > > A few years ago when the config was reworked, we used the term > > > "dispatcher" to > > > identify if a mail was dispatched to the mda or mta layer. > > > > > > Unless someone is very emotionally attached to the initial joke, I > > > suggest the > > > pony express process be renamed to dispatcher and klondike to crypto. The > > > goal > > > is not just to end the joke but also to avoid a process name with a > > > space, and > > > also because it makes it less obvious what these processes do. > > > > > > diff --git a/usr.sbin/smtpd/smtpd.c b/usr.sbin/smtpd/smtpd.c > > > index 854c2ab0cb6..b364b22e472 100644 > > > --- a/usr.sbin/smtpd/smtpd.c > > > +++ b/usr.sbin/smtpd/smtpd.c > > > @@ -1913,9 +1913,9 @@ proc_title(enum smtp_proc_type proc) > > > case PROC_SCHEDULER: > > > return "scheduler"; > > > case PROC_PONY: > > > - return "pony express"; > > > + return "dispatcher"; > > > case PROC_CA: > > > - return "klondike"; > > > + return "crypto"; > > > case PROC_CLIENT: > > > return "client"; > > > case PROC_PROCESSOR:
Re: [diff] src/usr.sbin/smtpd: change process names
I'm in favour of this change, since I like proper nomenclature. But I think you should push this one to its logical conclusion and also rename the enum and potential other pony/klondike references, because with your diff the naming is inconsistent, which is even more confusing. martijn@ On Sat, 2020-12-19 at 22:06 +, gil...@poolp.org wrote: > Hello, > > A very long time ago, smtpd had several more processes which then got factored > into a single one. We couldn't find a decent name back then but since a hacker > had requested a pony from me I temporarily named the process "pony express" as > it was in charge of delivering mail. Later, reyk improved the joke as he named > the privsep crypto process klondike. > > A few years ago when the config was reworked, we used the term "dispatcher" to > identify if a mail was dispatched to the mda or mta layer. > > Unless someone is very emotionally attached to the initial joke, I suggest the > pony express process be renamed to dispatcher and klondike to crypto. The goal > is not just to end the joke but also to avoid a process name with a space, and > also because it makes it less obvious what these processes do. > > > diff --git a/usr.sbin/smtpd/smtpd.c b/usr.sbin/smtpd/smtpd.c > index 854c2ab0cb6..b364b22e472 100644 > --- a/usr.sbin/smtpd/smtpd.c > +++ b/usr.sbin/smtpd/smtpd.c > @@ -1913,9 +1913,9 @@ proc_title(enum smtp_proc_type proc) > case PROC_SCHEDULER: > return "scheduler"; > case PROC_PONY: > - return "pony express"; > + return "dispatcher"; > case PROC_CA: > - return "klondike"; > + return "crypto"; > case PROC_CLIENT: > return "client"; > case PROC_PROCESSOR: >
doas sprinkle some more CFLAGS
So I ended up in doas again, this time with the CFLAGS I use for most of my other projects. This popped up a few new not very exciting warnings. Diff below compiles clean with both clang and gcc on amd64. Worth doing? martijn@ Index: Makefile === RCS file: /cvs/src/usr.bin/doas/Makefile,v retrieving revision 1.3 diff -u -p -r1.3 Makefile --- Makefile3 Jul 2017 22:21:47 - 1.3 +++ Makefile18 Dec 2020 21:18:51 - @@ -9,7 +9,11 @@ BINOWN= root BINMODE=4555 CFLAGS+= -I${.CURDIR} -COPTS+=-Wall +CFLAGS+= -Wall +CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes +CFLAGS+= -Wmissing-declarations +CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual +CFLAGS+= -Wsign-compare YFLAGS= .include Index: doas.c === RCS file: /cvs/src/usr.bin/doas/doas.c,v retrieving revision 1.84 diff -u -p -r1.84 doas.c --- doas.c 9 Oct 2020 07:43:38 - 1.84 +++ doas.c 18 Dec 2020 21:18:51 - @@ -94,7 +94,7 @@ parsegid(const char *s, gid_t *gid) static int match(uid_t uid, gid_t *groups, int ngroups, uid_t target, const char *cmd, -const char **cmdargs, struct rule *r) +const char * const*cmdargs, struct rule *r) { int i; @@ -134,7 +134,7 @@ match(uid_t uid, gid_t *groups, int ngro static int permit(uid_t uid, gid_t *groups, int ngroups, const struct rule **lastr, -uid_t target, const char *cmd, const char **cmdargs) +uid_t target, const char *cmd, const char * const*cmdargs) { int i; @@ -188,7 +188,7 @@ checkconfig(const char *confpath, int ar exit(0); if (permit(uid, groups, ngroups, , target, argv[0], - (const char **)argv + 1)) { + (const char * const*)argv + 1)) { printf("permit%s\n", (rule->options & NOPASS) ? " nopass" : ""); exit(0); } else { @@ -244,7 +244,7 @@ good: } } -int +static int unveilcommands(const char *ipath, const char *cmd) { char *path = NULL, *p; @@ -271,7 +271,7 @@ unveilcommands(const char *ipath, const if (cp) { int r = snprintf(buf, sizeof buf, "%s/%s", cp, cmd); - if (r >= 0 && r < sizeof buf) { + if (r >= 0 && (size_t)r < sizeof buf) { if (unveil(buf, "x") != -1) unveils++; } @@ -394,7 +394,7 @@ main(int argc, char **argv) cmd = argv[0]; if (!permit(uid, groups, ngroups, , target, cmd, - (const char **)argv + 1)) { + (const char * const*)argv + 1)) { syslog(LOG_AUTHPRIV | LOG_NOTICE, "command not permitted for %s: %s", mypw->pw_name, cmdline); errc(1, EPERM, NULL); Index: env.c === RCS file: /cvs/src/usr.bin/doas/env.c,v retrieving revision 1.10 diff -u -p -r1.10 env.c --- env.c 7 Jul 2019 19:21:28 - 1.10 +++ env.c 18 Dec 2020 21:18:51 - @@ -32,8 +32,8 @@ const char *formerpath; struct envnode { RB_ENTRY(envnode) node; - const char *key; - const char *value; + char *key; + char *value; }; struct env { Index: parse.y === RCS file: /cvs/src/usr.bin/doas/parse.y,v retrieving revision 1.28 diff -u -p -r1.28 parse.y --- parse.y 9 Oct 2020 07:43:38 - 1.28 +++ parse.y 18 Dec 2020 21:18:51 - @@ -56,7 +56,7 @@ static void yyerror(const char *, ...); static int yylex(void); static size_t -arraylen(const char **arr) +arraylen(const char * const*arr) { size_t cnt = 0; @@ -222,7 +222,8 @@ int yylex(void) { char buf[1024], *ebuf, *p, *str; - int i, c, quotes = 0, escape = 0, qpos = -1, nonkw = 0; + int c, quotes = 0, escape = 0, qpos = -1, nonkw = 0; + size_t i; p = buf; ebuf = buf + sizeof(buf);
Re: fortune: allow to use symlinks
On Tue, 2020-12-15 at 15:10 +0300, Vadim Zhukov wrote: > > I very rarely use fortune and I'm not familiar with the codebase, but > > from some quick testing and code-scanning I found the following: > > is_fortfile appends .dat to the input file and sees if it's accessible. > > Adding a symlink to the corresponding .dat file make the thing work > > perfectly well for me. Your diff seems to work, because you resolve > > the path, which in turn gives back the correct location for the .dat, > > not because symlinks are not suported. > > Thank you very much for review. Indeed, adding second symlink fixes > the initial issue, so the patch now seems useless... > > > Personally I don't see good reason to add the additional logic which > > can be solved with a second simple symlink, but if others think it's > > worth it, comments inline. > > ... but following your comments I've discovered that copy() function > in fortune.c can return NULL, and that value isn't checked. > > So I'm posting the whole diff for the sake of completeness, and what > I really think worths committing is the last chunk, replacing "return > NULL" with "err(1, NULL)" in copy(). Okay for it? OK martijn@ for this last bit. > > > martijn@ > > > > On Tue, 2020-12-15 at 01:09 +0300, Vadim Zhukov wrote: > > > Hello, all. > > > > > > This allows fortune(6) to open fortune files via symlinks. > > > Maybe this is a stupid idea, I dunno, but it seems inconsistent > > > that I can't put a symlink to my fortunes collection in > > > /usr/share/games/fortune and then simply call "fortune foo" > > > instead of "fortune /usr/local/share/games/fortune/ru/foo". > > > > > > I decided to call readlink(2) explicitly rather than adding > > > check of file type being open, since that resulted in less code. > > > > > > Ah, and yes, I have a port of Russian fortune files pending, > > > but that's for another list and another day. > > > > > > So... okay/notokay anyone? :) > > -- > WBR, > Vadim Zhukov > > > Index: fortune.c > === > RCS file: /cvs/src/games/fortune/fortune/fortune.c,v > retrieving revision 1.60 > diff -u -p -r1.60 fortune.c > --- fortune.c 10 Aug 2017 17:00:08 - 1.60 > +++ fortune.c 15 Dec 2020 11:46:00 - > @@ -39,6 +39,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -388,8 +389,9 @@ add_file(int percent, char *file, char * > FILEDESC *parent) > { > FILEDESC*fp; > + ssize_t lnklen; > int fd; > - char*path, *offensive; > + char*path, *offensive, lnkpath[PATH_MAX]; > boolwas_malloc; > boolisdir; > > @@ -420,8 +422,22 @@ add_file(int percent, char *file, char * > } > > DPRINTF(1, (stderr, "adding file \"%s\"\n", path)); > + > over: > + lnklen = readlink(path, lnkpath, sizeof(lnkpath)); > + if (lnklen == -1) { > + if (errno != EINVAL) > + goto openfailed; > + } else { > + lnkpath[lnklen] = '\0'; > + if (was_malloc) > + free(path); > + path = copy(lnkpath, NULL); > + was_malloc = 1; > + } > + > if ((fd = open(path, O_RDONLY)) < 0) { > +openfailed: > /* > * This is a sneak. If the user said -a, and if the > * file we're given isn't a file, we check to see if > @@ -718,7 +734,7 @@ copy(char *str, char *suf) > char*new; > > if (asprintf(, "%s%s", str, suf ? suf : "") == -1) > - return NULL; > + err(1, NULL); > return new; > } >
Re: fortune: allow to use symlinks
I very rarely use fortune and I'm not familiar with the codebase, but from some quick testing and code-scanning I found the following: is_fortfile appends .dat to the input file and sees if it's accessible. Adding a symlink to the corresponding .dat file make the thing work perfectly well for me. Your diff seems to work, because you resolve the path, which in turn gives back the correct location for the .dat, not because symlinks are not suported. Personally I don't see good reason to add the additional logic which can be solved with a second simple symlink, but if others think it's worth it, comments inline. martijn@ On Tue, 2020-12-15 at 01:09 +0300, Vadim Zhukov wrote: > Hello, all. > > This allows fortune(6) to open fortune files via symlinks. > Maybe this is a stupid idea, I dunno, but it seems inconsistent > that I can't put a symlink to my fortunes collection in > /usr/share/games/fortune and then simply call "fortune foo" > instead of "fortune /usr/local/share/games/fortune/ru/foo". > > I decided to call readlink(2) explicitly rather than adding > check of file type being open, since that resulted in less code. > > Ah, and yes, I have a port of Russian fortune files pending, > but that's for another list and another day. > > So... okay/notokay anyone? :) > > -- > WBR, > Vadim Zhukov > > > Index: fortune.c > === > RCS file: /cvs/src/games/fortune/fortune/fortune.c,v > retrieving revision 1.60 > diff -u -p -r1.60 fortune.c > --- fortune.c 10 Aug 2017 17:00:08 - 1.60 > +++ fortune.c 14 Dec 2020 22:05:33 - > @@ -39,6 +39,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -388,8 +389,9 @@ add_file(int percent, char *file, char * > FILEDESC *parent) > { > FILEDESC*fp; > + ssize_t lnklen; > int fd; > - char*path, *offensive; > + char*path, *offensive, lnkpath[PATH_MAX]; > boolwas_malloc; > boolisdir; > > @@ -420,8 +422,22 @@ add_file(int percent, char *file, char * > } > > DPRINTF(1, (stderr, "adding file \"%s\"\n", path)); > + > over: > + lnklen = readlink(path, lnkpath, PATH_MAX); I'd prefer sizeof(lnkpath) instead of PATH_MAX, just to be a little more robust. > + if (lnklen == -1) { > + if (errno != EINVAL) > + goto openfailed; > + } else { > + lnkpath[lnklen] = '\0'; > + if (was_malloc) > + free(path); > + path = strdup(lnkpath); This needs a NULL-check. > + was_malloc = 1; > + } > + > if ((fd = open(path, O_RDONLY)) < 0) { > +openfailed: > /* > * This is a sneak. If the user said -a, and if the > * file we're given isn't a file, we check to see if >
snmp - remove BER_TYPE_BOOLEAN
I can't find any reference in RFC2578 for a boolean type, nor have I seen it in the wild and the TruthValue diff I just committed give me a strong indication that this was added without any real reason. OK to remove? martijn@ Index: usr.bin/snmp/smi.c === RCS file: /cvs/src/usr.bin/snmp/smi.c,v retrieving revision 1.13 diff -u -p -r1.13 smi.c --- usr.bin/snmp/smi.c 14 Dec 2020 07:44:26 - 1.13 +++ usr.bin/snmp/smi.c 14 Dec 2020 11:12:29 - @@ -95,9 +95,6 @@ smi_debug_elements(struct ber_element *r case BER_TYPE_EOC: fprintf(stderr, "end-of-content"); break; - case BER_TYPE_BOOLEAN: - fprintf(stderr, "boolean"); - break; case BER_TYPE_INTEGER: fprintf(stderr, "integer"); break; @@ -196,9 +193,6 @@ smi_debug_elements(struct ber_element *r goto invalid; switch (root->be_encoding) { - case BER_TYPE_BOOLEAN: - fprintf(stderr, "%s", value); - break; case BER_TYPE_INTEGER: case BER_TYPE_ENUMERATED: fprintf(stderr, "value %s", value); @@ -255,7 +249,6 @@ smi_print_element(struct ber_oid *oid, s struct textconv tckey; size_t len, i, slen; long longv, ticks; - int d; int is_hex = 0, ret; struct ber_oid o; char strbuf[BUFSIZ]; @@ -277,17 +270,6 @@ smi_print_element(struct ber_oid *oid, s } switch (root->be_encoding) { - case BER_TYPE_BOOLEAN: - if (ober_get_boolean(root, ) == -1) - goto fail; - if (print_hint) { - if (asprintf(, "INTEGER: %s(%d)", - d ? "true" : "false", d) == -1) - goto fail; - } else - if (asprintf(, "%s", d ? "true" : "false") == -1) - goto fail; - break; case BER_TYPE_INTEGER: case BER_TYPE_ENUMERATED: if (ober_get_integer(root, ) == -1) Index: usr.sbin/snmpd/smi.c === RCS file: /cvs/src/usr.sbin/snmpd/smi.c,v retrieving revision 1.27 diff -u -p -r1.27 smi.c --- usr.sbin/snmpd/smi.c24 Oct 2019 12:39:27 - 1.27 +++ usr.sbin/snmpd/smi.c14 Dec 2020 11:12:29 - @@ -317,9 +317,6 @@ smi_debug_elements(struct ber_element *r case BER_TYPE_EOC: fprintf(stderr, "end-of-content"); break; - case BER_TYPE_BOOLEAN: - fprintf(stderr, "boolean"); - break; case BER_TYPE_INTEGER: fprintf(stderr, "integer"); break; @@ -417,9 +414,6 @@ smi_debug_elements(struct ber_element *r goto invalid; switch (root->be_encoding) { - case BER_TYPE_BOOLEAN: - fprintf(stderr, "%s", value); - break; case BER_TYPE_INTEGER: case BER_TYPE_ENUMERATED: fprintf(stderr, "value %s", value); @@ -473,17 +467,10 @@ smi_print_element(struct ber_element *ro char*str = NULL, *buf, *p; size_t len, i; long longv; - int d; struct ber_oid o; char strbuf[BUFSIZ]; switch (root->be_encoding) { - case BER_TYPE_BOOLEAN: - if (ober_get_boolean(root, ) == -1) - goto fail; - if (asprintf(, "%s(%d)", d ? "true" : "false", d) == -1) - goto fail; - break; case BER_TYPE_INTEGER: case BER_TYPE_ENUMERATED: if (ober_get_integer(root, ) == -1)
Re: snmpd drop traphandler process
Found some minor issues. Please disregard for now. On Tue, 2020-12-01 at 17:12 +0100, Martijn van Duren wrote: > Hello tech@, > > Long story short: the traphandler process in snmpd annoys me a great > deal and is in the way for overhauling the transport mapping section > of snmpe, which is needed for implementing new agentx master support. > > The current traphandler process is also a joke, since all it does is > receive a message, does a minimal parsing validation and then pass > then entire buffer to the parent process, which forks the actual > handlers. This means that the current pledgeset is also way too wide > for what traphandler does. > > Since snmpe already does a similar packet parsing I see no reason to > keep this initial verification in the traphandler process. The diff > below drops the traphandler process and moves the receiving of the > packets to snmpe, which then forwards the pdu (instead of the > current whole packet) to the parent. I also extended the checking, so > it should be a little more resilient to malformed packets. > > While here I also didn't like the fact that listening on a trap-port > always implies that snmp itself is also listening. This diff adds the > trap keyword (for udp) on the listen on line, so that we can setup a > traphandler-only setup. This gives the added bonus that we can now > also choose the port we listen on for traps. Adding a listen trap > statement requires a trap handle and vice versa. > > It's not the pretties code, but it's a stopgap that allows me to move > forward without creating even larger diffs and without (hopefully) > breaking existing setups (apart from the keyword change). > > OK? > > martijn@ > > Index: parse.y > === > RCS file: /cvs/src/usr.sbin/snmpd/parse.y,v > retrieving revision 1.62 > diff -u -p -r1.62 parse.y > --- parse.y 30 Oct 2020 07:43:48 - 1.62 > +++ parse.y 1 Dec 2020 16:12:20 - > @@ -94,11 +94,9 @@ char *symget(const char *); > struct snmpd *conf = NULL; > static int errors = 0; > static struct usmuser *user = NULL; > -static char*snmpd_port = SNMPD_PORT; > > int host(const char *, const char *, int, > struct sockaddr_storage *, int); > -int listen_add(struct sockaddr_storage *, int); > > typedef struct { > union { > @@ -284,13 +282,16 @@ listenproto : UDP listen_udp > listen_udp : STRING port { > struct sockaddr_storage ss[16]; > int nhosts, i; > + char *port = $2; > > - nhosts = host($1, $2, SOCK_DGRAM, ss, nitems(ss)); > + if (port == NULL) > + port = SNMPD_PORT; > + > + nhosts = host($1, port, SOCK_DGRAM, ss, nitems(ss)); > if (nhosts < 1) { > yyerror("invalid address: %s", $1); > free($1); > - if ($2 != snmpd_port) > - free($2); > + free($2); > YYERROR; > } > if (nhosts > (int)nitems(ss)) > @@ -298,10 +299,38 @@ listen_udp: STRING port { > $1, $2, nitems(ss)); > > free($1); > - if ($2 != snmpd_port) > + free($2); > + for (i = 0; i < nhosts; i++) { > + if (listen_add(&(ss[i]), SOCK_DGRAM, 0) == > -1) { > + yyerror("calloc"); > + YYERROR; > + } > + } > + } > + | STRING port TRAP { > + struct sockaddr_storage ss[16]; > + int nhosts, i; > + char *port = $2; > + > + if (port == NULL) > + port = SNMPD_TRAPPORT; > + > + nhosts = host($1, port, SOCK_DGRAM, ss, nitems(ss)); > + if (nhosts < 1) { > + yyerror("invalid address: %s", $1); > + free($1); > free($2); > + YYERROR; >
snmpd drop traphandler process
Hello tech@, Long story short: the traphandler process in snmpd annoys me a great deal and is in the way for overhauling the transport mapping section of snmpe, which is needed for implementing new agentx master support. The current traphandler process is also a joke, since all it does is receive a message, does a minimal parsing validation and then pass then entire buffer to the parent process, which forks the actual handlers. This means that the current pledgeset is also way too wide for what traphandler does. Since snmpe already does a similar packet parsing I see no reason to keep this initial verification in the traphandler process. The diff below drops the traphandler process and moves the receiving of the packets to snmpe, which then forwards the pdu (instead of the current whole packet) to the parent. I also extended the checking, so it should be a little more resilient to malformed packets. While here I also didn't like the fact that listening on a trap-port always implies that snmp itself is also listening. This diff adds the trap keyword (for udp) on the listen on line, so that we can setup a traphandler-only setup. This gives the added bonus that we can now also choose the port we listen on for traps. Adding a listen trap statement requires a trap handle and vice versa. It's not the pretties code, but it's a stopgap that allows me to move forward without creating even larger diffs and without (hopefully) breaking existing setups (apart from the keyword change). OK? martijn@ Index: parse.y === RCS file: /cvs/src/usr.sbin/snmpd/parse.y,v retrieving revision 1.62 diff -u -p -r1.62 parse.y --- parse.y 30 Oct 2020 07:43:48 - 1.62 +++ parse.y 1 Dec 2020 16:12:20 - @@ -94,11 +94,9 @@ char *symget(const char *); struct snmpd *conf = NULL; static int errors = 0; static struct usmuser *user = NULL; -static char*snmpd_port = SNMPD_PORT; int host(const char *, const char *, int, struct sockaddr_storage *, int); -int listen_add(struct sockaddr_storage *, int); typedef struct { union { @@ -284,13 +282,16 @@ listenproto : UDP listen_udp listen_udp : STRING port { struct sockaddr_storage ss[16]; int nhosts, i; + char *port = $2; - nhosts = host($1, $2, SOCK_DGRAM, ss, nitems(ss)); + if (port == NULL) + port = SNMPD_PORT; + + nhosts = host($1, port, SOCK_DGRAM, ss, nitems(ss)); if (nhosts < 1) { yyerror("invalid address: %s", $1); free($1); - if ($2 != snmpd_port) - free($2); + free($2); YYERROR; } if (nhosts > (int)nitems(ss)) @@ -298,10 +299,38 @@ listen_udp: STRING port { $1, $2, nitems(ss)); free($1); - if ($2 != snmpd_port) + free($2); + for (i = 0; i < nhosts; i++) { + if (listen_add(&(ss[i]), SOCK_DGRAM, 0) == -1) { + yyerror("calloc"); + YYERROR; + } + } + } + | STRING port TRAP { + struct sockaddr_storage ss[16]; + int nhosts, i; + char *port = $2; + + if (port == NULL) + port = SNMPD_TRAPPORT; + + nhosts = host($1, port, SOCK_DGRAM, ss, nitems(ss)); + if (nhosts < 1) { + yyerror("invalid address: %s", $1); + free($1); free($2); + YYERROR; + } + if (nhosts > (int)nitems(ss)) + log_warn("%s:%s resolves to more than %zu hosts", + $1, $2, nitems(ss)); + + free($1); + free($2); for (i = 0; i < nhosts; i++) { - if (listen_add(&(ss[i]), SOCK_DGRAM) == -1) { + if (listen_add(&(ss[i]), SOCK_DGRAM, + ADDRESS_FLAG_TRAP) == -1) { yyerror("calloc"); YYERROR;
Re: cat(1): simplify/flatten argument loops
This one reads a lot better to me and even shaves of 2LoC. :-) OK martijn@ On Mon, 2020-11-30 at 18:28 -0600, Scott Cheloha wrote: > Hi, > > The cook_args() and raw_args() functions in cat(1) are too clever. > They handle multiple special cases in a single big loop with lots of > branches. It's been like this since at least 1989: > > https://svnweb.freebsd.org/csrg/bin/cat/cat.c?view=markup=37179 > > The goal seems to be to avoid calling cook_buf()/raw_cat() from > multiple places. I think the result is convoluted. If we isolated > the special cases and called cook_buf()/raw_cat() from multiple places > the result would be simpler and flatter. > > You can break the cleanup in each function into four steps: > > 1. Pull the no-args case out of the loop and handle it first. Now we > don't need to check if (*argv == NULL) in the body of the loop. One > fewer assignment to fp/fd, too. > > 2. In the loop, isolate the (strcmp(*argv, "-") == 0) special case > from the normal filename case. Now we don't need to check whether > we're working with stdin when we clean up at the end of a loop > iteration. Setup and cleanup are adjacent, no additional branches > needed. > > 3. Pass the file name as an argument to cook_buf() and raw_cat(). > Now we don't need the global 'filename' variable. Obviously > this means we don't need to assign it a value, either. > > 4. Use a for-loop and move argv iteration into the loop header. > Now we increment argv in a single place in the loop. > > Thoughts? > > Index: cat.c > === > RCS file: /cvs/src/bin/cat/cat.c,v > retrieving revision 1.27 > diff -u -p -r1.27 cat.c > --- cat.c 28 Jun 2019 13:34:58 - 1.27 > +++ cat.c 1 Dec 2020 00:24:20 - > @@ -51,12 +51,11 @@ extern char *__progname; > > int bflag, eflag, nflag, sflag, tflag, vflag; > int rval; > -char *filename; > > void cook_args(char *argv[]); > -void cook_buf(FILE *); > +void cook_buf(FILE *, const char *); > void raw_args(char *argv[]); > -void raw_cat(int); > +void raw_cat(int, const char *); > > int > main(int argc, char *argv[]) > @@ -110,30 +109,29 @@ cook_args(char **argv) > { > FILE *fp; > > - fp = stdin; > - filename = "stdin"; > - do { > - if (*argv) { > - if (!strcmp(*argv, "-")) > - fp = stdin; > - else if ((fp = fopen(*argv, "r")) == NULL) { > - warn("%s", *argv); > - rval = 1; > - ++argv; > - continue; > - } > - filename = *argv++; > - } > - cook_buf(fp); > - if (fp == stdin) > + if (*argv == NULL) { > + cook_buf(stdin, "stdin"); > + return; > + } > + > + for (; *argv != NULL; argv++) { > + if (!strcmp(*argv, "-")) { > + cook_buf(stdin, "stdin"); > clearerr(fp); > - else > - (void)fclose(fp); > - } while (*argv); > + continue; > + } > + if ((fp = fopen(*argv, "r")) == NULL) { > + warn("%s", *argv); > + rval = 1; > + continue; > + } > + cook_buf(fp, *argv); > + (void)fclose(fp); > + } > } > > void > -cook_buf(FILE *fp) > +cook_buf(FILE *fp, const char *filename) > { > int ch, gobble, line, prev; > > @@ -200,28 +198,28 @@ raw_args(char **argv) > { > int fd; > > - fd = fileno(stdin); > - filename = "stdin"; > - do { > - if (*argv) { > - if (!strcmp(*argv, "-")) > - fd = fileno(stdin); > - else if ((fd = open(*argv, O_RDONLY, 0)) == -1) { > - warn("%s", *argv); > - rval = 1; > - ++argv; > - continue; > - } > - filename = *argv++; > + if (*argv == NULL) { > + raw_cat(fileno(stdin), "stdin"); > + return; > + } > + > + for(; *argv != NULL; argv++) { > + if (!strcmp(*argv, "-")) { > + raw_cat(fileno(stdin), "stdin"); > + continue; > + } > + if ((fd = open(*argv, O_RDONLY, 0)) == -1) { > + warn("%s", *argv); > + rval = 1; > + continue; > } > - raw_cat(fd); > - if (fd != fileno(stdin)) > - (void)close(fd); > -
snmp trap usage
I missed an argc check which causes snmp trap to segfault if called with too few arguments instead of showing usage. OK? martijn@ Index: snmpc.c === RCS file: /cvs/src/usr.bin/snmp/snmpc.c,v retrieving revision 1.30 diff -u -p -r1.30 snmpc.c --- snmpc.c 14 Sep 2020 15:12:27 - 1.30 +++ snmpc.c 30 Nov 2020 16:25:24 - @@ -788,6 +788,9 @@ snmpc_trap(int argc, char *argv[]) if (version == SNMP_V1) errx(1, "trap is not supported for snmp v1"); + if (argc < 3) + usage(); + if ((agent = snmpc_connect(argv[0], "162")) == NULL) err(1, "%s", snmp_app->name);
Re: kvm_getfiles and KERN_FILE_BYFILE
On Sun, 2020-11-29 at 16:15 -0800, Philip Guenther wrote: > On Sun, Nov 29, 2020 at 12:14 PM Martijn van Duren > wrote: > > On Sat, 2020-11-28 at 16:23 -0800, Philip Guenther wrote: > > > On Thu, Nov 26, 2020 at 1:08 PM Martijn van Duren > > > wrote: > > > > I'm currently playing around a bit with kvm_getfiles and found that I > > > > couldn't use KERN_FILE_BYFILE with DTYPE_SOCKET. > > > > According to kvm_getfiles(3): > > > > For KERN_FILE_BYFILE the recognized file types are defined in > > > > : > > > > > > > > DTYPE_VNODE files and devices > > > > DTYPE_SOCKET sockets, regardless of domain > > > > DTYPE_PIPE pipes and FIFOs > > > > DTYPE_KQUEUE kqueues > > > > > > > > But these defines are under ifdef _KERNEL. > > > > > > > > So is the manpage lying here, or should the defines be hoisted out > > > > of the ifdef? > > > > > > > > > > > > > Let's go ahead and hoist them: FreeBSD and NetBSD already have. If > > > possible, the diff to do that should also simplify the #include bits in > > > these files: > > > usr.bin/netstat/inet.c > > > usr.bin/fstat/fstat.c > > > usr.bin/fstat/fuser.c > > > usr.bin/systat/netstat.c > > > > > > > > > Philip Guenther > > > > > > > The others have the #endif/#ifdef break rather low in the file. > > Personally I reckon it's better reading if the common code is more > > towards the top. > > > > OK? > > > > > ok guenther@ > > How do the userland clean up bits look? > > > Philip Guenther > Something like this? Index: fstat/fstat.c === RCS file: /cvs/src/usr.bin/fstat/fstat.c,v retrieving revision 1.101 diff -u -p -r1.101 fstat.c --- fstat/fstat.c 22 Aug 2020 18:34:29 - 1.101 +++ fstat/fstat.c 30 Nov 2020 07:17:51 - @@ -55,9 +55,7 @@ #include #include #include -#define _KERNEL /* for DTYPE_* */ #include -#undef _KERNEL #include #include Index: fstat/fuser.c === RCS file: /cvs/src/usr.bin/fstat/fuser.c,v retrieving revision 1.8 diff -u -p -r1.8 fuser.c --- fstat/fuser.c 25 Jan 2019 00:19:26 - 1.8 +++ fstat/fuser.c 30 Nov 2020 07:17:51 - @@ -45,9 +45,7 @@ #include #include #include -#define _KERNEL /* for DTYPE_VNODE */ #include -#undef _KERNEL #include #include Index: systat/netstat.c === RCS file: /cvs/src/usr.bin/systat/netstat.c,v retrieving revision 1.45 diff -u -p -r1.45 netstat.c --- systat/netstat.c12 Mar 2015 01:03:00 - 1.45 +++ systat/netstat.c30 Nov 2020 07:17:51 - @@ -38,9 +38,7 @@ #include #include #include -#define _KERNEL #include -#undef _KERNEL #include #include Index: netstat/inet.c === RCS file: /cvs/src/usr.bin/netstat/inet.c,v retrieving revision 1.168 diff -u -p -r1.168 inet.c --- netstat/inet.c 15 Jan 2020 14:02:37 - 1.168 +++ netstat/inet.c 30 Nov 2020 07:17:51 - @@ -37,9 +37,7 @@ #include #include #include -#define _KERNEL #include -#undef _KERNEL #include #include
Re: kvm_getfiles and KERN_FILE_BYFILE
On Sat, 2020-11-28 at 16:23 -0800, Philip Guenther wrote: > On Thu, Nov 26, 2020 at 1:08 PM Martijn van Duren > wrote: > > I'm currently playing around a bit with kvm_getfiles and found that I > > couldn't use KERN_FILE_BYFILE with DTYPE_SOCKET. > > According to kvm_getfiles(3): > > For KERN_FILE_BYFILE the recognized file types are defined in > > : > > > > DTYPE_VNODE files and devices > > DTYPE_SOCKET sockets, regardless of domain > > DTYPE_PIPE pipes and FIFOs > > DTYPE_KQUEUE kqueues > > > > But these defines are under ifdef _KERNEL. > > > > So is the manpage lying here, or should the defines be hoisted out > > of the ifdef? > > > > > Let's go ahead and hoist them: FreeBSD and NetBSD already have. If possible, > the diff to do that should also simplify the #include bits in these files: > usr.bin/netstat/inet.c > usr.bin/fstat/fstat.c > usr.bin/fstat/fuser.c > usr.bin/systat/netstat.c > > > Philip Guenther > The others have the #endif/#ifdef break rather low in the file. Personally I reckon it's better reading if the common code is more towards the top. OK? martijn@ Index: file.h === RCS file: /cvs/src/sys/sys/file.h,v retrieving revision 1.61 diff -u -p -r1.61 file.h --- file.h 13 Mar 2020 10:07:01 - 1.61 +++ file.h 29 Nov 2020 20:12:30 - @@ -38,7 +38,15 @@ #else /* _KERNEL */ #include #include +#endif /* _KERNEL */ +#defineDTYPE_VNODE 1 /* file */ +#defineDTYPE_SOCKET2 /* communications endpoint */ +#defineDTYPE_PIPE 3 /* pipe */ +#defineDTYPE_KQUEUE4 /* event queue */ +#defineDTYPE_DMABUF5 /* DMA buffer (for DRM) */ + +#ifdef _KERNEL struct proc; struct uio; struct knote; @@ -80,11 +88,6 @@ struct file { LIST_ENTRY(file) f_list;/* [F] list of active files */ struct mutex f_mtx; u_int f_flag; /* [a] see fcntl.h */ -#defineDTYPE_VNODE 1 /* file */ -#defineDTYPE_SOCKET2 /* communications endpoint */ -#defineDTYPE_PIPE 3 /* pipe */ -#defineDTYPE_KQUEUE4 /* event queue */ -#defineDTYPE_DMABUF5 /* DMA buffer (for DRM) */ u_int f_iflags; /* [a] internal flags */ int f_type; /* [I] descriptor type */ u_int f_count;/* [a] reference count */
kvm_getfiles and KERN_FILE_BYFILE
I'm currently playing around a bit with kvm_getfiles and found that I couldn't use KERN_FILE_BYFILE with DTYPE_SOCKET. According to kvm_getfiles(3): For KERN_FILE_BYFILE the recognized file types are defined in : DTYPE_VNODE files and devices DTYPE_SOCKET sockets, regardless of domain DTYPE_PIPEpipes and FIFOs DTYPE_KQUEUE kqueues But these defines are under ifdef _KERNEL. So is the manpage lying here, or should the defines be hoisted out of the ifdef? martijn@
Minor tweak relayd agentx manpage
I think metrics is a better word than statistics and it might help people if they knew where to query for these metrics. OK? martijn@ Index: relayd.conf.5 === RCS file: /cvs/src/usr.sbin/relayd/relayd.conf.5,v retrieving revision 1.201 diff -u -p -r1.201 relayd.conf.5 --- relayd.conf.5 22 Oct 2020 08:00:24 - 1.201 +++ relayd.conf.5 30 Oct 2020 08:48:23 - @@ -121,10 +121,12 @@ Here are the settings that can be set gl .It Ic agentx Oo Ic context Ar context Oc Oo Ic path Ar path Oc Export .Xr relayd 8 -statistics via an agentx compatible +metrics via an agentx compatible .Pq snmp daemon by connecting to .Ar path . +Metrics can be found under the relaydMIBObjects subtree +.Pq enterprises.30155.3 . If .Ar path is omitted it will default to
snmpd(8) Remove old listen on syntax
6.8 has been released. Time to remove the old syntax. OK? martijn@ ? dispatcher_tm_udp.c Index: parse.y === RCS file: /cvs/src/usr.sbin/snmpd/parse.y,v retrieving revision 1.61 diff -u -p -r1.61 parse.y --- parse.y 10 Sep 2020 17:54:47 - 1.61 +++ parse.y 29 Oct 2020 15:14:24 - @@ -130,7 +130,7 @@ typedef struct { %token NUMBER %typehostcmn %typesrcaddr port -%typeoptwrite yesno seclevel proto +%typeoptwrite yesno seclevel %type objtype cmd %type oid hostoid trapoid %type auth @@ -279,7 +279,7 @@ main: LISTEN ON listenproto listenproto: UDP listen_udp | TCP listen_tcp - | listen_empty + | listen_udp listen_udp : STRING port { struct sockaddr_storage ss[16]; @@ -335,34 +335,6 @@ listen_tcp : STRING port { } } -/* Remove after deprecation period and replace with listen_udp */ -listen_empty : STRING port proto { - struct sockaddr_storage ss[16]; - int nhosts, i; - - nhosts = host($1, $2, $3, ss, nitems(ss)); - if (nhosts < 1) { - yyerror("invalid address: %s", $1); - free($1); - if ($2 != snmpd_port) - free($2); - YYERROR; - } - if (nhosts > (int)nitems(ss)) - log_warn("%s:%s resolves to more than %zu hosts", - $1, $2, nitems(ss)); - - free($1); - if ($2 != snmpd_port) - free($2); - for (i = 0; i < nhosts; i++) { - if (listen_add(&(ss[i]), $3) == -1) { - yyerror("calloc"); - YYERROR; - } - } - } - port : /* empty */ { $$ = snmpd_port; } @@ -385,21 +357,6 @@ port : /* empty */ { YYERROR; } $$ = number; - } - ; - -proto : /* empty */ { - $$ = SOCK_DGRAM; - } - | UDP { - log_warnx("udp as last keyword on listen on line is " - "deprecated"); - $$ = SOCK_DGRAM; - } - | TCP { - log_warnx("tcp as last keyword on listen on line is " - "deprecated"); - $$ = SOCK_STREAM; } ;
relayd(8) remove snmp keyword
6.8 is out in the wild. I guess this is as good a time as any to remove the old snmp keyword. OK? martijn@ Index: parse.y === RCS file: /cvs/src/usr.sbin/relayd/parse.y,v retrieving revision 1.248 diff -u -p -r1.248 parse.y --- parse.y 26 Oct 2020 16:52:06 - 1.248 +++ parse.y 29 Oct 2020 14:49:54 - @@ -175,15 +175,15 @@ typedef struct { %token LOOKUP METHOD MODE NAT NO DESTINATION NODELAY NOTHING ON PARENT PATH %token PFTAG PORT PREFORK PRIORITY PROTO QUERYSTR REAL REDIRECT RELAY REMOVE %token REQUEST RESPONSE RETRY QUICK RETURN ROUNDROBIN ROUTE SACK SCRIPT SEND -%token SESSION SNMP SOCKET SPLICE SSL STICKYADDR STYLE TABLE TAG TAGGED TCP -%token TIMEOUT TLS TO ROUTER RTLABEL TRANSPARENT TRAP URL WITH TTL RTABLE +%token SESSION SOCKET SPLICE SSL STICKYADDR STYLE TABLE TAG TAGGED TCP +%token TIMEOUT TLS TO ROUTER RTLABEL TRANSPARENT URL WITH TTL RTABLE %token MATCH PARAMS RANDOM LEASTSTATES SRCHASH KEY CERTIFICATE PASSWORD ECDHE %token EDH TICKETS CONNECTION CONNECTIONS CONTEXT ERRORS STATE CHANGES CHECKS %token WEBSOCKETS %token STRING %token NUMBER -%typecontext hostname interface table value optstring path -%typehttp_type loglevel quick trap +%typecontext hostname interface table value path +%typehttp_type loglevel quick %typedstmode flag forwardmode retry %typeopttls opttlsclient %typeredirect_proto relay_proto match @@ -457,23 +457,6 @@ main : INTERVAL NUMBER { AGENTX_MASTER_PATH, sizeof(conf->sc_conf.agentx_path)); } - | SNMP trap optstring { - log_warnx("The snmp keyword is deprecated, please use agentx"); - conf->sc_conf.flags |= F_AGENTX; - if ($3) { - if (strlcpy(conf->sc_conf.agentx_path, - $3, sizeof(conf->sc_conf.agentx_path)) >= - sizeof(conf->sc_conf.agentx_path)) { - yyerror("agentx path truncated"); - free($3); - YYERROR; - } - free($3); - } else - (void)strlcpy(conf->sc_conf.agentx_path, - "/var/run/agentx.sock", - sizeof(conf->sc_conf.agentx_path)); - } | SOCKET STRING { conf->sc_ps->ps_csock.cs_name = $2; } @@ -485,9 +468,6 @@ path: /* nothing */ { $$ = NULL; } context: /* nothing */ { $$ = NULL; } | CONTEXT STRING{ $$ = $2; } -trap : /* nothing */ { $$ = 0; } - | TRAP { $$ = 1; } - loglevel : STATE CHANGES { $$ = RELAYD_OPT_LOGUPDATE; } | HOST CHECKS { $$ = RELAYD_OPT_LOGHOSTCHECK; } | CONNECTION{ $$ = (RELAYD_OPT_LOGCON | @@ -2371,10 +2351,6 @@ optnl: '\n' optnl nl : '\n' optnl ; - -optstring : STRING{ $$ = $1; } - | /* nothing */ { $$ = NULL; } - ; %% struct keywords { @@ -2499,7 +2475,6 @@ lookup(char *s) { "send", SEND }, { "session",SESSION }, { "set",SET }, - { "snmp", SNMP }, { "socket", SOCKET }, { "source-hash",SRCHASH }, { "splice", SPLICE }, @@ -2516,7 +2491,6 @@ lookup(char *s) { "tls",TLS }, { "to", TO }, { "transparent",TRANSPARENT }, - { "trap", TRAP }, { "ttl",TTL }, { "url",URL }, { "value", VALUE },
Re: libagentx add agentx_varbind_unsigned32
On Tue, 2020-10-27 at 19:09 +0100, Martijn van Duren wrote: > To prevent any future confusion around unsigned ints I'd like to add > agentx_varbind_unsigned32 as an alias to agentx_varbind_gauge32. > > According to RFC 2578 section 2: > -- an unsigned 32-bit quantity > -- indistinguishable from Gauge32 > > OK? > Still OK to ride yesterdays bump? > > martijn@ > And of course the manpage bits: Index: agentx.3 === RCS file: /cvs/src/lib/libagentx/agentx.3,v retrieving revision 1.3 diff -u -p -r1.3 agentx.3 --- agentx.327 Oct 2020 17:33:05 - 1.3 +++ agentx.327 Oct 2020 18:15:39 - @@ -62,6 +62,7 @@ .Nm agentx_varbind_ipaddress , .Nm agentx_varbind_counter32 , .Nm agentx_varbind_gauge32 , +.Nm agentx_varbind_unsigned32 , .Nm agentx_varbind_timeticks , .Nm agentx_varbind_opaque , .Nm agentx_varbind_counter64 , @@ -222,6 +223,8 @@ .Ft void .Fn agentx_varbind_gauge32 "struct agentx_varbind *sav" "uint32_t value" .Ft void +.Fn agentx_varbind_unsigned32 "struct agentx_varbind *sav" "uint32_t value" +.Ft void .Fo agentx_varbind_timeticks .Fa "struct agentx_varbind *sav" "uint32_t value" .Fc @@ -517,6 +520,8 @@ Set the return value to ipaddress. Set the return value to an uint32_t of type counter32. .It Fn agentx_varbind_gauge32 Set the return value to an uint32_t of type gauge32. +.It Fn agentx_varbind_unsigned32 +A wrapper around agentx_varbind_gauge32. .It Fn agentx_varbind_timeticks Set the return value to an uint32_t of type timeticks. .It Fn agentx_varbind_opaque
libagentx add agentx_varbind_unsigned32
To prevent any future confusion around unsigned ints I'd like to add agentx_varbind_unsigned32 as an alias to agentx_varbind_gauge32. According to RFC 2578 section 2: -- an unsigned 32-bit quantity -- indistinguishable from Gauge32 OK? Still OK to ride yesterdays bump? martijn@ Index: Symbols.list === RCS file: /cvs/src/lib/libagentx/Symbols.list,v retrieving revision 1.2 diff -u -p -r1.2 Symbols.list --- Symbols.list26 Oct 2020 15:45:56 - 1.2 +++ Symbols.list27 Oct 2020 18:08:51 - @@ -42,6 +42,7 @@ agentx_varbind_index agentx_varbind_ipaddress agentx_varbind_counter32 agentx_varbind_gauge32 +agentx_varbind_unsigned32 agentx_varbind_timeticks agentx_varbind_opaque agentx_varbind_counter64 Index: agentx.c === RCS file: /cvs/src/lib/libagentx/agentx.c,v retrieving revision 1.7 diff -u -p -r1.7 agentx.c --- agentx.c27 Oct 2020 17:19:44 - 1.7 +++ agentx.c27 Oct 2020 18:08:51 - @@ -3152,6 +3152,12 @@ agentx_varbind_gauge32(struct agentx_var } void +agentx_varbind_unsigned32(struct agentx_varbind *axv, uint32_t value) +{ + agentx_varbind_gauge32(axv, value); +} + +void agentx_varbind_timeticks(struct agentx_varbind *axv, uint32_t value) { axv->axv_vb.avb_type = AX_DATA_TYPE_TIMETICKS; Index: agentx.h === RCS file: /cvs/src/lib/libagentx/agentx.h,v retrieving revision 1.4 diff -u -p -r1.4 agentx.h --- agentx.h27 Oct 2020 17:19:44 - 1.4 +++ agentx.h27 Oct 2020 18:08:51 - @@ -116,6 +116,7 @@ void agentx_varbind_ipaddress(struct age const struct in_addr *); void agentx_varbind_counter32(struct agentx_varbind *, uint32_t); void agentx_varbind_gauge32(struct agentx_varbind *, uint32_t); +void agentx_varbind_unsigned32(struct agentx_varbind *, uint32_t); void agentx_varbind_timeticks(struct agentx_varbind *, uint32_t); void agentx_varbind_opaque(struct agentx_varbind *, const char *, size_t); void agentx_varbind_counter64(struct agentx_varbind *, uint64_t);
libagentx use variable for malloc argument
OK? martijn@ Index: ax.c === RCS file: /cvs/src/lib/libagentx/ax.c,v retrieving revision 1.2 diff -u -p -r1.2 ax.c --- ax.c26 Oct 2020 16:02:16 - 1.2 +++ ax.c26 Oct 2020 18:07:30 - @@ -69,9 +69,9 @@ ax_new(int fd) if ((ax = calloc(1, sizeof(*ax))) == NULL) return NULL; ax->ax_fd = fd; - if ((ax->ax_rbuf = malloc(512)) == NULL) - goto fail; ax->ax_rbsize = 512; + if ((ax->ax_rbuf = malloc(ax->ax_rbsize)) == NULL) + goto fail; ax->ax_byteorder = AX_BYTE_ORDER_NATIVE; return ax;
Let relayd use libagentx
Mostly mechanical diff coping with the API-change for libagentx just committed and link it to libagentx instead of using its own copy. This also allows for the removal of {sub,}agentx.[ch] subagentx_internal.h and subagentx_log.c, not included in the diff. OK? martijn@ Index: Makefile === RCS file: /cvs/src/usr.sbin/relayd/Makefile,v retrieving revision 1.34 diff -u -p -r1.34 Makefile --- Makefile14 Sep 2020 11:30:25 - 1.34 +++ Makefile26 Oct 2020 16:19:09 - @@ -2,15 +2,14 @@ PROG= relayd SRCS= parse.y -SRCS+= agentx.c agentx_control.c ca.c carp.c check_icmp.c \ - check_script.c check_tcp.c check_tls.c config.c control.c \ - hce.c log.c name2id.c pfe.c pfe_filter.c pfe_route.c proc.c \ - relay.c relay_http.c relay_udp.c relayd.c \ - shuffle.c ssl.c subagentx.c subagentx_log.c util.c +SRCS+= agentx_control.c ca.c carp.c check_icmp.c check_script.c \ + check_tcp.c check_tls.c config.c control.c hce.c log.c \ + name2id.c pfe.c pfe_filter.c pfe_route.c proc.c relay.c \ + relay_http.c relay_udp.c relayd.c shuffle.c ssl.c util.c MAN= relayd.8 relayd.conf.5 -LDADD= -levent -ltls -lssl -lcrypto -lutil -DPADD= ${LIBEVENT} ${LIBSSL} ${LIBCRYPTO} ${LIBUTIL} +LDADD= -lagentx -levent -ltls -lssl -lcrypto -lutil +DPADD= ${LIBAGENTX} ${LIBEVENT} ${LIBSSL} ${LIBCRYPTO} ${LIBUTIL} CFLAGS+= -Wall -I${.CURDIR} CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes CFLAGS+= -Wmissing-declarations Index: agentx_control.c === RCS file: /cvs/src/usr.sbin/relayd/agentx_control.c,v retrieving revision 1.2 diff -u -p -r1.2 agentx_control.c --- agentx_control.c25 Oct 2020 10:17:49 - 1.2 +++ agentx_control.c26 Oct 2020 16:19:09 - @@ -37,7 +37,7 @@ #include #include "relayd.h" -#include "subagentx.h" +#include #define RELAYD_MIB "1.3.6.1.4.1.30155.3" #define SNMP_ELEMENT(x...) do {\ @@ -52,7 +52,7 @@ static struct snmp_oidhosttrapoid = { }; */ -#define RELAYDINFO SUBAGENTX_ENTERPRISES, 30155, 3, 2 +#define RELAYDINFO AGENTX_ENTERPRISES, 30155, 3, 2 #define RELAYDREDIRECTSRELAYDINFO, 1 #define RELAYDREDIRECTENTRYRELAYDREDIRECTS, 1 #define RELAYDREDIRECTINDEXRELAYDREDIRECTENTRY, 1 @@ -124,69 +124,69 @@ static struct snmp_oidhosttrapoid = { #define RELAYDTABLENAMERELAYDTABLEENTRY, 2 #define RELAYDTABLESTATUS RELAYDTABLEENTRY, 3 -void agentx_needsock(struct subagentx *, void *, int); +void agentx_needsock(struct agentx *, void *, int); struct relayd *env; -struct subagentx *sa = NULL; -struct subagentx_index *relaydRedirectIdx, *relaydRelayIdx; -struct subagentx_index *relaydRouterIdx, *relaydNetRouteIdx; -struct subagentx_index *relaydHostIdx, *relaydSessionRelayIdx; -struct subagentx_index *relaydSessionIdx, *relaydTableIdx; - -struct subagentx_object *relaydRedirectIndex, *relaydRedirectStatus; -struct subagentx_object *relaydRedirectName, *relaydRedirectCnt; -struct subagentx_object *relaydRedirectAvg, *relaydRedirectLast; -struct subagentx_object *relaydRedirectAvgHour, *relaydRedirectLastHour; -struct subagentx_object *relaydRedirectAvgDay, *relaydRedirectLastDay; - -struct subagentx_object *relaydRelayIndex, *relaydRelayStatus; -struct subagentx_object *relaydRelayName, *relaydRelayCnt; -struct subagentx_object *relaydRelayAvg, *relaydRelayLast; -struct subagentx_object *relaydRelayAvgHour, *relaydRelayLastHour; -struct subagentx_object *relaydRelayAvgDay, *relaydRelayLastDay; - -struct subagentx_object *relaydRouterIndex, *relaydRouterTableIndex; -struct subagentx_object *relaydRouterStatus, *relaydRouterName; -struct subagentx_object *relaydRouterLabel, *relaydRouterRtable; - -struct subagentx_object *relaydNetRouteIndex, *relaydNetRouteAddr; -struct subagentx_object *relaydNetRouteAddrType, *relaydNetRoutePrefixLen; -struct subagentx_object *relaydNetRouteRouterIndex; - -struct subagentx_object *relaydHostIndex, *relaydHostParentIndex; -struct subagentx_object *relaydHostTableIndex, *relaydHostName; -struct subagentx_object *relaydHostAddress, *relaydHostAddressType; -struct subagentx_object *relaydHostStatus, *relaydHostCheckCnt; -struct subagentx_object *relaydHostUpCnt, *relaydHostErrno; - -struct subagentx_object *relaydSessionIndex, *relaydSessionRelayIndex; -struct subagentx_object *relaydSessionInAddr, *relaydSessionInAddrType; -struct subagentx_object *relaydSessionOutAddr, *relaydSessionOutAddrType; -struct subagentx_object *relaydSessionPortIn, *relaydSessionPortOut; -struct subagentx_object *relaydSessionAge, *relaydSessionIdle; -struct subagentx_object *relaydSessionStatus, *relaydSessionPid; +struct agentx *sa
Re: ping(8) put hop_limit warning in verbose mode
On Tue, 2020-10-20 at 15:59 +0200, Florian Obser wrote: > On Tue, Oct 20, 2020 at 03:46:19PM +0200, Martijn van Duren wrote: > > On Tue, 2020-10-20 at 15:19 +0200, Florian Obser wrote: > > > On Tue, Oct 20, 2020 at 09:20:32AM +0200, Martijn van Duren wrote: > > > > I have an icinga-instance running on openbsd.amsterdam. Here I found > > > > that sometimes check_ping from the monitoring-plugins package fails, > > > > because ping(8) sends "failed to get receiving hop limit", but still > > > > receives all the ping replies. These packets/annomalies are clearly > > > > not meant for us. > > > > > > But it is. This is comming from the local machine, > > > see L949ff of netinet6/ip6_input.c. > > > > What I meant to say is meant for ping(8). All the icmp echo replies > > still arrive and are accounted for. > > > > I don't understand. > > I patched the kernel to make sbcreatecontrol() fail 50% of the time: > > $ ping6 -qc10 fe80::5667:51ff:fede:e7ce%vio0 > PING fe80::5667:51ff:fede:e7ce%vio0 (fe80::5667:51ff:fede:e7ce%vio0): 56 data > bytes > ping6: failed to get receiving hop limit > ping6: failed to get receiving hop limit > ping6: failed to get receiving hop limit > ping6: failed to get receiving hop limit > > --- fe80::5667:51ff:fede:e7ce%vio0 ping statistics --- > 10 packets transmitted, 6 packets received, 40.0% packet loss > round-trip min/avg/max/std-dev = 0.980/1.196/1.955/0.342 ms > > I assure you, I do not have 40% packet loss towards my gateway. > The packets are not accounted for. > When running: /usr/local/libexec/nagios/check_ping -vv -6 -H -c 500,75% -w 250,50% in a tight loop at some point I get the following output: CMD: /sbin/ping6 -n -c 5 Output: PING (): 56 data bytes Output: 64 bytes from : icmp_seq=0 hlim=57 time=1.724 ms Output: 64 bytes from : icmp_seq=1 hlim=57 time=1.612 ms Output: 64 bytes from : icmp_seq=2 hlim=57 time=1.785 ms Output: 64 bytes from : icmp_seq=3 hlim=57 time=1.762 ms Output: 64 bytes from : icmp_seq=4 hlim=57 time=1.708 ms Output: Output: --- ping statistics --- Output: 5 packets transmitted, 5 packets received, 0.0% packet loss Output: round-trip min/avg/max/std-dev = 1.612/1.718/1.785/0.060 ms Got stderr: ping6: failed to get receiving hop limit PING WARNING - System call sent warnings to stderr Packet loss = 0%, RTA = 1.72 ms|rta=1.718000ms;3000.00;5000.00;0.00 pl=0%;80;100;0 3000.00:80% 5000.00:100% So I have 5 echo requests, 5 echo replies and one unrelated packet not related to my ping command. Yet this notice to stderr forces check_ping into a warning state.
Re: ping(8) put hop_limit warning in verbose mode
On Tue, 2020-10-20 at 15:19 +0200, Florian Obser wrote: > On Tue, Oct 20, 2020 at 09:20:32AM +0200, Martijn van Duren wrote: > > I have an icinga-instance running on openbsd.amsterdam. Here I found > > that sometimes check_ping from the monitoring-plugins package fails, > > because ping(8) sends "failed to get receiving hop limit", but still > > receives all the ping replies. These packets/annomalies are clearly > > not meant for us. > > But it is. This is comming from the local machine, > see L949ff of netinet6/ip6_input.c. What I meant to say is meant for ping(8). All the icmp echo replies still arrive and are accounted for. > sbcreatecontrol() fails because it tries to allocate space with > M_DONTWAIT. Looks like you drove your system out of resources. I see nothing in dmesg or the logs. Is there another to verify this? And assuming it is indeed run out of resources, is there a way to fix this, because the (virtual) hardware doesn't looks swamped. > > While the local system receives all replies and passes them on to > ping6(8) they are not counted as received. So ping6(8) will report > packet loss while there is none. In this case it's the other way around: warnings are being generated, but all icmp echo replies are received intact by ping(8). But I understand your point. The question remains then how I can debug this further. > I think it's a mistake to hide the warning because it will lead people > on a wild goose chase. > Also since ping6(8) will report packet loss I'm not conviced this will > solve your problem. > > > Since this check is done before the ICMP6_ECHO_REPLY check and our > > manpage states: > > -v Verbose output. ICMP packets other than ECHO_REPLY that are > > received are listed. > > I think the following diff is warranted and solves my false warning > > states. > > > > OK? > > > > martijn@ > > > > Index: ping.c > > === > > RCS file: /cvs/src/sbin/ping/ping.c,v > > retrieving revision 1.240 > > diff -u -p -r1.240 ping.c > > --- ping.c 11 Feb 2020 18:41:39 - 1.240 > > +++ ping.c 20 Oct 2020 07:19:49 - > > @@ -1180,7 +1180,8 @@ pr_pack(u_char *buf, int cc, struct msgh > > icp6 = (struct icmp6_hdr *)buf; > > > > if ((hoplim = get_hoplim(mhdr)) == -1) { > > - warnx("failed to get receiving hop limit"); > > + if (options & F_VERBOSE) > > + warnx("failed to get receiving hop limit"); > > return; > > } > > > >
ping(8) put hop_limit warning in verbose mode
I have an icinga-instance running on openbsd.amsterdam. Here I found that sometimes check_ping from the monitoring-plugins package fails, because ping(8) sends "failed to get receiving hop limit", but still receives all the ping replies. These packets/annomalies are clearly not meant for us. Since this check is done before the ICMP6_ECHO_REPLY check and our manpage states: -v Verbose output. ICMP packets other than ECHO_REPLY that are received are listed. I think the following diff is warranted and solves my false warning states. OK? martijn@ Index: ping.c === RCS file: /cvs/src/sbin/ping/ping.c,v retrieving revision 1.240 diff -u -p -r1.240 ping.c --- ping.c 11 Feb 2020 18:41:39 - 1.240 +++ ping.c 20 Oct 2020 07:19:49 - @@ -1180,7 +1180,8 @@ pr_pack(u_char *buf, int cc, struct msgh icp6 = (struct icmp6_hdr *)buf; if ((hoplim = get_hoplim(mhdr)) == -1) { - warnx("failed to get receiving hop limit"); + if (options & F_VERBOSE) + warnx("failed to get receiving hop limit"); return; }
Re: Non-const basename: usr.bin/sed
On Sat, 2020-10-10 at 17:21 +0200, Christian Weisgerber wrote: > Changing basename(3) and dirname(3) to the POSIX-mandated non-const > parameters produces this warnings when compiling sed(1): > > /usr/src/usr.bin/sed/main.c:401:16: warning: passing 'const char *' to > parameter > of type 'char *' discards qualifiers > [-Wincompatible-pointer-types-discards-qua > lifiers] > > Here's a fix to accommodate a basename(3) that takes a non-const > parameter and may in fact modify the string buffer. Based on FreeBSD > like the surrounding in-place editing code. > > OK? > Wouldn't the following diff be a little simpler? No need to check the return value of strlcpy, since we do a lstat before, which can return a ENAMETOOLONG. martijn@ Index: main.c === RCS file: /cvs/src/usr.bin/sed/main.c,v retrieving revision 1.40 diff -u -p -r1.40 main.c --- main.c 8 Dec 2018 23:11:24 - 1.40 +++ main.c 10 Oct 2020 17:51:53 - @@ -343,6 +343,7 @@ mf_fgets(SPACE *sp, enum e_spflag spflag { struct stat sb; size_t len; + char dirbuf[PATH_MAX]; char *p; int c, fd; static int firstfile; @@ -397,8 +398,9 @@ mf_fgets(SPACE *sp, enum e_spflag spflag if (len > sizeof(oldfname)) error(FATAL, "%s: name too long", fname); } - len = snprintf(tmpfname, sizeof(tmpfname), "%s/sedXX", - dirname(fname)); + strlcpy(dirbuf, fname, sizeof(dirbuf)); + len = snprintf(tmpfname, sizeof(tmpfname), + "%s/sedXX", dirname(dirbuf)); if (len >= sizeof(tmpfname)) error(FATAL, "%s: name too long", fname); if ((fd = mkstemp(tmpfname)) == -1)
pthread_spin_unlock and ownership behaviour
Back in 2012 kurt@ added an abort call for the undefined behaviour cases on pthread_mutex_unlock. This helped me a great deal in examining the cause of some weird behaviour in icinga (or in the case of openbsd, just plain crash). For shits and giggles I deceided to look into pthread_spin_unlock and saw that we return EPERM here, while POSIX states that this behaviour is unconditionally undefined.[0] Is there a reason why we shouldn't abort here as well? I don't have a particular usecase for this, but the mutex case helped me and it only seems like the right thing to do from a semetrical point of view. The only cases of pthread_spin_unlock in base I found were in libunbound (which with my testing with unwind didn't caused any issues) and gnu/llvm/compiler-rt/lib/tsan, which I don't know where to test. I have no idea which ports use it. martijn@ [0] https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_spin_unlock.html Index: librthread/rthread_spin_lock.c === RCS file: /cvs/src/lib/librthread/rthread_spin_lock.c,v retrieving revision 1.5 diff -u -p -r1.5 rthread_spin_lock.c --- librthread/rthread_spin_lock.c 6 Apr 2020 00:01:08 - 1.5 +++ librthread/rthread_spin_lock.c 3 Oct 2020 09:42:21 - @@ -102,12 +102,12 @@ pthread_spin_unlock(pthread_spinlock_t * pthread_spinlock_t l; if (lock == NULL || *lock == NULL) - return (EINVAL); + abort(); l = *lock; if (l->owner != self) - return (EPERM); + abort(); l->owner = NULL; _spinunlock(>lock); Index: libpthread/man/pthread_spin_unlock.3 === RCS file: /cvs/src/lib/libpthread/man/pthread_spin_unlock.3,v retrieving revision 1.3 diff -u -p -r1.3 pthread_spin_unlock.3 --- libpthread/man/pthread_spin_unlock.36 Apr 2020 00:01:08 - 1.3 +++ libpthread/man/pthread_spin_unlock.33 Oct 2020 09:42:21 - @@ -38,17 +38,14 @@ functions. .Sh RETURN VALUES If successful, .Fn pthread_spin_unlock -returns zero; otherwise an error number is returned to indicate the error. +returns zero. .Sh ERRORS .Fn pthread_spin_unlock -will fail if: -.Bl -tag -width Er -.It Bq Er EINVAL -The value specified by +will call +.Xr abort 3 +if the value specified by .Fa lock -is invalid. -.It Bq Er EPERM -The lock is not owned by the calling thread. +is invalid or if the lock is not owned by the calling thread. .El .Sh SEE ALSO .Xr pthread_spin_init 3 ,
snmp(1) Add support for printing human readable enums
SNMP contains quite a few enumerations, which are annoying to read, even if you have the MIB at hand. This diff adds support for integer enumerations. I've only implemented TruthValue for now, but others should be easy to add. I went for a normal linear search since most enums don't even hit 10 elements, comparison is int-based and thus the added complexity of something like RB_* seems like enormous overkill. I've removed BER_TYPE_BOOLEAN, since it's not part of the SNMP-spec and thus dead code. I added it originally because snmpd's smi.c contained it. I should probably rewrite smi_print_element at some point, but I'm not confident enough in its intricacies to make that jump just yet. One thing at a time. OK? martijn@ Index: mib.h === RCS file: /cvs/src/usr.bin/snmp/mib.h,v retrieving revision 1.8 diff -u -p -r1.8 mib.h --- mib.h 12 Sep 2020 18:11:43 - 1.8 +++ mib.h 20 Sep 2020 15:23:48 - @@ -1034,8 +1034,8 @@ { MIBDECL(ifHCOutBroadcastPkts) }, \ { MIBDECL(ifLinkUpDownTrapEnable) },\ { MIBDECL(ifHighSpeed) }, \ - { MIBDECL(ifPromiscuousMode) }, \ - { MIBDECL(ifConnectorPresent) },\ + { MIBDECL(ifPromiscuousMode), "TruthValue" }, \ + { MIBDECL(ifConnectorPresent), "TruthValue" }, \ { MIBDECL(ifAlias) }, \ { MIBDECL(ifCounterDiscontinuityTime) },\ { MIBDECL(ifStackTable) }, \ @@ -1460,10 +1460,15 @@ { MIBEND } \ } -#define TEXTCONV_TREE {\ - { "SnmpAdminString", "255t", BER_TYPE_OCTETSTRING }, \ - { "DisplayString", "255a", BER_TYPE_OCTETSTRING }, \ - { NULL, NULL } \ +#define TEXTCONV_TREE { \ + { "SnmpAdminString", BER_TYPE_OCTETSTRING, "255t" },\ + { "DisplayString", BER_TYPE_OCTETSTRING, "255a" }, \ + { "TruthValue", BER_TYPE_INTEGER, NULL, (struct textconv_enum[]){\ + { 1, "true" }, \ + { 2, "false" }, \ + {} \ + }}, \ + { }\ } voidmib_init(void); Index: smi.c === RCS file: /cvs/src/usr.bin/snmp/smi.c,v retrieving revision 1.12 diff -u -p -r1.12 smi.c --- smi.c 8 Aug 2020 13:02:54 - 1.12 +++ smi.c 20 Sep 2020 15:23:48 - @@ -39,6 +39,7 @@ #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) char *smi_displayhint_os(struct textconv *, int, const char *, size_t, int); +char *smi_displayhint_int(struct textconv*, int, long long); int smi_oid_cmp(struct oid *, struct oid *); int smi_key_cmp(struct oid *, struct oid *); @@ -254,7 +255,6 @@ smi_print_element(struct ber_oid *oid, s struct textconv tckey; size_t len, i, slen; long longv, ticks; - int d; int is_hex = 0, ret; struct ber_oid o; char strbuf[BUFSIZ]; @@ -276,17 +276,6 @@ smi_print_element(struct ber_oid *oid, s } switch (root->be_encoding) { - case BER_TYPE_BOOLEAN: - if (ober_get_boolean(root, ) == -1) - goto fail; - if (print_hint) { - if (asprintf(, "INTEGER: %s(%d)", - d ? "true" : "false", d) == -1) - goto fail; - } else - if (asprintf(, "%s", d ? "true" : "false") == -1) - goto fail; - break; case BER_TYPE_INTEGER: case BER_TYPE_ENUMERATED: if (ober_get_integer(root, ) == -1) @@ -345,6 +334,10 @@ smi_print_element(struct ber_oid *oid, s break; } hint = "INTEGER: "; + if (object != NULL && object->o_textconv != NULL && + object->o_textconv->tc_syntax == root->be_encoding) + return smi_displayhint_int(object->o_textconv, + print_hint, v); if (root->be_class == BER_CLASS_APPLICATION) { if (root->be_type == SNMP_T_COUNTER32) hint = "Counter32: "; @@ -628,6 +621,31 @@ smi_foreach(struct oid *oid) if (oid == NULL) return RB_MIN(oidtree, _oidtree); return RB_NEXT(oidtree, _oidtree, oid); +} + +char *
Re: Fwd: opensmtpd can't handle long lines in aliases table
That's what you get if you're doing a quick diff on the job. Missed a free case which is in Edgar's original diff. Noticed by tb@ On Fri, 2020-09-18 at 14:46 +0200, Martijn van Duren wrote: > Could you try the diff below? > It should do exactly the same thing with less code. > > martijn@ > > On Fri, 2020-09-18 at 08:30 -0400, Aisha Tammy wrote: > > Hi, > > > > Edgar (cc'ed) has kindly provided patches to fix a buffer error in > > mailaddr.c > > for opensmtpd. > > > > I've minimally tested it and am forwarding the patches. > > > > Would like to be able to get them into 6.8 release as this is quite > > problematic > > with lots of aliases. > > > > Thanks, > > Aisha > > > > > > Forwarded Message > > Subject: Re: opensmtpd can't handle long lines in aliases table > > Date: Thu, 6 Aug 2020 19:47:33 -0500 > > From: Edgar Pettijohn > > To: AIsha Tammy > > > > Here are a few simple patches as discussed. These were written to apply > > against current. However, they are pretty simple and may well apply to > > others. With that in mind if you are using any filters they may not > > work. My production system is still a couple version behind and the > > current smtpd wouldn't work with some of my custom filters. So I had to > > use a fairly basic temporary config for testing. I'm also including my > > test table. > > > > Steps involved: (untested off memory mostly, use doas as necessary) > > > > cd /usr > > cvs -d $CVSROOT checkout src > > > > cp *.patch /usr/src/usr.sbin/smtpd > > cd /usr/src/usr.sbin/smtpd > > > > for file in `ls *.patch` > > do > > patch < $file > > done > > > > make > > rcctl stop smtpd > > > > #use the just built version at /usr/src/usr.sbin/smtpd/smtpd/smtpd > > smtpd/smtpd -d -T expand > > > > send a test email > > > > if all goes well run it for an appropriat amount of time and make sure > > there are not issues. If your satisfied send the patches to bugs@. > > > > Enjoy, > > > > Edgar > > Index: mailaddr.c === RCS file: /cvs/src/usr.sbin/smtpd/mailaddr.c,v retrieving revision 1.3 diff -u -p -r1.3 mailaddr.c --- mailaddr.c 31 May 2018 21:06:12 - 1.3 +++ mailaddr.c 18 Sep 2020 12:55:41 - @@ -80,12 +80,10 @@ int mailaddr_line(struct maddrmap *maddrmap, const char *s) { struct maddrnodemn; - charbuffer[LINE_MAX]; - char *p, *subrcpt; + char *p, *subrcpt, *buffer; int ret; - memset(buffer, 0, sizeof buffer); - if (strlcpy(buffer, s, sizeof buffer) >= sizeof buffer) + if ((buffer = strdup(s)) == NULL) return 0; p = buffer; @@ -93,11 +91,15 @@ mailaddr_line(struct maddrmap *maddrmap, subrcpt = strip(subrcpt); if (subrcpt[0] == '\0') continue; - if (!text_to_mailaddr(, subrcpt)) + if (!text_to_mailaddr(, subrcpt)) { + free(buffer); return 0; + } log_debug("subrcpt: [%s]", subrcpt); maddrmap_insert(maddrmap, ); } + + free(buffer); if (ret >= 0) return 1;
Re: Fwd: opensmtpd can't handle long lines in aliases table
Could you try the diff below? It should do exactly the same thing with less code. martijn@ On Fri, 2020-09-18 at 08:30 -0400, Aisha Tammy wrote: > Hi, > > Edgar (cc'ed) has kindly provided patches to fix a buffer error in > mailaddr.c > for opensmtpd. > > I've minimally tested it and am forwarding the patches. > > Would like to be able to get them into 6.8 release as this is quite > problematic > with lots of aliases. > > Thanks, > Aisha > > > Forwarded Message > Subject: Re: opensmtpd can't handle long lines in aliases table > Date: Thu, 6 Aug 2020 19:47:33 -0500 > From: Edgar Pettijohn > To: AIsha Tammy > > Here are a few simple patches as discussed. These were written to apply > against current. However, they are pretty simple and may well apply to > others. With that in mind if you are using any filters they may not > work. My production system is still a couple version behind and the > current smtpd wouldn't work with some of my custom filters. So I had to > use a fairly basic temporary config for testing. I'm also including my > test table. > > Steps involved: (untested off memory mostly, use doas as necessary) > > cd /usr > cvs -d $CVSROOT checkout src > > cp *.patch /usr/src/usr.sbin/smtpd > cd /usr/src/usr.sbin/smtpd > > for file in `ls *.patch` > do > patch < $file > done > > make > rcctl stop smtpd > > #use the just built version at /usr/src/usr.sbin/smtpd/smtpd/smtpd > smtpd/smtpd -d -T expand > > send a test email > > if all goes well run it for an appropriat amount of time and make sure > there are not issues. If your satisfied send the patches to bugs@. > > Enjoy, > > Edgar > > Index: mailaddr.c === RCS file: /cvs/src/usr.sbin/smtpd/mailaddr.c,v retrieving revision 1.3 diff -u -p -r1.3 mailaddr.c --- mailaddr.c 31 May 2018 21:06:12 - 1.3 +++ mailaddr.c 18 Sep 2020 12:45:46 - @@ -80,12 +80,10 @@ int mailaddr_line(struct maddrmap *maddrmap, const char *s) { struct maddrnodemn; - charbuffer[LINE_MAX]; - char *p, *subrcpt; + char *p, *subrcpt, *buffer; int ret; - memset(buffer, 0, sizeof buffer); - if (strlcpy(buffer, s, sizeof buffer) >= sizeof buffer) + if ((buffer = strdup(s)) == NULL) return 0; p = buffer; @@ -98,6 +96,8 @@ mailaddr_line(struct maddrmap *maddrmap, log_debug("subrcpt: [%s]", subrcpt); maddrmap_insert(maddrmap, ); } + + free(buffer); if (ret >= 0) return 1;
syslogd close higher fds on pipe exec
I don't think we should keep these fds around on exec. OK? Index: privsep.c === RCS file: /cvs/src/usr.sbin/syslogd/privsep.c,v retrieving revision 1.71 diff -u -p -r1.71 privsep.c --- privsep.c 5 Jul 2019 13:23:27 - 1.71 +++ privsep.c 16 Sep 2020 09:59:36 - @@ -519,6 +519,7 @@ open_pipe(char *cmd) if (dup2(fd[0], STDIN_FILENO) == -1) err(1, "dup2 failed"); + closefrom(STDERR_FILENO + 1); if (execv("/bin/sh", argp) == -1) err(1, "execv %s", cmd); /* NOTREACHED */
agentx in services
I currently don't see any reason for adding agentx over tcp support to our daemons, but according to RFC2741 section 8.1.1 it should go over "wel-known port 705". Worth adding or just drop it? martijn@ Index: services === RCS file: /cvs/src/etc/services,v retrieving revision 1.97 diff -u -p -r1.97 services --- services26 Jun 2020 19:51:14 - 1.97 +++ services15 Sep 2020 09:43:00 - @@ -175,6 +175,7 @@ ldaps 636/tcp # LDAP over SSL ldaps 636/udp ldp646/tcp ldp646/udp +agentx 705/tcp silc 706/tcp # Secure Live Internet Conferencing silc 706/udp kerberos-adm 749/tcp # Kerberos 5 kadmin
Re: agentx and clang static analyzer
> > Index: subagentx.c > > === > > RCS file: /cvs/src/usr.sbin/relayd/subagentx.c,v > > retrieving revision 1.1 > > diff -u -p -r1.1 subagentx.c > > --- subagentx.c 14 Sep 2020 11:30:25 - 1.1 > > +++ subagentx.c 15 Sep 2020 09:05:58 - > > @@ -2929,7 +2929,7 @@ getnext: > > index->sav_idatacomplete = 1; > > break; > > case AGENTX_DATA_TYPE_IPADDRESS: > > - ipaddress = calloc(1, sizeof(ipaddress)); > > + ipaddress = calloc(1, sizeof(*ipaddress)); > > if (ipaddress == NULL) { > > subagentx_log_sag_warn(sag, > > "Failed to bind ipaddress index"); > > Not ok for this, it's probably correct, but there are other instances of this > in this code and so you need to engage brain, not static analyzer, go fix or > don't fix them all in a separate commit. > Could only find one more: Index: subagentx.c === RCS file: /cvs/src/usr.sbin/relayd/subagentx.c,v retrieving revision 1.1 diff -u -p -r1.1 subagentx.c --- subagentx.c 14 Sep 2020 11:30:25 - 1.1 +++ subagentx.c 15 Sep 2020 09:27:46 - @@ -2929,7 +2929,7 @@ getnext: index->sav_idatacomplete = 1; break; case AGENTX_DATA_TYPE_IPADDRESS: - ipaddress = calloc(1, sizeof(ipaddress)); + ipaddress = calloc(1, sizeof(*ipaddress)); if (ipaddress == NULL) { subagentx_log_sag_warn(sag, "Failed to bind ipaddress index"); @@ -2951,7 +2951,7 @@ getnext: } if (j <= sav->sav_vb.avb_oid.aoi_idlen) index->sav_idatacomplete = 1; - data->avb_ostring.aos_slen = sizeof(ipaddress); + data->avb_ostring.aos_slen = sizeof(*ipaddress); data->avb_ostring.aos_string = (unsigned char *)ipaddress; break;
agentx and clang static analyzer
There are 3 things that actually look like valid complaints when running clang's static analyzer. 1) A dead store in agentx_recv. 2) sizeof(ipaddress) intead of sizeof(*ipaddress). Since this is ipv4, this is only a problem if sizeof(pointer) is smaller then 4 bytes, which can't happen afaik. 3) dst does indeed need to be dereffed, but since dstlen and buflen are initialized to 0 and srclen is practically always larger then 0 we're fine. I'm keeping the *dst here as an additional safeguard. The rest seem like false positives to me. OK? martijn@ Index: agentx.c === RCS file: /cvs/src/usr.sbin/relayd/agentx.c,v retrieving revision 1.16 diff -u -p -r1.16 agentx.c --- agentx.c14 Sep 2020 11:30:25 - 1.16 +++ agentx.c15 Sep 2020 09:05:57 - @@ -135,7 +135,6 @@ agentx_recv(struct agentx *ax) header.aph_packetid = agentx_pdutoh32(, u8); u8 += 4; header.aph_plength = agentx_pdutoh32(, u8); - u8 += 4; if (header.aph_version != 1) { errno = EPROTO; Index: subagentx.c === RCS file: /cvs/src/usr.sbin/relayd/subagentx.c,v retrieving revision 1.1 diff -u -p -r1.1 subagentx.c --- subagentx.c 14 Sep 2020 11:30:25 - 1.1 +++ subagentx.c 15 Sep 2020 09:05:58 - @@ -2929,7 +2929,7 @@ getnext: index->sav_idatacomplete = 1; break; case AGENTX_DATA_TYPE_IPADDRESS: - ipaddress = calloc(1, sizeof(ipaddress)); + ipaddress = calloc(1, sizeof(*ipaddress)); if (ipaddress == NULL) { subagentx_log_sag_warn(sag, "Failed to bind ipaddress index"); @@ -3833,7 +3833,7 @@ subagentx_strcat(char **dst, const char } srclen = strlen(src); - if (dst == NULL || dstlen + srclen > buflen) { + if (*dst == NULL || dstlen + srclen > buflen) { nbuflen = (((dstlen + srclen) / 512) + 1) * 512; tmp = recallocarray(*dst, buflen, nbuflen, sizeof(*tmp)); if (tmp == NULL)
snmp request specific OIDs from mibtree
Sometimes I want to know the OID from a name and vice versa. I'm done doing these by hand. Diff below does this for me: $ ./obj/snmp mibtree -On snmpTrapOID.0 .1.3.6.1.6.3.1.1.4.1.0 OK? martijn@ Index: snmp.1 === RCS file: /cvs/src/usr.bin/snmp/snmp.1,v retrieving revision 1.14 diff -u -p -r1.14 snmp.1 --- snmp.1 8 Aug 2020 07:11:47 - 1.14 +++ snmp.1 14 Sep 2020 14:50:09 - @@ -49,6 +49,7 @@ .Nm .Cm mibtree .Op Fl O Ar fns +.Op Ar oid ... .Sh DESCRIPTION The .Nm @@ -165,8 +166,12 @@ An SNMP based version of the .Xr df 1 command. If no size suffix is shown the sizes are in kilobytes. -.It Nm Cm mibtree Op Fl O Ar fnS +.It Nm Cm mibtree Oo Fl O Ar fnS Oc Op Ar oid ... Dump the tree of compiled-in MIB objects. +If +.Ar oid +is specified it wil print the objects in the requested output format if +available, or print a warning if the object can't be found. .El .Pp The Index: snmpc.c === RCS file: /cvs/src/usr.bin/snmp/snmpc.c,v retrieving revision 1.29 diff -u -p -r1.29 snmpc.c --- snmpc.c 12 Sep 2020 18:11:43 - 1.29 +++ snmpc.c 14 Sep 2020 14:50:10 - @@ -80,7 +80,7 @@ struct snmp_app snmp_apps[] = { { "set", 1, NULL, "agent oid type value [oid type value] ...", snmpc_set }, { "trap", 1, NULL, "agent uptime oid [oid type value] ...", snmpc_trap }, { "df", 1, "C:", "[-Ch] [-Cr] agent", snmpc_df }, - { "mibtree", 0, "O:", "[-O fnS]", snmpc_mibtree } + { "mibtree", 0, "O:", "[-O fnS] [oid] ...", snmpc_mibtree } }; struct snmp_app *snmp_app = NULL; @@ -1060,11 +1060,25 @@ int snmpc_mibtree(int argc, char *argv[]) { struct oid *oid; + struct ber_oid soid; char buf[BUFSIZ]; + int i; - for (oid = NULL; (oid = smi_foreach(oid)) != NULL;) { - smi_oid2string(>o_id, buf, sizeof(buf), oid_lookup); - printf("%s\n", buf); + if (argc == 0) { + for (oid = NULL; (oid = smi_foreach(oid)) != NULL;) { + smi_oid2string(>o_id, buf, sizeof(buf), + oid_lookup); + printf("%s\n", buf); + } + } else { + for (i = 0; i < argc; i++) { + if (smi_string2oid(argv[i], ) == -1) { + warnx("%s: Unknown object identifier", argv[i]); + continue; + } + smi_oid2string(, buf, sizeof(buf), oid_lookup); + printf("%s\n", buf); + } } return 0; }
Re: smtpd.conf add admd keyword
Any takers? On Sun, 2020-09-06 at 17:06 +0200, Martijn van Duren wrote: > EHLO, > > RFC8601 defines the authentication-results header which can be used to > show the verification-results of DKIM, SPF, DMARC, and others. > > I can think of quite a few filters that could be build around this > header: > - the prior mentioned > - detecting the header before accepting it into ones ADMD > - using it to calculate some sort of spam-score by some other filter > > These are the 3 main categories that spring to mind, with especially > the first one having the option to be split in quite a few different > filters on itself. > > Since setting the authservid on every of these filters (once they > arrive) will be cumbersome and error-prone I would like to propose to > distribute this value from a single point in the smtpd.conf. > > I already have a filter-admdscrub basically ready and I'm working on a > filter-dkimverify every now and then (no where near done yet) which can > use this feature. > > OK? > > martijn@ > > Index: lka_filter.c > === > RCS file: /cvs/src/usr.sbin/smtpd/lka_filter.c,v > retrieving revision 1.62 > diff -u -p -r1.62 lka_filter.c > --- lka_filter.c 24 Apr 2020 11:34:07 - 1.62 > +++ lka_filter.c 6 Sep 2020 15:05:21 - > @@ -210,6 +210,8 @@ lka_proc_config(struct processor_instanc > io_printf(pi->io, "config|subsystem|smtp-in\n"); > if (pi->subsystems & FILTER_SUBSYSTEM_SMTP_OUT) > io_printf(pi->io, "config|subsystem|smtp-out\n"); > + io_printf(pi->io, "config|admd|%s\n", > + env->sc_admd != NULL ? env->sc_admd : env->sc_hostname); > io_printf(pi->io, "config|ready\n"); > } > > Index: parse.y > === > RCS file: /cvs/src/usr.sbin/smtpd/parse.y,v > retrieving revision 1.278 > diff -u -p -r1.278 parse.y > --- parse.y 1 Jun 2020 05:21:30 - 1.278 > +++ parse.y 6 Sep 2020 15:05:21 - > @@ -173,7 +173,7 @@ typedef struct { > > %} > > -%token ACTION ALIAS ANY ARROW AUTH AUTH_OPTIONAL > +%token ACTION ADMD ALIAS ANY ARROW AUTH AUTH_OPTIONAL > %token BACKUP BOUNCE BYPASS > %token CA CERT CHAIN CHROOT CIPHERS COMMIT COMPRESSION CONNECT > %token DATA DATA_LINE DHE DISCONNECT DOMAIN > @@ -209,6 +209,7 @@ grammar : /* empty */ > | grammar include '\n' > | grammar varset '\n' > | grammar bounce '\n' > + | grammar admd '\n' > | grammar ca '\n' > | grammar mda '\n' > | grammar mta '\n' > @@ -310,6 +311,21 @@ BOUNCE WARN_INTERVAL { > ; > > > +admd: > +ADMD STRING { > + size_t i; > + > + for (i = 0; $2[i] != '\0'; i++) { > + if (!isprint($2[i])) { > + yyerror("not a valid admd"); > + free($2); > + YYERROR; > + } > + } > + conf->sc_admd = $2; > +}; > + > + > ca: > CA STRING { > char buf[HOST_NAME_MAX+1]; > @@ -2603,6 +2619,7 @@ lookup(char *s) > /* this has to be sorted always */ > static const struct keywords keywords[] = { > { "action", ACTION }, > + { "admd", ADMD }, > { "alias", ALIAS }, > { "any",ANY }, > { "auth", AUTH }, > Index: smtpd.conf.5 > === > RCS file: /cvs/src/usr.sbin/smtpd/smtpd.conf.5,v > retrieving revision 1.251 > diff -u -p -r1.251 smtpd.conf.5 > --- smtpd.conf.5 27 Aug 2020 08:58:30 - 1.251 > +++ smtpd.conf.5 6 Sep 2020 15:05:21 - > @@ -313,6 +313,11 @@ which is useful on machines with multipl > If the list contains more than one address, all of them are used > in such a way that traffic is routed as efficiently as possible. > .El > +.It Ic admd Ar authservid > +The Administrative Management Domain this mailserver belongs to. > +The authservid will be forwarded to filters using it to identify or mark > +authentication-results headers. > +If omitted it defaults to the server name. > .It Ic bounce Cm warn-interval Ar delay Op , Ar delay ... > Send warning messages to the envelope sender when temporary delivery > failures cause a message to remain on the queue for longer than > Index: smtpd.h >
Re: snmpd refactor listen on grammar
On Tue, 2020-09-08 at 19:33 +0200, Denis Fondras wrote: > On Sun, Sep 06, 2020 at 10:11:02PM +0200, Martijn van Duren wrote: > > Moving towards individual transport mappings, it's becoming more > > convenient to have the protocol directly after the listen on statement. > > This gives me more flexibility in using mapping-specific APIs, also > > when other transport mappings might become available in the future it > > allows for easier mapping-specific features. > > > > While here I decided to also add port support for snmpe, which at this > > point is rather trivial. Traphandler is not my point of focus at this > > time. > > > > having udp|tcp at the last position is still supported, but generates a > > pretty deprecated warning. Probably to be removed after release. > > > > OK? > > > > OK denis@ > > Can you check that port > 0 ? Because it prints "snmpd.conf:7: invalid > address: ::1" which is not correct (though using 0 or -1 for port is a weird > idea). > > > martijn@ > > Sure Index: parse.y === RCS file: /cvs/src/usr.sbin/snmpd/parse.y,v retrieving revision 1.60 diff -u -p -r1.60 parse.y --- parse.y 6 Sep 2020 15:51:28 - 1.60 +++ parse.y 9 Sep 2020 05:45:10 - @@ -40,9 +40,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -92,6 +94,7 @@ char *symget(const char *); struct snmpd *conf = NULL; static int errors = 0; static struct usmuser *user = NULL; +static char*snmpd_port = SNMPD_PORT; int host(const char *, const char *, int, struct sockaddr_storage *, int); @@ -122,11 +125,11 @@ typedef struct { %token SYSTEM CONTACT DESCR LOCATION NAME OBJECTID SERVICES RTFILTER %token READONLY READWRITE OCTETSTRING INTEGER COMMUNITY TRAP RECEIVER %token SECLEVEL NONE AUTH ENC USER AUTHKEY ENCKEY ERROR DISABLED -%token HANDLE DEFAULT SRCADDR TCP UDP PFADDRFILTER +%token HANDLE DEFAULT SRCADDR TCP UDP PFADDRFILTER PORT %token STRING %token NUMBER %typehostcmn -%typesrcaddr +%typesrcaddr port %typeoptwrite yesno seclevel proto %type objtype cmd %type oid hostoid trapoid @@ -193,28 +196,7 @@ yesno : STRING { } ; -main : LISTEN ON STRING proto{ - struct sockaddr_storage ss[16]; - int nhosts, i; - - nhosts = host($3, SNMPD_PORT, $4, ss, nitems(ss)); - if (nhosts < 1) { - yyerror("invalid address: %s", $3); - free($3); - YYERROR; - } - if (nhosts > (int)nitems(ss)) - log_warn("%s resolves to more than %zu hosts", - $3, nitems(ss)); - free($3); - - for (i = 0; i < nhosts; i++) { - if (listen_add(&(ss[i]), $4) == -1) { - yyerror("calloc"); - YYERROR; - } - } - } +main : LISTEN ON listenproto | READONLY COMMUNITY STRING { if (strlcpy(conf->sc_rdcommunity, $3, sizeof(conf->sc_rdcommunity)) >= @@ -295,6 +277,132 @@ main : LISTEN ON STRING proto{ } ; +listenproto: UDP listen_udp + | TCP listen_tcp + | listen_empty + +listen_udp : STRING port { + struct sockaddr_storage ss[16]; + int nhosts, i; + + nhosts = host($1, $2, SOCK_DGRAM, ss, nitems(ss)); + if (nhosts < 1) { + yyerror("invalid address: %s", $1); + free($1); + if ($2 != snmpd_port) + free($2); + YYERROR; + } + if (nhosts > (int)nitems(ss)) + log_warn("%s:%s resolves to more than %zu hosts", + $1, $2, nitems(ss)); + + free($1); + if ($2 != snmpd_port) + free($2); +
snmpd refactor listen on grammar
Moving towards individual transport mappings, it's becoming more convenient to have the protocol directly after the listen on statement. This gives me more flexibility in using mapping-specific APIs, also when other transport mappings might become available in the future it allows for easier mapping-specific features. While here I decided to also add port support for snmpe, which at this point is rather trivial. Traphandler is not my point of focus at this time. having udp|tcp at the last position is still supported, but generates a pretty deprecated warning. Probably to be removed after release. OK? martijn@ Index: parse.y === RCS file: /cvs/src/usr.sbin/snmpd/parse.y,v retrieving revision 1.60 diff -u -p -r1.60 parse.y --- parse.y 6 Sep 2020 15:51:28 - 1.60 +++ parse.y 6 Sep 2020 20:08:08 - @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -92,6 +93,7 @@ char *symget(const char *); struct snmpd *conf = NULL; static int errors = 0; static struct usmuser *user = NULL; +static char*snmpd_port = SNMPD_PORT; int host(const char *, const char *, int, struct sockaddr_storage *, int); @@ -122,11 +124,11 @@ typedef struct { %token SYSTEM CONTACT DESCR LOCATION NAME OBJECTID SERVICES RTFILTER %token READONLY READWRITE OCTETSTRING INTEGER COMMUNITY TRAP RECEIVER %token SECLEVEL NONE AUTH ENC USER AUTHKEY ENCKEY ERROR DISABLED -%token HANDLE DEFAULT SRCADDR TCP UDP PFADDRFILTER +%token HANDLE DEFAULT SRCADDR TCP UDP PFADDRFILTER PORT %token STRING %token NUMBER %typehostcmn -%typesrcaddr +%typesrcaddr port %typeoptwrite yesno seclevel proto %type objtype cmd %type oid hostoid trapoid @@ -193,28 +195,7 @@ yesno : STRING { } ; -main : LISTEN ON STRING proto{ - struct sockaddr_storage ss[16]; - int nhosts, i; - - nhosts = host($3, SNMPD_PORT, $4, ss, nitems(ss)); - if (nhosts < 1) { - yyerror("invalid address: %s", $3); - free($3); - YYERROR; - } - if (nhosts > (int)nitems(ss)) - log_warn("%s resolves to more than %zu hosts", - $3, nitems(ss)); - free($3); - - for (i = 0; i < nhosts; i++) { - if (listen_add(&(ss[i]), $4) == -1) { - yyerror("calloc"); - YYERROR; - } - } - } +main : LISTEN ON listenproto | READONLY COMMUNITY STRING { if (strlcpy(conf->sc_rdcommunity, $3, sizeof(conf->sc_rdcommunity)) >= @@ -295,6 +276,128 @@ main : LISTEN ON STRING proto{ } ; +listenproto: UDP listen_udp + | TCP listen_tcp + | listen_empty + +listen_udp : STRING port { + struct sockaddr_storage ss[16]; + int nhosts, i; + + nhosts = host($1, $2, SOCK_DGRAM, ss, nitems(ss)); + if (nhosts < 1) { + yyerror("invalid address: %s", $1); + free($1); + if ($2 != snmpd_port) + free($2); + YYERROR; + } + if (nhosts > (int)nitems(ss)) + log_warn("%s:%s resolves to more than %zu hosts", + $1, $2, nitems(ss)); + + free($1); + if ($2 != snmpd_port) + free($2); + for (i = 0; i < nhosts; i++) { + if (listen_add(&(ss[i]), SOCK_DGRAM) == -1) { + yyerror("calloc"); + YYERROR; + } + } + } + +listen_tcp : STRING port { + struct sockaddr_storage ss[16]; + int nhosts, i; + + nhosts = host($1, $2, SOCK_STREAM, ss, nitems(ss)); + if (nhosts < 1) { + yyerror("invalid address: %s", $1); + free($1); +
snmpd remove snmpe_dispatch_parent
going for another easy picking: snmpe_dispatch_parent is just an empty stub. proc.c assigns proc_dispatch_null to p_cb if it's null, which effectively does the same thing. OK? martijn@ Index: snmpe.c === RCS file: /cvs/src/usr.sbin/snmpd/snmpe.c,v retrieving revision 1.66 diff -u -p -r1.66 snmpe.c --- snmpe.c 6 Sep 2020 15:51:28 - 1.66 +++ snmpe.c 6 Sep 2020 16:37:10 - @@ -46,7 +46,6 @@ void snmpe_tryparse(int, struct snmp_me int snmpe_parsevarbinds(struct snmp_message *); voidsnmpe_response(struct snmp_message *); voidsnmpe_sig_handler(int sig, short, void *); -int snmpe_dispatch_parent(int, struct privsep_proc *, struct imsg *); int snmpe_bind(struct address *); voidsnmpe_recvmsg(int fd, short, void *); voidsnmpe_readcb(int fd, short, void *); @@ -60,7 +59,7 @@ struct imsgev *iev_parent; static const struct timevalsnmpe_tcp_timeout = { 10, 0 }; /* 10s */ static struct privsep_proc procs[] = { - { "parent", PROC_PARENT,snmpe_dispatch_parent } + { "parent", PROC_PARENT } }; void @@ -133,17 +132,6 @@ snmpe_shutdown(void) close(h->fd); } kr_shutdown(); -} - -int -snmpe_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg) -{ - switch (imsg->hdr.type) { - default: - break; - } - - return (-1); } int
smtpd.conf add admd keyword
EHLO, RFC8601 defines the authentication-results header which can be used to show the verification-results of DKIM, SPF, DMARC, and others. I can think of quite a few filters that could be build around this header: - the prior mentioned - detecting the header before accepting it into ones ADMD - using it to calculate some sort of spam-score by some other filter These are the 3 main categories that spring to mind, with especially the first one having the option to be split in quite a few different filters on itself. Since setting the authservid on every of these filters (once they arrive) will be cumbersome and error-prone I would like to propose to distribute this value from a single point in the smtpd.conf. I already have a filter-admdscrub basically ready and I'm working on a filter-dkimverify every now and then (no where near done yet) which can use this feature. OK? martijn@ Index: lka_filter.c === RCS file: /cvs/src/usr.sbin/smtpd/lka_filter.c,v retrieving revision 1.62 diff -u -p -r1.62 lka_filter.c --- lka_filter.c24 Apr 2020 11:34:07 - 1.62 +++ lka_filter.c6 Sep 2020 15:05:21 - @@ -210,6 +210,8 @@ lka_proc_config(struct processor_instanc io_printf(pi->io, "config|subsystem|smtp-in\n"); if (pi->subsystems & FILTER_SUBSYSTEM_SMTP_OUT) io_printf(pi->io, "config|subsystem|smtp-out\n"); + io_printf(pi->io, "config|admd|%s\n", + env->sc_admd != NULL ? env->sc_admd : env->sc_hostname); io_printf(pi->io, "config|ready\n"); } Index: parse.y === RCS file: /cvs/src/usr.sbin/smtpd/parse.y,v retrieving revision 1.278 diff -u -p -r1.278 parse.y --- parse.y 1 Jun 2020 05:21:30 - 1.278 +++ parse.y 6 Sep 2020 15:05:21 - @@ -173,7 +173,7 @@ typedef struct { %} -%token ACTION ALIAS ANY ARROW AUTH AUTH_OPTIONAL +%token ACTION ADMD ALIAS ANY ARROW AUTH AUTH_OPTIONAL %token BACKUP BOUNCE BYPASS %token CA CERT CHAIN CHROOT CIPHERS COMMIT COMPRESSION CONNECT %token DATA DATA_LINE DHE DISCONNECT DOMAIN @@ -209,6 +209,7 @@ grammar : /* empty */ | grammar include '\n' | grammar varset '\n' | grammar bounce '\n' + | grammar admd '\n' | grammar ca '\n' | grammar mda '\n' | grammar mta '\n' @@ -310,6 +311,21 @@ BOUNCE WARN_INTERVAL { ; +admd: +ADMD STRING { + size_t i; + + for (i = 0; $2[i] != '\0'; i++) { + if (!isprint($2[i])) { + yyerror("not a valid admd"); + free($2); + YYERROR; + } + } + conf->sc_admd = $2; +}; + + ca: CA STRING { char buf[HOST_NAME_MAX+1]; @@ -2603,6 +2619,7 @@ lookup(char *s) /* this has to be sorted always */ static const struct keywords keywords[] = { { "action", ACTION }, + { "admd", ADMD }, { "alias", ALIAS }, { "any",ANY }, { "auth", AUTH }, Index: smtpd.conf.5 === RCS file: /cvs/src/usr.sbin/smtpd/smtpd.conf.5,v retrieving revision 1.251 diff -u -p -r1.251 smtpd.conf.5 --- smtpd.conf.527 Aug 2020 08:58:30 - 1.251 +++ smtpd.conf.56 Sep 2020 15:05:21 - @@ -313,6 +313,11 @@ which is useful on machines with multipl If the list contains more than one address, all of them are used in such a way that traffic is routed as efficiently as possible. .El +.It Ic admd Ar authservid +The Administrative Management Domain this mailserver belongs to. +The authservid will be forwarded to filters using it to identify or mark +authentication-results headers. +If omitted it defaults to the server name. .It Ic bounce Cm warn-interval Ar delay Op , Ar delay ... Send warning messages to the envelope sender when temporary delivery failures cause a message to remain on the queue for longer than Index: smtpd.h === RCS file: /cvs/src/usr.sbin/smtpd/smtpd.h,v retrieving revision 1.656 diff -u -p -r1.656 smtpd.h --- smtpd.h 8 Apr 2020 07:30:44 - 1.656 +++ smtpd.h 6 Sep 2020 15:05:21 - @@ -624,6 +624,8 @@ struct smtpd { char *sc_srs_key; char *sc_srs_key_backup; int sc_srs_ttl; + + char *sc_admd; }; #defineTRACE_DEBUG 0x0001
Document errno for ober_read_elements
So here's my attempt at documenting errno for ober_read_elements. martijn@ Index: ober_read_elements.3 === RCS file: /cvs/src/lib/libutil/ober_read_elements.3,v retrieving revision 1.1 diff -u -p -r1.1 ober_read_elements.3 --- ober_read_elements.324 Oct 2019 12:39:26 - 1.1 +++ ober_read_elements.33 Sep 2020 18:48:56 - @@ -142,9 +142,10 @@ frees any dynamically allocated storage .Fn ober_read_elements returns a pointer to a fully populated list of one or more .Vt ber_element -structures or -.Dv NULL -on a type mismatch or read error. +structures. +Otherwise \-1 is returned and the global variable +.Va errno +is set to indicate the error. .Pp .Fn ober_get_writebuf returns the number of bytes contained within the buffer @@ -155,7 +156,30 @@ or \-1 on failure. returns the number of bytes written. Otherwise \-1 is returned and the global variable .Va errno -is set to indicate the error. +is set to +.Er ENOMEM +to indicate the error. +.Sh ERRORS +.Fn ober_read_elements +will fail if: +.Bl -tag -width Er +.It Bq Er ENOMEM +No memory was available to create the full +.Vt ber_element +structure list. +.It Bq Er ENOBUFS +.Fn ober_read_elements +was called before calling +.Fn ober_set_readbuf . +.It Bq Er ECANCELED +.Fa buf +does not contain enough data to complete the unpacking. +.It Bq Er EINVAL +.Fa buf +does not contain a valid BER data structure. +.It Bq Er ERANGE +One of the values in the structure is larger then the library can unpack. +.El .Sh SEE ALSO .Xr read 2 , .Xr recv 2 ,
Re: Add more errnos to ober_read_elements
Apparently I missed one... On Thu, 2020-09-03 at 18:00 +0200, Martijn van Duren wrote: > Just reminded myself of this one. > The manpage says nothing about ober_read_elements setting errno upon > failure, yet it does in most cases. Furthermore, applications like > snmpd use errno in ober_read_elements to determine if a read is > incomplete (checking for ECANCELED), without initializing errno to > 0. > > The danger here is that since some stale errno might linger and a > return from ober_read_elements with NULL could test against an old > errno. > > Diff below tries to remedy this. > > OK? > > martijn@ Index: ber.c === RCS file: /cvs/src/lib/libutil/ber.c,v retrieving revision 1.16 diff -u -p -r1.16 ber.c --- ber.c 3 Sep 2020 17:01:15 - 1.16 +++ ber.c 3 Sep 2020 18:47:38 - @@ -1258,8 +1258,10 @@ ober_read_element(struct ber *ber, struc } case BER_TYPE_INTEGER: case BER_TYPE_ENUMERATED: - if (len > (ssize_t)sizeof(long long)) + if (len > (ssize_t)sizeof(long long)) { + errno = ERANGE; return -1; + } for (i = 0; i < len; i++) { if (ober_getc(ber, ) != 1) return -1;
Add more errnos to ober_read_elements
Just reminded myself of this one. The manpage says nothing about ober_read_elements setting errno upon failure, yet it does in most cases. Furthermore, applications like snmpd use errno in ober_read_elements to determine if a read is incomplete (checking for ECANCELED), without initializing errno to 0. The danger here is that since some stale errno might linger and a return from ober_read_elements with NULL could test against an old errno. Diff below tries to remedy this. OK? martijn@ Index: ber.c === RCS file: /cvs/src/lib/libutil/ber.c,v retrieving revision 1.15 diff -u -p -r1.15 ber.c --- ber.c 24 Oct 2019 12:39:26 - 1.15 +++ ber.c 3 Sep 2020 15:58:23 - @@ -1266,8 +1266,10 @@ ober_read_element(struct ber *ber, struc /* smallest number of contents octets only */ if ((i == 1 && last == 0 && (c & 0x80) == 0) || - (i == 1 && last == 0xff && (c & 0x80) != 0)) + (i == 1 && last == 0xff && (c & 0x80) != 0)) { + errno = EINVAL; return -1; + } val <<= 8; val |= c; @@ -1299,8 +1301,10 @@ ober_read_element(struct ber *ber, struc ((u_char *)elm->be_val)[len] = '\0'; break; case BER_TYPE_NULL: /* no payload */ - if (len != 0) + if (len != 0) { + errno = EINVAL; return -1; + } break; case BER_TYPE_SEQUENCE: case BER_TYPE_SET: @@ -1346,8 +1350,10 @@ ober_read(struct ber *ber, void *buf, si { size_t sz; - if (ber->br_rbuf == NULL) + if (ber->br_rbuf == NULL) { + errno = ENOBUFS; return -1; + } sz = ber->br_rend - ber->br_rptr; if (len > sz) {
Re: snmp df, use smi_print_element
On Thu, 2020-09-03 at 09:49 +0200, Martijn van Duren wrote: > At the moment it's not wise to run "snmp df" against untrusted > instances, since it outputs the hrStorageDescr without checking the > bytes being printed. > > Make use of the new DISPLAY-HINT functionality of smi.c to make sure > the string is actually DisplayHint compliant. > > While here add the extra continuity-check in the second loop. > > OK? > > martijn@ > There was still a minor alignment issue in the previous diff, since printf looks at the bytes printed and not the width of the characters, which gives a wrong result if there's a replacement character in use. Diff below fixes this. All other fields should be printable ascii only and thus safe to use in this way. Index: mib.h === RCS file: /cvs/src/usr.bin/snmp/mib.h,v retrieving revision 1.7 diff -u -p -r1.7 mib.h --- mib.h 8 Aug 2020 14:01:31 - 1.7 +++ mib.h 3 Sep 2020 08:54:12 - @@ -961,7 +961,7 @@ { MIBDECL(hrStorageEntry) },\ { MIBDECL(hrStorageIndex) },\ { MIBDECL(hrStorageType) }, \ - { MIBDECL(hrStorageDescr) },\ + { MIBDECL(hrStorageDescr), "DisplayString" }, \ { MIBDECL(hrStorageAllocationUnits) }, \ { MIBDECL(hrStorageSize) }, \ { MIBDECL(hrStorageUsed) }, \ Index: snmpc.c === RCS file: /cvs/src/usr.bin/snmp/snmpc.c,v retrieving revision 1.28 diff -u -p -r1.28 snmpc.c --- snmpc.c 3 Aug 2020 14:45:54 - 1.28 +++ snmpc.c 3 Sep 2020 08:54:12 - @@ -39,6 +39,7 @@ #include #include #include +#include #include "smi.h" #include "snmp.h" @@ -58,6 +59,7 @@ int snmpc_print(struct ber_element *); __dead void snmpc_printerror(enum snmp_error, struct ber_element *, int, const char *); char *snmpc_hex2bin(char *, size_t *); +ssize_t snmpc_mbswidth(char *); struct ber_element *snmpc_varbindparse(int, char *[]); void usage(void); @@ -820,8 +822,8 @@ snmpc_df(int argc, char *argv[]) { struct snmpc_df { uint32_t index; - /* DisplayString is 255a DISPLAY-HINT */ - char descr[256]; + char *descr; + int descrwidth; /* Theoretical maximum for 2 32 bit values multiplied */ char size[21]; char used[21]; @@ -833,7 +835,8 @@ snmpc_df(int argc, char *argv[]) struct ber_oid sizeoid = {{ 1, 3, 6, 1, 2, 1, 25, 2, 3, 1, 5 }, 11}; struct ber_oid usedoid = {{ 1, 3, 6, 1, 2, 1, 25, 2, 3, 1, 6 }, 11}; struct ber_oid oid, *reqoid; - struct ber_element *pdu, *varbind; + char oids[SNMP_MAX_OID_STRLEN]; + struct ber_element *pdu, *varbind, *elm; struct snmp_agent *agent; int errorstatus, errorindex; int class; @@ -890,8 +893,9 @@ snmpc_df(int argc, char *argv[]) return 1; } for (; varbind != NULL; varbind = varbind->be_next) { - (void) ober_scanf_elements(varbind, "{oS", ); - if (ober_oid_cmp(, ) != 2) + if (ober_scanf_elements(varbind, "{os", , + ) == -1 || + ober_oid_cmp(, ) != 2) break; rows++; } @@ -899,19 +903,29 @@ snmpc_df(int argc, char *argv[]) err(1, "malloc"); (void) ober_scanf_elements(pdu, "{SSS{e", ); for (; i < rows; varbind = varbind->be_next, i++) { - if (ober_scanf_elements(varbind, "{os", , - ) == -1) { + if (ober_scanf_elements(varbind, "{oe", , + ) == -1) { i--; rows--; continue; } + if (ober_oid_cmp(, ) != 2) + break; df[i].index = oid.bo_id[oid.bo_n - 1]; - len = strlcpy(df[i].descr, string, - sizeof(df[i].descr)); - if (len > (int) sizeof(df[i].descr)) - len = (int) sizeof(df[i].descr) - 1; - if (len > descrlen) - descrlen = len; + if ((df[i].descr = smi_print_element(, elm, 0, + smi_os_ascii, 0, utf8)) == NULL) { + smi_oid2string(, oids, sizeof(oids)
snmp df, use smi_print_element
At the moment it's not wise to run "snmp df" against untrusted instances, since it outputs the hrStorageDescr without checking the bytes being printed. Make use of the new DISPLAY-HINT functionality of smi.c to make sure the string is actually DisplayHint compliant. While here add the extra continuity-check in the second loop. OK? martijn@ Index: mib.h === RCS file: /cvs/src/usr.bin/snmp/mib.h,v retrieving revision 1.7 diff -u -p -r1.7 mib.h --- mib.h 8 Aug 2020 14:01:31 - 1.7 +++ mib.h 3 Sep 2020 07:42:12 - @@ -961,7 +961,7 @@ { MIBDECL(hrStorageEntry) },\ { MIBDECL(hrStorageIndex) },\ { MIBDECL(hrStorageType) }, \ - { MIBDECL(hrStorageDescr) },\ + { MIBDECL(hrStorageDescr), "DisplayString" }, \ { MIBDECL(hrStorageAllocationUnits) }, \ { MIBDECL(hrStorageSize) }, \ { MIBDECL(hrStorageUsed) }, \ Index: snmpc.c === RCS file: /cvs/src/usr.bin/snmp/snmpc.c,v retrieving revision 1.28 diff -u -p -r1.28 snmpc.c --- snmpc.c 3 Aug 2020 14:45:54 - 1.28 +++ snmpc.c 3 Sep 2020 07:42:12 - @@ -39,6 +39,7 @@ #include #include #include +#include #include "smi.h" #include "snmp.h" @@ -58,6 +59,7 @@ int snmpc_print(struct ber_element *); __dead void snmpc_printerror(enum snmp_error, struct ber_element *, int, const char *); char *snmpc_hex2bin(char *, size_t *); +ssize_t snmpc_mbswidth(char *); struct ber_element *snmpc_varbindparse(int, char *[]); void usage(void); @@ -820,8 +822,7 @@ snmpc_df(int argc, char *argv[]) { struct snmpc_df { uint32_t index; - /* DisplayString is 255a DISPLAY-HINT */ - char descr[256]; + char *descr; /* Theoretical maximum for 2 32 bit values multiplied */ char size[21]; char used[21]; @@ -833,7 +834,8 @@ snmpc_df(int argc, char *argv[]) struct ber_oid sizeoid = {{ 1, 3, 6, 1, 2, 1, 25, 2, 3, 1, 5 }, 11}; struct ber_oid usedoid = {{ 1, 3, 6, 1, 2, 1, 25, 2, 3, 1, 6 }, 11}; struct ber_oid oid, *reqoid; - struct ber_element *pdu, *varbind; + char oids[SNMP_MAX_OID_STRLEN]; + struct ber_element *pdu, *varbind, *elm; struct snmp_agent *agent; int errorstatus, errorindex; int class; @@ -890,8 +892,9 @@ snmpc_df(int argc, char *argv[]) return 1; } for (; varbind != NULL; varbind = varbind->be_next) { - (void) ober_scanf_elements(varbind, "{oS", ); - if (ober_oid_cmp(, ) != 2) + if (ober_scanf_elements(varbind, "{os", , + ) == -1 || + ober_oid_cmp(, ) != 2) break; rows++; } @@ -899,17 +902,26 @@ snmpc_df(int argc, char *argv[]) err(1, "malloc"); (void) ober_scanf_elements(pdu, "{SSS{e", ); for (; i < rows; varbind = varbind->be_next, i++) { - if (ober_scanf_elements(varbind, "{os", , - ) == -1) { + if (ober_scanf_elements(varbind, "{oe", , + ) == -1) { i--; rows--; continue; } + if (ober_oid_cmp(, ) != 2) + break; df[i].index = oid.bo_id[oid.bo_n - 1]; - len = strlcpy(df[i].descr, string, - sizeof(df[i].descr)); - if (len > (int) sizeof(df[i].descr)) - len = (int) sizeof(df[i].descr) - 1; + if ((df[i].descr = smi_print_element(, elm, 0, + smi_os_ascii, 0, utf8)) == NULL) { + smi_oid2string(, oids, sizeof(oids), + oid_lookup); + warn("df: can't print oid %s", oids); + i--; + rows--; + continue; + } + if ((len = (int) snmpc_mbswidth(df[i].descr)) == -1) + err(1, "df: invalid hrStorageDescr"); if (len > descrlen) descrlen = len; } @@ -1325,6 +1337,24 @@ fail: errno = EINVAL; free(decstr); return NULL; +} + +ssize_t +snmpc_mbswidth(char *str) +{ + wchar_t
snmpd(8) start cleaning up socket code.
I would like to move snmpd(8) to a more modular dispatch/transport map system, but that's going to be quite the undertaking. To make things a little better to grok I'd like to split of the trap receiver components out of struct address as a first step. While doing this I can also greatly simplify the code for resolving hosts. According parse.y's cvs log: revision 1.15 date: 2008/07/18 12:35:27; author: reyk; state: Exp; lines: +22 -14; merge host_v6 with relayd's version to use getaddrinfo instead of inet_pton. host_v4, host_v6, and host_dns could be merged into one function using getaddrinfo but i keep it in multiple functions to keep it in sync with the other daemons using this common code. Since I intent to completely overhaul this part of the code I see no reason to keep this in sync. No functional change intended, except that trap receiver's source-address might now also be a resolvable hostname. OK? martijn@ Index: parse.y === RCS file: /cvs/src/usr.sbin/snmpd/parse.y,v retrieving revision 1.59 diff -u -p -r1.59 parse.y --- parse.y 23 Aug 2020 07:39:57 - 1.59 +++ parse.y 25 Aug 2020 19:52:01 - @@ -91,16 +91,11 @@ char*symget(const char *); struct snmpd *conf = NULL; static int errors = 0; -static struct addresslist *hlist; static struct usmuser *user = NULL; -struct address *host_v4(const char *); -struct address *host_v6(const char *); -int host_dns(const char *, struct addresslist *, - int, in_port_t, struct ber_oid *, char *, - struct address *, int); -int host(const char *, struct addresslist *, - int, in_port_t, struct ber_oid *, char *, char *, int); +int host(const char *, const char *, int, + struct sockaddr_storage *, int); +int listen_add(struct sockaddr_storage *, int); typedef struct { union { @@ -120,6 +115,8 @@ typedef struct { int lineno; } YYSTYPE; +#define NELEM(a) (sizeof(a) / sizeof((a)[0])) + %} %token INCLUDE @@ -199,13 +196,26 @@ yesno : STRING { ; main : LISTEN ON STRING proto{ - if (host($3, >sc_addresses, 16, SNMPD_PORT, NULL, - NULL, NULL, $4) <= 0) { - yyerror("invalid ip address: %s", $3); + struct sockaddr_storage ss[16]; + int nhosts, i; + + nhosts = host($3, SNMPD_PORT, $4, ss, NELEM(ss)); + if (nhosts < 1) { + yyerror("invalid address: %s", $3); free($3); YYERROR; } + if (nhosts > (int)NELEM(ss)) + log_warn("%s resolves to more than %zu hosts", + $3, NELEM(ss)); free($3); + + for (i = 0; i < nhosts; i++) { + if (listen_add(&(ss[i]), $4) == -1) { + yyerror("calloc"); + YYERROR; + } + } } | READONLY COMMUNITY STRING { if (strlcpy(conf->sc_rdcommunity, $3, @@ -240,11 +250,7 @@ main : LISTEN ON STRING proto{ } free($3); } - | TRAP RECEIVER { - hlist = >sc_trapreceivers; - } host { - hlist = NULL; - } + | TRAP RECEIVER host | TRAP HANDLE hostcmn trapoid cmd { struct trapcmd *cmd = $5.data; @@ -420,13 +426,40 @@ srcaddr : /* empty */ { $$ = NULL; } ; hostdef: STRING hostoid hostcmn srcaddr{ - if (host($1, hlist, 1, - SNMPD_TRAPPORT, $2, $3, $4, IPPROTO_UDP) <= 0) { + struct sockaddr_storage ss; + struct trap_address *tr; + + if ((tr = calloc(1, sizeof(*tr))) == NULL) { + yyerror("calloc"); + YYERROR; + } + + if (host($1, SNMPD_TRAPPORT, SOCK_DGRAM, , 1) <= 0) { yyerror("invalid host: %s", $1); free($1); + free($2); + free($3); + free($4); +
Re: smtpd filters: accept bypass in commit stage
Does this filter actually work for you? Not by my testing, nor my understanding of filters. Filter-dkimsign works during the filter-dataline phase, so you'd have to circumvent that one, which is not supported. Personally I'd sign the domain anyway, since it gives the receiver some additional information where a message might have been altered if it happens somewhere down a MTA-chain, but if you really don't want to sign the message you could try setting the phase to data, since that's where filter-dkimsign's magic happens. I haven't tested this though, so it might be just the data-command and not the actual data. If that doesn't work your best bet at this point is two different listen statement for the two domains. martijn@ On Tue, 2020-08-25 at 04:30 +, Lucas wrote: > Hello tech@, > > I keep getting a syntax error with the following seemingly correct > line: > > filter "dkimsign-override" phase commit \ > match mail-from bypass > > The problem (`/etc/mail/smtpd.conf:20: syntax error`) arises from > smtpd.conf's grammar only allowing `filter_action_builtin_nojunk` for > `commit` phase. It turns out that the current definition of > `filter_action_builtin_nojunk` means no junk and no bypass. Address > that moving bypass action to nojunk. > > My usecase for it is to avoid DKIM-signing emails that are externally > relayed with `opensmtpd-filters-dkimsign`: if I also own > lucas@domain.invalid, I don't want smtpd to sign lucas@domain.invalid's > emails, just lu...@sexy.is'. This seems possible with `filter-chain`, > and technically could be decided in `mail-from` phase, but sadly > `bypass` doesn't short-circuit. Second best option is to `bypass` > during `commit` phase, which is when `filter-dkimsign` does its magic. > > Comments? > > -Lucas > > > Index: parse.y > === > RCS file: /home/cvs/src/usr.sbin/smtpd/parse.y,v > retrieving revision 1.278 > diff -u -p -r1.278 parse.y > --- parse.y 1 Jun 2020 05:21:30 - 1.278 > +++ parse.y 25 Aug 2020 04:05:27 - > @@ -1527,9 +1527,6 @@ filter_action_builtin_nojunk > | JUNK { > filter_config->junk = 1; > } > -| BYPASS { > - filter_config->bypass = 1; > -} > ; > > filter_action_builtin_nojunk: > @@ -1544,6 +1541,9 @@ REJECT STRING { > } > | REPORT STRING { > filter_config->report = $2; > +} > +| BYPASS { > + filter_config->bypass = 1; > } > ; > >
snmpd(8) Remove struct listen_sock
I still want to move udp/tcp handling out of snmpe, so that there's better layering, but my previous diff never got any response and might do with some more polishing. For now, lets remove listen_sock from snmpd, since there's a 1:1 correlation with struct address. This saves a couple of callocs during startup and 18 LoC. OK? martijn@ Index: parse.y === RCS file: /cvs/src/usr.sbin/snmpd/parse.y,v retrieving revision 1.58 diff -u -p -r1.58 parse.y --- parse.y 30 Jun 2020 17:11:49 - 1.58 +++ parse.y 9 Aug 2020 14:08:18 - @@ -997,7 +997,6 @@ parse_config(const char *filename, u_int conf->sc_flags = flags; conf->sc_confpath = filename; TAILQ_INIT(>sc_addresses); - TAILQ_INIT(>sc_sockets); strlcpy(conf->sc_rdcommunity, "public", SNMPD_MAXCOMMUNITYLEN); strlcpy(conf->sc_rwcommunity, "private", SNMPD_MAXCOMMUNITYLEN); strlcpy(conf->sc_trcommunity, "public", SNMPD_MAXCOMMUNITYLEN); Index: snmpd.h === RCS file: /cvs/src/usr.sbin/snmpd/snmpd.h,v retrieving revision 1.88 diff -u -p -r1.88 snmpd.h --- snmpd.h 8 Aug 2020 13:39:57 - 1.88 +++ snmpd.h 9 Aug 2020 14:08:18 - @@ -482,6 +482,9 @@ struct address { struct sockaddr_storage ss; in_port_tport; int ipproto; + int fd; + struct event ev; + struct event evt; TAILQ_ENTRY(address) entry; @@ -492,15 +495,6 @@ struct address { }; TAILQ_HEAD(addresslist, address); -struct listen_sock { - int s_fd; - int s_ipproto; - struct events_ev; - struct events_evt; - TAILQ_ENTRY(listen_sock)entry; -}; -TAILQ_HEAD(socklist, listen_sock); - enum usmauth { AUTH_NONE = 0, AUTH_MD5, /* HMAC-MD5-96, RFC3414 */ @@ -545,7 +539,6 @@ struct snmpd { const char *sc_confpath; struct addresslist sc_addresses; - struct socklist sc_sockets; struct timeval sc_starttime; u_int32_tsc_engine_boots; Index: snmpe.c === RCS file: /cvs/src/usr.sbin/snmpd/snmpe.c,v retrieving revision 1.63 diff -u -p -r1.63 snmpe.c --- snmpe.c 8 Aug 2020 13:39:57 - 1.63 +++ snmpe.c 9 Aug 2020 14:08:18 - @@ -68,7 +68,6 @@ snmpe(struct privsep *ps, struct privsep { struct snmpd*env = ps->ps_env; struct address *h; - struct listen_sock *so; #ifdef DEBUG char buf[BUFSIZ]; struct oid *oid; @@ -82,14 +81,9 @@ snmpe(struct privsep *ps, struct privsep #endif /* bind SNMP UDP/TCP sockets */ - TAILQ_FOREACH(h, >sc_addresses, entry) { - if ((so = calloc(1, sizeof(*so))) == NULL) - fatal("snmpe: %s", __func__); - if ((so->s_fd = snmpe_bind(h)) == -1) + TAILQ_FOREACH(h, >sc_addresses, entry) + if ((h->fd = snmpe_bind(h)) == -1) fatal("snmpe: failed to bind SNMP socket"); - so->s_ipproto = h->ipproto; - TAILQ_INSERT_TAIL(>sc_sockets, so, entry); - } proc_run(ps, p, procs, nitems(procs), snmpe_init, NULL); } @@ -99,7 +93,7 @@ void snmpe_init(struct privsep *ps, struct privsep_proc *p, void *arg) { struct snmpd*env = ps->ps_env; - struct listen_sock *so; + struct address *h; kr_init(); trap_init(); @@ -107,17 +101,17 @@ snmpe_init(struct privsep *ps, struct pr usm_generate_keys(); /* listen for incoming SNMP UDP/TCP messages */ - TAILQ_FOREACH(so, >sc_sockets, entry) { - if (so->s_ipproto == IPPROTO_TCP) { - if (listen(so->s_fd, 5) < 0) + TAILQ_FOREACH(h, >sc_addresses, entry) { + if (h->ipproto == IPPROTO_TCP) { + if (listen(h->fd, 5) < 0) fatalx("snmpe: failed to listen on socket"); - event_set(>s_ev, so->s_fd, EV_READ, snmpe_acceptcb, so); - evtimer_set(>s_evt, snmpe_acceptcb, so); + event_set(>ev, h->fd, EV_READ, snmpe_acceptcb, h); + evtimer_set(>evt, snmpe_acceptcb, h); } else { - event_set(>s_ev, so->s_fd, EV_READ|EV_PERSIST, + event_set(>ev, h->fd, EV_READ|EV_PERSIST, snmpe_recvmsg, env); } - event_add(>s_ev, NULL); + event_add(>ev, NULL); } /* no filesystem
Re: ksh [emacs.c] -- simplify isu8cont()
On Sun, 2020-07-26 at 04:15 +0100, ropers wrote: > On 25/07/2020, Martijn van Duren wrote: > > This function is used throughout the OpenBSD tree and I think it's > > fine as it is. This way it's clearer to me that it's about byte > > 7 and 8 > > You mean bits 7 and 8 when counting from 1 from the right? obvious type-O is obvious. > > > and not have to do the math in my head to check if we > > might have botched it. > > > > Also compilers should be smart enough to optimize this out at > > compile-time anyway. > > > > martijn@ > > So the (0x80 | 0x40) was supposed to be *for* legibility? > > IMHO it hurts legibility, but admittedly, it depends on who you are > and what you have memorised: > Finding (0x80 | 0x40) easier than 0xC0 assumes that people have nibble > translation between binary and hexadecimal memorised all the way up to > 8 but *NOT* up to C. And that they find dealing with two values and > an extra binary OR still less hassle than remembering that C is 1100. > Of course if that's your decision, that's your decision, but speaking > as a novice C programmer, I think 'C' is easier. ;D [0] I'm lazy, so I only remember the power exponents (1-4) and everthing in between is just derivative. And since I and a handful of others maintain this code I think we should do what we think is most readable to us. If say schwarze@ were to change his mind and come up with this patch I'd give it more serious thought on how hard it would be for me to make the switch, but we're not going to change it because some outsider might find it easier to read. Don't get me wrong, I appreciate the patch and I do encourage you to find new things to work on, but this one is just a matter of opinion and in this case the people who actually maintain this code have a different opinion and they tend to win, maybe your next patch will convince us (I actually hope so). > > But while you're reading this, would you at least consider committing > the explanatory comment? Not everybody is already familiar with how > UTF-8 works, and I think this comment above the function is still some > extra hand-holding beginners might find useful: > /* is octet a UTF-8 continuation byte? */ Opinions differ, but I find comments like these just take up useless screen space, because it basically reiterates what it states in the function name. > > Also, while you're here, can anyone tell me what the zot in x_zots() / > x_zotc() actually stands for? I thought it was "zero out the > {string|character}" when I looked at x_zots(), but then I doubted > myself once I saw that that's not strictly what x_zotc() actually > does. Does anyone know? I have no idea, but it's been there since it's import in 1996 and with only a quick search I can't find the original repository, so no clue there. > > Ian > > > footnote: > [0] Which latter thought, incidentally, is also why someone invented BCHS. ;) > > > > > > On Sat, 2020-07-25 at 17:40 +0100, ropers wrote: > > > Index: emacs.c > > > === > > > RCS file: /cvs/src/bin/ksh/emacs.c,v > > > retrieving revision 1.87 > > > diff -u -r1.87 emacs.c > > > --- emacs.c 8 May 2020 14:30:42 - 1.87 > > > +++ emacs.c 25 Jul 2020 16:31:22 - > > > @@ -269,10 +269,11 @@ > > > { 0, 0, 0 }, > > > }; > > > > > > +/* is octet a UTF-8 continuation byte? */ > > > int > > > isu8cont(unsigned char c) > > > { > > > - return (c & (0x80 | 0x40)) == 0x80; > > > + return (c & 0xC0) == 0x80; > > > } > > > > > > int > > >
Re: ksh [emacs.c] -- simplify isu8cont()
This function is used throughout the OpenBSD tree and I think it's fine as it is. This way it's clearer to me that it's about byte 7 and 8 and not have to do the math in my head to check if we might have botched it. Also compilers should be smart enough to optimize this out at compile-time anyway. martijn@ On Sat, 2020-07-25 at 17:40 +0100, ropers wrote: > Index: emacs.c > === > RCS file: /cvs/src/bin/ksh/emacs.c,v > retrieving revision 1.87 > diff -u -r1.87 emacs.c > --- emacs.c 8 May 2020 14:30:42 - 1.87 > +++ emacs.c 25 Jul 2020 16:31:22 - > @@ -269,10 +269,11 @@ > { 0, 0, 0 }, > }; > > +/* is octet a UTF-8 continuation byte? */ > int > isu8cont(unsigned char c) > { > - return (c & (0x80 | 0x40)) == 0x80; > + return (c & 0xC0) == 0x80; > } > > int >
Re: Potential grep bug?
Any takers? On Wed, 2020-06-24 at 13:27 +0200, Martijn van Duren wrote: > Moving to tech@ > > On Tue, 2020-06-23 at 22:17 -0900, Philip Guenther wrote: > > Nope. This is a grep of a single file, so procfile() must be overflowing > > and this only 'fixes' it by relying on signed overflow, which is undefined > > behavior, being handled in a particular way by the compiler. So, luck > > (which fails when the compiler decides to hate you). There are more places > > that need to change for the reported problem to be handled safely. > > > > Philip Guenther > > I'm not sure I understand exactly what you mean, but the overflow can > still propagate through to the return value. Since everything propagated > up from procfile is only eventually used to determine the exit value we > can start treating it as a boolean. > > I gave a quick glance at freebsd and they also treat it as a boolean, > but more explicitly. They however don't appear have overflow detection. > > Is this better? > > martijn@ > > > > On Tue, Jun 23, 2020 at 9:58 PM Martijn van Duren < > > open...@list.imperialat.at> wrote: > > > > > This seems to fix the issue for me. > > > > > > OK? > > > > > > martijn@ > > > > > > On Tue, 2020-06-23 at 19:29 -0700, Jordan Geoghegan wrote: > > > > Hello, > > > > > > > > I was working on a couple POSIX regular expressions to search for and > > > > validate IPv4 and IPv6 addresses with optional CIDR blocks, and > > > > encountered some strange behaviour from the base system grep. > > > > > > > > I wanted to validate my regex against a list of every valid IPv4 > > > > address, so I generated a list with a zsh 1 liner: > > > > > > > > for i in {0..255}; do; echo $i.{0..255}.{0..255}.{0..255} ; done | > > > > tr '[:space:]' '\n' > IPv4.txt > > > > > > > > My intentions were to test the regex by running it with 'grep -c' to > > > > confirm there was indeed 2^32 addresses matched, and I also wanted to > > > > benchmark and compare performance between BSD grep, GNU grep and > > > > ripgrep. The command I used: > > > > > > > > grep -Eoc > > > > > > > "((25[0-5]|(2[0-4]|1{0,1}[[:digit:]]){0,1}[[:digit:]])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[[:digit:]]){0,1}[[:digit:]])(/[1-9]|/[1-2][[:digit:]]|/3[0-2])?" > > > > My findings were surprising. Both GNU grep and ripgrep were able get > > > > through the file in roughly 10 and 20 minutes respectively, whereas the > > > > base system grep took over 20 hours! What interested me the most was > > > > that the base system grep when run with '-c' returned '0' for match > > > > count. It seems that 'grep -c' will have its counter overflow if there > > > > are more than 2^32-1 matches (4294967295) and then the counter will > > > > start counting from zero again for further matches. > > > > > > > > ryzen$ time zcat IPv4.txt.gz | grep -Eoc > > > "((25[0-5]|(2[0-4]|1{0,1}... > > > > 0 > > > > 1222m09.32s real 1224m28.02s user 1m16.17s system > > > > > > > > ryzen$ time zcat allip.txt.gz | ggrep -Eoc > > > "((25[0-5]|(2[0-4]|1{0,1}... > > > > 4294967296 > > > > 10m00.38s real11m40.57s user 0m30.55s system > > > > > > > > ryzen$ time rg -zoc "((25[0-5]|(2[0-4]|1{0,1}... > > > > 4294967296 > > > > 21m06.36s real27m06.04s user 0m50.08s system > > > > > > > > # See the counter overflow/reset: > > > > jot 4294967350 | grep -c "^[[:digit:]]" > > > > 54 > > > > > > > > All testing was done on a Ryzen desktop machine running 6.7 stable. > > > > > > > > The grep counting bug can be reproduced with this command: > > > > jot 4294967296 | nice grep -c "^[[:digit:]]" > > > > > > > > Regards, > > > > > > > > Jordan > > > > > Index: grep.c > === > RCS file: /cvs/src/usr.bin/grep/grep.c,v > retrieving revision 1.64 > diff -u -p -r1.64 grep.c > --- grep.c3 Dec 2019 09:14:37 - 1.64 > +++ grep.c24 Jun 2020 11:26:25 - > @@ -517,7 +517,7 @@ main(int argc, char *argv[]) > c = grep_tree(argv); > else &g
join(1) remove redundant memory copy
When r1.28 converted join(1) to getline(3) it left the old intermediate line variable. This means using an additional memcpy and reallocing. I reckon this is wasted cycles and screen filling. Major difference is that our getline allocates to the next power of 2, while the current code overcommits a maximum of ~100 bytes. I reckon this is a fair trade-off. regress still passes. OK? martijn@ Index: join.c === RCS file: /cvs/src/usr.bin/join/join.c,v retrieving revision 1.32 diff -u -p -r1.32 join.c --- join.c 14 Nov 2018 15:16:09 - 1.32 +++ join.c 22 Jul 2020 18:19:34 - @@ -271,9 +271,8 @@ slurp(INPUT *F) { LINE *lp, *lastlp, tmp; ssize_t len; - size_t linesize; u_long cnt; - char *bp, *fieldp, *line; + char *bp, *fieldp; /* * Read all of the lines from an input file that have the same @@ -281,8 +280,6 @@ slurp(INPUT *F) */ F->setcnt = 0; - line = NULL; - linesize = 0; for (lastlp = NULL; ; ++F->setcnt) { /* * If we're out of space to hold line structures, allocate @@ -320,22 +317,12 @@ slurp(INPUT *F) F->pushbool = 0; continue; } - if ((len = getline(, , F->fp)) == -1) + if ((len = getline(&(lp->line), &(lp->linealloc), F->fp)) == -1) break; /* Remove trailing newline, if it exists, and copy line. */ - if (line[len - 1] == '\n') + if (lp->line[len - 1] == '\n') len--; - if (lp->linealloc <= len + 1) { - char *p; - u_long newsize = lp->linealloc + - MAXIMUM(100, len + 1 - lp->linealloc); - if ((p = realloc(lp->line, newsize)) == NULL) - err(1, NULL); - lp->line = p; - lp->linealloc = newsize; - } - memcpy(lp->line, line, len); lp->line[len] = '\0'; /* Split the line into fields, allocate space as necessary. */ @@ -363,7 +350,6 @@ slurp(INPUT *F) break; } } - free(line); } char *
snmpd(8) clean up snmpe_parsevarbinds
I'm not quite sure yet where I want to move with snmpe_parsevarbinds, but the current implementation just gives me a headache every time I read it. There's still of plenty of issues in here, like not fully complient gathering of statistics, relying on synchronous handling of varbinds (required for proper AgentX support) and not taking RFC3584 into acount. But my goal for now is a small step to making things more readable and see where we can go from there. Regress still passes and except for some minor changes in the handling of snmp_intotal{req,set}vars no functional changes intended. For people who wonder what happened to the 1 return value: this value was only used when agentx was called, which is currently no more. OK? martijn@ Index: snmpd.h === RCS file: /cvs/src/usr.sbin/snmpd/snmpd.h,v retrieving revision 1.87 diff -u -p -r1.87 snmpd.h --- snmpd.h 30 Jun 2020 17:11:49 - 1.87 +++ snmpd.h 19 Jul 2020 12:08:04 - @@ -394,19 +394,10 @@ struct snmp_message { struct ber_element *sm_req; struct ber_element *sm_resp; - int sm_i; - struct ber_element *sm_a; - struct ber_element *sm_b; - struct ber_element *sm_c; - struct ber_element *sm_next; - struct ber_element *sm_last; - struct ber_element *sm_end; - u_int8_t sm_data[READ_BUF_SIZE]; size_t sm_datalen; u_intsm_version; - u_intsm_state; /* V1, V2c */ char sm_community[SNMPD_MAXCOMMUNITYLEN]; Index: snmpe.c === RCS file: /cvs/src/usr.sbin/snmpd/snmpe.c,v retrieving revision 1.62 diff -u -p -r1.62 snmpe.c --- snmpe.c 2 May 2020 14:22:31 - 1.62 +++ snmpe.c 19 Jul 2020 12:08:04 - @@ -400,124 +400,112 @@ int snmpe_parsevarbinds(struct snmp_message *msg) { struct snmp_stats *stats = _env->sc_stats; + struct ber_element *varbind, *value, *rvarbind = NULL; + struct ber_element *pvarbind = NULL, *end; char buf[BUFSIZ]; struct ber_oid o; - int ret = 0; + int i; msg->sm_errstr = "invalid varbind element"; - if (msg->sm_i == 0) { - msg->sm_i = 1; - msg->sm_a = msg->sm_varbind; - msg->sm_last = NULL; - } - -for (; msg->sm_a != NULL && msg->sm_i < SNMPD_MAXVARBIND; - msg->sm_a = msg->sm_next, msg->sm_i++) { - msg->sm_next = msg->sm_a->be_next; - - if (msg->sm_a->be_class != BER_CLASS_UNIVERSAL || - msg->sm_a->be_type != BER_TYPE_SEQUENCE) - continue; - if ((msg->sm_b = msg->sm_a->be_sub) == NULL) - continue; - - for (msg->sm_state = 0; msg->sm_state < 2 && msg->sm_b != NULL; - msg->sm_b = msg->sm_b->be_next) { - switch (msg->sm_state++) { - case 0: - if (ober_get_oid(msg->sm_b, ) != 0) - goto varfail; - if (o.bo_n < BER_MIN_OID_LEN || - o.bo_n > BER_MAX_OID_LEN) - goto varfail; - if (msg->sm_context == SNMP_C_SETREQ) - stats->snmp_intotalsetvars++; - else - stats->snmp_intotalreqvars++; - log_debug("%s: %s: oid %s", - __func__, msg->sm_host, - smi_oid2string(, buf, sizeof(buf), 0)); - break; - case 1: - msg->sm_c = NULL; - msg->sm_end = NULL; - - switch (msg->sm_context) { - - case SNMP_C_GETNEXTREQ: - msg->sm_c = ober_add_sequence(NULL); - ret = mps_getnextreq(msg, msg->sm_c, - ); - if (ret == 0 || ret == 1) - break; - ober_free_elements(msg->sm_c); - msg->sm_error = SNMP_ERROR_NOSUCHNAME; - goto varfail; - - case SNMP_C_GETREQ: - msg->sm_c = ober_add_sequence(NULL); -
Re: LC_MESSAGES in xargs(1)
I gave a quick look at replacing prompt with readpassphrase(3), but that would be more trouble than it's worth. (adjusting pledge, semantics change in where the "?..." would be printed). Minor nits inline, but either way OK martijn@ On Thu, 2020-07-16 at 21:49 +0200, Ingo Schwarze wrote: > Hi Jan, > > Jan Stary wrote on Thu, Jul 16, 2020 at 09:45:44AM +0200: > > > Does xargs need to set LC_MESSAGES? > > As it stands, your patch doesn't make much sense. It is true that > it doesn't change behaviour, but it leaves more cruft behund than > it tidies up. > > That said, i agree that we will never implement LC_MESSAGES. > > That allows a nice cleanup, simplifying the code and getting rid > of several headers and several calls to complicated functions. > > Remarks: > * .Tn was deprecated years ago. > * On OpenBSD, as the manual page says, nl_langinfo(3) is really >only useful for CODESET. > * There is no need to put a marker "return value ignored on >purpose" where ignoring the return value almost never indicates >a bug, like for fprintf, fflush, fclose. If you're going to change this, please also remove them from run() > * Usually, we prefer getline(3) over fgetln(3), but none of the >arguments making it better really applies here, so we can as >well leave it. The only downside is that ttyfp needs to remain >open until the stdio input buffer has been inspected, so we need >another automatic variable, "doit", but it's still simpler than >the malloc(3) dance that getline(3) would require. Another option would be fgets, but probably still more hassle then it's worth. > OK? > Ingo > > > Index: xargs.1 > === > RCS file: /cvs/src/usr.bin/xargs/xargs.1,v > retrieving revision 1.28 > diff -u -p -r1.28 xargs.1 > --- xargs.1 4 Jun 2014 06:48:33 - 1.28 > +++ xargs.1 16 Jul 2020 19:29:52 - > @@ -213,11 +213,11 @@ at once. > .It Fl p > Echo each command to be executed and ask the user whether it should be > executed. > -An affirmative response, > +If the answer starts with > .Ql y > -in the POSIX locale, > -causes the command to be executed, any other response causes it to be > -skipped. > +or > +.Ql Y , > +the command is executed; otherwise it is skipped. > No commands are executed if the process is not attached to a terminal. > .It Fl R Ar replacements > Specify the maximum number of arguments that > @@ -330,8 +330,7 @@ The flags > are extensions to > .St -p1003.1-2008 . > .Pp > -The meanings of the 123, 124, and 125 exit values were taken from > -.Tn GNU > +The meanings of the 123, 124, and 125 exit values were taken from GNU > .Nm xargs . > .Sh HISTORY > The > Index: xargs.c > === > RCS file: /cvs/src/usr.bin/xargs/xargs.c,v > retrieving revision 1.34 > diff -u -p -r1.34 xargs.c > --- xargs.c 12 Jun 2018 15:24:31 - 1.34 > +++ xargs.c 16 Jul 2020 19:29:52 - > @@ -41,10 +41,7 @@ > #include > #include > #include > -#include > -#include > #include > -#include > #include > #include > #include > @@ -86,8 +83,6 @@ main(int argc, char *argv[]) > eofstr = ""; > Jflag = nflag = 0; > > - (void)setlocale(LC_MESSAGES, ""); > - > /* >* POSIX.2 limits the exec line length to ARG_MAX - 2K. Running that >* caused some E2BIG errors, so it was changed to ARG_MAX - 4K. Given > @@ -607,26 +602,19 @@ waitchildren(const char *name, int waita > static int > prompt(void) > { > - regex_t cre; > size_t rsize; > - int match; > char *response; > FILE *ttyfp; > + int doit = 0; > > if ((ttyfp = fopen(_PATH_TTY, "r")) == NULL) > return (2); /* Indicate that the TTY failed to open. */ > - (void)fprintf(stderr, "?..."); > - (void)fflush(stderr); > - if ((response = fgetln(ttyfp, )) == NULL || > - regcomp(, nl_langinfo(YESEXPR), REG_BASIC) != 0) { > - (void)fclose(ttyfp); > - return (0); > - } > - response[rsize - 1] = '\0'; > - match = regexec(, response, 0, NULL, 0); > - (void)fclose(ttyfp); > - regfree(); > - return (match == 0); > + fprintf(stderr, "?..."); > + fflush(stderr); According to setvbuf(3): The standard error stream stderr is initially unbuffered. And since setvbuf is not called in xargs this seems superfluous to me. If this is correct, there's a second fflush that can also be removed. > + response = fgetln(ttyfp, ); > + doit = response != NULL && (*response == 'y' || *response == 'Y'); > + fclose(ttyfp); > + return (doit); > } > > static void >
Re: [patch] snmpd hrStorageSize negative values
On Wed, 2020-07-01 at 10:59 -0400, Johan Huldtgren wrote: > hello, > > On 2017-11-27 10:31, Gerhard Roth wrote: > > On Sat, 25 Nov 2017 11:42:07 -0700 Joel Knight > > wrote: > > > On Thu, Mar 9, 2017 at 10:02 PM, Joel Knight > > > wrote: > > > > Hi. > > > > > > > > snmpd(8) uses unsigned ints internally to represent the size and used > > > > space of a file system. The HOST-RESOURCES-MIB defines the valid > > > > values for those OIDs as 0..2147483647. With sufficiently large file > > > > systems, this can cause negative numbers to be returned for the size > > > > and used space OIDs. > > > > > > > > .1.3.6.1.2.1.25.2.3.1.5.36=-1573167768 > > > > > > Hi. Just wanted to bump this again and see if anyone that cares about > > > snmp could take a look? Looking for oks and someone who wouldn't mind > > > committing it. > > > > > > > > > > At sthen's suggestion, do what net-snmp does and fiddle with the > > > > values to prevent wrapping. Yes this mucks with the actual values of > > > > size, used space, and block size, but it allows snmpd to convey the > > > > proper size and used space of the file system which is what most > > > > everybody is really interested in. > > > > > > > > In case gmail hoses this diff, it's also here: > > > > https://www.packetmischief.ca/files/patches/snmpd.hrstorage2.diff > > > > Hi Joel, > > > > I think this won't work unless you also change the type of 'size' and > > 'used' to u_int64_t. > > I ran into an issue where my snmpd underreported my filesystem size. > > $ df -h /ftp > Filesystem SizeUsed Avail Capacity Mounted on > /dev/sd0a 50.5T 13.7T 34.3T29%/ftp > > However snmp reports something different. > > $ snmp walk -v 2c -c public localhost hrStorage > > hrStorageDescr.40 = STRING: /ftp > hrStorageAllocationUnits.40 = INTEGER: 8192 Bytes > hrStorageSize.40 = INTEGER: 2487209520 > > sthen@ pointed me to this thread but suggested 'int_t' as opposed to > 'u_int_64_t', making that change and applying it fixes the issue for > me. > > hrStorageDescr.40 = STRING: /ftp > hrStorageAllocationUnits.40 = INTEGER: 32768 > hrStorageUsed.40 = INTEGER: 459624840 > > Updated patch attached. > > thanks, > > .jh Some minor tweaks: - Use u_int64_t instead of size_t - Put the calculation outside the switch, so memory can profit as well. OK? martijn@ Index: mib.c === RCS file: /cvs/src/usr.sbin/snmpd/mib.c,v retrieving revision 1.99 diff -u -p -r1.99 mib.c --- mib.c 15 May 2020 00:56:03 - 1.99 +++ mib.c 1 Jul 2020 15:39:37 - @@ -563,7 +563,7 @@ mib_hrstorage(struct oid *oid, struct be u_int32_tidx; struct statfs *mntbuf, *mnt; int mntsize, maxsize; - u_int32_tunits, size, used, fail = 0; + u_int64_tunits, size, used, fail = 0; const char *descr = NULL; int mib[] = { CTL_HW, 0 }; u_int64_tphysmem, realmem; @@ -645,6 +645,12 @@ mib_hrstorage(struct oid *oid, struct be used = mnt->f_blocks - mnt->f_bfree; sop = [3]; break; + } + + while (size > INT32_MAX) { + units *= 2; + size /= 2; + used /= 2; } /* Tables need to prepend the OID on their own */
Re: Potential grep bug?
Moving to tech@ On Tue, 2020-06-23 at 22:17 -0900, Philip Guenther wrote: > Nope. This is a grep of a single file, so procfile() must be overflowing > and this only 'fixes' it by relying on signed overflow, which is undefined > behavior, being handled in a particular way by the compiler. So, luck > (which fails when the compiler decides to hate you). There are more places > that need to change for the reported problem to be handled safely. > > Philip Guenther I'm not sure I understand exactly what you mean, but the overflow can still propagate through to the return value. Since everything propagated up from procfile is only eventually used to determine the exit value we can start treating it as a boolean. I gave a quick glance at freebsd and they also treat it as a boolean, but more explicitly. They however don't appear have overflow detection. Is this better? martijn@ > > > On Tue, Jun 23, 2020 at 9:58 PM Martijn van Duren < > open...@list.imperialat.at> wrote: > > > This seems to fix the issue for me. > > > > OK? > > > > martijn@ > > > > On Tue, 2020-06-23 at 19:29 -0700, Jordan Geoghegan wrote: > > > Hello, > > > > > > I was working on a couple POSIX regular expressions to search for and > > > validate IPv4 and IPv6 addresses with optional CIDR blocks, and > > > encountered some strange behaviour from the base system grep. > > > > > > I wanted to validate my regex against a list of every valid IPv4 > > > address, so I generated a list with a zsh 1 liner: > > > > > > for i in {0..255}; do; echo $i.{0..255}.{0..255}.{0..255} ; done | > > > tr '[:space:]' '\n' > IPv4.txt > > > > > > My intentions were to test the regex by running it with 'grep -c' to > > > confirm there was indeed 2^32 addresses matched, and I also wanted to > > > benchmark and compare performance between BSD grep, GNU grep and > > > ripgrep. The command I used: > > > > > > grep -Eoc > > > > > "((25[0-5]|(2[0-4]|1{0,1}[[:digit:]]){0,1}[[:digit:]])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[[:digit:]]){0,1}[[:digit:]])(/[1-9]|/[1-2][[:digit:]]|/3[0-2])?" > > > My findings were surprising. Both GNU grep and ripgrep were able get > > > through the file in roughly 10 and 20 minutes respectively, whereas the > > > base system grep took over 20 hours! What interested me the most was > > > that the base system grep when run with '-c' returned '0' for match > > > count. It seems that 'grep -c' will have its counter overflow if there > > > are more than 2^32-1 matches (4294967295) and then the counter will > > > start counting from zero again for further matches. > > > > > > ryzen$ time zcat IPv4.txt.gz | grep -Eoc > > "((25[0-5]|(2[0-4]|1{0,1}... > > > 0 > > > 1222m09.32s real 1224m28.02s user 1m16.17s system > > > > > > ryzen$ time zcat allip.txt.gz | ggrep -Eoc > > "((25[0-5]|(2[0-4]|1{0,1}... > > > 4294967296 > > > 10m00.38s real11m40.57s user 0m30.55s system > > > > > > ryzen$ time rg -zoc "((25[0-5]|(2[0-4]|1{0,1}... > > > 4294967296 > > > 21m06.36s real27m06.04s user 0m50.08s system > > > > > > # See the counter overflow/reset: > > > jot 4294967350 | grep -c "^[[:digit:]]" > > > 54 > > > > > > All testing was done on a Ryzen desktop machine running 6.7 stable. > > > > > > The grep counting bug can be reproduced with this command: > > > jot 4294967296 | nice grep -c "^[[:digit:]]" > > > > > > Regards, > > > > > > Jordan > > > Index: grep.c === RCS file: /cvs/src/usr.bin/grep/grep.c,v retrieving revision 1.64 diff -u -p -r1.64 grep.c --- grep.c 3 Dec 2019 09:14:37 - 1.64 +++ grep.c 24 Jun 2020 11:26:25 - @@ -517,7 +517,7 @@ main(int argc, char *argv[]) c = grep_tree(argv); else for (c = 0; argc--; ++argv) - c += procfile(*argv); + c |= procfile(*argv); exit(c ? (file_err ? (qflag ? 0 : 2) : 0) : (file_err ? 2 : 1)); } Index: util.c === RCS file: /cvs/src/usr.bin/grep/util.c,v retrieving revision 1.62 diff -u -p -r1.62 util.c --- util.c 3 Dec 2019 09:14:37 - 1.62 +++ util.c 24 Jun 2020 11:26:25 - @@ -91,7 +91,7 @@ grep_tree(char **argv)
Re: snmp(1) initial UTF-8 support
And of course I still had a potential buffer overflow in there... On Sat, 2020-06-13 at 09:16 +0200, Martijn van Duren wrote: > Minor change: I forgot to forward the display_hint flag to > smi_displayhint_os. Now -OQ and -Oq work as well. > > On Thu, 2020-06-11 at 21:17 +0200, Martijn van Duren wrote: > > Hello Ingo, > > > > Thanks for looking into this. > > > > On Sun, 2020-05-31 at 16:32 +0200, Ingo Schwarze wrote: > > > Hi Martijn, > > > > > > Martijn van Duren wrote on Tue, May 19, 2020 at 10:25:37PM +0200: > > > > > > > So according to RFC2579 an octetstring can contain UTF-8 characters if > > > > so described in the DISPLAY-HINT. One of the main consumers of this is > > > > SnmpAdminString, which is used quite a lot. > > > > > > > > Now that we trimmed a little fat from snmp's oid, I wanted to fill it > > > > up again and implemented the bare minimum DISPLAY-HINT parsing that is > > > > required for SnmpAdminString. Other parts of the syntax can be atter > > > > at a later state if desirable. > > > > > > > > Now I decided to implement this a little different from net-snmp, > > > > because they throw incomplete sequences directly to the terminal, > > > > which I recon is not a sane approach. > > > > > > No, definitely not. Never throw invalid or incomplete UTF-8 at the > > > terminal unless the user unambiguously requests just that (like > > > with `printf "a\x80z\n"` or `cat /usr/bin/cc` or something like that). > > > > > > > I choose to take the approach taken by the likes of wall(1) and replace > > > > invalid and incomplete sequences with a '?'. > > > > > > If the specification says that the user is only allowed to put valid > > > UTF-8 into octetstrings (and not arbitrary bytes), replacing invalid > > > bytes at output time is both acceptable and feels like the only > > > sensible option, unless something like vis(3) is considered more > > > appropriate. > > > > RFC2579 section 3.1 bullet (3): or `t' for UTF-8 > > So it should be valid UTF-8. > > > However, the reason why wall(1) uses '?' as the replacement character > > > is because wall(1) must not assume that the output device can handle > > > UTF-8 and has to work safely if all the output device can handle is > > > ASCII. So, wall(1) has to live with the inconvenience that when you > > > see a question mark, you don't know whether it really is a question > > > mark or whether it originally used to be garbage input. > > > > Fair enough. > > > If i understand correctly, here we are talking about output that is > > > UTF-8 anyway. So instead of (ab)using the question mark, you might > > > consider using the U+FFFD REPLACEMENT CHARACTER. The intended > > > purpose of that one is to stand in for invalid and inconplete > > > byte sequences, and also for characters that cannot be displayed. > > > > I like that one, used in diff below. > > > > This because DISPLAY-HINT already states that too long sequences > > > > strings should be cut short at the final multibyte character fitting > > > > inside the specified length, meaning that output can already get > > > > mangled. > > > > > > > > This also brings me to the question how we should handle DISPLAY-HINT > > > > in the case of -Oa and -Ox. Net-snmp prioritizes DISPLAY-HINT over > > > > these, but it has the option to disable this by disabling MIB-loading > > > > via -m''; This implementation doesn't give us the that option (yet?). > > > > The current diff follows net-snmp, but there is something to say to > > > > prioritize -Ox over DISPLAY-HINT, so an admin can use it to debug > > > > snmp-output without it being mangled. Any feedback here is welcome. > > > > > > > > Once it's clear if this is the right approach I'll do a thorough search > > > > through mib.h on which objects actually can use this new definition. > > > > > > I can't really comment on what snmp(1) should do, or which settings > > > should override which other settings. > > > > I'll leave it as is for now. If people actually need to original mangled > > data we can always revisit. It's not something major that people heavily > > rely on. > > > Do i understand correctly that you want to make -Oa print invalid > > > UTF-8 to the terminal? > > > > No, to be in line w
Re: snmp(1) initial UTF-8 support
Minor change: I forgot to forward the display_hint flag to smi_displayhint_os. Now -OQ and -Oq work as well. On Thu, 2020-06-11 at 21:17 +0200, Martijn van Duren wrote: > Hello Ingo, > > Thanks for looking into this. > > On Sun, 2020-05-31 at 16:32 +0200, Ingo Schwarze wrote: > > Hi Martijn, > > > > Martijn van Duren wrote on Tue, May 19, 2020 at 10:25:37PM +0200: > > > > > So according to RFC2579 an octetstring can contain UTF-8 characters if > > > so described in the DISPLAY-HINT. One of the main consumers of this is > > > SnmpAdminString, which is used quite a lot. > > > > > > Now that we trimmed a little fat from snmp's oid, I wanted to fill it > > > up again and implemented the bare minimum DISPLAY-HINT parsing that is > > > required for SnmpAdminString. Other parts of the syntax can be atter > > > at a later state if desirable. > > > > > > Now I decided to implement this a little different from net-snmp, > > > because they throw incomplete sequences directly to the terminal, > > > which I recon is not a sane approach. > > > > No, definitely not. Never throw invalid or incomplete UTF-8 at the > > terminal unless the user unambiguously requests just that (like > > with `printf "a\x80z\n"` or `cat /usr/bin/cc` or something like that). > > > > > I choose to take the approach taken by the likes of wall(1) and replace > > > invalid and incomplete sequences with a '?'. > > > > If the specification says that the user is only allowed to put valid > > UTF-8 into octetstrings (and not arbitrary bytes), replacing invalid > > bytes at output time is both acceptable and feels like the only > > sensible option, unless something like vis(3) is considered more > > appropriate. > > RFC2579 section 3.1 bullet (3): or `t' for UTF-8 > So it should be valid UTF-8. > > However, the reason why wall(1) uses '?' as the replacement character > > is because wall(1) must not assume that the output device can handle > > UTF-8 and has to work safely if all the output device can handle is > > ASCII. So, wall(1) has to live with the inconvenience that when you > > see a question mark, you don't know whether it really is a question > > mark or whether it originally used to be garbage input. > > Fair enough. > > If i understand correctly, here we are talking about output that is > > UTF-8 anyway. So instead of (ab)using the question mark, you might > > consider using the U+FFFD REPLACEMENT CHARACTER. The intended > > purpose of that one is to stand in for invalid and inconplete > > byte sequences, and also for characters that cannot be displayed. > > I like that one, used in diff below. > > > This because DISPLAY-HINT already states that too long sequences > > > strings should be cut short at the final multibyte character fitting > > > inside the specified length, meaning that output can already get > > > mangled. > > > > > > This also brings me to the question how we should handle DISPLAY-HINT > > > in the case of -Oa and -Ox. Net-snmp prioritizes DISPLAY-HINT over > > > these, but it has the option to disable this by disabling MIB-loading > > > via -m''; This implementation doesn't give us the that option (yet?). > > > The current diff follows net-snmp, but there is something to say to > > > prioritize -Ox over DISPLAY-HINT, so an admin can use it to debug > > > snmp-output without it being mangled. Any feedback here is welcome. > > > > > > Once it's clear if this is the right approach I'll do a thorough search > > > through mib.h on which objects actually can use this new definition. > > > > I can't really comment on what snmp(1) should do, or which settings > > should override which other settings. > > I'll leave it as is for now. If people actually need to original mangled > data we can always revisit. It's not something major that people heavily > rely on. > > Do i understand correctly that you want to make -Oa print invalid > > UTF-8 to the terminal? > > No, to be in line with net-snmp, what snmp(1) does is the following: > - Without a -O flag it sees if all bytes are printable and if so print > the string, if not prints the full string in hex. > - With -Oa it prints all printable bytes and replaces unprintable > characters with '.'. > - With -Ox it prints all bytes in hex. > > > If so, that would sound reasonable to me, > > for the following reason. Printing non-printable ASCII to the > > terminal is often dangerous, it can screw up or reconfigure the >
Re: snmp(1) initial UTF-8 support
Hello Ingo, Thanks for looking into this. On Sun, 2020-05-31 at 16:32 +0200, Ingo Schwarze wrote: > Hi Martijn, > > Martijn van Duren wrote on Tue, May 19, 2020 at 10:25:37PM +0200: > > > So according to RFC2579 an octetstring can contain UTF-8 characters if > > so described in the DISPLAY-HINT. One of the main consumers of this is > > SnmpAdminString, which is used quite a lot. > > > > Now that we trimmed a little fat from snmp's oid, I wanted to fill it > > up again and implemented the bare minimum DISPLAY-HINT parsing that is > > required for SnmpAdminString. Other parts of the syntax can be atter > > at a later state if desirable. > > > > Now I decided to implement this a little different from net-snmp, > > because they throw incomplete sequences directly to the terminal, > > which I recon is not a sane approach. > > No, definitely not. Never throw invalid or incomplete UTF-8 at the > terminal unless the user unambiguously requests just that (like > with `printf "a\x80z\n"` or `cat /usr/bin/cc` or something like that). > > > I choose to take the approach taken by the likes of wall(1) and replace > > invalid and incomplete sequences with a '?'. > > If the specification says that the user is only allowed to put valid > UTF-8 into octetstrings (and not arbitrary bytes), replacing invalid > bytes at output time is both acceptable and feels like the only > sensible option, unless something like vis(3) is considered more > appropriate. RFC2579 section 3.1 bullet (3): or `t' for UTF-8 So it should be valid UTF-8. > > However, the reason why wall(1) uses '?' as the replacement character > is because wall(1) must not assume that the output device can handle > UTF-8 and has to work safely if all the output device can handle is > ASCII. So, wall(1) has to live with the inconvenience that when you > see a question mark, you don't know whether it really is a question > mark or whether it originally used to be garbage input. Fair enough. > > If i understand correctly, here we are talking about output that is > UTF-8 anyway. So instead of (ab)using the question mark, you might > consider using the U+FFFD REPLACEMENT CHARACTER. The intended > purpose of that one is to stand in for invalid and inconplete > byte sequences, and also for characters that cannot be displayed. I like that one, used in diff below. > > > This because DISPLAY-HINT already states that too long sequences > > strings should be cut short at the final multibyte character fitting > > inside the specified length, meaning that output can already get > > mangled. > > > > This also brings me to the question how we should handle DISPLAY-HINT > > in the case of -Oa and -Ox. Net-snmp prioritizes DISPLAY-HINT over > > these, but it has the option to disable this by disabling MIB-loading > > via -m''; This implementation doesn't give us the that option (yet?). > > The current diff follows net-snmp, but there is something to say to > > prioritize -Ox over DISPLAY-HINT, so an admin can use it to debug > > snmp-output without it being mangled. Any feedback here is welcome. > > > > Once it's clear if this is the right approach I'll do a thorough search > > through mib.h on which objects actually can use this new definition. > > I can't really comment on what snmp(1) should do, or which settings > should override which other settings. I'll leave it as is for now. If people actually need to original mangled data we can always revisit. It's not something major that people heavily rely on. > > Do i understand correctly that you want to make -Oa print invalid > UTF-8 to the terminal? No, to be in line with net-snmp, what snmp(1) does is the following: - Without a -O flag it sees if all bytes are printable and if so print the string, if not prints the full string in hex. - With -Oa it prints all printable bytes and replaces unprintable characters with '.'. - With -Ox it prints all bytes in hex. > If so, that would sound reasonable to me, > for the following reason. Printing non-printable ASCII to the > terminal is often dangerous, it can screw up or reconfigure the > terminal, so -Oa is already an option that must be used with care, > just like `cat /usr/bin/cc`. While printing invalid UTF-8 is not > a good idea in general, it is less dangerous than printing non-printable > ASCII, so just passing the bytes through for -Oa doesn't make > anything more dangerous than it already is. > > Maybe -Oa should have a warning in the manual page about the dangers > of using it on untrusted data? Not sure. So no, it's not dangerous. > > Oh, by the way, when -Oa is not specified and there is UTF-8 > content,
Re: Some redundant code lines in sys
On Fri, 2020-06-05 at 14:20 +0100, Stuart Henderson wrote: > On 2020/06/05 13:50, Denis Fondras wrote: > > On Fri, Jun 05, 2020 at 12:56:21PM +0200, Prof. Dr. Steffen Wendzel wrote: > > > Dear all: > > > > > > just in case this appears useful to you: I found some redundant code > > > lines in the following files. > > > > > > sys/net/pipex.h: > > >struct pipex_session *pipex_pppoe_lookup_session (struct mbuf *); > > >struct pipex_session *pipex_pppoe_lookup_session (struct mbuf *); > > > > > > usr.sbin/relayd/agentx.c > > >snmp_agentx_oid(pdu, oid) == -1 || > > >snmp_agentx_oid(pdu, oid) == -1 || > > > > > > usr.sbin/snmpd/agentx.c: > > > snmp_agentx_oid(pdu, oid) == -1 || > > > snmp_agentx_oid(pdu, oid) == -1 || > > My first thought for these two was "were they just accidentally > duplicated, or was something else meant to be there instead". Looking at > the commit and code (the function is identical in snmpd and relayd) I am > going more on the side of accidental dup (plus removing it doesn't > change behaviour of code that been running for a while) so OK with me. It's definitely a duplicate. This is when an unregister-pdu is created, which only contains a single OID. Ranges can be specified, that's done via the range_index/range_bound combo, or as the RFC names them: range_subid/upper_bound. Since the unregister pdu is a client generated pdu it's by definition not being called in snmpd(8). A quick grep in relayd shows that it's also never called there. > > > > usr.sbin/bgpd/rde.h: > > > void path_init(u_int32_t); > > > void path_init(u_int32_t); > > > > > > lib/libcurses/nc_tparm.h: > > > #define TPARM_1(a,b) TPARM_2(a,b,0) > > > #define TPARM_1(a,b) TPARM_2(a,b,0) > > > > > > > Nice catch, thank you. > > > > > > Index: lib/libcurses/nc_tparm.h > > === > > RCS file: /cvs/src/lib/libcurses/nc_tparm.h,v > > retrieving revision 1.1 > > diff -u -p -r1.1 nc_tparm.h > > --- lib/libcurses/nc_tparm.h12 Jan 2010 23:21:59 - 1.1 > > +++ lib/libcurses/nc_tparm.h5 Jun 2020 11:45:41 - > > @@ -62,6 +62,5 @@ > > #define TPARM_3(a,b,c,d) TPARM_4(a,b,c,d,0) > > #define TPARM_2(a,b,c) TPARM_3(a,b,c,0) > > #define TPARM_1(a,b) TPARM_2(a,b,0) > > -#define TPARM_1(a,b) TPARM_2(a,b,0) > > #define TPARM_0(a) TPARM_1(a,0) > > #endif > > Index: sys/net/pipex.h > > === > > RCS file: /cvs/src/sys/net/pipex.h,v > > retrieving revision 1.22 > > diff -u -p -r1.22 pipex.h > > --- sys/net/pipex.h 26 May 2020 07:06:37 - 1.22 > > +++ sys/net/pipex.h 5 Jun 2020 11:45:44 - > > @@ -206,7 +206,6 @@ int pipex_notify_close > > > > struct mbuf *pipex_output (struct mbuf *, int, int, struct > > pipex_iface_context *); > > struct pipex_session *pipex_pppoe_lookup_session (struct mbuf *); > > -struct pipex_session *pipex_pppoe_lookup_session (struct mbuf *); > > struct mbuf *pipex_pppoe_input (struct mbuf *, struct > > pipex_session *); > > struct pipex_session *pipex_pptp_lookup_session (struct mbuf *); > > struct mbuf *pipex_pptp_input (struct mbuf *, struct > > pipex_session *); > > Index: usr.sbin/bgpd/rde.h > > === > > RCS file: /cvs/src/usr.sbin/bgpd/rde.h,v > > retrieving revision 1.233 > > diff -u -p -r1.233 rde.h > > --- usr.sbin/bgpd/rde.h 24 Jan 2020 05:44:05 - 1.233 > > +++ usr.sbin/bgpd/rde.h 5 Jun 2020 11:45:45 - > > @@ -557,7 +557,6 @@ re_rib(struct rib_entry *re) > > } > > > > voidpath_init(u_int32_t); > > -voidpath_init(u_int32_t); > > voidpath_shutdown(void); > > voidpath_hash_stats(struct rde_hashstats *); > > int path_compare(struct rde_aspath *, struct rde_aspath *); > > Index: usr.sbin/relayd/agentx.c > > === > > RCS file: /cvs/src/usr.sbin/relayd/agentx.c,v > > retrieving revision 1.14 > > diff -u -p -r1.14 agentx.c > > --- usr.sbin/relayd/agentx.c28 May 2017 10:39:15 - 1.14 > > +++ usr.sbin/relayd/agentx.c5 Jun 2020 11:45:45 - > > @@ -654,7 +654,6 @@ snmp_agentx_unregister_pdu(struct snmp_o > > > > if (snmp_agentx_raw(pdu, , sizeof(uhdr)) == -1 || > > snmp_agentx_oid(pdu, oid) == -1 || > > - snmp_agentx_oid(pdu, oid) == -1 || > > (range_index && snmp_agentx_int(pdu, _bound) == -1)) { > > snmp_agentx_pdu_free(pdu); > > return (NULL); > > Index: usr.sbin/snmpd/agentx.c > > === > > RCS file: /cvs/src/usr.sbin/snmpd/agentx.c,v > > retrieving revision 1.13 > > diff -u -p -r1.13 agentx.c > > --- usr.sbin/snmpd/agentx.c 17 Jun 2018 18:19:59 -
Re: Some redundant code lines in sys
OK martijn@ On Fri, 2020-06-05 at 13:50 +0200, Denis Fondras wrote: > On Fri, Jun 05, 2020 at 12:56:21PM +0200, Prof. Dr. Steffen Wendzel wrote: > > Dear all: > > > > just in case this appears useful to you: I found some redundant code > > lines in the following files. > > > > sys/net/pipex.h: > >struct pipex_session *pipex_pppoe_lookup_session (struct mbuf *); > >struct pipex_session *pipex_pppoe_lookup_session (struct mbuf *); > > > > usr.sbin/relayd/agentx.c > >snmp_agentx_oid(pdu, oid) == -1 || > >snmp_agentx_oid(pdu, oid) == -1 || > > > > usr.sbin/snmpd/agentx.c: > > snmp_agentx_oid(pdu, oid) == -1 || > > snmp_agentx_oid(pdu, oid) == -1 || > > > > usr.sbin/bgpd/rde.h: > > void path_init(u_int32_t); > > void path_init(u_int32_t); > > > > lib/libcurses/nc_tparm.h: > > #define TPARM_1(a,b) TPARM_2(a,b,0) > > #define TPARM_1(a,b) TPARM_2(a,b,0) > > > > Nice catch, thank you. > > > Index: lib/libcurses/nc_tparm.h > === > RCS file: /cvs/src/lib/libcurses/nc_tparm.h,v > retrieving revision 1.1 > diff -u -p -r1.1 nc_tparm.h > --- lib/libcurses/nc_tparm.h 12 Jan 2010 23:21:59 - 1.1 > +++ lib/libcurses/nc_tparm.h 5 Jun 2020 11:45:41 - > @@ -62,6 +62,5 @@ > #define TPARM_3(a,b,c,d) TPARM_4(a,b,c,d,0) > #define TPARM_2(a,b,c) TPARM_3(a,b,c,0) > #define TPARM_1(a,b) TPARM_2(a,b,0) > -#define TPARM_1(a,b) TPARM_2(a,b,0) > #define TPARM_0(a) TPARM_1(a,0) > #endif > Index: sys/net/pipex.h > === > RCS file: /cvs/src/sys/net/pipex.h,v > retrieving revision 1.22 > diff -u -p -r1.22 pipex.h > --- sys/net/pipex.h 26 May 2020 07:06:37 - 1.22 > +++ sys/net/pipex.h 5 Jun 2020 11:45:44 - > @@ -206,7 +206,6 @@ int pipex_notify_close > > struct mbuf *pipex_output (struct mbuf *, int, int, struct > pipex_iface_context *); > struct pipex_session *pipex_pppoe_lookup_session (struct mbuf *); > -struct pipex_session *pipex_pppoe_lookup_session (struct mbuf *); > struct mbuf *pipex_pppoe_input (struct mbuf *, struct > pipex_session *); > struct pipex_session *pipex_pptp_lookup_session (struct mbuf *); > struct mbuf *pipex_pptp_input (struct mbuf *, struct pipex_session > *); > Index: usr.sbin/bgpd/rde.h > === > RCS file: /cvs/src/usr.sbin/bgpd/rde.h,v > retrieving revision 1.233 > diff -u -p -r1.233 rde.h > --- usr.sbin/bgpd/rde.h 24 Jan 2020 05:44:05 - 1.233 > +++ usr.sbin/bgpd/rde.h 5 Jun 2020 11:45:45 - > @@ -557,7 +557,6 @@ re_rib(struct rib_entry *re) > } > > void path_init(u_int32_t); > -void path_init(u_int32_t); > void path_shutdown(void); > void path_hash_stats(struct rde_hashstats *); > int path_compare(struct rde_aspath *, struct rde_aspath *); > Index: usr.sbin/relayd/agentx.c > === > RCS file: /cvs/src/usr.sbin/relayd/agentx.c,v > retrieving revision 1.14 > diff -u -p -r1.14 agentx.c > --- usr.sbin/relayd/agentx.c 28 May 2017 10:39:15 - 1.14 > +++ usr.sbin/relayd/agentx.c 5 Jun 2020 11:45:45 - > @@ -654,7 +654,6 @@ snmp_agentx_unregister_pdu(struct snmp_o > > if (snmp_agentx_raw(pdu, , sizeof(uhdr)) == -1 || > snmp_agentx_oid(pdu, oid) == -1 || > - snmp_agentx_oid(pdu, oid) == -1 || > (range_index && snmp_agentx_int(pdu, _bound) == -1)) { > snmp_agentx_pdu_free(pdu); > return (NULL); > Index: usr.sbin/snmpd/agentx.c > === > RCS file: /cvs/src/usr.sbin/snmpd/agentx.c,v > retrieving revision 1.13 > diff -u -p -r1.13 agentx.c > --- usr.sbin/snmpd/agentx.c 17 Jun 2018 18:19:59 - 1.13 > +++ usr.sbin/snmpd/agentx.c 5 Jun 2020 11:45:45 - > @@ -658,7 +658,6 @@ snmp_agentx_unregister_pdu(struct snmp_o > > if (snmp_agentx_raw(pdu, , sizeof(uhdr)) == -1 || > snmp_agentx_oid(pdu, oid) == -1 || > - snmp_agentx_oid(pdu, oid) == -1 || > (range_index && snmp_agentx_int(pdu, _bound) == -1)) { > snmp_agentx_pdu_free(pdu); > return (NULL); >
"extent" in dmesg
After updating today I noticed a couple of new extent messages in my dmesg, which I apparently missed last upgrade. Luckily the dmesg buffer is large enough to find the first mention. The machine runs just fine, but I just wanted to post it here, because it does stand out and I don't know how useful the information is. full dmesg with and without below martijn@ OpenBSD 6.7 (GENERIC.MP) #182: Thu May 7 11:11:58 MDT 2020 dera...@amd64.openbsd.org:/usr/src/sys/arch/amd64/compile/GENERIC.MP real mem = 16908218368 (16124MB) avail mem = 16383160320 (15624MB) mpath0 at root scsibus0 at mpath0: 256 targets mainbus0 at root bios0 at mainbus0: SMBIOS rev. 3.0 @ 0xaf04c000 (63 entries) bios0: vendor LENOVO version "N22ET53W (1.30 )" date 02/19/2019 bios0: LENOVO 20L7S27G00 acpi0 at bios0: ACPI 5.0 acpi0: sleep states S0 S3 S4 S5 acpi0: tables DSDT FACP SSDT UEFI SSDT SSDT HPET APIC MCFG ECDT SSDT SSDT BOOT BATB SLIC SSDT SSDT SSDT LPIT WSMT SSDT SSDT SSDT DBGP DBG2 MSDM DMAR ASF! FPDT BGRT UEFI acpi0: wakeup devices GLAN(S4) XHC_(S3) XDCI(S4) HDAS(S4) RP01(S4) PXSX(S4) RP02(S4) PXSX(S4) PXSX(S4) RP04(S4) PXSX(S4) RP05(S4) PXSX(S4) RP06(S4) PXSX(S4) RP07(S4) [...] acpitimer0 at acpi0: 3579545 Hz, 24 bits acpihpet0 at acpi0: 2399 Hz acpimadt0 at acpi0 addr 0xfee0: PC-AT compat cpu0 at mainbus0: apid 0 (boot processor) cpu0: Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz, 1789.11 MHz, 06-8e-0a cpu0: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS- CPL,VMX,EST,TM2,SSSE3,SDBG,FMA3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,x2APIC,MOVBE,POPCNT,DEADLINE,AES,XSAVE,AVX,F16C,RDRAND,NXE,PAGE1GB,RDTSCP,LONG,LAHF,ABM,3DNOWP,PERF,ITSC,FSGSBASE,TSC_ADJUST,SGX,BMI1, AVX2,SMEP,BMI2,ERMS,INVPCID,MPX,RDSEED,ADX,SMAP,CLFLUSHOPT,PT,MD_CLEAR,TSXFA,IBRS,IBPB,STIBP,L1DF,SSBD,SENSOR,ARAT,XSAVEOPT,XSAVEC,XGETBV1,XSAVES,MELTDOWN cpu0: 256KB 64b/line 8-way L2 cache cpu0: smt 0, core 0, package 0 mtrr: Pentium Pro MTRR support, 10 var ranges, 88 fixed ranges cpu0: apic clock running at 24MHz cpu0: mwait min=64, max=64, C-substates=0.2.1.2.4.1.1.1, IBE cpu1 at mainbus0: apid 2 (application processor) cpu1: Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz, 1789.26 MHz, 06-8e-0a cpu1: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS- CPL,VMX,EST,TM2,SSSE3,SDBG,FMA3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,x2APIC,MOVBE,POPCNT,DEADLINE,AES,XSAVE,AVX,F16C,RDRAND,NXE,PAGE1GB,RDTSCP,LONG,LAHF,ABM,3DNOWP,PERF,ITSC,FSGSBASE,TSC_ADJUST,SGX,BMI1, AVX2,SMEP,BMI2,ERMS,INVPCID,MPX,RDSEED,ADX,SMAP,CLFLUSHOPT,PT,MD_CLEAR,TSXFA,IBRS,IBPB,STIBP,L1DF,SSBD,SENSOR,ARAT,XSAVEOPT,XSAVEC,XGETBV1,XSAVES,MELTDOWN cpu1: 256KB 64b/line 8-way L2 cache cpu1: smt 0, core 1, package 0 cpu2 at mainbus0: apid 4 (application processor) cpu2: Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz, 1789.27 MHz, 06-8e-0a cpu2: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS- CPL,VMX,EST,TM2,SSSE3,SDBG,FMA3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,x2APIC,MOVBE,POPCNT,DEADLINE,AES,XSAVE,AVX,F16C,RDRAND,NXE,PAGE1GB,RDTSCP,LONG,LAHF,ABM,3DNOWP,PERF,ITSC,FSGSBASE,TSC_ADJUST,SGX,BMI1, AVX2,SMEP,BMI2,ERMS,INVPCID,MPX,RDSEED,ADX,SMAP,CLFLUSHOPT,PT,MD_CLEAR,TSXFA,IBRS,IBPB,STIBP,L1DF,SSBD,SENSOR,ARAT,XSAVEOPT,XSAVEC,XGETBV1,XSAVES,MELTDOWN cpu2: 256KB 64b/line 8-way L2 cache cpu2: smt 0, core 2, package 0 cpu3 at mainbus0: apid 6 (application processor) cpu3: Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz, 1790.42 MHz, 06-8e-0a cpu3: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS- CPL,VMX,EST,TM2,SSSE3,SDBG,FMA3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,x2APIC,MOVBE,POPCNT,DEADLINE,AES,XSAVE,AVX,F16C,RDRAND,NXE,PAGE1GB,RDTSCP,LONG,LAHF,ABM,3DNOWP,PERF,ITSC,FSGSBASE,TSC_ADJUST,SGX,BMI1, AVX2,SMEP,BMI2,ERMS,INVPCID,MPX,RDSEED,ADX,SMAP,CLFLUSHOPT,PT,MD_CLEAR,TSXFA,IBRS,IBPB,STIBP,L1DF,SSBD,SENSOR,ARAT,XSAVEOPT,XSAVEC,XGETBV1,XSAVES,MELTDOWN cpu3: 256KB 64b/line 8-way L2 cache cpu3: smt 0, core 3, package 0 ioapic0 at mainbus0: apid 2 pa 0xfec0, version 20, 120 pins acpimcfg0 at acpi0 acpimcfg0: addr 0xf800, bus 0-63 acpiec0 at acpi0 acpiprt0 at acpi0: bus 0 (PCI0) acpiprt1 at acpi0: bus 1 (RP01) acpiprt2 at acpi0: bus -1 (RP02) acpiprt3 at acpi0: bus -1 (RP03) acpiprt4 at acpi0: bus -1 (RP04) acpiprt5 at acpi0: bus 4 (RP05) acpiprt6 at acpi0: bus -1 (RP06) acpiprt7 at acpi0: bus 61 (RP07) acpiprt8 at acpi0: bus -1 (RP08) acpiprt9 at acpi0: bus 62 (RP09) acpiprt10 at acpi0: bus -1 (RP10) acpiprt11 at acpi0: bus -1 (RP11) acpiprt12 at acpi0: bus -1 (RP12) acpiprt13 at acpi0: bus -1 (RP13) acpiprt14 at acpi0: bus -1 (RP14) acpiprt15 at acpi0: bus -1 (RP15) acpiprt16 at acpi0: bus -1 (RP16) acpiprt17 at acpi0: bus -1 (RP17) acpiprt18 at
snmp(1) initial UTF-8 support
So according to RFC2579 an octetstring can contain UTF-8 characters if so described in the DISPLAY-HINT. One of the main consumers of this is SnmpAdminString, which is used quite a lot. Now that we trimmed a little fat from snmp's oid, I wanted to fill it up again and implemented the bare minimum DISPLAY-HINT parsing that is required for SnmpAdminString. Other parts of the syntax can be atter at a later state if desirable. Now I decided to implement this a little different from net-snmp, because they throw incomplete sequences directly to the terminal, which I recon is not a sane approach. I choose to take the approach taken by the likes of wall(1) and replace invalid and incomplete sequences with a '?'. This because DISPLAY-HINT already states that too long sequences strings should be cut short at the final multibyte character fitting inside the specified length, meaning that output can already get mangled. This also brings me to the question how we should handle DISPLAY-HINT in the case of -Oa and -Ox. Net-snmp prioritizes DISPLAY-HINT over these, but it has the option to disable this by disabling MIB-loading via -m''; This implementation doesn't give us the that option (yet?). The current diff follows net-snmp, but there is something to say to prioritize -Ox over DISPLAY-HINT, so an admin can use it to debug snmp-output without it being mangled. Any feedback here is welcome. Once it's clear if this is the right approach I'll do a thorough search through mib.h on which objects actually can use this new definition. Example choosen because his copyright was in front of me: $ snmp walk 127.0.0.1 sysContact sysContact.0 = Hex-STRING: 52 65 79 6B 20 46 6C C3 B6 74 65 72 $ ./obj/snmp walk 127.0.0.1 sysContact sysContact.0 = Reyk Flöter $ LC_ALL=C $ ./obj/snmp walk 127.0.0.1 sysContact sysContact.0 = Reyk Fl?ter Thoughts? martijn@ Index: mib.c === RCS file: /cvs/src/usr.bin/snmp/mib.c,v retrieving revision 1.2 diff -u -p -r1.2 mib.c --- mib.c 19 May 2020 13:41:01 - 1.2 +++ mib.c 19 May 2020 20:21:42 - @@ -27,9 +27,11 @@ #include "smi.h" static struct oid mib_tree[] = MIB_TREE; +static struct textconv textconv_tree[] = TEXTCONV_TREE; void mib_init(void) { smi_mibtree(mib_tree); + smi_textconvtree(textconv_tree); } Index: mib.h === RCS file: /cvs/src/usr.bin/snmp/mib.h,v retrieving revision 1.1 diff -u -p -r1.1 mib.h --- mib.h 9 Aug 2019 06:17:59 - 1.1 +++ mib.h 19 May 2020 20:21:42 - @@ -751,7 +751,7 @@ { MIBDECL(sysDescr) }, \ { MIBDECL(sysOID) },\ { MIBDECL(sysUpTime) }, \ - { MIBDECL(sysContact) },\ + { MIBDECL(sysContact), "SnmpAdminString" }, \ { MIBDECL(sysName) }, \ { MIBDECL(sysLocation) }, \ { MIBDECL(sysServices) }, \ @@ -1345,6 +1345,11 @@ { MIBDECL(ipfRouteEntRouteMetric5) }, \ { MIBDECL(ipfRouteEntStatus) }, \ { MIBEND } \ +} + +#define TEXTCONV_TREE {\ + { "SnmpAdminString", "255t", BER_TYPE_OCTETSTRING }, \ + { NULL, NULL } \ } voidmib_init(void); Index: smi.c === RCS file: /cvs/src/usr.bin/snmp/smi.c,v retrieving revision 1.8 diff -u -p -r1.8 smi.c --- smi.c 19 May 2020 13:41:01 - 1.8 +++ smi.c 19 May 2020 20:21:42 - @@ -24,10 +24,13 @@ #include #include +#include +#include #include #include #include #include +#include #include "ber.h" #include "mib.h" @@ -36,8 +39,12 @@ #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) +int isu8cont(unsigned char); +char *smi_displayhint_os(struct textconv *, const char *, size_t); + int smi_oid_cmp(struct oid *, struct oid *); int smi_key_cmp(struct oid *, struct oid *); +int smi_textconv_cmp(struct textconv *, struct textconv *); struct oid * smi_findkey(char *); RB_HEAD(oidtree, oid); @@ -48,6 +55,10 @@ RB_HEAD(keytree, oid); RB_PROTOTYPE(keytree, oid, o_keyword, smi_key_cmp) struct keytree smi_keytree; +RB_HEAD(textconvtree, textconv); +RB_PROTOTYPE(textconvtree, textconv, tc_entry, smi_textconv_cmp); +struct textconvtree smi_tctree; + int smi_init(void) { @@ -181,7 +192,7 @@ smi_debug_elements(struct ber_element *r fprintf(stderr, "(%u) encoding %u ", root->be_type, root->be_encoding); - if ((value = smi_print_element(root, 1, smi_os_default, + if ((value = smi_print_element(NULL, root, 1, smi_os_default, smi_oidl_numeric)) == NULL) goto
Re: snmp(1) cleanup snmpd legacy
Anyone feeling like trimming a little fat? On Fri, 2020-05-08 at 11:41 +0200, Martijn van Duren wrote: > Diff below removes fields from struct oid used by snmpd but not useful > for snmp(1). Minus 503LoC and -200kb on installed binary. > No functional change intended. > > OK? > > martijn@ > > Index: mib.c > === > RCS file: /cvs/src/usr.bin/snmp/mib.c,v > retrieving revision 1.1 > diff -u -p -r1.1 mib.c > --- mib.c 9 Aug 2019 06:17:59 - 1.1 > +++ mib.c 8 May 2020 09:40:59 - > @@ -27,466 +27,9 @@ > #include "smi.h" > > static struct oid mib_tree[] = MIB_TREE; > -static struct oid base_mib[] = { > - { MIB(mib_2), OID_MIB }, > - { MIB(sysDescr),OID_RD }, > - { MIB(sysOID), OID_RD }, > - { MIB(sysUpTime), OID_RD }, > - { MIB(sysContact), OID_RW }, > - { MIB(sysName), OID_RW }, > - { MIB(sysLocation), OID_RW }, > - { MIB(sysServices), OID_RS }, > - { MIB(sysORLastChange), OID_RD }, > - { MIB(sysORIndex), OID_TRD }, > - { MIB(sysORID), OID_TRD }, > - { MIB(sysORDescr), OID_TRD }, > - { MIB(sysORUpTime), OID_TRD }, > - { MIB(snmp),OID_MIB }, > - { MIB(snmpInPkts), OID_RD }, > - { MIB(snmpOutPkts), OID_RD }, > - { MIB(snmpInBadVersions), OID_RD }, > - { MIB(snmpInBadCommunityNames), OID_RD }, > - { MIB(snmpInBadCommunityUses), OID_RD }, > - { MIB(snmpInASNParseErrs), OID_RD }, > - { MIB(snmpInTooBigs), OID_RD }, > - { MIB(snmpInNoSuchNames), OID_RD }, > - { MIB(snmpInBadValues), OID_RD }, > - { MIB(snmpInReadOnlys), OID_RD }, > - { MIB(snmpInGenErrs), OID_RD }, > - { MIB(snmpInTotalReqVars), OID_RD }, > - { MIB(snmpInTotalSetVars), OID_RD }, > - { MIB(snmpInGetRequests), OID_RD }, > - { MIB(snmpInGetNexts), OID_RD }, > - { MIB(snmpInSetRequests), OID_RD }, > - { MIB(snmpInGetResponses), OID_RD }, > - { MIB(snmpInTraps), OID_RD }, > - { MIB(snmpOutTooBigs), OID_RD }, > - { MIB(snmpOutNoSuchNames), OID_RD }, > - { MIB(snmpOutBadValues),OID_RD }, > - { MIB(snmpOutGenErrs), OID_RD }, > - { MIB(snmpOutGetRequests), OID_RD }, > - { MIB(snmpOutGetNexts), OID_RD }, > - { MIB(snmpOutSetRequests), OID_RD }, > - { MIB(snmpOutGetResponses), OID_RD }, > - { MIB(snmpOutTraps),OID_RD }, > - { MIB(snmpEnableAuthenTraps), OID_RW }, > - { MIB(snmpSilentDrops), OID_RD }, > - { MIB(snmpProxyDrops), OID_RD }, > - { MIBEND } > -}; > - > -static struct oid usm_mib[] = { > - { MIB(snmpEngine), OID_MIB }, > - { MIB(snmpEngineID),OID_RD }, > - { MIB(snmpEngineBoots), OID_RD }, > - { MIB(snmpEngineTime), OID_RD }, > - { MIB(snmpEngineMaxMsgSize),OID_RD }, > - { MIB(usmStats),OID_MIB }, > - { MIB(usmStatsUnsupportedSecLevels),OID_RD }, > - { MIB(usmStatsNotInTimeWindow), OID_RD }, > - { MIB(usmStatsUnknownUserNames),OID_RD }, > - { MIB(usmStatsUnknownEngineId), OID_RD }, > - { MIB(usmStatsWrongDigests),OID_RD }, > - { MIB(usmStatsDecryptionErrors),OID_RD }, > - { MIBEND } > -}; > - > -static struct oid hr_mib[] = { > - { MIB(host),OID_MIB }, > - { MIB(hrSystemUptime), OID_RD }, > - { MIB(hrSystemDate),OID_RD }, > - { MIB(hrSystemProcesses), OID_RD }, > - { MIB(hrSystemMaxProcesses),OID_RD }, > - { MIB(hrMemorySize),OID_RD }, > - { MIB(hrStorageIndex), OID_TRD }, > - { MIB(hrStorageType), OID_TRD }, > - { MIB(hrStorageDescr), OID_TRD }, > - { MIB(hrStorageAllocationUnits),OID_TRD }, > - { MIB(hrStorageSize), OID_TRD }, > - { MIB(hrStorageUsed), OID_TRD }, > - { MIB(hrStorageAllocationFailures), OID_TRD }, > - { MIB(hrDeviceIndex), OID_TRD }, > - { MIB(hrDeviceType),OID_TRD }, > - { MIB(hrDeviceDescr), OID_TRD }, > -
snmp(1): Silence gcc warnings
Clang is smart enough to know that the usage of the variables is guarded, gcc apparently is not. No functional change, just silence some compiler warnings. OK? martijn@ Index: snmpc.c === RCS file: /cvs/src/usr.bin/snmp/snmpc.c,v retrieving revision 1.23 diff -u -p -r1.23 snmpc.c --- snmpc.c 8 May 2020 12:21:07 - 1.23 +++ snmpc.c 10 May 2020 16:39:55 - @@ -111,10 +111,10 @@ main(int argc, char *argv[]) const EVP_CIPHER *cipher = NULL; struct snmp_sec *sec; char *user = NULL; - enum usm_key_level authkeylevel; + enum usm_key_level authkeylevel = USM_KEY_UNSET; char *authkey = NULL; size_t authkeylen = 0; - enum usm_key_level privkeylevel; + enum usm_key_level privkeylevel = USM_KEY_UNSET; char *privkey = NULL; size_t privkeylen = 0; int seclevel = SNMP_MSGFLAG_REPORT; @@ -122,7 +122,7 @@ main(int argc, char *argv[]) char *ctxengineid = NULL, *secengineid = NULL; size_t ctxengineidlen, secengineidlen; int zflag = 0; - long long boots, time; + long long boots = 0, time = 0; char optstr[BUFSIZ]; const char *errstr; char *strtolp;
snmp(1) cleanup snmpd legacy
Diff below removes fields from struct oid used by snmpd but not useful for snmp(1). Minus 503LoC and -200kb on installed binary. No functional change intended. OK? martijn@ Index: mib.c === RCS file: /cvs/src/usr.bin/snmp/mib.c,v retrieving revision 1.1 diff -u -p -r1.1 mib.c --- mib.c 9 Aug 2019 06:17:59 - 1.1 +++ mib.c 8 May 2020 09:40:59 - @@ -27,466 +27,9 @@ #include "smi.h" static struct oid mib_tree[] = MIB_TREE; -static struct oid base_mib[] = { - { MIB(mib_2), OID_MIB }, - { MIB(sysDescr),OID_RD }, - { MIB(sysOID), OID_RD }, - { MIB(sysUpTime), OID_RD }, - { MIB(sysContact), OID_RW }, - { MIB(sysName), OID_RW }, - { MIB(sysLocation), OID_RW }, - { MIB(sysServices), OID_RS }, - { MIB(sysORLastChange), OID_RD }, - { MIB(sysORIndex), OID_TRD }, - { MIB(sysORID), OID_TRD }, - { MIB(sysORDescr), OID_TRD }, - { MIB(sysORUpTime), OID_TRD }, - { MIB(snmp),OID_MIB }, - { MIB(snmpInPkts), OID_RD }, - { MIB(snmpOutPkts), OID_RD }, - { MIB(snmpInBadVersions), OID_RD }, - { MIB(snmpInBadCommunityNames), OID_RD }, - { MIB(snmpInBadCommunityUses), OID_RD }, - { MIB(snmpInASNParseErrs), OID_RD }, - { MIB(snmpInTooBigs), OID_RD }, - { MIB(snmpInNoSuchNames), OID_RD }, - { MIB(snmpInBadValues), OID_RD }, - { MIB(snmpInReadOnlys), OID_RD }, - { MIB(snmpInGenErrs), OID_RD }, - { MIB(snmpInTotalReqVars), OID_RD }, - { MIB(snmpInTotalSetVars), OID_RD }, - { MIB(snmpInGetRequests), OID_RD }, - { MIB(snmpInGetNexts), OID_RD }, - { MIB(snmpInSetRequests), OID_RD }, - { MIB(snmpInGetResponses), OID_RD }, - { MIB(snmpInTraps), OID_RD }, - { MIB(snmpOutTooBigs), OID_RD }, - { MIB(snmpOutNoSuchNames), OID_RD }, - { MIB(snmpOutBadValues),OID_RD }, - { MIB(snmpOutGenErrs), OID_RD }, - { MIB(snmpOutGetRequests), OID_RD }, - { MIB(snmpOutGetNexts), OID_RD }, - { MIB(snmpOutSetRequests), OID_RD }, - { MIB(snmpOutGetResponses), OID_RD }, - { MIB(snmpOutTraps),OID_RD }, - { MIB(snmpEnableAuthenTraps), OID_RW }, - { MIB(snmpSilentDrops), OID_RD }, - { MIB(snmpProxyDrops), OID_RD }, - { MIBEND } -}; - -static struct oid usm_mib[] = { - { MIB(snmpEngine), OID_MIB }, - { MIB(snmpEngineID),OID_RD }, - { MIB(snmpEngineBoots), OID_RD }, - { MIB(snmpEngineTime), OID_RD }, - { MIB(snmpEngineMaxMsgSize),OID_RD }, - { MIB(usmStats),OID_MIB }, - { MIB(usmStatsUnsupportedSecLevels),OID_RD }, - { MIB(usmStatsNotInTimeWindow), OID_RD }, - { MIB(usmStatsUnknownUserNames),OID_RD }, - { MIB(usmStatsUnknownEngineId), OID_RD }, - { MIB(usmStatsWrongDigests),OID_RD }, - { MIB(usmStatsDecryptionErrors),OID_RD }, - { MIBEND } -}; - -static struct oid hr_mib[] = { - { MIB(host),OID_MIB }, - { MIB(hrSystemUptime), OID_RD }, - { MIB(hrSystemDate),OID_RD }, - { MIB(hrSystemProcesses), OID_RD }, - { MIB(hrSystemMaxProcesses),OID_RD }, - { MIB(hrMemorySize),OID_RD }, - { MIB(hrStorageIndex), OID_TRD }, - { MIB(hrStorageType), OID_TRD }, - { MIB(hrStorageDescr), OID_TRD }, - { MIB(hrStorageAllocationUnits),OID_TRD }, - { MIB(hrStorageSize), OID_TRD }, - { MIB(hrStorageUsed), OID_TRD }, - { MIB(hrStorageAllocationFailures), OID_TRD }, - { MIB(hrDeviceIndex), OID_TRD }, - { MIB(hrDeviceType),OID_TRD }, - { MIB(hrDeviceDescr), OID_TRD }, - { MIB(hrDeviceID), OID_TRD }, - { MIB(hrDeviceStatus), OID_TRD }, - { MIB(hrDeviceErrors), OID_TRD }, - { MIB(hrProcessorFrwID),OID_TRD }, - { MIB(hrProcessorLoad), OID_TRD }, - { MIB(hrSWRunIndex),OID_TRD }, - { MIB(hrSWRunName), OID_TRD }, - { MIB(hrSWRunID), OID_TRD }, - {
Re: Disable snmpd 'private' community
Moving to tech@ On 5/1/20 5:17 PM, Steven Surdock wrote: > I see that snmpd.conf supports "read-write disabled", but this doesn't seem > to _completely_ disable the private community. If I set "read-write > disabled" I can still poll values using the 'private' community. Is this a > bug or a feature? > > -Steve S. > I'd say this is a bug, disabled should be disabled. Diff below fixes this. With this we can most likely also remove the test on snmpe.c:467, but I don't feel confident enough to do that just yet. Another important question is if we should enable read-write by default, but let's save that discussion for a different time/thread. OK? martijn@ Index: snmpe.c === RCS file: /cvs/src/usr.sbin/snmpd/snmpe.c,v retrieving revision 1.61 diff -u -p -r1.61 snmpe.c --- snmpe.c 14 Feb 2020 15:08:46 - 1.61 +++ snmpe.c 1 May 2020 15:38:40 - @@ -309,7 +309,8 @@ snmpe_parse(struct snmp_message *msg) stats->snmp_ingetnexts++; if (msg->sm_version != SNMP_V3 && strcmp(env->sc_rdcommunity, msg->sm_community) != 0 && - strcmp(env->sc_rwcommunity, msg->sm_community) != 0) { + (env->sc_readonly || + strcmp(env->sc_rwcommunity, msg->sm_community) != 0)) { stats->snmp_inbadcommunitynames++; msg->sm_errstr = "wrong read community"; goto fail; @@ -320,7 +321,8 @@ snmpe_parse(struct snmp_message *msg) case SNMP_C_SETREQ: stats->snmp_insetrequests++; if (msg->sm_version != SNMP_V3 && - strcmp(env->sc_rwcommunity, msg->sm_community) != 0) { + (env->sc_readonly || + strcmp(env->sc_rwcommunity, msg->sm_community) != 0)) { if (strcmp(env->sc_rdcommunity, msg->sm_community) != 0) stats->snmp_inbadcommunitynames++; else
Re: a POSIXy diff for what(1)
Looks fine to me. And I don't expect the tool to be widely used on OpenBSD. Anyone objects/OK? Small sidenote: Could you attach your diffs inline in the future? It's the standard way of doing things here. I've added it here, so people who don't want to open the file can see it. martijn@ On 4/18/20 10:06 AM, Andras Farkas wrote: > I don't use what often, but I do use it sometimes. Today I noticed > the format of what's output on OpenBSD was different than that of what > on FreeBSD. > Looking in what.1: > https://man.openbsd.org/what > I noticed OpenBSD's what is documented as abiding by POSIX: > https://pubs.opengroup.org/onlinepubs/9699919799/utilities/what.html > Thus, the following output: > > tewi$ what /usr/bin/lorder > /usr/bin/lorder > $OpenBSD: lorder.sh,v 1.15 2015/07/03 11:43:55 jca Exp $ > lorder.sh 8.1 (Berkeley) 6/6/93 > > is missing a single colon after the name/path/argument. > After applying the attached diff, the output is: > > tewi$ ./what /usr/bin/lorder > /usr/bin/lorder: > $OpenBSD: lorder.sh,v 1.15 2015/07/03 11:43:55 jca Exp $ > lorder.sh 8.1 (Berkeley) 6/6/93 > > Hope this helps! Of course, if there's a reason the : is omitted, > that's fine too. > Index: what.c === RCS file: /cvs/src/usr.bin/what/what.c,v retrieving revision 1.15 diff -u -p -r1.15 what.c --- what.c 9 Oct 2015 01:37:09 - 1.15 +++ what.c 18 Apr 2020 07:55:29 - @@ -85,7 +85,7 @@ main(int argc, char *argv[]) perror(*argv); exit(matches ? 0 : 1); } - printf("%s\n", *argv); + printf("%s:\n", *argv); search(match); } while(*++argv); exit(matches ? 0 : 1);
Re: smtpd: fix report event format
On 4/8/20 6:15 PM, Joerg Jung wrote: > >> On 8. Apr 2020, at 17:19, Eric Faurot wrote: >> >> Some users had issues with report events for MAIL FROM and RCPT TO >> when "|" appear in the mail address (yes, it seems to happen), because >> that's also the field separator. To make parsing the report lines a >> bit more straightforward, it's better to put the address as the last >> field. > > While this obviously would fix things, I wonder if there is a better choice > for > the separator available, to avoid similar issues in future. > Something that does not show up in hostnames, mail from, rcpt to, or > anything else SMTP (filter) protocol related. > Maybe better use ‘$' or even a control character like RS/US record/unit > separator (ASCII no 29/30)? Ultimately I'm fine either way, as long as I get the time to update libopensmtpd between when it's decided and the actual commit. But if we're going to change the separator we need to think this through, because I don't want to open a new can of worms while cleaning up the previous. For example '$' doesn't seem like a reasonable candidate. If we look at RFC5321 section 4.1.2. we see that local-part is defined as Dot-string / Quoted-string and Dot-string is defined as Atom *("." Atom) and finally Atom is defined as 1*atext. Unfortunately atext isn't defined in this document, but the closest I found (number-wise) was in RFC5322, which states: atext = ALPHA / DIGIT /; Printable US-ASCII "!" / "#" /; characters not including "$" / "%" /; specials. Used for atoms. "&" / "'" / "*" / "+" / "-" / "/" / "=" / "?" / "^" / "_" / "`" / "{" / "|" / "}" / "~" So practically any non-control ascii character. Furthermore, I fixed the data-section some time ago, so I'm fairly confident that that is safe in its current form, but if we want to pick something that prevents us from things blowing up in our face in the future we should also consider the part of the transaction that accepts the widest range of input. According to RFC5321 section 4.1.1.4: The mail data may contain any of the 128 ASCII character codes, although experience has indicated that use of control characters other than SP, HT, CR, and LF may cause problems and SHOULD be avoided when possible. So even though people should not send control-characters, they may be send anyway, which brings us back into the risky category. This means that control-characters are also out the window, which would leave us with a field-separator in the 128-255 range. I could update libopensmtpd quite easily to use a byte in that range, but considering the protocol was intended to also be used with standard unix tools as well I reckon that a lot of people wouldn't know how to cope with that without some very firm handholding and the same probably goes for control characters. So to be clear: I'm not saying we shouldn't change the separator, but if we want to go down that route there are quite a few edge cases that need to be covered. So until someone works out the perfect candidate it might be better to stick with the devil we know. > >> Note that this is a protocol change, so external filters will have >> to be updated. >> >> Eric. >> >> Index: lka_filter.c >> === >> RCS file: /cvs/src/usr.sbin/smtpd/lka_filter.c,v >> retrieving revision 1.60 >> diff -u -p -r1.60 lka_filter.c >> --- lka_filter.c 8 Jan 2020 01:41:11 - 1.60 >> +++ lka_filter.c 4 Apr 2020 08:39:19 - >> @@ -35,7 +35,7 @@ >> #include "smtpd.h" >> #include "log.h" >> >> -#define PROTOCOL_VERSION"0.5" >> +#define PROTOCOL_VERSION"0.6" >> >> struct filter; >> struct filter_session; >> @@ -1526,7 +1526,7 @@ lka_report_smtp_tx_mail(const char *dire >> break; >> } >> report_smtp_broadcast(reqid, direction, tv, "tx-mail", "%08x|%s|%s\n", >> -msgid, address, result); >> +msgid, result, address); >> } >> >> void >> @@ -1546,7 +1546,7 @@ lka_report_smtp_tx_rcpt(const char *dire >> break; >> } >> report_smtp_broadcast(reqid, direction, tv, "tx-rcpt", "%08x|%s|%s\n", >> -msgid, address, result); >> +msgid, result, address); >> } >> >> void >> >
Include /var/www/tmp into base install
This came up during u2k20 while discussing tempfiles for gotweb inside a chroot. At the moment we don't include it by default and ports have to create it themselves. Since I assume we want web applications to run inside a /var/www chroot as much as possible and even some libc functions depend on /tmp being available I'd argue we should include it by default. I also choose to make the directory 1777, similar to a normal /tmp, since both multiple slowcgi or php-fpm pools can run simultaneously under different users. The cleanup functions don't reflect the current /tmp cleanup style, but we can move the existing find statements to -delete in a separate patch. I already had some positive feedback during u2k20 on the concept. OK? martijn@ Index: etc//daily === RCS file: /cvs/src/etc/daily,v retrieving revision 1.93 diff -u -p -r1.93 daily --- etc//daily 9 Sep 2019 20:02:26 - 1.93 +++ etc//daily 7 Apr 2020 14:37:15 - @@ -55,6 +55,11 @@ if [ -d /tmp -a ! -L /tmp ]; then ! -path ./.ICE-unix ! -name . \ -execdir rmdir -- {} \; >/dev/null 2>&1; } fi +if [ -d /var/www/tmp -a ! -L /var/www/tmp ]; then + cd /var/www/tmp && { + find -x . -type f -atime +7 -delete 2>/dev/null + find -x . -type d -empty -delete 2>/dev/null +fi # Additional junk directory cleanup would go like this: #if [ -d /scratch -a ! -L /scratch ]; then Index: etc//rc === RCS file: /cvs/src/etc/rc,v retrieving revision 1.543 diff -u -p -r1.543 rc --- etc//rc 24 Jan 2020 06:17:37 - 1.543 +++ etc//rc 7 Apr 2020 14:37:15 - @@ -532,7 +532,7 @@ if [[ -f /etc/ptmp ]]; then 'password file may be incorrect -- /etc/ptmp exists' fi -echo clearing /tmp +echo clearing temporary directories # Prune quickly with one rm, then use find to clean up /tmp/[lqv]* # (not needed with mfs /tmp, but doesn't hurt there...). @@ -540,6 +540,7 @@ echo clearing /tmp (cd /tmp && find . -maxdepth 1 ! -name . ! -name lost+found ! -name quota.user \ ! -name quota.group ! -name vi.recover -execdir rm -rf -- {} \;) +(cd /var/www/tmp && find . -x -delete) # Create Unix sockets directories for X if needed and make sure they have # correct permissions. Index: etc//mtree/4.4BSD.dist === RCS file: /cvs/src/etc/mtree/4.4BSD.dist,v retrieving revision 1.314 diff -u -p -r1.314 4.4BSD.dist --- etc//mtree/4.4BSD.dist 29 Nov 2019 03:28:20 - 1.314 +++ etc//mtree/4.4BSD.dist 7 Apr 2020 14:37:15 - @@ -749,6 +749,7 @@ var .. runtype=dir uname=root gname=daemon mode=755 .. +tmptype=dir uname=root gname=wheel mode=01777 .. # ./var/audit
worm(6): Remove stdin garbage after end
When playing worm(6) and you crash there's a sleep of 2 seconds that still allows input to be put into the terminal buffer that doesn't get read until the application stops. A similar case is possible in a more limited timespan if you win the game. The diff below flushes the input buffer just before exiting curses and the application, leaving me with no clutter in my $SHELL. I choose to also add '\n' as an escape character, since it's not part of the game and allows me to exit after a crash faster (which always annoys me) and allows me to add a new command straight away. The crash() case might be a bit elaborate, but it's the closest to the behaviour we have right now, minus the garbage. Thoughts? OK? martijn Index: worm.c === RCS file: /cvs/src/games/worm/worm.c,v retrieving revision 1.39 diff -u -p -r1.39 worm.c --- worm.c 24 Aug 2018 11:14:49 - 1.39 +++ worm.c 1 Apr 2020 08:27:03 - @@ -40,6 +40,7 @@ #include #include #include +#include #include #define HEAD '@' @@ -239,7 +240,12 @@ rnd(int range) void newpos(struct body *bp) { + int ch; + if (visible_len == (LINES-3) * (COLS-3) - 1) { + timeout(0); + while ((ch = getch()) != '\n' && ch != ERR) + continue; endwin(); printf("\nYou won!\nYour final score was %d\n\n", score); exit(0); @@ -387,7 +393,17 @@ newlink(void) void crash(void) { - sleep(2); + int ch, delay; + struct timespec tstart, tnow, texp; + + timeout(2000); + (void) clock_gettime(CLOCK_MONOTONIC, ); + while ((ch = getch()) != ERR && ch != '\n') { + (void) clock_gettime(CLOCK_MONOTONIC, ); + timespecsub(, , ); + delay = 2000 - (texp.tv_sec * 1000) - (texp.tv_nsec / 100); + timeout(delay >= 0 ? delay : 0); + } clear(); endwin(); printf("Well, you ran into something and the game is over.\n");
snmpd(8) (temporary) removal of sysortable
We currently abuse sysORTable to display information in a way that it shouldn't. According to SNMPv2-MIB: "The (conceptual) table listing the capabilities of the local SNMP application acting as a command responder with respect to various MIB modules. SNMP entities having dynamically-configurable support of MIB modules will have a dynamically-varying number of conceptual rows." I must admit that from a first glance our usage seems correct, but I found the following text in RFC2741 (AGENTX): An Object Identifier containing the value of an invocation of the AGENT-CAPABILITIES macro, which the master agent exports as a value of sysORID for the indicated context. (Recall that the value of an invocation of an AGENT- CAPABILITIES macro is an object identifier that describes a precise level of support with respect to implemented MIB modules. A more complete discussion of the AGENT- CAPABILITIES macro and related sysORID values can be found in section 6 of STD 58, RFC 2580 [7].) And if we look at section 6.6 of RFC 2580: 6.6. Mapping of the AGENT-CAPABILITIES value The value of an invocation of the AGENT-CAPABILITIES macro is an OBJECT IDENTIFIER, which names the value of sysORID [3] for which this capabilities statement is valid. This means that that the OIDs used in the sysORTable need to reference an AGENT-CAPABILITIES macro, which need to be defined separately and we currently don't have those. Apart from the above we also falsely return sysORIndex, which has MAX-ACCESS not-accessible. I propose we remove the sysORTable code until we either: 1) Have a proper AGENT-CAPABILITIES file for snmpd(8) 2) Have proper support for agentx-AddAgentCaps-PDU This removes falsities from our code and allows us to reimplement it in a more scalable way for agentx support in the future. OK? martijn@ ps. I know that net-snmp does something similar, but that doesn't mean I would like to copy their spec-violations. Index: mib.c === --- mib.c (revision 1) +++ mib.c (working copy) @@ -65,7 +65,6 @@ int mib_getsys(struct oid *, struct ber_oid *, struct ber_element **); int mib_getsnmp(struct oid *, struct ber_oid *, struct ber_element **); -int mib_sysor(struct oid *, struct ber_oid *, struct ber_element **); int mib_setsnmp(struct oid *, struct ber_oid *, struct ber_element **); static struct oid mib_tree[] = MIB_TREE; @@ -75,7 +74,6 @@ /* base MIB tree */ static struct oid base_mib[] = { - { MIB(mib_2), OID_MIB }, { MIB(sysDescr),OID_RD, mib_getsys }, { MIB(sysOID), OID_RD, mib_getsys }, { MIB(sysUpTime), OID_RD, mib_getsys }, @@ -84,11 +82,6 @@ { MIB(sysLocation), OID_RW, mib_getsys, mps_setstr }, { MIB(sysServices), OID_RS, mib_getsys }, { MIB(sysORLastChange), OID_RD, mps_getts }, - { MIB(sysORIndex), OID_TRD, mib_sysor }, - { MIB(sysORID), OID_TRD, mib_sysor }, - { MIB(sysORDescr), OID_TRD, mib_sysor }, - { MIB(sysORUpTime), OID_TRD, mib_sysor }, - { MIB(snmp),OID_MIB }, { MIB(snmpInPkts), OID_RD, mib_getsnmp }, { MIB(snmpOutPkts), OID_RD, mib_getsnmp }, { MIB(snmpInBadVersions), OID_RD, mib_getsnmp }, @@ -190,68 +183,6 @@ } int -mib_sysor(struct oid *oid, struct ber_oid *o, struct ber_element **elm) -{ - struct ber_element *ber = *elm; - u_int32_tidx = 1, nmib = 0; - struct oid *next, *miboid; - char buf[SNMPD_MAXSTRLEN]; - - /* Count MIB root OIDs in the tree */ - for (next = NULL; - (next = smi_foreach(next, OID_MIB)) != NULL; nmib++); - - /* Get and verify the current row index */ - idx = o->bo_id[OIDIDX_sysOREntry]; - if (idx > nmib) - return (1); - - /* Find the MIB root element for this Id */ - for (next = miboid = NULL, nmib = 1; - (next = smi_foreach(next, OID_MIB)) != NULL; nmib++) { - if (nmib == idx) - miboid = next; - } - if (miboid == NULL) - return (-1); - - /* Tables need to prepend the OID on their own */ - ber = ober_add_oid(ber, o); - - switch (o->bo_id[OIDIDX_sysOR]) { - case 1: - ber = ober_add_integer(ber, idx); - break; - case 2: - ber = ober_add_oid(ber, >o_id); - break; - case 3: - /* -* This should be a description of the MIB. -* But we use the
snmpd(8): Remove restricted socket
snmpd's normal socket is pretty much deprecated and the restricted variant is even more useless. In other words lets pick it apart one step at a time. This diff removes the restricted keyword and related code. While here I also removed the unimplemented IMSG_CTL_RELOAD logic. For those wondering why I removed the CTL_CONN_LOCKED flag: It's only checked in control_dispatch_imsg, so there's no point in setting it on agentx sockets. OK? martijn@ Index: control.c === --- control.c (revision 1) +++ control.c (working copy) @@ -80,7 +80,7 @@ return (-1); } - if (cs->cs_restricted || cs->cs_agentx) { + if (cs->cs_agentx) { old_umask = umask(S_IXUSR|S_IXGRP|S_IXOTH); mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; } else { @@ -174,7 +174,6 @@ log_warn("%s: agentx", __func__); return; } - c->flags |= CTL_CONN_LOCKED; c->iev.handler = control_dispatch_agentx; TAILQ_INIT(>oids); } else @@ -249,21 +248,6 @@ if (n == 0) break; - if (cs->cs_restricted || (c->flags & CTL_CONN_LOCKED)) { - switch (imsg.hdr.type) { - case IMSG_SNMP_AGENTX: - case IMSG_SNMP_ELEMENT: - case IMSG_SNMP_END: - case IMSG_SNMP_LOCK: - break; - default: - control_close(c, - "client requested restricted command", - ); - return; - } - } - control_imsg_forward(); switch (imsg.hdr.type) { @@ -282,14 +266,6 @@ c->flags |= CTL_CONN_NOTIFY; break; - case IMSG_SNMP_LOCK: - if (IMSG_DATA_SIZE()) - return control_close(c, "invalid size", ); - - /* enable restricted control mode */ - c->flags |= CTL_CONN_LOCKED; - break; - case IMSG_SNMP_AGENTX: if (IMSG_DATA_SIZE()) return control_close(c, "invalid size", ); @@ -313,7 +289,6 @@ } /* disable IMSG notifications */ c->flags &= ~CTL_CONN_NOTIFY; - c->flags |= CTL_CONN_LOCKED; c->iev.handler = control_dispatch_agentx; break; @@ -330,11 +305,7 @@ proc_forward_imsg(>sc_ps, , i, -1); } break; - case IMSG_CTL_RELOAD: - if (IMSG_DATA_SIZE()) - return control_close(c, "invalid size", ); - proc_forward_imsg(>sc_ps, , PROC_PARENT, -1); - break; + default: control_close(c, "invalid type", ); return; Index: parse.y === --- parse.y (revision 1) +++ parse.y (working copy) @@ -51,11 +51,6 @@ #include "snmpd.h" #include "mib.h" -enum socktype { - SOCK_TYPE_RESTRICTED = 1, - SOCK_TYPE_AGENTX = 2 -}; - TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files); static struct file { TAILQ_ENTRY(file)entry; @@ -133,7 +128,7 @@ %token SYSTEM CONTACT DESCR LOCATION NAME OBJECTID SERVICES RTFILTER %token READONLY READWRITE OCTETSTRING INTEGER COMMUNITY TRAP RECEIVER %token SECLEVEL NONE AUTH ENC USER AUTHKEY ENCKEY ERROR DISABLED -%token SOCKET RESTRICTED AGENTX HANDLE DEFAULT SRCADDR TCP UDP PFADDRFILTER +%token SOCKET AGENTX HANDLE DEFAULT SRCADDR TCP UDP PFADDRFILTER %token STRING %token NUMBER %typehostcmn @@ -305,10 +300,7 @@ YYERROR; } rcsock->cs_name = $2; - if ($3 == SOCK_TYPE_RESTRICTED) - rcsock->cs_restricted = 1; - else if ($3 == SOCK_TYPE_AGENTX) - rcsock->cs_agentx = 1; + rcsock->cs_agentx = 1; TAILQ_INSERT_TAIL(>sc_ps.ps_rcsocks, rcsock, cs_entry); } else { @@ -541,8 +533,7 @@ } ; -socktype : RESTRICTED{ $$ =