remove libfmd_snmp and smnp-notify
[unleashed.git] / usr / src / cmd / hal / addons / network-devices / common.c
blob13d40ed9ef3995afe558538fe5e8c8a5595b6374
1 /*
2 * Copyright 2017 Gary Mills
3 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
5 * Licensed under the Academic Free License version 2.1
6 */
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <unistd.h>
11 #include <signal.h>
12 #include <string.h>
13 #include <sys/types.h>
14 #include <sys/socket.h>
15 #include <sys/ioctl.h>
16 #include <sys/sockio.h>
17 #include <net/if.h>
18 #include <net/if_arp.h>
19 #include <netinet/in.h>
20 #include <arpa/inet.h>
21 #include <netdb.h>
23 #include <libhal.h>
24 #include <logger.h>
26 #include <glib.h>
28 #include "network-discovery.h"
29 #define NP(x) (x?x:"NULL")
31 extern int snmp_printer_info(char *hostname, char *community,
32 char **manufacturer, char **model, char **description,
33 char **serial_no, char ***command_set, char **uri);
35 void
36 network_device_name_to_udi(char *udi, size_t size, ...)
38 va_list ap;
39 char *element;
40 int i;
42 udi[0] = '\0';
43 va_start(ap, size);
44 while ((element = va_arg(ap, char *)) != NULL) {
45 if (element[0] != '/')
46 strlcat(udi, "/", size);
47 strlcat(udi, element, size);
49 va_end(ap);
51 for (i = 0; udi[i] != '\0'; i++)
52 if (udi[i] == '.')
53 udi[i] = '_';
56 static void nop(int sig) {}
58 static int
59 test_socket_access(struct in6_addr *addr, int port)
61 int sd, rc;
62 struct sockaddr_in6 sin6;
63 void (*hndlr)(int);
65 memset(&sin6, 0, sizeof (sin6));
66 sin6.sin6_family = AF_INET6;
67 memcpy(&sin6.sin6_addr, addr, sizeof (*addr));
68 sin6.sin6_port = htons(port);
70 sd = socket(AF_INET6, SOCK_STREAM, 0);
71 hndlr = signal(SIGALRM, nop);
72 alarm(1);
73 rc = connect(sd, (struct sockaddr *)&sin6, sizeof (sin6));
74 alarm(0);
75 if (hndlr != NULL)
76 signal(SIGALRM, hndlr);
77 close(sd);
79 return ((rc < 0) ? 1 : 0);
82 int
83 is_listening(char *hostname, int port)
85 char *uri = NULL, addr_string[INET6_ADDRSTRLEN];
86 struct in6_addr ipv6addr[1];
87 int errnum;
88 struct hostent *hp;
90 hp = getipnodebyname(hostname, AF_INET6,
91 AI_ALL | AI_ADDRCONFIG | AI_V4MAPPED, &errnum);
92 if (hp != NULL) {
93 (void) memcpy(&ipv6addr, hp->h_addr_list[0], hp->h_length);
94 } else
95 return (-1);
97 return (test_socket_access(ipv6addr, port));
100 static char *
101 addr_to_string(char *prefix, uchar_t *mac, int mac_len, char *buf, int buf_len)
103 int i, n = 0;
105 buf[0] = '\0';
106 if (prefix != NULL)
107 n = sprintf(buf, prefix);
108 for (i = 0; ((i < (mac_len)) && (n < buf_len)); i++)
109 n += sprintf(buf + n, "%2.2X", *mac++);
111 return (buf);
114 static char *
115 pseudo_serialno_from_addr(char *name)
117 int sd, errnum;
118 char buf[128];
119 struct hostent *hp;
120 struct xarpreq ar;
122 if (name == NULL)
123 return (NULL);
125 memset(&ar, 0, sizeof (ar));
127 hp = getipnodebyname(name, AF_INET6, AI_ADDRCONFIG, &errnum);
128 if (hp != NULL) {
129 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ar.xarp_pa;
131 sin6->sin6_family = AF_INET6;
132 (void) memcpy(&sin6->sin6_addr, hp->h_addr_list[0],
133 hp->h_length);
134 } else {
135 struct sockaddr_in *sin = (struct sockaddr_in *)&ar.xarp_pa;
137 sin->sin_family = AF_INET;
138 sin->sin_addr.s_addr = inet_addr(name);
141 sd = socket(AF_INET, SOCK_DGRAM, 0);
143 ar.xarp_ha.sdl_family = AF_LINK;
144 (void) ioctl(sd, SIOCGXARP, (caddr_t)&ar);
146 close(sd);
148 if (ar.xarp_flags & ATF_COM) { /* use the MAC address */
149 uchar_t *ea = (uchar_t *)LLADDR(&ar.xarp_ha);
151 addr_to_string("LLADDR-", ea, ar.xarp_ha.sdl_alen,
152 buf, sizeof (buf));
154 } else if (hp != NULL) { /* use the IPv6 address */
155 addr_to_string("IPV6ADDR-", (uchar_t *)&hp->h_addr_list[0],
156 hp->h_length, buf, sizeof (buf));
157 } else { /* use the IPv4 address */
158 struct sockaddr_in *sin = (struct sockaddr_in *)&ar.xarp_pa;
160 addr_to_string("IPV4ADDR-", (uchar_t *)&sin->sin_addr.s_addr, 4,
161 buf, sizeof (buf));
164 return (strdup(buf));
168 add_network_printer(LibHalContext *ctx, char *base, char *hostaddr,
169 char *device, char *community)
171 DBusError error;
172 int rc = -1;
173 char udi[128];
174 char *tmp_udi = NULL;
175 static char *parent = NULL;
176 char *manufacturer = NULL, *model = NULL, *description = NULL,
177 *uri = NULL, *sn, *serial;
179 sn = serial = pseudo_serialno_from_addr(hostaddr);
181 if (parent == NULL)
182 parent = getenv("UDI");
184 dbus_error_init(&error);
186 network_device_name_to_udi(udi, sizeof (udi), base, serial, NULL);
188 if (libhal_device_exists(ctx, udi, &error) == TRUE)
189 goto out;
191 if ((tmp_udi = libhal_new_device(ctx, &error)) == NULL)
192 goto out;
194 snmp_printer_info(hostaddr, community, &manufacturer, &model,
195 &description, &serial, NULL, &uri);
197 libhal_device_set_property_string(ctx, tmp_udi,
198 "info.parent", parent, &error);
200 libhal_device_set_property_string(ctx, tmp_udi,
201 "info.category", "printer", &error);
203 libhal_device_property_strlist_append(ctx, tmp_udi,
204 "info.capabilities", "printer", &error);
205 libhal_device_property_strlist_append(ctx, tmp_udi,
206 "info.capabilities", "network_device", &error);
208 libhal_device_set_property_string(ctx, tmp_udi,
209 "network_device.address", hostaddr, &error);
211 if ((community != NULL) && (strcasecmp(community, "public") != 0))
212 libhal_device_set_property_string(ctx, tmp_udi,
213 "network_device.snmp_community", community, &error);
215 if ((uri != NULL) || (device != NULL))
216 libhal_device_set_property_string(ctx, tmp_udi,
217 "printer.device", (uri ? uri : device), &error);
219 if (serial != NULL)
220 libhal_device_set_property_string(ctx, tmp_udi,
221 "printer.serial", serial, &error);
223 if (manufacturer != NULL)
224 libhal_device_set_property_string(ctx, tmp_udi,
225 "printer.vendor", manufacturer, &error);
227 if (model != NULL)
228 libhal_device_set_property_string(ctx, tmp_udi,
229 "printer.product", model, &error);
231 if (description != NULL)
232 libhal_device_set_property_string(ctx, tmp_udi,
233 "printer.description", description, &error);
235 /* commit the changes to the new UDI */
236 rc = libhal_device_commit_to_gdl(ctx, tmp_udi, udi, &error);
238 out:
239 HAL_DEBUG(("result: %s (%s): %s, %s, %s, %s, %s", hostaddr, udi,
240 NP(manufacturer), NP(model), NP(description), NP(serial),
241 NP(uri)));
243 free(tmp_udi);
244 free(manufacturer);
245 free(model);
246 free(description);
247 free(uri);
248 free(sn);
250 if (dbus_error_is_set(&error)) {
251 HAL_WARNING(("%s: %s", error.name, error.message));
252 dbus_error_free(&error);
255 HAL_DEBUG(("add: %s (%s)", hostaddr, udi));
257 return (rc);
260 static int
261 number_of_interfaces(int s)
263 int rc = -1;
264 struct lifnum n;
266 memset(&n, 0 , sizeof (n));
267 n.lifn_family = AF_INET;
268 if (ioctl(s, SIOCGLIFNUM, (char *)&n) == 0)
269 rc = n.lifn_count;
271 return (rc);
274 static char *
275 broadcast_address(int s, char *ifname)
277 char *result = NULL;
278 struct lifreq r;
280 memset(&r, 0, sizeof (r));
281 strlcpy(r.lifr_name, ifname, sizeof (r.lifr_name));
282 if (ioctl(s, SIOCGLIFFLAGS, (caddr_t)&r) < 0) {
283 HAL_DEBUG(("broadcast_address: ioctl(SIOCGLIFFLAGS) failed."));
284 return (NULL);
286 if ((r.lifr_flags & (IFF_UP | IFF_LOOPBACK)) != IFF_UP) {
287 return (NULL);
289 if (ioctl(s, SIOCGLIFBRDADDR, (char *)&r) >= 0) {
290 char buf[INET_ADDRSTRLEN];
291 struct sockaddr_in *s =
292 (struct sockaddr_in *)&r.lifr_broadaddr;
293 result = (char *)inet_ntop(AF_INET,
294 &s->sin_addr, buf, sizeof (buf));
295 if (result != NULL)
296 result = strdup(result);
299 return (result);
302 GList *
303 broadcast_addresses()
305 GList *result = NULL;
306 int s;
307 struct lifconf c;
308 int count;
310 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
311 return (NULL);
313 count = number_of_interfaces(s);
315 memset(&c, 0, sizeof (c));
316 c.lifc_family = AF_INET;
317 c.lifc_flags = 0;
318 c.lifc_buf = calloc(count, sizeof (struct lifreq));
319 c.lifc_len = (count * sizeof (struct lifreq));
321 if (ioctl(s, SIOCGLIFCONF, (char *)&c) == 0) {
322 struct lifreq *r = c.lifc_req;
324 for (count = c.lifc_len / sizeof (struct lifreq);
325 count > 0; count--, r++) {
326 char *address = broadcast_address(s, r->lifr_name);
328 if (address != NULL) /* add it to the list */
329 result = g_list_append(result, address);
332 free(c.lifc_buf);
333 close(s);
335 return (result);