summaryrefslogtreecommitdiff
path: root/usr.sbin/snmpd/parse.y
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/snmpd/parse.y')
-rw-r--r--usr.sbin/snmpd/parse.y49
1 files changed, 38 insertions, 11 deletions
diff --git a/usr.sbin/snmpd/parse.y b/usr.sbin/snmpd/parse.y
index 8ad6fcc46b5..f173650fcab 100644
--- a/usr.sbin/snmpd/parse.y
+++ b/usr.sbin/snmpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.39 2016/06/21 21:35:25 benno Exp $ */
+/* $OpenBSD: parse.y,v 1.40 2016/11/09 20:31:56 jca Exp $ */
/*
* Copyright (c) 2007, 2008, 2012 Reyk Floeter <reyk@openbsd.org>
@@ -98,9 +98,10 @@ static int nctlsocks = 0;
struct address *host_v4(const char *);
struct address *host_v6(const char *);
int host_dns(const char *, struct addresslist *,
- int, in_port_t, struct ber_oid *, char *);
+ int, in_port_t, struct ber_oid *, char *,
+ struct address *);
int host(const char *, struct addresslist *,
- int, in_port_t, struct ber_oid *, char *);
+ int, in_port_t, struct ber_oid *, char *, char *);
typedef struct {
union {
@@ -127,10 +128,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 SOCKET RESTRICTED AGENTX HANDLE DEFAULT
+%token SOCKET RESTRICTED AGENTX HANDLE DEFAULT SRCADDR
%token <v.string> STRING
%token <v.number> NUMBER
%type <v.string> hostcmn
+%type <v.string> srcaddr
%type <v.number> optwrite yesno seclevel socktype
%type <v.data> objtype cmd
%type <v.oid> oid hostoid trapoid
@@ -200,7 +202,8 @@ main : LISTEN ON STRING {
struct address *h;
TAILQ_INIT(&al);
- if (host($3, &al, 1, SNMPD_PORT, NULL, NULL) <= 0) {
+ if (host($3, &al, 1, SNMPD_PORT, NULL, NULL, NULL)
+ <= 0) {
yyerror("invalid ip address: %s", $3);
free($3);
YYERROR;
@@ -445,9 +448,13 @@ hostcmn : /* empty */ { $$ = NULL; }
| COMMUNITY STRING { $$ = $2; }
;
-hostdef : STRING hostoid hostcmn {
+srcaddr : /* empty */ { $$ = NULL; }
+ | SRCADDR STRING { $$ = $2; }
+ ;
+
+hostdef : STRING hostoid hostcmn srcaddr {
if (host($1, hlist, 1,
- SNMPD_TRAPPORT, $2, $3) <= 0) {
+ SNMPD_TRAPPORT, $2, $3, $4) <= 0) {
yyerror("invalid host: %s", $1);
free($1);
YYERROR;
@@ -636,6 +643,7 @@ lookup(char *s)
{ "seclevel", SECLEVEL },
{ "services", SERVICES },
{ "socket", SOCKET },
+ { "source-address", SRCADDR },
{ "string", OCTETSTRING },
{ "system", SYSTEM },
{ "trap", TRAP },
@@ -1151,7 +1159,7 @@ host_v6(const char *s)
int
host_dns(const char *s, struct addresslist *al, int max,
- in_port_t port, struct ber_oid *oid, char *cmn)
+ in_port_t port, struct ber_oid *oid, char *cmn, struct address *src)
{
struct addrinfo hints, *res0, *res;
int error, cnt = 0;
@@ -1176,6 +1184,8 @@ host_dns(const char *s, struct addresslist *al, int max,
if (res->ai_family != AF_INET &&
res->ai_family != AF_INET6)
continue;
+ if (src != NULL && src->ss.ss_family != res->ai_family)
+ continue;
if ((h = calloc(1, sizeof(*h))) == NULL)
fatal(__func__);
@@ -1203,6 +1213,8 @@ host_dns(const char *s, struct addresslist *al, int max,
res->ai_addr)->sin6_addr, sizeof(struct in6_addr));
}
+ h->sa_srcaddr = src;
+
TAILQ_INSERT_HEAD(al, h, entry);
cnt++;
}
@@ -1220,9 +1232,19 @@ host_dns(const char *s, struct addresslist *al, int max,
int
host(const char *s, struct addresslist *al, int max,
- in_port_t port, struct ber_oid *oid, char *cmn)
+ in_port_t port, struct ber_oid *oid, char *cmn, char *srcaddr)
{
- struct address *h;
+ struct address *h, *src = NULL;
+
+ if (srcaddr != NULL) {
+ src = host_v4(srcaddr);
+ if (src == NULL)
+ src = host_v6(srcaddr);
+ if (src == NULL) {
+ log_warnx("invalid source-address %s", srcaddr);
+ return (-1);
+ }
+ }
h = host_v4(s);
@@ -1234,10 +1256,15 @@ host(const char *s, struct addresslist *al, int max,
h->port = port;
h->sa_oid = oid;
h->sa_community = cmn;
+ if (src != NULL && h->ss.ss_family != src->ss.ss_family) {
+ log_warnx("host and source-address family mismatch");
+ return (-1);
+ }
+ h->sa_srcaddr = src;
TAILQ_INSERT_HEAD(al, h, entry);
return (1);
}
- return (host_dns(s, al, max, port, oid, cmn));
+ return (host_dns(s, al, max, port, oid, cmn, src));
}