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