2 * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 /* Some of the code here (agent_priv_unix_*) has been adapted from code from
18 * Net-SNMP project (snmplib/snmpUnixDomain.c). Net-SNMP project is licensed
19 * using BSD and BSD-like licenses. I don't know the exact license of the file
20 * snmplib/snmpUnixDomain.c. */
27 #include <net-snmp/net-snmp-config.h>
28 #include <net-snmp/net-snmp-includes.h>
29 #include <net-snmp/agent/net-snmp-agent-includes.h>
30 #include <net-snmp/agent/snmp_vars.h>
31 #include <net-snmp/library/snmpUnixDomain.h>
33 static oid netsnmp_unix
[] = { TRANSPORT_DOMAIN_LOCAL
};
34 static netsnmp_tdomain unixDomain
;
37 agent_priv_unix_fmtaddr(netsnmp_transport
*t
, void *data
, int len
)
39 /* We don't bother to implement the full function */
40 return strdup("Local Unix socket with privilege separation: unknown");
44 agent_priv_unix_recv(netsnmp_transport
*t
, void *buf
, int size
,
45 void **opaque
, int *olength
)
48 socklen_t tolen
= sizeof(struct sockaddr_un
);
49 struct sockaddr
*to
= NULL
;
51 if (t
== NULL
|| t
->sock
< 0)
53 to
= (struct sockaddr
*)malloc(sizeof(struct sockaddr_un
));
57 if (getsockname(t
->sock
, to
, &tolen
) != 0)
60 rc
= recv(t
->sock
, buf
, size
, 0);
61 if (rc
< 0 && errno
!= EINTR
) {
62 LLOG_WARN("unable to receive from fd %d",
68 *olength
= sizeof(struct sockaddr_un
);
79 agent_priv_unix_send(netsnmp_transport
*t
, void *buf
, int size
,
80 void **opaque
, int *olength
)
83 if (t
!= NULL
&& t
->sock
>= 0) {
85 rc
= send(t
->sock
, buf
, size
, 0);
86 if (rc
< 0 && errno
!= EINTR
) {
95 agent_priv_unix_close(netsnmp_transport
*t
)
108 agent_priv_unix_accept(netsnmp_transport
*t
)
110 LLOG_WARNX("should not have been called");
114 static netsnmp_transport
*
115 agent_priv_unix_transport(const char *string
, int len
, int local
)
117 struct sockaddr_un addr
;
118 netsnmp_transport
*t
= NULL
;
121 LLOG_WARNX("should not have been called for local transport");
126 if (len
> 0 && len
< (sizeof(addr
.sun_path
) - 1)) {
127 addr
.sun_family
= AF_UNIX
;
128 memset(addr
.sun_path
, 0, sizeof(addr
.sun_path
));
129 strncpy(addr
.sun_path
, string
, len
);
131 LLOG_WARNX("path too long for Unix domain transport");
135 if ((t
= (netsnmp_transport
*)
136 malloc(sizeof(netsnmp_transport
))) == NULL
)
139 memset(t
, 0, sizeof(netsnmp_transport
));
141 t
->domain
= netsnmp_unix
;
143 sizeof(netsnmp_unix
) / sizeof(netsnmp_unix
[0]);
145 if ((t
->sock
= priv_snmp_socket(&addr
)) < 0) {
146 netsnmp_transport_free(t
);
150 t
->flags
= NETSNMP_TRANSPORT_FLAG_STREAM
;
152 if ((t
->remote
= (u_char
*)
153 malloc(strlen(addr
.sun_path
))) == NULL
) {
154 agent_priv_unix_close(t
);
155 netsnmp_transport_free(t
);
158 memcpy(t
->remote
, addr
.sun_path
, strlen(addr
.sun_path
));
159 t
->remote_length
= strlen(addr
.sun_path
);
161 t
->msgMaxSize
= 0x7fffffff;
162 t
->f_recv
= agent_priv_unix_recv
;
163 t
->f_send
= agent_priv_unix_send
;
164 t
->f_close
= agent_priv_unix_close
;
165 t
->f_accept
= agent_priv_unix_accept
;
166 t
->f_fmtaddr
= agent_priv_unix_fmtaddr
;
172 #if !HAVE_NETSNMP_TDOMAIN_F_CREATE_FROM_TSTRING_NEW
173 agent_priv_unix_create_tstring(const char *string
, int local
)
175 agent_priv_unix_create_tstring(const char *string
, int local
, const char *default_target
)
178 #if HAVE_NETSNMP_TDOMAIN_F_CREATE_FROM_TSTRING_NEW
179 if ((!string
|| *string
== '\0') && default_target
&&
180 *default_target
!= '\0') {
181 string
= default_target
;
186 return agent_priv_unix_transport(string
, strlen(string
), local
);
189 static netsnmp_transport
*
190 agent_priv_unix_create_ostring(const u_char
* o
, size_t o_len
, int local
)
192 return agent_priv_unix_transport((char *)o
, o_len
, local
);
196 agent_priv_register_domain()
198 unixDomain
.name
= netsnmp_unix
;
199 unixDomain
.name_length
= sizeof(netsnmp_unix
) / sizeof(oid
);
200 unixDomain
.prefix
= (const char**)calloc(2, sizeof(char *));
201 unixDomain
.prefix
[0] = "unix";
202 #if !HAVE_NETSNMP_TDOMAIN_F_CREATE_FROM_TSTRING_NEW
203 unixDomain
.f_create_from_tstring
= agent_priv_unix_create_tstring
;
205 unixDomain
.f_create_from_tstring_new
= agent_priv_unix_create_tstring
;
207 unixDomain
.f_create_from_ostring
= agent_priv_unix_create_ostring
;
208 netsnmp_tdomain_register(&unixDomain
);