On Thu, Oct 03, 2019 at 10:01:06AM +0200, Martijn van Duren wrote: > On 10/3/19 9:21 AM, Sebastien Marie wrote: > > On Thu, Sep 26, 2019 at 02:33:11PM +0200, Martijn van Duren wrote: > >> On 9/26/19 9:54 AM, Martijn van Duren wrote: > >>> Hello, > >>> > >>> I reckon this will be on of the last major additions. > >>> Adding "snmp set" allows us to run snmpd's regress without installing > >>> netsnmp. :-) > >>> > >>> Tested with snmpd's regress test. > >>> > >>> Majority of diff is moving oid/value parsing from snmp trap to a > >>> separate function. > >>> > >>> OK? > >>> > >>> martijn@ > > > > few comments. > > > > thanks. > > > >> Index: snmpc.c > >> =================================================================== > >> RCS file: /cvs/src/usr.bin/snmp/snmpc.c,v > >> retrieving revision 1.11 > >> diff -u -p -r1.11 snmpc.c > >> --- snmpc.c 18 Sep 2019 09:54:36 -0000 1.11 > >> +++ snmpc.c 26 Sep 2019 12:32:38 -0000 > >> @@ -666,19 +669,54 @@ snmpc_walk(int argc, char *argv[]) > >> } > >> > >> int > >> +snmpc_set(int argc, char *argv[]) > >> +{ > >> + struct snmp_agent *agent; > >> + struct ber_element *pdu, *varbind; > >> + int errorstatus, errorindex; > >> + int class; > >> + unsigned type; > >> + > >> + if (argc < 4) > >> + usage(); > >> + if ((agent = snmpc_connect(argv[0], "161")) == NULL) > >> + err(1, "%s", snmp_app->name); > >> + argc--; > >> + argv++; > >> + > >> + if (argc < 3 || argc % 3 != 0) > >> + usage(); > >> + > >> + if (pledge("stdio", NULL) == -1) > >> + err(1, "pledge"); > >> + > >> + pdu = snmp_set(agent, snmpc_varbindparse(argc, argv)); > >> + > >> + (void) ber_scanf_elements(pdu, "t{Sdd{e", &class, &type, &errorstatus, > >> + &errorindex, &varbind); > >> + if (errorstatus != 0) > >> + snmpc_printerror((enum snmp_error) errorstatus, > >> + argv[errorindex - 1]); > > > > is "errorindex - 1" the right index ? > > Yes: RFC 3416 section 4.1: > A variable binding is identified by its index value. The first variable > binding in a variable-binding list is index one, the second is index > two, etc. > > I choose to use argv, because it's easier for the end user to see his > own input for where he mistyped instead of a double parsed oid to -O > based output. > > > > > $ ./obj/snmp set 192.168.1.5 sysContact.0 s "test" > > snmp: Can't parse oid 192.168.1.5: Not writable > > > > Note that the same pattern is used in others commands. > > Somehow the machines I test against don't return a not writable message. > Tested against snmpd, net-snmpd, HP Laserjet. > Could you show me a tcpdump -v output on this output? > > > > >> +struct ber_element * > >> +snmpc_varbindparse(int argc, char *argv[]) > >> +{ > >> + struct ber_oid oid, oidval; > >> + struct in_addr addr4; > >> + char *addr = (char *)&addr4; > >> + char *str = NULL, *tmpstr, *endstr; > >> + const char *errstr = NULL; > >> + struct ber_element *varbind = NULL, *vblist = NULL; > >> + int i, ret; > >> + size_t strl, byte; > >> + long long lval; > >> + > >> + if (argc % 3 != 0) > >> + usage(); > > > > if I don't mess myself, callers already checks that 'argc % 3 != 0'. So I > > think > > the condition is more a defense for programmer error that user error, and I > > would use an assert(argc % 3 == 0) or abort(). > > I removed these checks from snmpc_{set,trap}. Even less code. :-) > > Index: snmp.1 > =================================================================== > RCS file: /cvs/src/usr.bin/snmp/snmp.1,v > retrieving revision 1.6 > diff -u -p -r1.6 snmp.1 > --- snmp.1 18 Sep 2019 09:54:36 -0000 1.6 > +++ snmp.1 3 Oct 2019 07:59:07 -0000 > @@ -110,6 +110,28 @@ > .Ar agent > .Op Ar oid > .Nm > +.Cm set > +.Op Fl A Ar authpass > +.Op Fl a Ar digest > +.Op Fl c Ar community > +.Op Fl E Ar ctxengineid > +.Op Fl e Ar secengineid > +.Op Fl K Ar localpriv > +.Op Fl k Ar localauth > +.Op Fl l Ar seclevel > +.Op Fl n Ar ctxname > +.Op Fl O Cm afnQqSvx > +.Op Fl r Ar retries > +.Op Fl t Ar timeout > +.Op Fl u Ar user > +.Op Fl v Ar version > +.Op Fl X Ar privpass > +.Op Fl x Ar cipher > +.Op Fl Z Ar boots , Ns Ar time > +.Ar agent > +.Ar varoid type value > +.Oo Ar varoid type value Oc ... > +.Nm > .Cm trap > .Op Fl A Ar authpass > .Op Fl a Ar digest > @@ -182,6 +204,12 @@ This uses the > subcommand internally to retrieve multiple MIBs at a time. > This command is not available for > .Fl v Cm 1 . > +.It Cm set > +Set one or more OID to a new value. > +The triple > +.Ar varoid , type , value > +is described in > +.Sx Data types . > .It Cm trap > Send a trap message to the > .Ar agent . > @@ -194,8 +222,8 @@ The > .Ar trapoid > is the identification OID used by the trap handler to determine its action. > The triple > -.Op Ar varoid , type, value > -is described below > +.Op Ar varoid , type , value > +is described in > .Sx Data types . > This command is not available for > .Fl v Cm 1 . > Index: snmp.c > =================================================================== > RCS file: /cvs/src/usr.bin/snmp/snmp.c,v > retrieving revision 1.6 > diff -u -p -r1.6 snmp.c > --- snmp.c 18 Sep 2019 09:54:36 -0000 1.6 > +++ snmp.c 3 Oct 2019 07:59:07 -0000 > @@ -249,6 +249,22 @@ fail: > return NULL; > } > > +struct ber_element * > +snmp_set(struct snmp_agent *agent, struct ber_element *vblist) > +{ > + struct ber_element *pdu; > + > + if ((pdu = ber_add_sequence(NULL)) == NULL) > + return NULL; > + if (ber_printf_elements(pdu, "tddd{e", BER_CLASS_CONTEXT, > + SNMP_C_SETREQ, arc4random() & 0x7fffffff, 0, 0, vblist) == NULL) { > + ber_free_elements(pdu);
Shouldn't this be ber_free_elements(vblist)? If ber_printf_elements() fails pdu was already freed there. Apart from that OK claudio@ -- :wq Claudio