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