summaryrefslogtreecommitdiff
path: root/protocol
diff options
context:
space:
mode:
authorDidier Raboud <odyx@debian.org>2020-10-03 17:47:15 +0200
committerDidier Raboud <odyx@debian.org>2020-10-03 17:47:15 +0200
commitc3dcb444f2b2ef562a316b6324bb49599ca25841 (patch)
treecb95b1749ab90a8e239e9541d5ee5163a0c52157 /protocol
parentd7163f9ff2653bf7b37a8e535edeccf2c42be9fe (diff)
New upstream version 3.20.9
Diffstat (limited to 'protocol')
-rw-r--r--protocol/discovery/avahiDiscovery.c521
-rw-r--r--protocol/discovery/avahiDiscovery.h88
-rw-r--r--protocol/discovery/mdns.c496
-rw-r--r--protocol/discovery/mdns.h104
-rw-r--r--protocol/hp_ipp.c11
-rw-r--r--protocol/hp_ipp.h4
6 files changed, 617 insertions, 607 deletions
diff --git a/protocol/discovery/avahiDiscovery.c b/protocol/discovery/avahiDiscovery.c
new file mode 100644
index 000000000..8d325ffc0
--- /dev/null
+++ b/protocol/discovery/avahiDiscovery.c
@@ -0,0 +1,521 @@
+/*
+ * This file is derived from avahi_client_browse.c, part of avahi.
+ *
+ * avahi is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * avahi is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with avahi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA.
+ */
+
+#include "avahiDiscovery.h"
+#include <errno.h>
+#include <dbus/dbus.h>
+
+DBusConnection *conn;
+
+char* aUriBuf=NULL;
+char ipAddressBuff[MAX_IP_ADDR_LEN]={'\0'};
+static int aBytesRead = 0;
+static AvahiSimplePoll *aSimplePoll = NULL;
+static int aMemAllocated = 0;
+
+/*
+This function will fill the dictionary arguments for the dbus function call
+*/
+static void addDictWithStringValue(DBusMessageIter *iter,
+ const char *key, const char *str)
+{
+ DBusMessageIter dict, entry, value;
+
+ dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+ dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
+ NULL, &entry);
+
+ dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
+
+ dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
+ DBUS_TYPE_STRING_AS_STRING, &value);
+ dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &str);
+ dbus_message_iter_close_container(&entry, &value);
+
+ dbus_message_iter_close_container(&dict, &entry);
+ dbus_message_iter_close_container(iter, &dict);
+}
+/*
+This function will form the empty dictionary for the dbus function call
+*/
+static void addEmptyStringDict(DBusMessageIter *iter)
+{
+ DBusMessageIter dict;
+
+ dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_STRING_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+
+ dbus_message_iter_close_container(iter, &dict);
+}
+/*
+This function will fill the arguments for the dbus function call
+*/
+static void addArgumentsForAuthentication(DBusConnection *conn, DBusMessageIter *iter)
+{
+ const char *busname = dbus_bus_get_unique_name(conn);
+ const char *kind = SYSTEM_BUS_NAME;
+ const char *action = ACTION_ID;
+
+ const char *cancel = "";
+ dbus_uint32_t flags = 1;
+ DBusMessageIter subject;
+
+ dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT,
+ NULL, &subject);
+ dbus_message_iter_append_basic(&subject, DBUS_TYPE_STRING, &kind);
+ addDictWithStringValue(&subject, "name", busname);
+ dbus_message_iter_close_container(iter, &subject);
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &action);
+ addEmptyStringDict(iter);
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &flags);
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &cancel);
+}
+/*
+This function will start the avahi service if the process authorized by polkit
+*/
+static bool systemdStartAvahiService()
+{
+ DBusMessage *msg, *response;
+ DBusError err;
+
+ dbus_error_init(&err);
+
+ const char *aAvahiUnitName = AVAHI_SERVICE_NAME;
+ const char *aAvahiUnitMode = AVHHI_SERVICE_MODE_REPLACE;
+
+ msg = dbus_message_new_method_call(SYSTEMD_DBUS_NAME, SYSTEMD_DBUS_PATH, SYSTEMD_DBUS_INTF, SYSTEMD_START_SERVICE_METHOD);
+ if(!msg)
+ {
+ BUG("failed to create dbus message\n");
+ return false;
+ }
+ dbus_message_append_args(msg, DBUS_TYPE_STRING, &aAvahiUnitName, DBUS_TYPE_STRING, &aAvahiUnitMode, DBUS_TYPE_INVALID);
+
+ response = dbus_connection_send_with_reply_and_block(conn, msg,SYSTEMD_SERVICE_TIMEOUT, &err);
+
+ if(dbus_error_is_set(&err))
+ {
+ dbus_message_unref(msg);
+ BUG("failed to start service : %s\n", err.message);
+ return false;
+ }
+
+ dbus_message_unref(msg);
+ dbus_message_unref(response);
+ return true;
+}
+/*
+This function will involk polkit based authorization using dbus
+*/
+static bool checkAuthorizationForAvahiService()
+{
+ DBusMessage *msg, *reply;
+ DBusMessageIter iter;
+ DBusError err;
+ bool authorized = false;
+ conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
+ if (!conn)
+ {
+ BUG("Can't get on system bus");
+ return authorized;
+ }
+ msg = dbus_message_new_method_call(POLKIT_AUTH_DBUS, POLKIT_AUTH_PATH,
+ POLKIT_AUTH_INTF, POLKIT_AUTH_METHOD_CALL);
+ if (!msg)
+ {
+ BUG("Can't allocate new method call\n");
+ return authorized;
+ }
+ dbus_message_iter_init_append(msg, &iter);
+ addArgumentsForAuthentication(conn, &iter);
+ dbus_error_init(&err);
+ reply = dbus_connection_send_with_reply_and_block(conn, msg, DBUS_TIMEOUT_INFINITE, &err);
+ dbus_message_unref(msg);
+ if (!reply)
+ {
+ if (dbus_error_is_set(&err))
+ {
+ BUG("%s\n", err.message);
+ dbus_error_free(&err);
+ }
+ else
+ {
+ BUG("Can't check authorization\n");
+ }
+ return authorized;
+ }
+ //verify the response with dbus response signature
+ if (dbus_message_has_signature(reply, "(bba{ss})"))
+ {
+ DBusMessageIter result;
+ dbus_bool_t respAuthorized;
+ //iterate the dbus response
+ dbus_message_iter_init(reply, &iter);
+ dbus_message_iter_recurse(&iter, &result);
+ //get the authorization status
+ dbus_message_iter_get_basic(&result, &respAuthorized);
+ DBG("Authorized %d \n", respAuthorized);
+ if(respAuthorized)
+ {
+ authorized = true;
+ }
+ }
+ else
+ {
+ BUG("dbus response signature mismatch\n");
+ }
+ dbus_message_unref(reply);
+ return authorized;
+}
+
+/*
+This function will get the value for the given key if found in the string list.
+Returns true if found the value ,otherwise returns false
+Parameters:
+ iStrList - INPUT - Avahi device (scanner) string list.
+ ikey - INPUT - Key to find in the stringlist.
+ oKeyValue - OUTPUT - Value of the given key.
+ aMdlStrLen - OUTPUT - size of oKeyValue.
+Note:
+ Possible value in iStrList (avahi response for a device)
+ "duplex=F" "is=platen" "cs=binary,color,grayscale" "rs=eSCL" "representation=images/printer.png"
+ "UUID=6fcbd42d-b117-5352-ab4c-35acfabefc34" "note=" "adminurl=http://HPE4E749F6A0F7.local."
+ "ty=HP DeskJet 2700 series" "pdl=application/octet-stream,application/pdf,image/jpeg"
+ "mopria-certified-scan=1.2" "vers=2.63" "txtvers=1"
+*/
+
+static bool getHPScannerModel(AvahiStringList *iStrList, const char *ikey,char **oKeyValue,size_t *aMdlStrLen)
+{
+ AvahiStringList *aStrList = NULL;
+ bool aValueFound = false;
+ char *aKey = NULL;
+ aStrList = avahi_string_list_find(iStrList, ikey);
+ /*
+ aStrList will be Null ,if given key is not found,
+ avahi_string_list_get_pair will return zero if key found,
+ also need to process the response form HP scanner only.
+ */
+ if( ( aStrList != NULL ) && ( avahi_string_list_get_pair(aStrList, &aKey, oKeyValue, aMdlStrLen) == 0 )
+ && ( *oKeyValue != NULL ) && ( strncmp(MFG_HP,*oKeyValue,MFG_HP_LEN) == 0 ))
+ {
+ size_t aIndex = 0;
+ for(aIndex = 0; aIndex<(*aMdlStrLen); aIndex++)
+ {
+ if(isspace((*oKeyValue)[aIndex]))
+ {
+ (*oKeyValue)[aIndex] = '_';
+ }
+ (*oKeyValue)[aIndex] = tolower((*oKeyValue)[aIndex]);
+ }
+ DBG("oKeyValue is %s\n", *oKeyValue);
+ aValueFound = true;
+ }
+ if( aKey != NULL )
+ avahi_free( (void *)aKey );
+ return aValueFound;
+}
+
+/*
+This function will gets called whenever a service has been resolved successfully or timed out
+*/
+static void resolve_callback(
+ AvahiServiceResolver *r,
+ AVAHI_GCC_UNUSED AvahiIfIndex interface,
+ AVAHI_GCC_UNUSED AvahiProtocol protocol,
+ AvahiResolverEvent event,
+ const char *name,
+ const char *type,
+ const char *domain,
+ const char *host_name,
+ const AvahiAddress *address,
+ uint16_t port,
+ AvahiStringList *txt,
+ AvahiLookupResultFlags flags,
+ AVAHI_GCC_UNUSED void* userdata) {
+ assert(r);
+ switch (event) {
+ case AVAHI_RESOLVER_FAILURE:
+ BUG( "(Resolver) Failed to resolve service '%s' of type '%s' in domain '%s': %s\n", name, type, domain, avahi_strerror(avahi_client_errno(avahi_service_resolver_get_client(r))));
+ break;
+
+ case AVAHI_RESOLVER_FOUND: {
+ char aIPAddress[AVAHI_ADDRESS_STR_MAX]={'\0'};
+ char *aMdlStr = NULL;
+ size_t aMdlStrLen = 0 ;
+ DBG( "Service '%s' of type '%s' in domain '%s':\n", name, type, domain);
+ avahi_address_snprint(aIPAddress, AVAHI_ADDRESS_STR_MAX, address);
+ DBG("avahi_address_snprint : \n %s \n",aIPAddress);
+ if( getHPScannerModel(txt,TYPE_NAME,&aMdlStr,&aMdlStrLen) == true )
+ {
+ DBG("aMdlStr name is %s \n",aMdlStr);
+ DBG("aMdlStrLen is %zu \n",aMdlStrLen);
+ char aTempUri[MAX_URI_LEN] = {'\0'};
+ snprintf( aTempUri, MAX_URI_LEN, "hp:/net/%s?ip=%s&queue=false", aMdlStr+HP_SKIP_MFG_NAME_SIZE, aIPAddress);
+ if(aUriBuf == NULL)
+ {
+ aUriBuf = (char *)calloc(HP_MAX_SCAN_BUFF,sizeof(char));
+ if(aUriBuf == NULL)
+ {
+ BUG("Unable to alloacate the memeory\n");
+ exit(0);
+ }
+ aMemAllocated = HP_MAX_SCAN_BUFF ;
+ }
+ //Check whether buffer has enough space to add new URI and check for duplicate URIs.
+ if( !strstr(aUriBuf, aTempUri) )
+ {
+ if ( (aBytesRead + MAX_URI_LEN) > aMemAllocated )
+ {
+ aUriBuf = realloc(aUriBuf, ( MAX_URI_LEN * sizeof(char) ) );
+ aMemAllocated = aMemAllocated + HP_EXT_SCAN_BUFF;
+ }
+ aBytesRead += snprintf(aUriBuf + aBytesRead, MAX_URI_LEN,"%s;", aTempUri);
+ }
+ }
+ if( aMdlStr != NULL )
+ avahi_free( (void *)aMdlStr );
+ break;
+ }
+ }
+ //avahi_service_resolver_free(r);
+}
+/* Called whenever a new services becomes available on the LAN or is removed from the LAN */
+static void browse_callback(
+ AvahiServiceBrowser *b,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiBrowserEvent event,
+ const char *name,
+ const char *type,
+ const char *domain,
+ AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
+ void* userdata) {
+
+ AvahiClient *c = (AvahiClient *)userdata;
+ assert(b);
+ switch (event) {
+
+ case AVAHI_BROWSER_CACHE_EXHAUSTED:
+ case AVAHI_BROWSER_REMOVE:
+ break;
+
+ case AVAHI_BROWSER_FAILURE:
+
+ BUG( "(Browser) %s\n", avahi_strerror(avahi_client_errno(avahi_service_browser_get_client(b))));
+ avahi_simple_poll_quit(aSimplePoll);
+ return;
+
+ case AVAHI_BROWSER_NEW:
+ BUG( "(Browser) NEW: service '%s' of type '%s' in domain '%s'\n", name, type, domain);
+
+ /* We ignore the returned resolver object. In the callback
+ function we free it. If the server is terminated before
+ the callback function is called the server will free
+ the resolver for us. */
+
+ if (!(avahi_service_resolver_new(c, interface, protocol, name, type, domain, AVAHI_PROTO_INET, (AvahiLookupFlags)0, resolve_callback, c)))
+ BUG( "Failed to resolve service '%s': %s\n", name, avahi_strerror(avahi_client_errno(c)));
+
+ break;
+
+ case AVAHI_BROWSER_ALL_FOR_NOW:
+ avahi_simple_poll_quit(aSimplePoll);
+ break;
+ }
+}
+/* Called whenever the client or server state changes */
+static void client_callback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UNUSED void * userdata) {
+ assert(c);
+ if (state == AVAHI_CLIENT_FAILURE) {
+ BUG( "Server connection failure: %s\n", avahi_strerror(avahi_client_errno(c)));
+ avahi_simple_poll_quit(aSimplePoll);
+ }
+}
+/*
+This function will gets called whenever a host name has been resolved successfully or timed out
+*/
+static void host_name_resolver_callback(
+ AvahiHostNameResolver *r,
+ AVAHI_GCC_UNUSED AvahiIfIndex interface,
+ AVAHI_GCC_UNUSED AvahiProtocol protocol,
+ AvahiResolverEvent event,
+ const char *name,
+ const AvahiAddress *a,
+ AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
+ AVAHI_GCC_UNUSED void *userdata) {
+
+ assert(r);
+
+ switch (event) {
+ case AVAHI_RESOLVER_FOUND: {
+ avahi_address_snprint(ipAddressBuff, sizeof(ipAddressBuff), a);
+ DBG("%s\t%s\n", name, ipAddressBuff);
+ avahi_simple_poll_quit(aSimplePoll);
+ break;
+ }
+ case AVAHI_RESOLVER_FAILURE:
+ BUG( "Failed to resolve host name '%s'\n", name);
+ avahi_simple_poll_quit(aSimplePoll);
+ break;
+ }
+ avahi_host_name_resolver_free(r);
+}
+/*
+This function will register the callbacks for the avahi calls.
+Parameters:
+ iCommandType - INPUT - Lookup / Probe scanner.
+ iHostName - INPUT - Host name of the scanner.
+Note:
+ iHostName will be empty for command type AVAHI_NET_DISCOVERY
+*/
+static void avahi_setup(const int iCommandType, const char* iHostName)
+{
+
+ AvahiClient *client = NULL;
+ AvahiServiceBrowser *sb = NULL;
+ int error = 0;
+ if (!(aSimplePoll = avahi_simple_poll_new()))
+ {
+ BUG( "Failed to create simple poll object.\n");
+ goto fail;
+ }
+
+ if (!(client = avahi_client_new(avahi_simple_poll_get(aSimplePoll), AVAHI_CLIENT_IGNORE_USER_CONFIG, client_callback, NULL, &error)))
+ {
+ //if Daemon connection failed or daemon not running,
+ //call systemctl for authorization once it authorized start the service
+ if ( ( ( error == AVAHI_ERR_NO_DAEMON ) || (error == AVAHI_ERR_DISCONNECTED) )
+ && checkAuthorizationForAvahiService() && systemdStartAvahiService() )
+ {
+ if (!(client = avahi_client_new(avahi_simple_poll_get(aSimplePoll), AVAHI_CLIENT_IGNORE_USER_CONFIG, client_callback, NULL, &error)))
+ {
+ BUG( "Failed to create client object: %s\n", avahi_strerror(error));
+ goto fail;
+ }
+ }
+ else
+ {
+ BUG( "Failed to create client object: %s\n", avahi_strerror(error));
+ goto fail;
+ }
+ }
+
+ if ( iCommandType == AVAHI_NET_DISCOVERY ) /* Probe network scanner */
+ {
+ /* Create the service browser */
+ if (!(sb = avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_INET, "_uscan._tcp", NULL, (AvahiLookupFlags)0, browse_callback, client)))
+ {
+ //if Daemon connection failed or daemon not running,
+ //call systemctl for authorization once it authorized start the service
+ if ( ( ( error == AVAHI_ERR_NO_DAEMON ) || (error == AVAHI_ERR_DISCONNECTED) )
+ && checkAuthorizationForAvahiService() && systemdStartAvahiService() )
+ {
+ if (!(sb = avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_INET, "_uscan._tcp", NULL, (AvahiLookupFlags)0, browse_callback, client)))
+ {
+ BUG( "Failed to create service browser: %s\n", avahi_strerror(avahi_client_errno(client)));
+ goto fail;
+ }
+ }
+ else
+ {
+ BUG( "Failed to create service browser: %s\n", avahi_strerror(avahi_client_errno(client)));
+ goto fail;
+ }
+ }
+
+ /* Create the service browser */
+ if (!(sb = avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_INET, "_scanner._tcp", NULL, (AvahiLookupFlags)0, browse_callback, client)))
+ {
+ BUG( "Failed to create service browser: %s\n", avahi_strerror(avahi_client_errno(client)));
+ goto fail;
+ }
+ }
+ else if ( iCommandType == AVAHI_HOST_LOOKUP ) /* Find the IP (IPV4) address of given host name */
+ {
+ if ( !(avahi_host_name_resolver_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, iHostName, AVAHI_PROTO_INET, (AvahiLookupFlags)0,
+ host_name_resolver_callback, NULL) ) )
+ {
+ BUG( "Failed to create host name resolver: %s\n", avahi_strerror(avahi_client_errno(client)));
+ goto fail;
+ }
+ }
+ avahi_simple_poll_loop(aSimplePoll);
+fail:
+ if (client)
+ avahi_client_free(client);
+ if (aSimplePoll)
+ avahi_simple_poll_free(aSimplePoll);
+}
+/*
+This function will return URIs of the scanner found in
+the network.
+Parameters:
+ oUrisBuf - OUTPUT - Buffer to hold URIs of Scanner
+ iBufsize - INPUT - Size of output buffer.
+Note:
+ URIs will be splited useing ';' delimiter
+*/
+int avahi_probe_nw_scanners()
+{
+ int aRet = AVAHI_STATUS_ERROR;
+ avahi_setup(AVAHI_NET_DISCOVERY,"");
+ //size_t aStrLen = strlen(aUriBuf);
+ if(aBytesRead > 0)
+ {
+ aRet = AVAHI_STATUS_OK;
+ }
+ return aRet;
+}
+/*
+This function will return the IP address of given hostname
+Parameters:
+ iHostName - INPUT - Hostname of the scanner
+ oIP - OUTPUT - IP Address of given host name
+Note:
+ Output IP address will be in IPV4 format
+*/
+int avahi_lookup(const char *iHostName)
+{
+ int aRet = AVAHI_STATUS_ERROR;
+ char aUpdatedHostname[MAX_NAME_LENGTH] = {0};
+ int aHostNameLen = strlen(iHostName);
+ size_t aStrLen = 0;
+ //DNS host name size is 256 inclusive of '.local'
+ //So the incoming host name length should be less than or equal to 250
+ if ( aHostNameLen <= ( MAX_NAME_LENGTH - APPEND_LOCAL_LEN ) )
+ {
+ //Host name should be appended with .local
+ snprintf(aUpdatedHostname,MAX_NAME_LENGTH,"%s.local", iHostName);
+ avahi_setup(AVAHI_HOST_LOOKUP,aUpdatedHostname);
+ aStrLen = strlen(ipAddressBuff);
+ if ( (aStrLen <= MAX_IP_ADDR_LEN) && (aStrLen > 0) )
+ {
+ //strncpy(oIP,ipAddressBuff,aStrLen);
+ DBG("IP address is %s \n",ipAddressBuff);
+ aRet = AVAHI_STATUS_OK;
+ }
+ }
+ return aRet;
+}
diff --git a/protocol/discovery/avahiDiscovery.h b/protocol/discovery/avahiDiscovery.h
new file mode 100644
index 000000000..2bc3ce292
--- /dev/null
+++ b/protocol/discovery/avahiDiscovery.h
@@ -0,0 +1,88 @@
+#ifndef _DISCOVERY_AVAHI_H
+#define _DISCOVERY_AVAHI_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdbool.h>
+#include <syslog.h>
+#include <stdarg.h>
+
+#include <avahi-client/client.h>
+#include <avahi-client/lookup.h>
+#include <avahi-common/simple-watch.h>
+#include <avahi-common/malloc.h>
+#include <avahi-common/error.h>
+
+#ifndef DBUS_TIMEOUT_INFINITE
+#define DBUS_TIMEOUT_INFINITE ((int) 0x7fffffff)
+#endif
+
+#define NULL_CHAR_SIZE 1
+#define HP_PLAIN_URI_LEN 24
+#define HP_SKIP_MFG_NAME_SIZE 3
+#define MFG_HP "HP"
+#define MFG_HP_LEN 2
+#define MFG_NAME "usb_MFG"
+#define MDL_NAME "mdl"
+#define TYPE_NAME "ty"
+#define HPMUD_LINE_SIZE 256
+#define MAX_URI_LEN 512
+#define HP_MAX_SCAN_BUFF 16384
+#define HP_EXT_SCAN_BUFF 8192
+#define MAX_NAME_LENGTH 256
+#define AVAHI_NET_DISCOVERY 1
+#define AVAHI_HOST_LOOKUP 2
+#define MAX_IP_ADDR_LEN 16
+#define APPEND_LOCAL_LEN 6
+
+//Error Codes
+#define AVAHI_STATUS_OK 0
+#define AVAHI_STATUS_ERROR 1
+#define AVAHI_STATUS_TIMEOUT 2
+#define SYSTEMD_SERVICE_TIMEOUT 10000
+
+#define POLKIT_AUTH_DBUS "org.freedesktop.PolicyKit1"
+#define POLKIT_AUTH_INTF "org.freedesktop.PolicyKit1.Authority"
+#define POLKIT_AUTH_PATH "/org/freedesktop/PolicyKit1/Authority"
+#define POLKIT_AUTH_METHOD_CALL "CheckAuthorization"
+
+#define ACTION_ID "org.freedesktop.systemd1.manage-units"
+#define SYSTEM_BUS_NAME "system-bus-name"
+#define AVAHI_SERVICE_NAME "avahi-daemon.service"
+#define AVHHI_SERVICE_MODE_REPLACE "replace"
+
+#define SYSTEMD_DBUS_NAME "org.freedesktop.systemd1"
+#define SYSTEMD_DBUS_PATH "/org/freedesktop/systemd1"
+#define SYSTEMD_DBUS_INTF "org.freedesktop.systemd1.Manager"
+#define SYSTEMD_START_SERVICE_METHOD "StartUnit"
+
+extern char* aUriBuf;
+extern char ipAddressBuff[MAX_IP_ADDR_LEN];
+
+//#define MDNS_DEBUG
+
+#define _STRINGIZE(x) #x
+#define STRINGIZE(x) _STRINGIZE(x)
+
+#define BUG(args...) syslog(LOG_ERR, __FILE__ " " STRINGIZE(__LINE__) ": " args)
+#ifdef AVAHI_DEBUG
+ #define DBG(args...) syslog(LOG_INFO, __FILE__ " " STRINGIZE(__LINE__) ": " args)
+#else
+ #define DBG(args...)
+#endif
+
+/*Function Prototypes*/
+
+int avahi_probe_nw_scanners();
+int avahi_lookup(const char* hostname);
+
+#endif // _DISCOVERY_AVAHI_H
+
diff --git a/protocol/discovery/mdns.c b/protocol/discovery/mdns.c
deleted file mode 100644
index abca295af..000000000
--- a/protocol/discovery/mdns.c
+++ /dev/null
@@ -1,496 +0,0 @@
-/*****************************************************************************
- mdns.c - mDNS related calls
-
- (c) 2015 Copyright HP Development Company, LP
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- of the Software, and to permit persons to whom the Software is furnished to do
- so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- Client/Server generic message format (see messaging-protocol.doc):
-
- Author: Sanjay Kumar
- \*****************************************************************************/
-
-//#include <stdio.h>
-#include <string.h>
-#include <syslog.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <arpa/inet.h>
-#include "mdns.h"
-
-/* Convert "www.google.com" to "3www6google3com". */
-static int mdns_convert_name_to_dns(const char *name, int name_size, char *dns_name)
-{
- int i, x = 0;
- char *p = dns_name;
-
- if (name == 0 || name[0] == 0)
- return 0;
-
- for (i = 0; i < name_size && name[i]; i++)
- {
- if (name[i] == '.')
- {
- *p++ = i - x; /* length */
- for (; x < i; x++)
- *p++ = name[x];
- x++;
- }
- }
-
- if (i)
- {
- *p++ = i - x; /* length */
- for (; x < i; x++)
- *p++ = name[x];
- x++;
- }
-
- p[x++] = 0;
-
- return x; /* return length DOES include null termination */
-}
-
-
-static int mdns_open_socket(int *psocket)
-{
- int stat = MDNS_STATUS_ERROR;
- int udp_socket = -1, yes = 1;
- char loop = 0, ttl = 255;
- struct sockaddr_in recv_addr , addr;
- struct ip_mreq mreq;
-
- DBG("mdns_open_socket entry.\n");
-
- if ((udp_socket = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
- {
- BUG("unable to create udp socket: %m\n");
- goto bugout;
- }
-
- /* Get rid of "address already in use" error message. */
- if (setsockopt(udp_socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1)
- {
- BUG("unable to setsockopt: %m\n");
- goto bugout;
- }
-
- /* Bind the socket to port and IP equal to INADDR_ANY. */
- bzero(&recv_addr, sizeof(recv_addr));
- recv_addr.sin_family = AF_INET;
- recv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- recv_addr.sin_port = htons(5353);
- if (bind(udp_socket, (struct sockaddr *) &recv_addr, sizeof(recv_addr)) == -1)
- {
- BUG("unable to bind udp socket: %m\n");
- goto bugout;
- }
-
- /* Set multicast loopback off. */
- if (setsockopt(udp_socket, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) == -1)
- {
- BUG("unable to setsockopt: %m\n");
- goto bugout;
- }
-
- /* Set ttl to 255. Required by mdns. */
- if (setsockopt(udp_socket, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl))== -1)
- {
- BUG("unable to setsockopt: %m\n");
- goto bugout;
- }
-
- /* Join the .local multicast group */
- mreq.imr_multiaddr.s_addr = inet_addr("224.0.0.251");
- mreq.imr_interface.s_addr = htonl(INADDR_ANY);
- if (setsockopt(udp_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(struct ip_mreq)) == -1) {
- BUG("unable to add to multicast group: %m\n");
- close(udp_socket);
- goto bugout;
- }
-
- *psocket = udp_socket;
- DBG("pSocket = [%d]: %m\n", *psocket);
- stat = MDNS_STATUS_OK;
-
-bugout:
- return stat;
-}
-
-static void mdns_create_query_packet(char* fqdn, int query_type, char* querybuf, int *length)
-{
- int n = 0;
- char header[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- // ID/FLAGS/QDCNT/ANCNT/NSCNT/ARCNT
-
- DBG("mdns_create_query_packet.\n");
- memcpy(querybuf, header, sizeof(header));
- n = sizeof(header);
-
- n += mdns_convert_name_to_dns(fqdn, strlen(fqdn), querybuf + n);
- querybuf[n++] = 0x00;
- querybuf[n++] = query_type;
- querybuf[n++] = 0x00;
- querybuf[n++] = QCLASS_IN;
-
- //DBG_DUMP(dnsquery, n);
- *length = n;
-}
-
-static int mdns_send_query(int udp_socket, char *fqdn, int query_type)
-{
- char querybuf[256] = {0,};
- int length = 0;
- int stat = MDNS_STATUS_OK;
- struct sockaddr_in send_addr;
-
- DBG("mdns_send_query entry. send socket=%d len=%d\n", udp_socket, length);
-
- mdns_create_query_packet(fqdn, query_type, querybuf, &length);
-
- bzero(&send_addr, sizeof(send_addr));
- send_addr.sin_family = AF_INET;
- send_addr.sin_addr.s_addr = inet_addr("224.0.0.251");
- send_addr.sin_port = htons(5353);
- if (sendto(udp_socket, querybuf, length, 0, (struct sockaddr *) &send_addr, sizeof(send_addr)) < 0)
- stat = MDNS_STATUS_ERROR;
-
- DBG("mdns_send_query returning with status(%d)...\n", stat);
- return stat;
-}
-
-static int mdns_readName(unsigned char* start, unsigned char *Response, char *buf)
-{
- int size = 0;
- char *name = buf;
- unsigned char *p = Response;
-
- while (size = *p++)
- {
- if (size >= 0xC0)
- {
- //Compressed Size. Just ignore it.
- p++; //skip Offset byte
- return (p - Response);
- }
- memcpy(name, p, size);
- name[size] = '.';
- p += size;
- name += size + 1;
- }
-
- *(name - 1) = '\0';
-
- DBG("Name = [%s]\n", buf);
- return (p - Response);
-}
-
-
-static unsigned char* mdns_readMDL(unsigned char *p, unsigned char *normalized_mdl, int len)
-{
- int i = 0;
- int j = 0;
- int z = 0;
- int size = 0;
-
- unsigned char* mdl = normalized_mdl;
- while (i < len)
- {
- size = *p++;
- i += size + 1;
-
- if (strncmp(p, "mdl=", 4) == 0)
- {
- z = 4;
- }
- else if (strncmp(p, "ty=", 3) == 0)
- {
- z = 3+3;
- }
-
- if(z > 0)
- {
- for (j = z; j < size; j++)
- {
- if (*(p + j) == ' ')
- *mdl++ = '_'; //Replace white space with underscore
- else
- *mdl++ = tolower(*(p + j));
- }
-
- *mdl++ = '\0';
- break;
- }
- p += size;
-
- }
- DBG("MDL = [%s]\n", normalized_mdl);
- return p + 4;
-}
-
-static void mdns_read_header(char *Response, DNS_PKT_HEADER *h)
-{
- h->id = Response[0] << 8 | Response[1];
- h->flags = Response[2] << 8 | Response[3];
- h->questions = Response[4] << 8 | Response[5];
- h->answers = Response[6] << 8 | Response[7];
- h->authorities = Response[8] << 8 | Response[9];
- h->additionals = Response[10]<< 8 | Response[11];
-
- DBG("ID=%x flags=%x Q=%x A=%x AUTH=%x ADD=%x\n", h->id, h->flags, h->questions,
- h->answers, h->authorities, h->additionals);
-
-}
-
-static void mdns_parse_respponse(unsigned char *Response, DNS_RECORD *rr)
-{
- unsigned char *p = Response;
- unsigned short type = 0, data_len = 0;
- DNS_PKT_HEADER h;
- int i = 0;
-
- DBG("mdns_parse_respponse entry.\n");
- mdns_read_header(Response, &h);
- p += MDNS_HEADER_SIZE;
-
- for (i = 0; i < h.questions; i++)
- {
- p += mdns_readName(Response, p, rr->name);
- p += 4; //Skip TYPE(2 bytes)/CLASS(2 bytes)
- }
-
- for (i = 0; i < (h.answers + h.additionals); i++)
- {
- p += mdns_readName(Response, p, rr->name);
- type = (*p << 8 | *(p+1));
- p += 8; //Skip type(2 bytes)/class(2 bytes)/TTL(4 bytes)
-
- data_len = ( *p << 8 | *(p+1));
- p += 2; //Skip data_len(2 bytes)
-
- switch (type)
- {
- case QTYPE_A:
- sprintf(rr->ip, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
- break;
- case QTYPE_TXT:
- mdns_readMDL(p, rr->mdl, data_len);
- break;
- default:
- break;
- }
-
- p += data_len;
- //DBG("TYPE = %d, Length = %d\n",type, data_len);
- }
-
- DBG("mdns_parse_respponse returning MDL = %s, IP = %s\n",rr->mdl, rr->ip);
-}
-
-static int mdns_read_single_response(int udp_socket, char *recvbuffer, int recvbufsize)
-{
- struct timeval tmo;
- struct sockaddr_in addr;
- socklen_t addrlen = sizeof(addr);
- fd_set master, readfd;
- int len = 0, maxfd = 0, ret = 0;
-
- DBG("mdns_read_single_response.\n");
- FD_ZERO(&master);
- FD_SET(udp_socket, &master);
- maxfd = udp_socket;
- tmo.tv_sec = 0;
- tmo.tv_usec = 300000;
-
- readfd = master;
- ret = select(maxfd + 1, &readfd, NULL, NULL, &tmo);
- if (ret > 0)
- {
- bzero(&addr, sizeof(addr));
- if ((len = recvfrom(udp_socket, recvbuffer, recvbufsize, 0, (struct sockaddr *) &addr, &addrlen)) < 0)
- {
- BUG("recvfrom error: (%m)\n");
- ret = -1;
- }
- }
-
- DBG("mdns_read_single_response exiting with ret = %d\n", ret);
- return ret;
-}
-
-static DNS_RECORD *mdns_read_responses(int udp_socket, int mode)
-{
- int retries = 3, ret = 0;
- char recvbuffer[MAX_MDNS_RESPONSE_LEN] = { 0, };
- DNS_RECORD *rr = NULL, *head = NULL, *temp = NULL;
-
- DBG("mdns_read_responses.\n");
- while (1 )
- {
- memset(recvbuffer, 0, sizeof(recvbuffer));
- ret = mdns_read_single_response(udp_socket, recvbuffer, sizeof(recvbuffer));
- if (ret <= 0)
- {
- if (ret == 0 && retries--) //READ TIMEOUT. Retry few more times.
- continue;
- else
- break;
- }
- else
- {
- temp = (DNS_RECORD *)malloc(sizeof(DNS_RECORD));
- if(temp)
- {
- temp->next = NULL;
- if(head == NULL)
- rr = head = temp;
- else
- {
- rr->next = temp;
- rr = rr->next;
- }
-
- memset(rr, 0, sizeof(DNS_RECORD));
- mdns_parse_respponse(recvbuffer, rr);
-
- if(mode == MODE_READ_SINGLE)
- break;
- }
- }
- } // while(1)
-
- DBG("mdns_read_responses returning with (%p).\n", head);
- return head;
-}
-
-static int mdns_update_uris(DNS_RECORD *rr, char* uris_buf, int buf_size, int *count)
-{
- char tempuri[MAX_URI_LEN] = {0};
- int bytes_read = 0;
-
- DBG("mdns_update_uris.\n");
-
- *count = 0;
- memset(uris_buf, 0, buf_size);
-
- while(rr)
- {
- if (rr->mdl[0] && rr->ip[0] /*&& strstr(rr->mdl, "scanjet")*/)
- {
- memset(tempuri, 0, sizeof(tempuri));
- sprintf(tempuri, "hp:/net/%s?ip=%s&queue=false", rr->mdl, rr->ip);
-
- //Check whether buffer has enough space to add new URI and check for duplicate URIs.
- if(bytes_read + sizeof(tempuri) < buf_size && !strstr(uris_buf, tempuri))
- {
- bytes_read += sprintf(uris_buf + bytes_read, "%s;", tempuri);
- (*count)++;
- *(uris_buf + bytes_read) = '\0';
- }
- }
- rr = rr->next;
- }
-
- DBG("mdns_update_uris Count=[%d] bytes=[%d] URIs = %s\n",*count, bytes_read, uris_buf);
- return bytes_read;
-}
-
-static void mdns_rr_cleanup(DNS_RECORD *rr)
-{
- DNS_RECORD *temp = NULL;
-
- DBG("mdns_rr_cleanup entry.\n");
- while(rr)
- {
- temp = rr->next;
- free(rr);
- rr = temp;
- }
-}
-
-int mdns_probe_nw_scanners(char* uris_buf, int buf_size, int *count)
-{
- int n = 0, bytes_read = 0;
- int udp_socket = 0;
- int stat = MDNS_STATUS_ERROR;
- DNS_RECORD *rr_list = NULL;
-
- DBG("mdns_probe_nw_scanners entry.\n");
- /* Open UDP socket */
- if (mdns_open_socket(&udp_socket) != MDNS_STATUS_OK)
- goto bugout;
-
- /* Send dns query */
- mdns_send_query(udp_socket, "_scanner._tcp.local", QTYPE_PTR);
- mdns_send_query(udp_socket, "_uscan._tcp.local", QTYPE_PTR);
-
- /* Read Responses */
- rr_list = mdns_read_responses(udp_socket, MODE_READ_ALL);
-
- /* Update URIs buffer */
- bytes_read = mdns_update_uris(rr_list, uris_buf, buf_size, count);
- DBG("mdns_probe_nw_scanners returned with bytes_read = [%d].\n",bytes_read);
-
-bugout:
- if (udp_socket >= 0)
- close(udp_socket);
-
- mdns_rr_cleanup(rr_list);
-
- return bytes_read;
-}
-
-/*
- * Lookup IP for MDNS host name.
- * MDNS host name example: "npi7c8a3e" (LaserJet p2055dn)
- */
-int mdns_lookup(char* hostname, unsigned char* ip)
-{
- int udp_socket = 0;
- int stat = MDNS_STATUS_ERROR;
- char fqdn[MAX_NAME_LENGTH] = {0};
- DNS_RECORD *rr_list = NULL;
-
- DBG("mdns_probe_nw_scanners entry.\n");
- /* Open UDP socket */
- if (mdns_open_socket(&udp_socket) != MDNS_STATUS_OK)
- goto bugout;
-
- /* Send dns query */
- sprintf(fqdn, "%s.local", hostname);
- mdns_send_query(udp_socket, fqdn, QTYPE_A);
-
- /* Read Responses */
- rr_list = mdns_read_responses(udp_socket, MODE_READ_SINGLE);
-
- /* Update IP Address buffer */
- if(rr_list)
- {
- strcpy(ip, rr_list->ip);
- stat = MDNS_STATUS_OK;
- DBG("IP = [%s].\n",ip);
- }
-
-bugout:
- if (udp_socket >= 0)
- close(udp_socket);
-
- mdns_rr_cleanup(rr_list);
- return stat;
-}
-
diff --git a/protocol/discovery/mdns.h b/protocol/discovery/mdns.h
deleted file mode 100644
index 8fccc82e2..000000000
--- a/protocol/discovery/mdns.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*****************************************************************************\
-
- mdns.h - mDNS related calls
-
- (c) 2015 Copyright HP Development Company, LP
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- of the Software, and to permit persons to whom the Software is furnished to do
- so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- Client/Server generic message format (see messaging-protocol.doc):
-
- Author: Sanjay Kumar
-\*****************************************************************************/
-
-#ifndef _DISCOVERY_MDNS_H
-#define _DISCOVERY_MDNS_H
-
-//MDNS Packet fields
-#define QTYPE_A 1
-#define QTYPE_TXT 16
-#define QTYPE_SRV 33
-#define QTYPE_AAAA 28
-#define QTYPE_PTR 12
-#define QCLASS_IN 1
-#define MDNS_HEADER_SIZE 12
-
-//Error Codes
-#define MDNS_STATUS_OK 0
-#define MDNS_STATUS_ERROR 1
-#define MDNS_STATUS_TIMEOUT 2
-
-#define MAX_IP_ADDR_LEN 16
-#define MAX_URI_LEN 256
-#define MAX_MDL_NAME_LEN 256
-#define MAX_NAME_LENGTH 256
-#define MAX_MDNS_RESPONSE_LEN 2048
-#define MODE_READ_ALL 0
-#define MODE_READ_SINGLE 1
-
-/*Relevant MDNS Resource Record(RR) fields */
-typedef struct _DNS_RECORD
-{
- char ip[MAX_IP_ADDR_LEN];
- char mdl[MAX_MDL_NAME_LEN];
- char name[MAX_MDL_NAME_LEN];
- struct _DNS_RECORD *next;
-}DNS_RECORD;
-
-typedef struct _DNS_PKT_HEADER
-{
- unsigned short id;
- unsigned short flags;
- unsigned short questions;
- unsigned short answers;
- unsigned short authorities;
- unsigned short additionals;
-}DNS_PKT_HEADER;
-
-
-//#define MDNS_DEBUG
-
-#define _STRINGIZE(x) #x
-#define STRINGIZE(x) _STRINGIZE(x)
-
-#define BUG(args...) syslog(LOG_ERR, __FILE__ " " STRINGIZE(__LINE__) ": " args)
-#ifdef MDNS_DEBUG
- #define DBG(args...) syslog(LOG_INFO, __FILE__ " " STRINGIZE(__LINE__) ": " args)
-#else
- #define DBG(args...)
-#endif
-
-/*Function Prototypes*/
-int mdns_probe_nw_scanners(char* buf, int buf_size, int *count);
-int mdns_lookup(char* hostname, unsigned char* ip);
-
-
-/*Helper Function Prototypes*/
-static int mdns_convert_name_to_dns(const char *name, int name_size, char *dns_name);
-static int mdns_read_single_response(int udp_socket, char *recvbuffer, int recvbufsize);
-static int mdns_open_socket(int *psocket);
-static int mdns_send_query(int udp_socket, char *fqdn, int query_type);
-static int mdns_readName(unsigned char* start, unsigned char *p, char *buf);
-static int mdns_update_uris(DNS_RECORD *rr, char* uris_buf, int buf_size, int *count);
-static void mdns_create_query_packet(char* fqdn, int query_type, char* dnsquery, int *length);
-static void mdns_read_header(char *Response, DNS_PKT_HEADER *h);
-static void mdns_parse_respponse(unsigned char *Response, DNS_RECORD *rr);
-static void mdns_rr_cleanup(DNS_RECORD *rr);
-static DNS_RECORD *mdns_read_responses(int udp_socket, int mode);
-static unsigned char* mdns_readMDL(unsigned char *p, unsigned char *normalized_mdl, int len);
-#endif // _DISCOVERY_MDNS_H
-
diff --git a/protocol/hp_ipp.c b/protocol/hp_ipp.c
index 24b6b5544..af7013bf7 100644
--- a/protocol/hp_ipp.c
+++ b/protocol/hp_ipp.c
@@ -586,9 +586,9 @@ void initializeIPPRequest(ipp_t *request)
/*
* 'createDeviceStatusRequest()' - Create IPP request and update the same with values needed for getting device status attributes.
*/
-ipp_t * createDeviceStatusRequest()
+ipp_t * createDeviceStatusRequest(const char *printer_name)
{
-
+ char uri[ HTTP_MAX_URI ] = {0};
ipp_t *request = NULL; /* IPP request object */
static const char * attrs[] = /* Requested attributes */
{
@@ -605,7 +605,8 @@ ipp_t * createDeviceStatusRequest()
initializeIPPRequest(request);
if (request)
{
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, "");
+ snprintf(uri, HTTP_MAX_URI, "ipp://localhost/printers/%s", printer_name);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
ippAddStrings( request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", sizeof( attrs ) / sizeof( attrs[ 0 ] ), NULL, attrs );
}
@@ -693,7 +694,7 @@ HPIPP_RESULT parseResponseHeader(char *header, int *content_length, int *chunked
* marker-names, marker-types, marker-levels, marker-low-levels, printer-state, printer-state-reasons.
* In addition to this it also updates the attribute count in the response.
*/
-ipp_t * getDeviceStatusAttributes(char* device_uri, int *count)
+ipp_t * getDeviceStatusAttributes(char* device_uri,char* printer_name, int *count)
{
ipp_t *request = NULL; /* IPP request object */
ipp_t *response = NULL; /* IPP response object */
@@ -701,7 +702,7 @@ ipp_t * getDeviceStatusAttributes(char* device_uri, int *count)
int max_count = 0;
//Create Device Status Request
- request = createDeviceStatusRequest();
+ request = createDeviceStatusRequest(printer_name);
if (request == NULL)
goto abort;
diff --git a/protocol/hp_ipp.h b/protocol/hp_ipp.h
index 3853f8432..245e798ad 100644
--- a/protocol/hp_ipp.h
+++ b/protocol/hp_ipp.h
@@ -157,10 +157,10 @@ static ssize_t raw_ipp_request_callback(volatile raw_ipp *raw_buffer, ipp_uchar
void initializeIPPRequest(ipp_t *request);
int parsePrinterAttributes(ipp_t *response, printer_t * printer_list, int size);
-ipp_t * createDeviceStatusRequest();
+ipp_t * createDeviceStatusRequest(const char* printer_name);
ipp_t * usbDoRequest(ipp_t *request, char* device_uri);
ipp_t * networkDoRequest(ipp_t *request, char* device_uri);
-ipp_t * getDeviceStatusAttributes(char* device_uri, int *count);
+ipp_t * getDeviceStatusAttributes(char* device_uri,char* printer_name, int *count);
int getCupsPrinters(printer_t **printer_list);
HPIPP_RESULT parseResponseHeader(char* header, int *content_length, int *chunked, int* header_size);