2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
5 * Licensed under the Academic Free License version 2.1
23 #include <dbus/dbus-glib-lowlevel.h>
26 #include "../../hald/logger.h"
28 #include "network-discovery.h"
31 #define DBUS_INTERFACE "org.freedesktop.Hal.Device.NetworkDiscovery"
32 #define NP(x) (x?x:"NULL")
33 #define STRDUP(x) (x?strdup(x):NULL)
43 static nds_snmp_cbdata_t
*snmp_cb_data
= NULL
;
46 nds_snmp_scan(LibHalContext
*ctx
, char *parent
, char *community
, char *network
)
50 HAL_DEBUG(("nds_snmp_scan(0x%8.8x, %s, %s, %s)",
51 ctx
, NP(parent
), NP(community
), NP(network
)));
52 HAL_DEBUG(("NetworkDiscovery snmp scan initated"));
54 /* scan for devices */
56 if (network
== NULL
) {
57 GList
*elem
, *list
= broadcast_addresses();
59 for (elem
= list
; elem
!= NULL
; elem
= g_list_next(elem
)) {
60 scan_for_devices_using_snmp(ctx
, parent
, community
,
66 scan_for_devices_using_snmp(ctx
, parent
, community
, network
);
68 /* remove devices that haven't been seen since before this scan */
69 scan_for_stale_devices(ctx
, start
);
71 HAL_DEBUG(("NetworkDiscovery snmp scan completed"));
77 nds_snmp_scan_cb(gpointer data
)
79 nds_snmp_cbdata_t
*args
= data
;
81 if (args
->enabled
== FALSE
) {
82 if (args
->parent
) free(args
->parent
);
83 if (args
->community
) free(args
->community
);
84 if (args
->network
) free(args
->network
);
89 nds_snmp_scan(args
->ctx
, args
->parent
, args
->community
, args
->network
);
95 nds_EnablePrinterScanningViaSNMP(LibHalContext
*ctx
, char *parent
, int interval
,
96 char *community
, char *network
)
98 HAL_DEBUG(("NetworkDiscovery.EnablePrinterScanningViaSNMP(0x%8.8x, %s, %d, %s, %s)",
99 ctx
, NP(parent
), interval
, NP(community
), NP(network
)));
101 /* are we already discoverying network devices ? */
102 if (snmp_cb_data
!= NULL
) {
103 snmp_cb_data
->enabled
= FALSE
; /* cancel it */
106 /* setup for network device discovery */
107 if ((snmp_cb_data
= calloc(1, sizeof (*snmp_cb_data
))) != NULL
) {
108 snmp_cb_data
->ctx
= ctx
;
109 snmp_cb_data
->enabled
= TRUE
;
110 snmp_cb_data
->parent
= STRDUP(parent
);
111 snmp_cb_data
->community
= STRDUP(community
);
112 snmp_cb_data
->network
= STRDUP(network
);
114 /* prime the pump with an initial scan */
115 nds_snmp_scan(ctx
, parent
, community
, network
);
117 /* add a regular network scan */
118 g_timeout_add(interval
* 1000, nds_snmp_scan_cb
, snmp_cb_data
);
125 nds_DisablePrinterScanningViaSNMP(LibHalContext
*ctx
)
127 HAL_DEBUG(("NetworkDiscovery.DisablePrinterScanningViaSNMP(0x%8.8x)", ctx
));
129 if (snmp_cb_data
!= NULL
)
130 snmp_cb_data
->enabled
= FALSE
;
137 nds_ScanForPrintersViaSNMP(LibHalContext
*ctx
, char *parent
, char *community
,
142 HAL_DEBUG(("NetworkDiscovery.ScanForPrintersViaSNMP(0x%8.8x, %s, %s, %s)",
143 ctx
, NP(parent
), NP(community
), NP(network
)));
145 return (nds_snmp_scan(ctx
, parent
, community
, network
));
148 static DBusHandlerResult
149 nds_filter_function(DBusConnection
*connection
, DBusMessage
*message
,
152 LibHalContext
*ctx
= user_data
;
155 const char *member
= dbus_message_get_member(message
);
156 const char *path
= dbus_message_get_path(message
);
159 dbus_error_init(&error
);
161 HAL_DEBUG(("DBus message: %s, %s ", member
, path
));
163 if (dbus_message_is_method_call(message
,
164 DBUS_INTERFACE
, "EnablePrinterScanningViaSNMP")) {
166 char *udi
= getenv("UDI");
167 char *community
= "public";
168 char *network
= "0.0.0.0";
170 dbus_message_get_args(message
, &error
,
171 DBUS_TYPE_INT32
, &interval
,
172 DBUS_TYPE_STRING
, &community
,
173 DBUS_TYPE_STRING
, &network
,
176 if (strcmp(network
, "0.0.0.0") == 0)
179 rc
= nds_EnablePrinterScanningViaSNMP(ctx
, udi
, interval
,
181 } else if (dbus_message_is_method_call(message
,
182 DBUS_INTERFACE
, "ScanForPrintersViaSNMP")) {
184 char *udi
= getenv("UDI");
185 char *community
= "public";
186 char *network
= "0.0.0.0";
188 dbus_message_get_args(message
, &error
,
189 DBUS_TYPE_STRING
, &community
,
190 DBUS_TYPE_STRING
, &network
,
193 if (strcmp(network
, "0.0.0.0") == 0)
196 rc
= nds_ScanForPrintersViaSNMP(ctx
, udi
, community
, network
);
197 } else if (dbus_message_is_method_call(message
,
198 DBUS_INTERFACE
, "DisablePrinterScanningViaSNMP")) {
199 rc
= nds_DisablePrinterScanningViaSNMP(ctx
);
201 /* bypass not-handled messages */
202 HAL_WARNING(("Unknown DBus message: %s, %s ", member
, path
));
203 return (DBUS_HANDLER_RESULT_NOT_YET_HANDLED
);
206 if (dbus_error_is_set(&error
))
207 dbus_error_free(&error
);
209 if ((reply
= dbus_message_new_method_return(message
)) == NULL
) {
210 HAL_WARNING(("Could not allocate memory for the DBus reply"));
214 dbus_message_append_args(reply
, DBUS_TYPE_INT32
, &rc
,
217 if (!dbus_connection_send(connection
, reply
, NULL
)) {
218 HAL_WARNING(("Could not sent reply"));
220 dbus_connection_flush(connection
);
221 dbus_message_unref(reply
);
223 return (DBUS_HANDLER_RESULT_HANDLED
);
227 nds_claim_interface(LibHalContext
*ctx
, char *udi
, DBusError
*error
)
229 DBusConnection
*connection
;
230 char *interface_xml
=
231 "<method name=\"EnablePrinterScanningViaSNMP\">\n"
232 " <arg name=\"interval\" direction=\"in\" type=\"i\"/>\n"
233 " <arg name=\"community\" direction=\"in\" type=\"s\"/>\n"
234 " <arg name=\"network\" direction=\"in\" type=\"s\"/>\n"
235 " <arg name=\"return_code\" direction=\"out\" type=\"i\"/>\n"
237 "<method name=\"DisablePrinterScanningViaSNMP\">\n"
238 " <arg name=\"return_code\" direction=\"out\" type=\"i\"/>\n"
240 "<method name=\"ScanForPrintersViaSNMP\">\n"
241 " <arg name=\"community\" direction=\"in\" type=\"s\"/>\n"
242 " <arg name=\"network\" direction=\"in\" type=\"s\"/>\n"
243 " <arg name=\"return_code\" direction=\"out\" type=\"i\"/>\n"
246 HAL_DEBUG(("nds_claim_interface(0x%8.8x, %s, 0x%8.8x): %s",
247 ctx
, udi
, error
, DBUS_INTERFACE
));
249 if ((connection
= libhal_ctx_get_dbus_connection(ctx
)) == NULL
) {
250 HAL_WARNING(("Could not get DBus connection"));
254 if (libhal_device_claim_interface(ctx
, udi
,
255 DBUS_INTERFACE
, interface_xml
, error
) == 0) {
256 HAL_WARNING(("Could not claim interface: %s", error
->message
));
260 dbus_connection_setup_with_g_main(connection
, NULL
);
261 dbus_connection_add_filter(connection
, nds_filter_function
, ctx
, NULL
);
262 dbus_connection_set_exit_on_disconnect(connection
, 0);
270 priv_set_t
*pPrivSet
= NULL
;
271 priv_set_t
*lPrivSet
= NULL
;
274 * Start with the 'basic' privilege set and then remove any
275 * of the 'basic' privileges that will not be needed.
277 if ((pPrivSet
= priv_str_to_set("basic", ",", NULL
)) == NULL
) {
281 /* Clear privileges we will not need from the 'basic' set */
282 (void) priv_delset(pPrivSet
, PRIV_FILE_LINK_ANY
);
283 (void) priv_delset(pPrivSet
, PRIV_PROC_EXEC
);
284 (void) priv_delset(pPrivSet
, PRIV_PROC_FORK
);
285 (void) priv_delset(pPrivSet
, PRIV_PROC_INFO
);
286 (void) priv_delset(pPrivSet
, PRIV_PROC_SESSION
);
288 /* Set the permitted privilege set. */
289 if (setppriv(PRIV_SET
, PRIV_PERMITTED
, pPrivSet
) != 0) {
293 /* Clear the limit set. */
294 if ((lPrivSet
= priv_allocset()) == NULL
) {
298 priv_emptyset(lPrivSet
);
300 if (setppriv(PRIV_SET
, PRIV_LIMIT
, lPrivSet
) != 0) {
304 priv_freeset(lPrivSet
);
309 main(int argc
, char **argv
)
311 LibHalContext
*ctx
= NULL
;
313 GMainLoop
*loop
= g_main_loop_new(NULL
, FALSE
);
316 if ((udi
= getenv("UDI")) == NULL
) {
324 dbus_error_init(&error
);
326 if ((ctx
= libhal_ctx_init_direct(&error
)) == NULL
) {
330 if (!libhal_device_addon_is_ready(ctx
, udi
, &error
)) {
334 if (nds_claim_interface(ctx
, udi
, &error
) != 0) {
338 g_main_loop_run(loop
);