1 /* -*- mode: c; c-file-style: "openbsd" -*- */
3 * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 /* Some of the code here (agent_priv_unix_*) has been adapted from code from
19 * Net-SNMP project (snmplib/snmpUnixDomain.c). Net-SNMP project is licensed
20 * using BSD and BSD-like licenses. I don't know the exact license of the file
21 * snmplib/snmpUnixDomain.c. */
28 #include <net-snmp/net-snmp-config.h>
29 #include <net-snmp/net-snmp-includes.h>
30 #include <net-snmp/agent/net-snmp-agent-includes.h>
31 #include <net-snmp/agent/snmp_vars.h>
32 #include <net-snmp/library/snmpUnixDomain.h>
34 static oid netsnmp_unix
[] = { TRANSPORT_DOMAIN_LOCAL
};
35 static netsnmp_tdomain unixDomain
;
38 agent_priv_unix_fmtaddr(netsnmp_transport
*t
, void *data
, int len
)
40 /* We don't bother to implement the full function */
41 return strdup("Local Unix socket with privilege separation: unknown");
45 agent_priv_unix_recv(netsnmp_transport
*t
, void *buf
, int size
,
46 void **opaque
, int *olength
)
49 socklen_t tolen
= sizeof(struct sockaddr_un
);
50 struct sockaddr
*to
= NULL
;
52 if (t
== NULL
|| t
->sock
< 0)
54 to
= (struct sockaddr
*)malloc(sizeof(struct sockaddr_un
));
58 if (getsockname(t
->sock
, to
, &tolen
) != 0)
61 rc
= recv(t
->sock
, buf
, size
, 0);
62 if (rc
< 0 && errno
!= EINTR
) {
63 log_warn("snmp", "unable to receive from fd %d",
69 *olength
= sizeof(struct sockaddr_un
);
80 agent_priv_unix_send(netsnmp_transport
*t
, void *buf
, int size
,
81 void **opaque
, int *olength
)
84 if (t
!= NULL
&& t
->sock
>= 0) {
86 rc
= send(t
->sock
, buf
, size
, 0);
87 if (rc
< 0 && errno
!= EINTR
) {
96 agent_priv_unix_close(netsnmp_transport
*t
)
109 agent_priv_unix_accept(netsnmp_transport
*t
)
111 log_warnx("snmp", "should not have been called");
115 static netsnmp_transport
*
116 agent_priv_unix_transport(const char *string
, int len
, int local
)
118 struct sockaddr_un addr
;
119 netsnmp_transport
*t
= NULL
;
122 log_warnx("snmp", "should not have been called for local transport");
127 if (len
> 0 && len
< (sizeof(addr
.sun_path
) - 1)) {
128 addr
.sun_family
= AF_UNIX
;
129 memset(addr
.sun_path
, 0, sizeof(addr
.sun_path
));
130 strncpy(addr
.sun_path
, string
, len
);
132 log_warnx("snmp", "path too long for Unix domain transport");
136 if ((t
= (netsnmp_transport
*)
137 malloc(sizeof(netsnmp_transport
))) == NULL
)
140 memset(t
, 0, sizeof(netsnmp_transport
));
142 t
->domain
= netsnmp_unix
;
144 sizeof(netsnmp_unix
) / sizeof(netsnmp_unix
[0]);
146 if ((t
->sock
= priv_snmp_socket(&addr
)) < 0) {
147 netsnmp_transport_free(t
);
151 t
->flags
= NETSNMP_TRANSPORT_FLAG_STREAM
;
153 if ((t
->remote
= (u_char
*)
154 malloc(strlen(addr
.sun_path
))) == NULL
) {
155 agent_priv_unix_close(t
);
156 netsnmp_transport_free(t
);
159 memcpy(t
->remote
, addr
.sun_path
, strlen(addr
.sun_path
));
160 t
->remote_length
= strlen(addr
.sun_path
);
162 t
->msgMaxSize
= 0x7fffffff;
163 t
->f_recv
= agent_priv_unix_recv
;
164 t
->f_send
= agent_priv_unix_send
;
165 t
->f_close
= agent_priv_unix_close
;
166 t
->f_accept
= agent_priv_unix_accept
;
167 t
->f_fmtaddr
= agent_priv_unix_fmtaddr
;
173 #if !HAVE_NETSNMP_TDOMAIN_F_CREATE_FROM_TSTRING_NEW
174 agent_priv_unix_create_tstring(const char *string
, int local
)
176 agent_priv_unix_create_tstring(const char *string
, int local
, const char *default_target
)
179 #if HAVE_NETSNMP_TDOMAIN_F_CREATE_FROM_TSTRING_NEW
180 if ((!string
|| *string
== '\0') && default_target
&&
181 *default_target
!= '\0') {
182 string
= default_target
;
187 return agent_priv_unix_transport(string
, strlen(string
), local
);
190 static netsnmp_transport
*
191 agent_priv_unix_create_ostring(const u_char
* o
, size_t o_len
, int local
)
193 return agent_priv_unix_transport((char *)o
, o_len
, local
);
197 agent_priv_register_domain()
199 unixDomain
.name
= netsnmp_unix
;
200 unixDomain
.name_length
= sizeof(netsnmp_unix
) / sizeof(oid
);
201 unixDomain
.prefix
= (const char**)calloc(2, sizeof(char *));
202 unixDomain
.prefix
[0] = "unix";
203 #if !HAVE_NETSNMP_TDOMAIN_F_CREATE_FROM_TSTRING_NEW
204 unixDomain
.f_create_from_tstring
= agent_priv_unix_create_tstring
;
206 unixDomain
.f_create_from_tstring_new
= agent_priv_unix_create_tstring
;
208 unixDomain
.f_create_from_ostring
= agent_priv_unix_create_ostring
;
209 netsnmp_tdomain_register(&unixDomain
);