Re: snmpd(8): Remove traphandler process attempt 2

2021-01-18 Thread Martijn van Duren
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));
> if (nhosts < 1) {
> yyerror("invalid address: %s", $1);
> free($1);
> -   if ($2 != snmpd_port)
> -   free($2);
> +   free($2);
> YYERROR;
> }
> if (nhost

snmpd(8): Remove traphandler process attempt 2

2021-01-05 Thread Martijn van Duren
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)
-