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.