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 -0000       1.60
+++ parse.y     6 Sep 2020 20:08:08 -0000
@@ -40,6 +40,7 @@
 #include <err.h>
 #include <errno.h>
 #include <event.h>
+#include <inttypes.h>
 #include <limits.h>
 #include <stdint.h>
 #include <stdarg.h>
@@ -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 <v.string>      STRING
 %token  <v.number>     NUMBER
 %type  <v.string>      hostcmn
-%type  <v.string>      srcaddr
+%type  <v.string>      srcaddr port
 %type  <v.number>      optwrite yesno seclevel proto
 %type  <v.data>        objtype cmd
 %type  <v.oid>         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);
+                               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_STREAM) == -1) {
+                                       yyerror("calloc");
+                                       YYERROR;
+                               }
+                       }
+               }
+
+/* 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;
+               }
+               | PORT STRING                   {
+                       $$ = $2;
+               }
+               | PORT NUMBER                   {
+                       char *number;
+
+                       if ($2 > UINT16_MAX) {
+                               yyerror("port number too large");
+                               YYERROR;
+                       }
+                       if (asprintf(&number, "%"PRId64, $2) == -1) {
+                               yyerror("malloc");
+                               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;
+               }
+               ;
+
 system         : SYSTEM sysmib
                ;
 
@@ -541,11 +644,6 @@ enc                : STRING                        {
                }
                ;
 
-proto          : /* empty */                   { $$ = SOCK_DGRAM; }
-               | TCP                           { $$ = SOCK_STREAM; }
-               | UDP                           { $$ = SOCK_DGRAM; }
-               ;
-
 cmd            : STRING                {
                        struct trapcmd  *cmd;
                        size_t           span, limit;
@@ -646,6 +744,7 @@ lookup(char *s)
                { "none",                       NONE },
                { "oid",                        OBJECTID },
                { "on",                         ON },
+               { "port",                       PORT },
                { "read-only",                  READONLY },
                { "read-write",                 READWRITE },
                { "receiver",                   RECEIVER },
Index: snmpd.conf.5
===================================================================
RCS file: /cvs/src/usr.sbin/snmpd/snmpd.conf.5,v
retrieving revision 1.43
diff -u -p -r1.43 snmpd.conf.5
--- snmpd.conf.5        30 Jun 2020 17:11:49 -0000      1.43
+++ snmpd.conf.5        6 Sep 2020 20:08:08 -0000
@@ -95,7 +95,7 @@ Routing table information will not be av
 reduced during bulk updates.
 The default is
 .Ic no .
-.It Ic listen on Ar address Op Ic tcp | udp
+.It Ic listen on Oo Ic tcp | udp Oc Ar address Op Ic port Ar port
 Specify the local address
 .Xr snmpd 8
 should listen on for incoming SNMP messages.

Reply via email to