]> git.ipfire.org Git - thirdparty/lldpd.git/blob - src/agent_priv.c
Update ISC license wording.
[thirdparty/lldpd.git] / src / agent_priv.c
1 /*
2 * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
3 *
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.
7 *
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.
15 */
16
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. */
21
22 #include "lldpd.h"
23
24 #include <unistd.h>
25 #include <errno.h>
26
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>
32
33 static oid netsnmp_unix[] = { TRANSPORT_DOMAIN_LOCAL };
34 static netsnmp_tdomain unixDomain;
35
36 static char *
37 agent_priv_unix_fmtaddr(netsnmp_transport *t, void *data, int len)
38 {
39 /* We don't bother to implement the full function */
40 return strdup("Local Unix socket with privilege separation: unknown");
41 }
42
43 static int
44 agent_priv_unix_recv(netsnmp_transport *t, void *buf, int size,
45 void **opaque, int *olength)
46 {
47 int rc = -1;
48 socklen_t tolen = sizeof(struct sockaddr_un);
49 struct sockaddr *to = NULL;
50
51 if (t == NULL || t->sock < 0)
52 goto recv_error;
53 to = (struct sockaddr *)malloc(sizeof(struct sockaddr_un));
54 if (to == NULL)
55 goto recv_error;
56 memset(to, 0, tolen);
57 if (getsockname(t->sock, to, &tolen) != 0)
58 goto recv_error;
59 while (rc < 0) {
60 rc = recv(t->sock, buf, size, 0);
61 if (rc < 0 && errno != EINTR) {
62 LLOG_WARN("unable to receive from fd %d",
63 t->sock);
64 goto recv_error;
65 }
66 }
67 *opaque = (void*)to;
68 *olength = sizeof(struct sockaddr_un);
69 return rc;
70
71 recv_error:
72 free(to);
73 *opaque = NULL;
74 *olength = 0;
75 return -1;
76 }
77
78 static int
79 agent_priv_unix_send(netsnmp_transport *t, void *buf, int size,
80 void **opaque, int *olength)
81 {
82 int rc = -1;
83 if (t != NULL && t->sock >= 0) {
84 while (rc < 0) {
85 rc = send(t->sock, buf, size, 0);
86 if (rc < 0 && errno != EINTR) {
87 break;
88 }
89 }
90 }
91 return rc;
92 }
93
94 static int
95 agent_priv_unix_close(netsnmp_transport *t)
96 {
97 int rc = 0;
98
99 if (t->sock >= 0) {
100 rc = close(t->sock);
101 t->sock = -1;
102 return rc;
103 }
104 return -1;
105 }
106
107 static int
108 agent_priv_unix_accept(netsnmp_transport *t)
109 {
110 LLOG_WARNX("should not have been called");
111 return -1;
112 }
113
114 static netsnmp_transport *
115 agent_priv_unix_transport(const char *string, int len, int local)
116 {
117 struct sockaddr_un addr;
118 netsnmp_transport *t = NULL;
119
120 if (local) {
121 LLOG_WARNX("should not have been called for local transport");
122 return NULL;
123 }
124 if (!string)
125 return NULL;
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);
130 } else {
131 LLOG_WARNX("path too long for Unix domain transport");
132 return NULL;
133 }
134
135 if ((t = (netsnmp_transport *)
136 malloc(sizeof(netsnmp_transport))) == NULL)
137 return NULL;
138
139 memset(t, 0, sizeof(netsnmp_transport));
140
141 t->domain = netsnmp_unix;
142 t->domain_length =
143 sizeof(netsnmp_unix) / sizeof(netsnmp_unix[0]);
144
145 if ((t->sock = priv_snmp_socket(&addr)) < 0) {
146 netsnmp_transport_free(t);
147 return NULL;
148 }
149
150 t->flags = NETSNMP_TRANSPORT_FLAG_STREAM;
151
152 if ((t->remote = (u_char *)
153 malloc(strlen(addr.sun_path))) == NULL) {
154 agent_priv_unix_close(t);
155 netsnmp_transport_free(t);
156 return NULL;
157 }
158 memcpy(t->remote, addr.sun_path, strlen(addr.sun_path));
159 t->remote_length = strlen(addr.sun_path);
160
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;
167
168 return t;
169 }
170
171 netsnmp_transport *
172 #if !HAVE_NETSNMP_TDOMAIN_F_CREATE_FROM_TSTRING_NEW
173 agent_priv_unix_create_tstring(const char *string, int local)
174 #else
175 agent_priv_unix_create_tstring(const char *string, int local, const char *default_target)
176 #endif
177 {
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;
182 }
183 #endif
184 if (!string)
185 return NULL;
186 return agent_priv_unix_transport(string, strlen(string), local);
187 }
188
189 static netsnmp_transport *
190 agent_priv_unix_create_ostring(const u_char * o, size_t o_len, int local)
191 {
192 return agent_priv_unix_transport((char *)o, o_len, local);
193 }
194
195 void
196 agent_priv_register_domain()
197 {
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;
204 #else
205 unixDomain.f_create_from_tstring_new = agent_priv_unix_create_tstring;
206 #endif
207 unixDomain.f_create_from_ostring = agent_priv_unix_create_ostring;
208 netsnmp_tdomain_register(&unixDomain);
209 }