xref: /aosp_15_r20/external/libcups/backend/snmp.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker  * SNMP discovery backend for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker  *
4*5e7646d2SAndroid Build Coastguard Worker  * Copyright © 2007-2014 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker  * Copyright © 2006-2007 by Easy Software Products, all rights reserved.
6*5e7646d2SAndroid Build Coastguard Worker  *
7*5e7646d2SAndroid Build Coastguard Worker  * Licensed under Apache License v2.0.  See the file "LICENSE" for more
8*5e7646d2SAndroid Build Coastguard Worker  * information.
9*5e7646d2SAndroid Build Coastguard Worker  */
10*5e7646d2SAndroid Build Coastguard Worker 
11*5e7646d2SAndroid Build Coastguard Worker /*
12*5e7646d2SAndroid Build Coastguard Worker  * Include necessary headers.
13*5e7646d2SAndroid Build Coastguard Worker  */
14*5e7646d2SAndroid Build Coastguard Worker 
15*5e7646d2SAndroid Build Coastguard Worker #include "backend-private.h"
16*5e7646d2SAndroid Build Coastguard Worker #include <cups/array.h>
17*5e7646d2SAndroid Build Coastguard Worker #include <cups/file.h>
18*5e7646d2SAndroid Build Coastguard Worker #include <cups/http-private.h>
19*5e7646d2SAndroid Build Coastguard Worker #include <regex.h>
20*5e7646d2SAndroid Build Coastguard Worker 
21*5e7646d2SAndroid Build Coastguard Worker 
22*5e7646d2SAndroid Build Coastguard Worker /*
23*5e7646d2SAndroid Build Coastguard Worker  * This backend implements SNMP printer discovery.  It uses a broadcast-
24*5e7646d2SAndroid Build Coastguard Worker  * based approach to get SNMP response packets from potential printers,
25*5e7646d2SAndroid Build Coastguard Worker  * requesting OIDs from the Host and Port Monitor MIBs, does a URI
26*5e7646d2SAndroid Build Coastguard Worker  * lookup based on the device description string, and finally a probe of
27*5e7646d2SAndroid Build Coastguard Worker  * port 9100 (AppSocket) and 515 (LPD).
28*5e7646d2SAndroid Build Coastguard Worker  *
29*5e7646d2SAndroid Build Coastguard Worker  * The current focus is on printers with internal network cards, although
30*5e7646d2SAndroid Build Coastguard Worker  * the code also works with many external print servers as well.
31*5e7646d2SAndroid Build Coastguard Worker  *
32*5e7646d2SAndroid Build Coastguard Worker  * The backend reads the snmp.conf file from the CUPS_SERVERROOT directory
33*5e7646d2SAndroid Build Coastguard Worker  * which can contain comments, blank lines, or any number of the following
34*5e7646d2SAndroid Build Coastguard Worker  * directives:
35*5e7646d2SAndroid Build Coastguard Worker  *
36*5e7646d2SAndroid Build Coastguard Worker  *     Address ip-address
37*5e7646d2SAndroid Build Coastguard Worker  *     Address @LOCAL
38*5e7646d2SAndroid Build Coastguard Worker  *     Address @IF(name)
39*5e7646d2SAndroid Build Coastguard Worker  *     Community name
40*5e7646d2SAndroid Build Coastguard Worker  *     DebugLevel N
41*5e7646d2SAndroid Build Coastguard Worker  *     DeviceURI "regex pattern" uri
42*5e7646d2SAndroid Build Coastguard Worker  *     HostNameLookups on
43*5e7646d2SAndroid Build Coastguard Worker  *     HostNameLookups off
44*5e7646d2SAndroid Build Coastguard Worker  *     MaxRunTime N
45*5e7646d2SAndroid Build Coastguard Worker  *
46*5e7646d2SAndroid Build Coastguard Worker  * The default is to use:
47*5e7646d2SAndroid Build Coastguard Worker  *
48*5e7646d2SAndroid Build Coastguard Worker  *     Address @LOCAL
49*5e7646d2SAndroid Build Coastguard Worker  *     Community public
50*5e7646d2SAndroid Build Coastguard Worker  *     DebugLevel 0
51*5e7646d2SAndroid Build Coastguard Worker  *     HostNameLookups off
52*5e7646d2SAndroid Build Coastguard Worker  *     MaxRunTime 120
53*5e7646d2SAndroid Build Coastguard Worker  *
54*5e7646d2SAndroid Build Coastguard Worker  * This backend is known to work with the following network printers and
55*5e7646d2SAndroid Build Coastguard Worker  * print servers:
56*5e7646d2SAndroid Build Coastguard Worker  *
57*5e7646d2SAndroid Build Coastguard Worker  *     Axis OfficeBasic, 5400, 5600
58*5e7646d2SAndroid Build Coastguard Worker  *     Brother
59*5e7646d2SAndroid Build Coastguard Worker  *     EPSON
60*5e7646d2SAndroid Build Coastguard Worker  *     Genicom
61*5e7646d2SAndroid Build Coastguard Worker  *     HP JetDirect
62*5e7646d2SAndroid Build Coastguard Worker  *     Lexmark
63*5e7646d2SAndroid Build Coastguard Worker  *     Sharp
64*5e7646d2SAndroid Build Coastguard Worker  *     Tektronix
65*5e7646d2SAndroid Build Coastguard Worker  *     Xerox
66*5e7646d2SAndroid Build Coastguard Worker  *
67*5e7646d2SAndroid Build Coastguard Worker  * It does not currently work with:
68*5e7646d2SAndroid Build Coastguard Worker  *
69*5e7646d2SAndroid Build Coastguard Worker  *     DLink
70*5e7646d2SAndroid Build Coastguard Worker  *     Linksys
71*5e7646d2SAndroid Build Coastguard Worker  *     Netgear
72*5e7646d2SAndroid Build Coastguard Worker  *     Okidata
73*5e7646d2SAndroid Build Coastguard Worker  *
74*5e7646d2SAndroid Build Coastguard Worker  * (for all of these, they do not support the Host MIB)
75*5e7646d2SAndroid Build Coastguard Worker  */
76*5e7646d2SAndroid Build Coastguard Worker 
77*5e7646d2SAndroid Build Coastguard Worker /*
78*5e7646d2SAndroid Build Coastguard Worker  * Types...
79*5e7646d2SAndroid Build Coastguard Worker  */
80*5e7646d2SAndroid Build Coastguard Worker 
81*5e7646d2SAndroid Build Coastguard Worker enum					/**** Request IDs for each field ****/
82*5e7646d2SAndroid Build Coastguard Worker {
83*5e7646d2SAndroid Build Coastguard Worker   DEVICE_TYPE = 1,
84*5e7646d2SAndroid Build Coastguard Worker   DEVICE_DESCRIPTION,
85*5e7646d2SAndroid Build Coastguard Worker   DEVICE_LOCATION,
86*5e7646d2SAndroid Build Coastguard Worker   DEVICE_ID,
87*5e7646d2SAndroid Build Coastguard Worker   DEVICE_URI,
88*5e7646d2SAndroid Build Coastguard Worker   DEVICE_PRODUCT
89*5e7646d2SAndroid Build Coastguard Worker };
90*5e7646d2SAndroid Build Coastguard Worker 
91*5e7646d2SAndroid Build Coastguard Worker typedef struct device_uri_s		/**** DeviceURI values ****/
92*5e7646d2SAndroid Build Coastguard Worker {
93*5e7646d2SAndroid Build Coastguard Worker   regex_t	re;			/* Regular expression to match */
94*5e7646d2SAndroid Build Coastguard Worker   cups_array_t	*uris;			/* URIs */
95*5e7646d2SAndroid Build Coastguard Worker } device_uri_t;
96*5e7646d2SAndroid Build Coastguard Worker 
97*5e7646d2SAndroid Build Coastguard Worker typedef struct snmp_cache_s		/**** SNMP scan cache ****/
98*5e7646d2SAndroid Build Coastguard Worker {
99*5e7646d2SAndroid Build Coastguard Worker   http_addr_t	address;		/* Address of device */
100*5e7646d2SAndroid Build Coastguard Worker   char		*addrname,		/* Name of device */
101*5e7646d2SAndroid Build Coastguard Worker 		*uri,			/* device-uri */
102*5e7646d2SAndroid Build Coastguard Worker 		*id,			/* device-id */
103*5e7646d2SAndroid Build Coastguard Worker 		*info,			/* device-info */
104*5e7646d2SAndroid Build Coastguard Worker 		*location,		/* device-location */
105*5e7646d2SAndroid Build Coastguard Worker 		*make_and_model;	/* device-make-and-model */
106*5e7646d2SAndroid Build Coastguard Worker   int		sent;			/* Has this device been listed? */
107*5e7646d2SAndroid Build Coastguard Worker } snmp_cache_t;
108*5e7646d2SAndroid Build Coastguard Worker 
109*5e7646d2SAndroid Build Coastguard Worker 
110*5e7646d2SAndroid Build Coastguard Worker /*
111*5e7646d2SAndroid Build Coastguard Worker  * Local functions...
112*5e7646d2SAndroid Build Coastguard Worker  */
113*5e7646d2SAndroid Build Coastguard Worker 
114*5e7646d2SAndroid Build Coastguard Worker static char		*add_array(cups_array_t *a, const char *s);
115*5e7646d2SAndroid Build Coastguard Worker static void		add_cache(http_addr_t *addr, const char *addrname,
116*5e7646d2SAndroid Build Coastguard Worker 			          const char *uri, const char *id,
117*5e7646d2SAndroid Build Coastguard Worker 				  const char *make_and_model);
118*5e7646d2SAndroid Build Coastguard Worker static device_uri_t	*add_device_uri(char *value);
119*5e7646d2SAndroid Build Coastguard Worker static void		alarm_handler(int sig);
120*5e7646d2SAndroid Build Coastguard Worker static int		compare_cache(snmp_cache_t *a, snmp_cache_t *b);
121*5e7646d2SAndroid Build Coastguard Worker static void		debug_printf(const char *format, ...);
122*5e7646d2SAndroid Build Coastguard Worker static void		fix_make_model(char *make_model,
123*5e7646d2SAndroid Build Coastguard Worker 			               const char *old_make_model,
124*5e7646d2SAndroid Build Coastguard Worker 				       int make_model_size);
125*5e7646d2SAndroid Build Coastguard Worker static void		free_array(cups_array_t *a);
126*5e7646d2SAndroid Build Coastguard Worker static void		free_cache(void);
127*5e7646d2SAndroid Build Coastguard Worker static http_addrlist_t	*get_interface_addresses(const char *ifname);
128*5e7646d2SAndroid Build Coastguard Worker static void		list_device(snmp_cache_t *cache);
129*5e7646d2SAndroid Build Coastguard Worker static const char	*password_cb(const char *prompt);
130*5e7646d2SAndroid Build Coastguard Worker static void		probe_device(snmp_cache_t *device);
131*5e7646d2SAndroid Build Coastguard Worker static void		read_snmp_conf(const char *address);
132*5e7646d2SAndroid Build Coastguard Worker static void		read_snmp_response(int fd);
133*5e7646d2SAndroid Build Coastguard Worker static double		run_time(void);
134*5e7646d2SAndroid Build Coastguard Worker static void		scan_devices(int ipv4, int ipv6);
135*5e7646d2SAndroid Build Coastguard Worker static int		try_connect(http_addr_t *addr, const char *addrname,
136*5e7646d2SAndroid Build Coastguard Worker 			            int port);
137*5e7646d2SAndroid Build Coastguard Worker static void		update_cache(snmp_cache_t *device, const char *uri,
138*5e7646d2SAndroid Build Coastguard Worker 			             const char *id, const char *make_model);
139*5e7646d2SAndroid Build Coastguard Worker 
140*5e7646d2SAndroid Build Coastguard Worker 
141*5e7646d2SAndroid Build Coastguard Worker /*
142*5e7646d2SAndroid Build Coastguard Worker  * Local globals...
143*5e7646d2SAndroid Build Coastguard Worker  */
144*5e7646d2SAndroid Build Coastguard Worker 
145*5e7646d2SAndroid Build Coastguard Worker static cups_array_t	*Addresses = NULL;
146*5e7646d2SAndroid Build Coastguard Worker static cups_array_t	*Communities = NULL;
147*5e7646d2SAndroid Build Coastguard Worker static cups_array_t	*Devices = NULL;
148*5e7646d2SAndroid Build Coastguard Worker static int		DebugLevel = 0;
149*5e7646d2SAndroid Build Coastguard Worker static const int	DescriptionOID[] = { CUPS_OID_hrDeviceDescr, 1, -1 };
150*5e7646d2SAndroid Build Coastguard Worker static const int	LocationOID[] = { CUPS_OID_sysLocation, 0, -1 };
151*5e7646d2SAndroid Build Coastguard Worker static const int	DeviceTypeOID[] = { CUPS_OID_hrDeviceType, 1, -1 };
152*5e7646d2SAndroid Build Coastguard Worker static const int	DeviceIdOID[] = { CUPS_OID_ppmPrinterIEEE1284DeviceId, 1, -1 };
153*5e7646d2SAndroid Build Coastguard Worker static const int	UriOID[] = { CUPS_OID_ppmPortServiceNameOrURI, 1, 1, -1 };
154*5e7646d2SAndroid Build Coastguard Worker static const int	LexmarkProductOID[] = { 1,3,6,1,4,1,641,2,1,2,1,2,1,-1 };
155*5e7646d2SAndroid Build Coastguard Worker static const int	LexmarkProductOID2[] = { 1,3,6,1,4,1,674,10898,100,2,1,2,1,2,1,-1 };
156*5e7646d2SAndroid Build Coastguard Worker static const int	LexmarkDeviceIdOID[] = { 1,3,6,1,4,1,641,2,1,2,1,3,1,-1 };
157*5e7646d2SAndroid Build Coastguard Worker static const int	HPDeviceIdOID[] = { 1,3,6,1,4,1,11,2,3,9,1,1,7,0,-1 };
158*5e7646d2SAndroid Build Coastguard Worker static const int	RicohDeviceIdOID[] = { 1,3,6,1,4,1,367,3,2,1,1,1,11,0,-1 };
159*5e7646d2SAndroid Build Coastguard Worker static const int	XeroxProductOID[] = { 1,3,6,1,4,1,128,2,1,3,1,2,0,-1 };
160*5e7646d2SAndroid Build Coastguard Worker static cups_array_t	*DeviceURIs = NULL;
161*5e7646d2SAndroid Build Coastguard Worker static int		HostNameLookups = 0;
162*5e7646d2SAndroid Build Coastguard Worker static int		MaxRunTime = 120;
163*5e7646d2SAndroid Build Coastguard Worker static struct timeval	StartTime;
164*5e7646d2SAndroid Build Coastguard Worker 
165*5e7646d2SAndroid Build Coastguard Worker 
166*5e7646d2SAndroid Build Coastguard Worker /*
167*5e7646d2SAndroid Build Coastguard Worker  * 'main()' - Discover printers via SNMP.
168*5e7646d2SAndroid Build Coastguard Worker  */
169*5e7646d2SAndroid Build Coastguard Worker 
170*5e7646d2SAndroid Build Coastguard Worker int					/* O - Exit status */
main(int argc,char * argv[])171*5e7646d2SAndroid Build Coastguard Worker main(int  argc,				/* I - Number of command-line arguments (6 or 7) */
172*5e7646d2SAndroid Build Coastguard Worker      char *argv[])			/* I - Command-line arguments */
173*5e7646d2SAndroid Build Coastguard Worker {
174*5e7646d2SAndroid Build Coastguard Worker   int		ipv4,			/* SNMP IPv4 socket */
175*5e7646d2SAndroid Build Coastguard Worker 		ipv6;			/* SNMP IPv6 socket */
176*5e7646d2SAndroid Build Coastguard Worker #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
177*5e7646d2SAndroid Build Coastguard Worker   struct sigaction action;		/* Actions for POSIX signals */
178*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
179*5e7646d2SAndroid Build Coastguard Worker 
180*5e7646d2SAndroid Build Coastguard Worker 
181*5e7646d2SAndroid Build Coastguard Worker  /*
182*5e7646d2SAndroid Build Coastguard Worker   * Check command-line options...
183*5e7646d2SAndroid Build Coastguard Worker   */
184*5e7646d2SAndroid Build Coastguard Worker 
185*5e7646d2SAndroid Build Coastguard Worker   if (argc > 2)
186*5e7646d2SAndroid Build Coastguard Worker   {
187*5e7646d2SAndroid Build Coastguard Worker     _cupsLangPuts(stderr, _("Usage: snmp [host-or-ip-address]"));
188*5e7646d2SAndroid Build Coastguard Worker     return (1);
189*5e7646d2SAndroid Build Coastguard Worker   }
190*5e7646d2SAndroid Build Coastguard Worker 
191*5e7646d2SAndroid Build Coastguard Worker  /*
192*5e7646d2SAndroid Build Coastguard Worker   * Set the password callback for IPP operations...
193*5e7646d2SAndroid Build Coastguard Worker   */
194*5e7646d2SAndroid Build Coastguard Worker 
195*5e7646d2SAndroid Build Coastguard Worker   cupsSetPasswordCB(password_cb);
196*5e7646d2SAndroid Build Coastguard Worker 
197*5e7646d2SAndroid Build Coastguard Worker  /*
198*5e7646d2SAndroid Build Coastguard Worker   * Catch SIGALRM signals...
199*5e7646d2SAndroid Build Coastguard Worker   */
200*5e7646d2SAndroid Build Coastguard Worker 
201*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_SIGSET
202*5e7646d2SAndroid Build Coastguard Worker   sigset(SIGALRM, alarm_handler);
203*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_SIGACTION)
204*5e7646d2SAndroid Build Coastguard Worker   memset(&action, 0, sizeof(action));
205*5e7646d2SAndroid Build Coastguard Worker 
206*5e7646d2SAndroid Build Coastguard Worker   sigemptyset(&action.sa_mask);
207*5e7646d2SAndroid Build Coastguard Worker   sigaddset(&action.sa_mask, SIGALRM);
208*5e7646d2SAndroid Build Coastguard Worker   action.sa_handler = alarm_handler;
209*5e7646d2SAndroid Build Coastguard Worker   sigaction(SIGALRM, &action, NULL);
210*5e7646d2SAndroid Build Coastguard Worker #else
211*5e7646d2SAndroid Build Coastguard Worker   signal(SIGALRM, alarm_handler);
212*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_SIGSET */
213*5e7646d2SAndroid Build Coastguard Worker 
214*5e7646d2SAndroid Build Coastguard Worker  /*
215*5e7646d2SAndroid Build Coastguard Worker   * Open the SNMP socket...
216*5e7646d2SAndroid Build Coastguard Worker   */
217*5e7646d2SAndroid Build Coastguard Worker 
218*5e7646d2SAndroid Build Coastguard Worker   if ((ipv4 = _cupsSNMPOpen(AF_INET)) < 0)
219*5e7646d2SAndroid Build Coastguard Worker     return (1);
220*5e7646d2SAndroid Build Coastguard Worker 
221*5e7646d2SAndroid Build Coastguard Worker #ifdef AF_INET6
222*5e7646d2SAndroid Build Coastguard Worker   if ((ipv6 = _cupsSNMPOpen(AF_INET6)) < 0)
223*5e7646d2SAndroid Build Coastguard Worker     perror("DEBUG: Unable to create IPv6 socket");
224*5e7646d2SAndroid Build Coastguard Worker #else
225*5e7646d2SAndroid Build Coastguard Worker   ipv6 = -1;
226*5e7646d2SAndroid Build Coastguard Worker #endif /* AF_INET6 */
227*5e7646d2SAndroid Build Coastguard Worker 
228*5e7646d2SAndroid Build Coastguard Worker  /*
229*5e7646d2SAndroid Build Coastguard Worker   * Read the configuration file and any cache data...
230*5e7646d2SAndroid Build Coastguard Worker   */
231*5e7646d2SAndroid Build Coastguard Worker 
232*5e7646d2SAndroid Build Coastguard Worker   read_snmp_conf(argv[1]);
233*5e7646d2SAndroid Build Coastguard Worker 
234*5e7646d2SAndroid Build Coastguard Worker   _cupsSNMPSetDebug(DebugLevel);
235*5e7646d2SAndroid Build Coastguard Worker 
236*5e7646d2SAndroid Build Coastguard Worker   Devices = cupsArrayNew((cups_array_func_t)compare_cache, NULL);
237*5e7646d2SAndroid Build Coastguard Worker 
238*5e7646d2SAndroid Build Coastguard Worker  /*
239*5e7646d2SAndroid Build Coastguard Worker   * Scan for devices...
240*5e7646d2SAndroid Build Coastguard Worker   */
241*5e7646d2SAndroid Build Coastguard Worker 
242*5e7646d2SAndroid Build Coastguard Worker   scan_devices(ipv4, ipv6);
243*5e7646d2SAndroid Build Coastguard Worker 
244*5e7646d2SAndroid Build Coastguard Worker  /*
245*5e7646d2SAndroid Build Coastguard Worker   * Close, free, and return with no errors...
246*5e7646d2SAndroid Build Coastguard Worker   */
247*5e7646d2SAndroid Build Coastguard Worker 
248*5e7646d2SAndroid Build Coastguard Worker   _cupsSNMPClose(ipv4);
249*5e7646d2SAndroid Build Coastguard Worker   if (ipv6 >= 0)
250*5e7646d2SAndroid Build Coastguard Worker     _cupsSNMPClose(ipv6);
251*5e7646d2SAndroid Build Coastguard Worker 
252*5e7646d2SAndroid Build Coastguard Worker   free_array(Addresses);
253*5e7646d2SAndroid Build Coastguard Worker   free_array(Communities);
254*5e7646d2SAndroid Build Coastguard Worker   free_cache();
255*5e7646d2SAndroid Build Coastguard Worker 
256*5e7646d2SAndroid Build Coastguard Worker   return (0);
257*5e7646d2SAndroid Build Coastguard Worker }
258*5e7646d2SAndroid Build Coastguard Worker 
259*5e7646d2SAndroid Build Coastguard Worker 
260*5e7646d2SAndroid Build Coastguard Worker /*
261*5e7646d2SAndroid Build Coastguard Worker  * 'add_array()' - Add a string to an array.
262*5e7646d2SAndroid Build Coastguard Worker  */
263*5e7646d2SAndroid Build Coastguard Worker 
264*5e7646d2SAndroid Build Coastguard Worker static char *				/* O - New string */
add_array(cups_array_t * a,const char * s)265*5e7646d2SAndroid Build Coastguard Worker add_array(cups_array_t *a,		/* I - Array */
266*5e7646d2SAndroid Build Coastguard Worker           const char   *s)		/* I - String to add */
267*5e7646d2SAndroid Build Coastguard Worker {
268*5e7646d2SAndroid Build Coastguard Worker   char	*dups;				/* New string */
269*5e7646d2SAndroid Build Coastguard Worker 
270*5e7646d2SAndroid Build Coastguard Worker 
271*5e7646d2SAndroid Build Coastguard Worker   dups = strdup(s);
272*5e7646d2SAndroid Build Coastguard Worker 
273*5e7646d2SAndroid Build Coastguard Worker   cupsArrayAdd(a, dups);
274*5e7646d2SAndroid Build Coastguard Worker 
275*5e7646d2SAndroid Build Coastguard Worker   return (dups);
276*5e7646d2SAndroid Build Coastguard Worker }
277*5e7646d2SAndroid Build Coastguard Worker 
278*5e7646d2SAndroid Build Coastguard Worker 
279*5e7646d2SAndroid Build Coastguard Worker /*
280*5e7646d2SAndroid Build Coastguard Worker  * 'add_cache()' - Add a cached device...
281*5e7646d2SAndroid Build Coastguard Worker  */
282*5e7646d2SAndroid Build Coastguard Worker 
283*5e7646d2SAndroid Build Coastguard Worker static void
add_cache(http_addr_t * addr,const char * addrname,const char * uri,const char * id,const char * make_and_model)284*5e7646d2SAndroid Build Coastguard Worker add_cache(http_addr_t *addr,		/* I - Device IP address */
285*5e7646d2SAndroid Build Coastguard Worker           const char  *addrname,	/* I - IP address or name string */
286*5e7646d2SAndroid Build Coastguard Worker           const char  *uri,		/* I - Device URI */
287*5e7646d2SAndroid Build Coastguard Worker           const char  *id,		/* I - 1284 device ID */
288*5e7646d2SAndroid Build Coastguard Worker 	  const char  *make_and_model)	/* I - Make and model */
289*5e7646d2SAndroid Build Coastguard Worker {
290*5e7646d2SAndroid Build Coastguard Worker   snmp_cache_t	*temp;			/* New device entry */
291*5e7646d2SAndroid Build Coastguard Worker 
292*5e7646d2SAndroid Build Coastguard Worker 
293*5e7646d2SAndroid Build Coastguard Worker   debug_printf("DEBUG: add_cache(addr=%p, addrname=\"%s\", uri=\"%s\", "
294*5e7646d2SAndroid Build Coastguard Worker                   "id=\"%s\", make_and_model=\"%s\")\n",
295*5e7646d2SAndroid Build Coastguard Worker                addr, addrname, uri ? uri : "(null)", id ? id : "(null)",
296*5e7646d2SAndroid Build Coastguard Worker 	       make_and_model ? make_and_model : "(null)");
297*5e7646d2SAndroid Build Coastguard Worker 
298*5e7646d2SAndroid Build Coastguard Worker   temp = calloc(1, sizeof(snmp_cache_t));
299*5e7646d2SAndroid Build Coastguard Worker   memcpy(&(temp->address), addr, sizeof(temp->address));
300*5e7646d2SAndroid Build Coastguard Worker 
301*5e7646d2SAndroid Build Coastguard Worker   temp->addrname = strdup(addrname);
302*5e7646d2SAndroid Build Coastguard Worker 
303*5e7646d2SAndroid Build Coastguard Worker   if (uri)
304*5e7646d2SAndroid Build Coastguard Worker     temp->uri = strdup(uri);
305*5e7646d2SAndroid Build Coastguard Worker 
306*5e7646d2SAndroid Build Coastguard Worker   if (id)
307*5e7646d2SAndroid Build Coastguard Worker     temp->id = strdup(id);
308*5e7646d2SAndroid Build Coastguard Worker 
309*5e7646d2SAndroid Build Coastguard Worker   if (make_and_model)
310*5e7646d2SAndroid Build Coastguard Worker     temp->make_and_model = strdup(make_and_model);
311*5e7646d2SAndroid Build Coastguard Worker 
312*5e7646d2SAndroid Build Coastguard Worker   cupsArrayAdd(Devices, temp);
313*5e7646d2SAndroid Build Coastguard Worker 
314*5e7646d2SAndroid Build Coastguard Worker   if (uri)
315*5e7646d2SAndroid Build Coastguard Worker     list_device(temp);
316*5e7646d2SAndroid Build Coastguard Worker }
317*5e7646d2SAndroid Build Coastguard Worker 
318*5e7646d2SAndroid Build Coastguard Worker 
319*5e7646d2SAndroid Build Coastguard Worker /*
320*5e7646d2SAndroid Build Coastguard Worker  * 'add_device_uri()' - Add a device URI to the cache.
321*5e7646d2SAndroid Build Coastguard Worker  *
322*5e7646d2SAndroid Build Coastguard Worker  * The value string is modified (chopped up) as needed.
323*5e7646d2SAndroid Build Coastguard Worker  */
324*5e7646d2SAndroid Build Coastguard Worker 
325*5e7646d2SAndroid Build Coastguard Worker static device_uri_t *			/* O - Device URI */
add_device_uri(char * value)326*5e7646d2SAndroid Build Coastguard Worker add_device_uri(char *value)		/* I - Value from snmp.conf */
327*5e7646d2SAndroid Build Coastguard Worker {
328*5e7646d2SAndroid Build Coastguard Worker   device_uri_t	*device_uri;		/* Device URI */
329*5e7646d2SAndroid Build Coastguard Worker   char		*start;			/* Start of value */
330*5e7646d2SAndroid Build Coastguard Worker 
331*5e7646d2SAndroid Build Coastguard Worker 
332*5e7646d2SAndroid Build Coastguard Worker  /*
333*5e7646d2SAndroid Build Coastguard Worker   * Allocate memory as needed...
334*5e7646d2SAndroid Build Coastguard Worker   */
335*5e7646d2SAndroid Build Coastguard Worker 
336*5e7646d2SAndroid Build Coastguard Worker   if (!DeviceURIs)
337*5e7646d2SAndroid Build Coastguard Worker     DeviceURIs = cupsArrayNew(NULL, NULL);
338*5e7646d2SAndroid Build Coastguard Worker 
339*5e7646d2SAndroid Build Coastguard Worker   if (!DeviceURIs)
340*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
341*5e7646d2SAndroid Build Coastguard Worker 
342*5e7646d2SAndroid Build Coastguard Worker   if ((device_uri = calloc(1, sizeof(device_uri_t))) == NULL)
343*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
344*5e7646d2SAndroid Build Coastguard Worker 
345*5e7646d2SAndroid Build Coastguard Worker   if ((device_uri->uris = cupsArrayNew(NULL, NULL)) == NULL)
346*5e7646d2SAndroid Build Coastguard Worker   {
347*5e7646d2SAndroid Build Coastguard Worker     free(device_uri);
348*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
349*5e7646d2SAndroid Build Coastguard Worker   }
350*5e7646d2SAndroid Build Coastguard Worker 
351*5e7646d2SAndroid Build Coastguard Worker  /*
352*5e7646d2SAndroid Build Coastguard Worker   * Scan the value string for the regular expression and URI(s)...
353*5e7646d2SAndroid Build Coastguard Worker   */
354*5e7646d2SAndroid Build Coastguard Worker 
355*5e7646d2SAndroid Build Coastguard Worker   value ++; /* Skip leading " */
356*5e7646d2SAndroid Build Coastguard Worker 
357*5e7646d2SAndroid Build Coastguard Worker   for (start = value; *value && *value != '\"'; value ++)
358*5e7646d2SAndroid Build Coastguard Worker     if (*value == '\\' && value[1])
359*5e7646d2SAndroid Build Coastguard Worker       _cups_strcpy(value, value + 1);
360*5e7646d2SAndroid Build Coastguard Worker 
361*5e7646d2SAndroid Build Coastguard Worker   if (!*value)
362*5e7646d2SAndroid Build Coastguard Worker   {
363*5e7646d2SAndroid Build Coastguard Worker     fputs("ERROR: Missing end quote for DeviceURI!\n", stderr);
364*5e7646d2SAndroid Build Coastguard Worker 
365*5e7646d2SAndroid Build Coastguard Worker     cupsArrayDelete(device_uri->uris);
366*5e7646d2SAndroid Build Coastguard Worker     free(device_uri);
367*5e7646d2SAndroid Build Coastguard Worker 
368*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
369*5e7646d2SAndroid Build Coastguard Worker   }
370*5e7646d2SAndroid Build Coastguard Worker 
371*5e7646d2SAndroid Build Coastguard Worker   *value++ = '\0';
372*5e7646d2SAndroid Build Coastguard Worker 
373*5e7646d2SAndroid Build Coastguard Worker   if (regcomp(&(device_uri->re), start, REG_EXTENDED | REG_ICASE))
374*5e7646d2SAndroid Build Coastguard Worker   {
375*5e7646d2SAndroid Build Coastguard Worker     fputs("ERROR: Bad regular expression for DeviceURI!\n", stderr);
376*5e7646d2SAndroid Build Coastguard Worker 
377*5e7646d2SAndroid Build Coastguard Worker     cupsArrayDelete(device_uri->uris);
378*5e7646d2SAndroid Build Coastguard Worker     free(device_uri);
379*5e7646d2SAndroid Build Coastguard Worker 
380*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
381*5e7646d2SAndroid Build Coastguard Worker   }
382*5e7646d2SAndroid Build Coastguard Worker 
383*5e7646d2SAndroid Build Coastguard Worker   while (*value)
384*5e7646d2SAndroid Build Coastguard Worker   {
385*5e7646d2SAndroid Build Coastguard Worker     while (isspace(*value & 255))
386*5e7646d2SAndroid Build Coastguard Worker       value ++;
387*5e7646d2SAndroid Build Coastguard Worker 
388*5e7646d2SAndroid Build Coastguard Worker     if (!*value)
389*5e7646d2SAndroid Build Coastguard Worker       break;
390*5e7646d2SAndroid Build Coastguard Worker 
391*5e7646d2SAndroid Build Coastguard Worker     for (start = value; *value && !isspace(*value & 255); value ++);
392*5e7646d2SAndroid Build Coastguard Worker 
393*5e7646d2SAndroid Build Coastguard Worker     if (*value)
394*5e7646d2SAndroid Build Coastguard Worker       *value++ = '\0';
395*5e7646d2SAndroid Build Coastguard Worker 
396*5e7646d2SAndroid Build Coastguard Worker     cupsArrayAdd(device_uri->uris, strdup(start));
397*5e7646d2SAndroid Build Coastguard Worker   }
398*5e7646d2SAndroid Build Coastguard Worker 
399*5e7646d2SAndroid Build Coastguard Worker  /*
400*5e7646d2SAndroid Build Coastguard Worker   * Add the device URI to the list and return it...
401*5e7646d2SAndroid Build Coastguard Worker   */
402*5e7646d2SAndroid Build Coastguard Worker 
403*5e7646d2SAndroid Build Coastguard Worker   cupsArrayAdd(DeviceURIs, device_uri);
404*5e7646d2SAndroid Build Coastguard Worker 
405*5e7646d2SAndroid Build Coastguard Worker   return (device_uri);
406*5e7646d2SAndroid Build Coastguard Worker }
407*5e7646d2SAndroid Build Coastguard Worker 
408*5e7646d2SAndroid Build Coastguard Worker 
409*5e7646d2SAndroid Build Coastguard Worker /*
410*5e7646d2SAndroid Build Coastguard Worker  * 'alarm_handler()' - Handle alarm signals...
411*5e7646d2SAndroid Build Coastguard Worker  */
412*5e7646d2SAndroid Build Coastguard Worker 
413*5e7646d2SAndroid Build Coastguard Worker static void
alarm_handler(int sig)414*5e7646d2SAndroid Build Coastguard Worker alarm_handler(int sig)			/* I - Signal number */
415*5e7646d2SAndroid Build Coastguard Worker {
416*5e7646d2SAndroid Build Coastguard Worker  /*
417*5e7646d2SAndroid Build Coastguard Worker   * Do nothing...
418*5e7646d2SAndroid Build Coastguard Worker   */
419*5e7646d2SAndroid Build Coastguard Worker 
420*5e7646d2SAndroid Build Coastguard Worker   (void)sig;
421*5e7646d2SAndroid Build Coastguard Worker 
422*5e7646d2SAndroid Build Coastguard Worker #if !defined(HAVE_SIGSET) && !defined(HAVE_SIGACTION)
423*5e7646d2SAndroid Build Coastguard Worker   signal(SIGALRM, alarm_handler);
424*5e7646d2SAndroid Build Coastguard Worker #endif /* !HAVE_SIGSET && !HAVE_SIGACTION */
425*5e7646d2SAndroid Build Coastguard Worker 
426*5e7646d2SAndroid Build Coastguard Worker   if (DebugLevel)
427*5e7646d2SAndroid Build Coastguard Worker     backendMessage("DEBUG: ALARM!\n");
428*5e7646d2SAndroid Build Coastguard Worker }
429*5e7646d2SAndroid Build Coastguard Worker 
430*5e7646d2SAndroid Build Coastguard Worker 
431*5e7646d2SAndroid Build Coastguard Worker /*
432*5e7646d2SAndroid Build Coastguard Worker  * 'compare_cache()' - Compare two cache entries.
433*5e7646d2SAndroid Build Coastguard Worker  */
434*5e7646d2SAndroid Build Coastguard Worker 
435*5e7646d2SAndroid Build Coastguard Worker static int				/* O - Result of comparison */
compare_cache(snmp_cache_t * a,snmp_cache_t * b)436*5e7646d2SAndroid Build Coastguard Worker compare_cache(snmp_cache_t *a,		/* I - First cache entry */
437*5e7646d2SAndroid Build Coastguard Worker               snmp_cache_t *b)		/* I - Second cache entry */
438*5e7646d2SAndroid Build Coastguard Worker {
439*5e7646d2SAndroid Build Coastguard Worker   return (_cups_strcasecmp(a->addrname, b->addrname));
440*5e7646d2SAndroid Build Coastguard Worker }
441*5e7646d2SAndroid Build Coastguard Worker 
442*5e7646d2SAndroid Build Coastguard Worker 
443*5e7646d2SAndroid Build Coastguard Worker /*
444*5e7646d2SAndroid Build Coastguard Worker  * 'debug_printf()' - Display some debugging information.
445*5e7646d2SAndroid Build Coastguard Worker  */
446*5e7646d2SAndroid Build Coastguard Worker 
447*5e7646d2SAndroid Build Coastguard Worker static void
debug_printf(const char * format,...)448*5e7646d2SAndroid Build Coastguard Worker debug_printf(const char *format,	/* I - Printf-style format string */
449*5e7646d2SAndroid Build Coastguard Worker              ...)			/* I - Additional arguments as needed */
450*5e7646d2SAndroid Build Coastguard Worker {
451*5e7646d2SAndroid Build Coastguard Worker   va_list	ap;			/* Pointer to arguments */
452*5e7646d2SAndroid Build Coastguard Worker 
453*5e7646d2SAndroid Build Coastguard Worker 
454*5e7646d2SAndroid Build Coastguard Worker   if (!DebugLevel)
455*5e7646d2SAndroid Build Coastguard Worker     return;
456*5e7646d2SAndroid Build Coastguard Worker 
457*5e7646d2SAndroid Build Coastguard Worker   va_start(ap, format);
458*5e7646d2SAndroid Build Coastguard Worker   vfprintf(stderr, format, ap);
459*5e7646d2SAndroid Build Coastguard Worker   va_end(ap);
460*5e7646d2SAndroid Build Coastguard Worker }
461*5e7646d2SAndroid Build Coastguard Worker 
462*5e7646d2SAndroid Build Coastguard Worker 
463*5e7646d2SAndroid Build Coastguard Worker /*
464*5e7646d2SAndroid Build Coastguard Worker  * 'fix_make_model()' - Fix common problems in the make-and-model string.
465*5e7646d2SAndroid Build Coastguard Worker  */
466*5e7646d2SAndroid Build Coastguard Worker 
467*5e7646d2SAndroid Build Coastguard Worker static void
fix_make_model(char * make_model,const char * old_make_model,int make_model_size)468*5e7646d2SAndroid Build Coastguard Worker fix_make_model(
469*5e7646d2SAndroid Build Coastguard Worker     char       *make_model,		/* I - New make-and-model string */
470*5e7646d2SAndroid Build Coastguard Worker     const char *old_make_model,		/* I - Old make-and-model string */
471*5e7646d2SAndroid Build Coastguard Worker     int        make_model_size)		/* I - Size of new string buffer */
472*5e7646d2SAndroid Build Coastguard Worker {
473*5e7646d2SAndroid Build Coastguard Worker   char	*mmptr;				/* Pointer into make-and-model string */
474*5e7646d2SAndroid Build Coastguard Worker 
475*5e7646d2SAndroid Build Coastguard Worker 
476*5e7646d2SAndroid Build Coastguard Worker  /*
477*5e7646d2SAndroid Build Coastguard Worker   * Fix some common problems with the make-and-model string so
478*5e7646d2SAndroid Build Coastguard Worker   * that printer driver detection works better...
479*5e7646d2SAndroid Build Coastguard Worker   */
480*5e7646d2SAndroid Build Coastguard Worker 
481*5e7646d2SAndroid Build Coastguard Worker   if (!_cups_strncasecmp(old_make_model, "Hewlett-Packard", 15))
482*5e7646d2SAndroid Build Coastguard Worker   {
483*5e7646d2SAndroid Build Coastguard Worker    /*
484*5e7646d2SAndroid Build Coastguard Worker     * Strip leading Hewlett-Packard and hp prefixes and replace
485*5e7646d2SAndroid Build Coastguard Worker     * with a single HP manufacturer prefix...
486*5e7646d2SAndroid Build Coastguard Worker     */
487*5e7646d2SAndroid Build Coastguard Worker 
488*5e7646d2SAndroid Build Coastguard Worker     mmptr = (char *)old_make_model + 15;
489*5e7646d2SAndroid Build Coastguard Worker 
490*5e7646d2SAndroid Build Coastguard Worker     while (isspace(*mmptr & 255))
491*5e7646d2SAndroid Build Coastguard Worker       mmptr ++;
492*5e7646d2SAndroid Build Coastguard Worker 
493*5e7646d2SAndroid Build Coastguard Worker     if (!_cups_strncasecmp(mmptr, "hp", 2))
494*5e7646d2SAndroid Build Coastguard Worker     {
495*5e7646d2SAndroid Build Coastguard Worker       mmptr += 2;
496*5e7646d2SAndroid Build Coastguard Worker 
497*5e7646d2SAndroid Build Coastguard Worker       while (isspace(*mmptr & 255))
498*5e7646d2SAndroid Build Coastguard Worker 	mmptr ++;
499*5e7646d2SAndroid Build Coastguard Worker     }
500*5e7646d2SAndroid Build Coastguard Worker 
501*5e7646d2SAndroid Build Coastguard Worker     make_model[0] = 'H';
502*5e7646d2SAndroid Build Coastguard Worker     make_model[1] = 'P';
503*5e7646d2SAndroid Build Coastguard Worker     make_model[2] = ' ';
504*5e7646d2SAndroid Build Coastguard Worker     strlcpy(make_model + 3, mmptr, (size_t)make_model_size - 3);
505*5e7646d2SAndroid Build Coastguard Worker   }
506*5e7646d2SAndroid Build Coastguard Worker   else if (!_cups_strncasecmp(old_make_model, "deskjet", 7))
507*5e7646d2SAndroid Build Coastguard Worker     snprintf(make_model, (size_t)make_model_size, "HP DeskJet%s", old_make_model + 7);
508*5e7646d2SAndroid Build Coastguard Worker   else if (!_cups_strncasecmp(old_make_model, "officejet", 9))
509*5e7646d2SAndroid Build Coastguard Worker     snprintf(make_model, (size_t)make_model_size, "HP OfficeJet%s", old_make_model + 9);
510*5e7646d2SAndroid Build Coastguard Worker   else if (!_cups_strncasecmp(old_make_model, "stylus_pro_", 11))
511*5e7646d2SAndroid Build Coastguard Worker     snprintf(make_model, (size_t)make_model_size, "EPSON Stylus Pro %s", old_make_model + 11);
512*5e7646d2SAndroid Build Coastguard Worker   else
513*5e7646d2SAndroid Build Coastguard Worker     strlcpy(make_model, old_make_model, (size_t)make_model_size);
514*5e7646d2SAndroid Build Coastguard Worker 
515*5e7646d2SAndroid Build Coastguard Worker   if ((mmptr = strstr(make_model, ", Inc.,")) != NULL)
516*5e7646d2SAndroid Build Coastguard Worker   {
517*5e7646d2SAndroid Build Coastguard Worker    /*
518*5e7646d2SAndroid Build Coastguard Worker     * Strip inc. from name, e.g. "Tektronix, Inc., Phaser 560"
519*5e7646d2SAndroid Build Coastguard Worker     * becomes "Tektronix Phaser 560"...
520*5e7646d2SAndroid Build Coastguard Worker     */
521*5e7646d2SAndroid Build Coastguard Worker 
522*5e7646d2SAndroid Build Coastguard Worker     _cups_strcpy(mmptr, mmptr + 7);
523*5e7646d2SAndroid Build Coastguard Worker   }
524*5e7646d2SAndroid Build Coastguard Worker 
525*5e7646d2SAndroid Build Coastguard Worker   if ((mmptr = strstr(make_model, " Network")) != NULL)
526*5e7646d2SAndroid Build Coastguard Worker   {
527*5e7646d2SAndroid Build Coastguard Worker    /*
528*5e7646d2SAndroid Build Coastguard Worker     * Drop unnecessary informational text, e.g. "Xerox DocuPrint N2025
529*5e7646d2SAndroid Build Coastguard Worker     * Network LaserJet - 2.12" becomes "Xerox DocuPrint N2025"...
530*5e7646d2SAndroid Build Coastguard Worker     */
531*5e7646d2SAndroid Build Coastguard Worker 
532*5e7646d2SAndroid Build Coastguard Worker     *mmptr = '\0';
533*5e7646d2SAndroid Build Coastguard Worker   }
534*5e7646d2SAndroid Build Coastguard Worker 
535*5e7646d2SAndroid Build Coastguard Worker   if ((mmptr = strchr(make_model, ',')) != NULL)
536*5e7646d2SAndroid Build Coastguard Worker   {
537*5e7646d2SAndroid Build Coastguard Worker    /*
538*5e7646d2SAndroid Build Coastguard Worker     * Drop anything after a trailing comma...
539*5e7646d2SAndroid Build Coastguard Worker     */
540*5e7646d2SAndroid Build Coastguard Worker 
541*5e7646d2SAndroid Build Coastguard Worker     *mmptr = '\0';
542*5e7646d2SAndroid Build Coastguard Worker   }
543*5e7646d2SAndroid Build Coastguard Worker }
544*5e7646d2SAndroid Build Coastguard Worker 
545*5e7646d2SAndroid Build Coastguard Worker 
546*5e7646d2SAndroid Build Coastguard Worker /*
547*5e7646d2SAndroid Build Coastguard Worker  * 'free_array()' - Free an array of strings.
548*5e7646d2SAndroid Build Coastguard Worker  */
549*5e7646d2SAndroid Build Coastguard Worker 
550*5e7646d2SAndroid Build Coastguard Worker static void
free_array(cups_array_t * a)551*5e7646d2SAndroid Build Coastguard Worker free_array(cups_array_t *a)		/* I - Array */
552*5e7646d2SAndroid Build Coastguard Worker {
553*5e7646d2SAndroid Build Coastguard Worker   char	*s;				/* Current string */
554*5e7646d2SAndroid Build Coastguard Worker 
555*5e7646d2SAndroid Build Coastguard Worker 
556*5e7646d2SAndroid Build Coastguard Worker   for (s = (char *)cupsArrayFirst(a); s; s = (char *)cupsArrayNext(a))
557*5e7646d2SAndroid Build Coastguard Worker     free(s);
558*5e7646d2SAndroid Build Coastguard Worker 
559*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(a);
560*5e7646d2SAndroid Build Coastguard Worker }
561*5e7646d2SAndroid Build Coastguard Worker 
562*5e7646d2SAndroid Build Coastguard Worker 
563*5e7646d2SAndroid Build Coastguard Worker /*
564*5e7646d2SAndroid Build Coastguard Worker  * 'free_cache()' - Free the array of cached devices.
565*5e7646d2SAndroid Build Coastguard Worker  */
566*5e7646d2SAndroid Build Coastguard Worker 
567*5e7646d2SAndroid Build Coastguard Worker static void
free_cache(void)568*5e7646d2SAndroid Build Coastguard Worker free_cache(void)
569*5e7646d2SAndroid Build Coastguard Worker {
570*5e7646d2SAndroid Build Coastguard Worker   snmp_cache_t	*cache;			/* Cached device */
571*5e7646d2SAndroid Build Coastguard Worker 
572*5e7646d2SAndroid Build Coastguard Worker 
573*5e7646d2SAndroid Build Coastguard Worker   for (cache = (snmp_cache_t *)cupsArrayFirst(Devices);
574*5e7646d2SAndroid Build Coastguard Worker        cache;
575*5e7646d2SAndroid Build Coastguard Worker        cache = (snmp_cache_t *)cupsArrayNext(Devices))
576*5e7646d2SAndroid Build Coastguard Worker   {
577*5e7646d2SAndroid Build Coastguard Worker     free(cache->addrname);
578*5e7646d2SAndroid Build Coastguard Worker 
579*5e7646d2SAndroid Build Coastguard Worker     if (cache->uri)
580*5e7646d2SAndroid Build Coastguard Worker       free(cache->uri);
581*5e7646d2SAndroid Build Coastguard Worker 
582*5e7646d2SAndroid Build Coastguard Worker     if (cache->id)
583*5e7646d2SAndroid Build Coastguard Worker       free(cache->id);
584*5e7646d2SAndroid Build Coastguard Worker 
585*5e7646d2SAndroid Build Coastguard Worker     if (cache->make_and_model)
586*5e7646d2SAndroid Build Coastguard Worker       free(cache->make_and_model);
587*5e7646d2SAndroid Build Coastguard Worker 
588*5e7646d2SAndroid Build Coastguard Worker     free(cache);
589*5e7646d2SAndroid Build Coastguard Worker   }
590*5e7646d2SAndroid Build Coastguard Worker 
591*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(Devices);
592*5e7646d2SAndroid Build Coastguard Worker   Devices = NULL;
593*5e7646d2SAndroid Build Coastguard Worker }
594*5e7646d2SAndroid Build Coastguard Worker 
595*5e7646d2SAndroid Build Coastguard Worker 
596*5e7646d2SAndroid Build Coastguard Worker /*
597*5e7646d2SAndroid Build Coastguard Worker  * 'get_interface_addresses()' - Get the broadcast address(es) associated
598*5e7646d2SAndroid Build Coastguard Worker  *                               with an interface.
599*5e7646d2SAndroid Build Coastguard Worker  */
600*5e7646d2SAndroid Build Coastguard Worker 
601*5e7646d2SAndroid Build Coastguard Worker static http_addrlist_t *		/* O - List of addresses */
get_interface_addresses(const char * ifname)602*5e7646d2SAndroid Build Coastguard Worker get_interface_addresses(
603*5e7646d2SAndroid Build Coastguard Worker     const char *ifname)			/* I - Interface name */
604*5e7646d2SAndroid Build Coastguard Worker {
605*5e7646d2SAndroid Build Coastguard Worker   struct ifaddrs	*addrs,		/* Interface address list */
606*5e7646d2SAndroid Build Coastguard Worker 			*addr;		/* Current interface address */
607*5e7646d2SAndroid Build Coastguard Worker   http_addrlist_t	*first,		/* First address in list */
608*5e7646d2SAndroid Build Coastguard Worker 			*last,		/* Last address in list */
609*5e7646d2SAndroid Build Coastguard Worker 			*current;	/* Current address */
610*5e7646d2SAndroid Build Coastguard Worker 
611*5e7646d2SAndroid Build Coastguard Worker 
612*5e7646d2SAndroid Build Coastguard Worker   if (getifaddrs(&addrs) < 0)
613*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
614*5e7646d2SAndroid Build Coastguard Worker 
615*5e7646d2SAndroid Build Coastguard Worker   for (addr = addrs, first = NULL, last = NULL; addr; addr = addr->ifa_next)
616*5e7646d2SAndroid Build Coastguard Worker     if ((addr->ifa_flags & IFF_BROADCAST) && addr->ifa_broadaddr &&
617*5e7646d2SAndroid Build Coastguard Worker         addr->ifa_broadaddr->sa_family == AF_INET &&
618*5e7646d2SAndroid Build Coastguard Worker 	(!ifname || !strcmp(ifname, addr->ifa_name)))
619*5e7646d2SAndroid Build Coastguard Worker     {
620*5e7646d2SAndroid Build Coastguard Worker       current = calloc(1, sizeof(http_addrlist_t));
621*5e7646d2SAndroid Build Coastguard Worker 
622*5e7646d2SAndroid Build Coastguard Worker       memcpy(&(current->addr), addr->ifa_broadaddr,
623*5e7646d2SAndroid Build Coastguard Worker              sizeof(struct sockaddr_in));
624*5e7646d2SAndroid Build Coastguard Worker 
625*5e7646d2SAndroid Build Coastguard Worker       if (!last)
626*5e7646d2SAndroid Build Coastguard Worker         first = current;
627*5e7646d2SAndroid Build Coastguard Worker       else
628*5e7646d2SAndroid Build Coastguard Worker         last->next = current;
629*5e7646d2SAndroid Build Coastguard Worker 
630*5e7646d2SAndroid Build Coastguard Worker       last = current;
631*5e7646d2SAndroid Build Coastguard Worker     }
632*5e7646d2SAndroid Build Coastguard Worker 
633*5e7646d2SAndroid Build Coastguard Worker   freeifaddrs(addrs);
634*5e7646d2SAndroid Build Coastguard Worker 
635*5e7646d2SAndroid Build Coastguard Worker   return (first);
636*5e7646d2SAndroid Build Coastguard Worker }
637*5e7646d2SAndroid Build Coastguard Worker 
638*5e7646d2SAndroid Build Coastguard Worker 
639*5e7646d2SAndroid Build Coastguard Worker /*
640*5e7646d2SAndroid Build Coastguard Worker  * 'list_device()' - List a device we found...
641*5e7646d2SAndroid Build Coastguard Worker  */
642*5e7646d2SAndroid Build Coastguard Worker 
643*5e7646d2SAndroid Build Coastguard Worker static void
list_device(snmp_cache_t * cache)644*5e7646d2SAndroid Build Coastguard Worker list_device(snmp_cache_t *cache)	/* I - Cached device */
645*5e7646d2SAndroid Build Coastguard Worker {
646*5e7646d2SAndroid Build Coastguard Worker   if (cache->uri)
647*5e7646d2SAndroid Build Coastguard Worker     cupsBackendReport("network", cache->uri, cache->make_and_model,
648*5e7646d2SAndroid Build Coastguard Worker                       cache->info, cache->id, cache->location);
649*5e7646d2SAndroid Build Coastguard Worker }
650*5e7646d2SAndroid Build Coastguard Worker 
651*5e7646d2SAndroid Build Coastguard Worker 
652*5e7646d2SAndroid Build Coastguard Worker /*
653*5e7646d2SAndroid Build Coastguard Worker  * 'password_cb()' - Handle authentication requests.
654*5e7646d2SAndroid Build Coastguard Worker  *
655*5e7646d2SAndroid Build Coastguard Worker  * All we do right now is return NULL, indicating that no authentication
656*5e7646d2SAndroid Build Coastguard Worker  * is possible.
657*5e7646d2SAndroid Build Coastguard Worker  */
658*5e7646d2SAndroid Build Coastguard Worker 
659*5e7646d2SAndroid Build Coastguard Worker static const char *			/* O - Password (NULL) */
password_cb(const char * prompt)660*5e7646d2SAndroid Build Coastguard Worker password_cb(const char *prompt)		/* I - Prompt message */
661*5e7646d2SAndroid Build Coastguard Worker {
662*5e7646d2SAndroid Build Coastguard Worker   (void)prompt;				/* Anti-compiler-warning-code */
663*5e7646d2SAndroid Build Coastguard Worker 
664*5e7646d2SAndroid Build Coastguard Worker   return (NULL);
665*5e7646d2SAndroid Build Coastguard Worker }
666*5e7646d2SAndroid Build Coastguard Worker 
667*5e7646d2SAndroid Build Coastguard Worker 
668*5e7646d2SAndroid Build Coastguard Worker /*
669*5e7646d2SAndroid Build Coastguard Worker  * 'probe_device()' - Probe a device to discover whether it is a printer.
670*5e7646d2SAndroid Build Coastguard Worker  *
671*5e7646d2SAndroid Build Coastguard Worker  * TODO: Try using the Port Monitor MIB to discover the correct protocol
672*5e7646d2SAndroid Build Coastguard Worker  *       to use - first need a commercially-available printer that supports
673*5e7646d2SAndroid Build Coastguard Worker  *       it, though...
674*5e7646d2SAndroid Build Coastguard Worker  */
675*5e7646d2SAndroid Build Coastguard Worker 
676*5e7646d2SAndroid Build Coastguard Worker static void
probe_device(snmp_cache_t * device)677*5e7646d2SAndroid Build Coastguard Worker probe_device(snmp_cache_t *device)	/* I - Device */
678*5e7646d2SAndroid Build Coastguard Worker {
679*5e7646d2SAndroid Build Coastguard Worker   char		uri[1024],		/* Full device URI */
680*5e7646d2SAndroid Build Coastguard Worker 		*uriptr,		/* Pointer into URI */
681*5e7646d2SAndroid Build Coastguard Worker 		*format;		/* Format string for device */
682*5e7646d2SAndroid Build Coastguard Worker   device_uri_t	*device_uri;		/* Current DeviceURI match */
683*5e7646d2SAndroid Build Coastguard Worker 
684*5e7646d2SAndroid Build Coastguard Worker 
685*5e7646d2SAndroid Build Coastguard Worker   debug_printf("DEBUG: %.3f Probing %s...\n", run_time(), device->addrname);
686*5e7646d2SAndroid Build Coastguard Worker 
687*5e7646d2SAndroid Build Coastguard Worker #ifdef __APPLE__
688*5e7646d2SAndroid Build Coastguard Worker  /*
689*5e7646d2SAndroid Build Coastguard Worker   * If the printer supports Bonjour/mDNS, don't report it from the SNMP backend.
690*5e7646d2SAndroid Build Coastguard Worker   */
691*5e7646d2SAndroid Build Coastguard Worker 
692*5e7646d2SAndroid Build Coastguard Worker   if (!try_connect(&(device->address), device->addrname, 5353))
693*5e7646d2SAndroid Build Coastguard Worker   {
694*5e7646d2SAndroid Build Coastguard Worker     debug_printf("DEBUG: %s supports mDNS, not reporting!\n", device->addrname);
695*5e7646d2SAndroid Build Coastguard Worker     return;
696*5e7646d2SAndroid Build Coastguard Worker   }
697*5e7646d2SAndroid Build Coastguard Worker #endif /* __APPLE__ */
698*5e7646d2SAndroid Build Coastguard Worker 
699*5e7646d2SAndroid Build Coastguard Worker  /*
700*5e7646d2SAndroid Build Coastguard Worker   * Lookup the device in the match table...
701*5e7646d2SAndroid Build Coastguard Worker   */
702*5e7646d2SAndroid Build Coastguard Worker 
703*5e7646d2SAndroid Build Coastguard Worker   for (device_uri = (device_uri_t *)cupsArrayFirst(DeviceURIs);
704*5e7646d2SAndroid Build Coastguard Worker        device_uri;
705*5e7646d2SAndroid Build Coastguard Worker        device_uri = (device_uri_t *)cupsArrayNext(DeviceURIs))
706*5e7646d2SAndroid Build Coastguard Worker     if (device->make_and_model &&
707*5e7646d2SAndroid Build Coastguard Worker         !regexec(&(device_uri->re), device->make_and_model, 0, NULL, 0))
708*5e7646d2SAndroid Build Coastguard Worker     {
709*5e7646d2SAndroid Build Coastguard Worker      /*
710*5e7646d2SAndroid Build Coastguard Worker       * Found a match, add the URIs...
711*5e7646d2SAndroid Build Coastguard Worker       */
712*5e7646d2SAndroid Build Coastguard Worker 
713*5e7646d2SAndroid Build Coastguard Worker       for (format = (char *)cupsArrayFirst(device_uri->uris);
714*5e7646d2SAndroid Build Coastguard Worker            format;
715*5e7646d2SAndroid Build Coastguard Worker 	   format = (char *)cupsArrayNext(device_uri->uris))
716*5e7646d2SAndroid Build Coastguard Worker       {
717*5e7646d2SAndroid Build Coastguard Worker         for (uriptr = uri; *format && uriptr < (uri + sizeof(uri) - 1);)
718*5e7646d2SAndroid Build Coastguard Worker 	  if (*format == '%' && format[1] == 's')
719*5e7646d2SAndroid Build Coastguard Worker 	  {
720*5e7646d2SAndroid Build Coastguard Worker 	   /*
721*5e7646d2SAndroid Build Coastguard Worker 	    * Insert hostname/address...
722*5e7646d2SAndroid Build Coastguard Worker 	    */
723*5e7646d2SAndroid Build Coastguard Worker 
724*5e7646d2SAndroid Build Coastguard Worker 	    strlcpy(uriptr, device->addrname, sizeof(uri) - (size_t)(uriptr - uri));
725*5e7646d2SAndroid Build Coastguard Worker 	    uriptr += strlen(uriptr);
726*5e7646d2SAndroid Build Coastguard Worker 	    format += 2;
727*5e7646d2SAndroid Build Coastguard Worker 	  }
728*5e7646d2SAndroid Build Coastguard Worker 	  else
729*5e7646d2SAndroid Build Coastguard Worker 	    *uriptr++ = *format++;
730*5e7646d2SAndroid Build Coastguard Worker 
731*5e7646d2SAndroid Build Coastguard Worker         *uriptr = '\0';
732*5e7646d2SAndroid Build Coastguard Worker 
733*5e7646d2SAndroid Build Coastguard Worker         update_cache(device, uri, NULL, NULL);
734*5e7646d2SAndroid Build Coastguard Worker       }
735*5e7646d2SAndroid Build Coastguard Worker 
736*5e7646d2SAndroid Build Coastguard Worker       return;
737*5e7646d2SAndroid Build Coastguard Worker     }
738*5e7646d2SAndroid Build Coastguard Worker 
739*5e7646d2SAndroid Build Coastguard Worker  /*
740*5e7646d2SAndroid Build Coastguard Worker   * Then try the standard ports...
741*5e7646d2SAndroid Build Coastguard Worker   */
742*5e7646d2SAndroid Build Coastguard Worker 
743*5e7646d2SAndroid Build Coastguard Worker   if (!try_connect(&(device->address), device->addrname, 9100))
744*5e7646d2SAndroid Build Coastguard Worker   {
745*5e7646d2SAndroid Build Coastguard Worker     debug_printf("DEBUG: %s supports AppSocket!\n", device->addrname);
746*5e7646d2SAndroid Build Coastguard Worker 
747*5e7646d2SAndroid Build Coastguard Worker     snprintf(uri, sizeof(uri), "socket://%s", device->addrname);
748*5e7646d2SAndroid Build Coastguard Worker     update_cache(device, uri, NULL, NULL);
749*5e7646d2SAndroid Build Coastguard Worker   }
750*5e7646d2SAndroid Build Coastguard Worker   else if (!try_connect(&(device->address), device->addrname, 515))
751*5e7646d2SAndroid Build Coastguard Worker   {
752*5e7646d2SAndroid Build Coastguard Worker     debug_printf("DEBUG: %s supports LPD!\n", device->addrname);
753*5e7646d2SAndroid Build Coastguard Worker 
754*5e7646d2SAndroid Build Coastguard Worker     snprintf(uri, sizeof(uri), "lpd://%s/", device->addrname);
755*5e7646d2SAndroid Build Coastguard Worker     update_cache(device, uri, NULL, NULL);
756*5e7646d2SAndroid Build Coastguard Worker   }
757*5e7646d2SAndroid Build Coastguard Worker }
758*5e7646d2SAndroid Build Coastguard Worker 
759*5e7646d2SAndroid Build Coastguard Worker 
760*5e7646d2SAndroid Build Coastguard Worker /*
761*5e7646d2SAndroid Build Coastguard Worker  * 'read_snmp_conf()' - Read the snmp.conf file.
762*5e7646d2SAndroid Build Coastguard Worker  */
763*5e7646d2SAndroid Build Coastguard Worker 
764*5e7646d2SAndroid Build Coastguard Worker static void
read_snmp_conf(const char * address)765*5e7646d2SAndroid Build Coastguard Worker read_snmp_conf(const char *address)	/* I - Single address to probe */
766*5e7646d2SAndroid Build Coastguard Worker {
767*5e7646d2SAndroid Build Coastguard Worker   cups_file_t	*fp;			/* File pointer */
768*5e7646d2SAndroid Build Coastguard Worker   char		filename[1024],		/* Filename */
769*5e7646d2SAndroid Build Coastguard Worker 		line[1024],		/* Line from file */
770*5e7646d2SAndroid Build Coastguard Worker 		*value;			/* Value on line */
771*5e7646d2SAndroid Build Coastguard Worker   int		linenum;		/* Line number */
772*5e7646d2SAndroid Build Coastguard Worker   const char	*cups_serverroot;	/* CUPS_SERVERROOT env var */
773*5e7646d2SAndroid Build Coastguard Worker   const char	*debug;			/* CUPS_DEBUG_LEVEL env var */
774*5e7646d2SAndroid Build Coastguard Worker   const char	*runtime;		/* CUPS_MAX_RUN_TIME env var */
775*5e7646d2SAndroid Build Coastguard Worker 
776*5e7646d2SAndroid Build Coastguard Worker 
777*5e7646d2SAndroid Build Coastguard Worker  /*
778*5e7646d2SAndroid Build Coastguard Worker   * Initialize the global address and community lists...
779*5e7646d2SAndroid Build Coastguard Worker   */
780*5e7646d2SAndroid Build Coastguard Worker 
781*5e7646d2SAndroid Build Coastguard Worker   Addresses   = cupsArrayNew(NULL, NULL);
782*5e7646d2SAndroid Build Coastguard Worker   Communities = cupsArrayNew(NULL, NULL);
783*5e7646d2SAndroid Build Coastguard Worker 
784*5e7646d2SAndroid Build Coastguard Worker   if (address)
785*5e7646d2SAndroid Build Coastguard Worker     add_array(Addresses, address);
786*5e7646d2SAndroid Build Coastguard Worker 
787*5e7646d2SAndroid Build Coastguard Worker   if ((debug = getenv("CUPS_DEBUG_LEVEL")) != NULL)
788*5e7646d2SAndroid Build Coastguard Worker     DebugLevel = atoi(debug);
789*5e7646d2SAndroid Build Coastguard Worker 
790*5e7646d2SAndroid Build Coastguard Worker   if ((runtime = getenv("CUPS_MAX_RUN_TIME")) != NULL)
791*5e7646d2SAndroid Build Coastguard Worker     MaxRunTime = atoi(runtime);
792*5e7646d2SAndroid Build Coastguard Worker 
793*5e7646d2SAndroid Build Coastguard Worker  /*
794*5e7646d2SAndroid Build Coastguard Worker   * Find the snmp.conf file...
795*5e7646d2SAndroid Build Coastguard Worker   */
796*5e7646d2SAndroid Build Coastguard Worker 
797*5e7646d2SAndroid Build Coastguard Worker   if ((cups_serverroot = getenv("CUPS_SERVERROOT")) == NULL)
798*5e7646d2SAndroid Build Coastguard Worker     cups_serverroot = CUPS_SERVERROOT;
799*5e7646d2SAndroid Build Coastguard Worker 
800*5e7646d2SAndroid Build Coastguard Worker   snprintf(filename, sizeof(filename), "%s/snmp.conf", cups_serverroot);
801*5e7646d2SAndroid Build Coastguard Worker 
802*5e7646d2SAndroid Build Coastguard Worker   if ((fp = cupsFileOpen(filename, "r")) != NULL)
803*5e7646d2SAndroid Build Coastguard Worker   {
804*5e7646d2SAndroid Build Coastguard Worker    /*
805*5e7646d2SAndroid Build Coastguard Worker     * Read the snmp.conf file...
806*5e7646d2SAndroid Build Coastguard Worker     */
807*5e7646d2SAndroid Build Coastguard Worker 
808*5e7646d2SAndroid Build Coastguard Worker     linenum = 0;
809*5e7646d2SAndroid Build Coastguard Worker 
810*5e7646d2SAndroid Build Coastguard Worker     while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
811*5e7646d2SAndroid Build Coastguard Worker     {
812*5e7646d2SAndroid Build Coastguard Worker       if (!value)
813*5e7646d2SAndroid Build Coastguard Worker         fprintf(stderr, "ERROR: Missing value on line %d of %s!\n", linenum,
814*5e7646d2SAndroid Build Coastguard Worker 	        filename);
815*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strcasecmp(line, "Address"))
816*5e7646d2SAndroid Build Coastguard Worker       {
817*5e7646d2SAndroid Build Coastguard Worker         if (!address)
818*5e7646d2SAndroid Build Coastguard Worker           add_array(Addresses, value);
819*5e7646d2SAndroid Build Coastguard Worker       }
820*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strcasecmp(line, "Community"))
821*5e7646d2SAndroid Build Coastguard Worker         add_array(Communities, value);
822*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strcasecmp(line, "DebugLevel"))
823*5e7646d2SAndroid Build Coastguard Worker         DebugLevel = atoi(value);
824*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strcasecmp(line, "DeviceURI"))
825*5e7646d2SAndroid Build Coastguard Worker       {
826*5e7646d2SAndroid Build Coastguard Worker         if (*value != '\"')
827*5e7646d2SAndroid Build Coastguard Worker 	  fprintf(stderr,
828*5e7646d2SAndroid Build Coastguard Worker 	          "ERROR: Missing double quote for regular expression on "
829*5e7646d2SAndroid Build Coastguard Worker 		  "line %d of %s!\n", linenum, filename);
830*5e7646d2SAndroid Build Coastguard Worker         else
831*5e7646d2SAndroid Build Coastguard Worker 	  add_device_uri(value);
832*5e7646d2SAndroid Build Coastguard Worker       }
833*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strcasecmp(line, "HostNameLookups"))
834*5e7646d2SAndroid Build Coastguard Worker         HostNameLookups = !_cups_strcasecmp(value, "on") ||
835*5e7646d2SAndroid Build Coastguard Worker 	                  !_cups_strcasecmp(value, "yes") ||
836*5e7646d2SAndroid Build Coastguard Worker 	                  !_cups_strcasecmp(value, "true") ||
837*5e7646d2SAndroid Build Coastguard Worker 	                  !_cups_strcasecmp(value, "double");
838*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strcasecmp(line, "MaxRunTime"))
839*5e7646d2SAndroid Build Coastguard Worker         MaxRunTime = atoi(value);
840*5e7646d2SAndroid Build Coastguard Worker       else
841*5e7646d2SAndroid Build Coastguard Worker         fprintf(stderr, "ERROR: Unknown directive %s on line %d of %s!\n",
842*5e7646d2SAndroid Build Coastguard Worker 	        line, linenum, filename);
843*5e7646d2SAndroid Build Coastguard Worker     }
844*5e7646d2SAndroid Build Coastguard Worker 
845*5e7646d2SAndroid Build Coastguard Worker     cupsFileClose(fp);
846*5e7646d2SAndroid Build Coastguard Worker   }
847*5e7646d2SAndroid Build Coastguard Worker 
848*5e7646d2SAndroid Build Coastguard Worker  /*
849*5e7646d2SAndroid Build Coastguard Worker   * Use defaults if parameters are undefined...
850*5e7646d2SAndroid Build Coastguard Worker   */
851*5e7646d2SAndroid Build Coastguard Worker 
852*5e7646d2SAndroid Build Coastguard Worker   if (cupsArrayCount(Addresses) == 0)
853*5e7646d2SAndroid Build Coastguard Worker   {
854*5e7646d2SAndroid Build Coastguard Worker    /*
855*5e7646d2SAndroid Build Coastguard Worker     * If we have no addresses, exit immediately...
856*5e7646d2SAndroid Build Coastguard Worker     */
857*5e7646d2SAndroid Build Coastguard Worker 
858*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr,
859*5e7646d2SAndroid Build Coastguard Worker             "DEBUG: No address specified and no Address line in %s...\n",
860*5e7646d2SAndroid Build Coastguard Worker 	    filename);
861*5e7646d2SAndroid Build Coastguard Worker     exit(0);
862*5e7646d2SAndroid Build Coastguard Worker   }
863*5e7646d2SAndroid Build Coastguard Worker 
864*5e7646d2SAndroid Build Coastguard Worker   if (cupsArrayCount(Communities) == 0)
865*5e7646d2SAndroid Build Coastguard Worker   {
866*5e7646d2SAndroid Build Coastguard Worker     fputs("INFO: Using default SNMP Community public\n", stderr);
867*5e7646d2SAndroid Build Coastguard Worker     add_array(Communities, "public");
868*5e7646d2SAndroid Build Coastguard Worker   }
869*5e7646d2SAndroid Build Coastguard Worker }
870*5e7646d2SAndroid Build Coastguard Worker 
871*5e7646d2SAndroid Build Coastguard Worker 
872*5e7646d2SAndroid Build Coastguard Worker /*
873*5e7646d2SAndroid Build Coastguard Worker  * 'read_snmp_response()' - Read and parse a SNMP response...
874*5e7646d2SAndroid Build Coastguard Worker  */
875*5e7646d2SAndroid Build Coastguard Worker 
876*5e7646d2SAndroid Build Coastguard Worker static void
read_snmp_response(int fd)877*5e7646d2SAndroid Build Coastguard Worker read_snmp_response(int fd)		/* I - SNMP socket file descriptor */
878*5e7646d2SAndroid Build Coastguard Worker {
879*5e7646d2SAndroid Build Coastguard Worker   char		addrname[256];		/* Source address name */
880*5e7646d2SAndroid Build Coastguard Worker   cups_snmp_t	packet;			/* Decoded packet */
881*5e7646d2SAndroid Build Coastguard Worker   snmp_cache_t	key,			/* Search key */
882*5e7646d2SAndroid Build Coastguard Worker 		*device;		/* Matching device */
883*5e7646d2SAndroid Build Coastguard Worker 
884*5e7646d2SAndroid Build Coastguard Worker 
885*5e7646d2SAndroid Build Coastguard Worker  /*
886*5e7646d2SAndroid Build Coastguard Worker   * Read the response data...
887*5e7646d2SAndroid Build Coastguard Worker   */
888*5e7646d2SAndroid Build Coastguard Worker 
889*5e7646d2SAndroid Build Coastguard Worker   if (!_cupsSNMPRead(fd, &packet, -1.0))
890*5e7646d2SAndroid Build Coastguard Worker   {
891*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "ERROR: Unable to read data from socket: %s\n",
892*5e7646d2SAndroid Build Coastguard Worker             strerror(errno));
893*5e7646d2SAndroid Build Coastguard Worker     return;
894*5e7646d2SAndroid Build Coastguard Worker   }
895*5e7646d2SAndroid Build Coastguard Worker 
896*5e7646d2SAndroid Build Coastguard Worker   if (HostNameLookups)
897*5e7646d2SAndroid Build Coastguard Worker     httpAddrLookup(&(packet.address), addrname, sizeof(addrname));
898*5e7646d2SAndroid Build Coastguard Worker   else
899*5e7646d2SAndroid Build Coastguard Worker     httpAddrString(&(packet.address), addrname, sizeof(addrname));
900*5e7646d2SAndroid Build Coastguard Worker 
901*5e7646d2SAndroid Build Coastguard Worker   debug_printf("DEBUG: %.3f Received data from %s...\n", run_time(), addrname);
902*5e7646d2SAndroid Build Coastguard Worker 
903*5e7646d2SAndroid Build Coastguard Worker  /*
904*5e7646d2SAndroid Build Coastguard Worker   * Look for the response status code in the SNMP message header...
905*5e7646d2SAndroid Build Coastguard Worker   */
906*5e7646d2SAndroid Build Coastguard Worker 
907*5e7646d2SAndroid Build Coastguard Worker   if (packet.error)
908*5e7646d2SAndroid Build Coastguard Worker   {
909*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "ERROR: Bad SNMP packet from %s: %s\n", addrname,
910*5e7646d2SAndroid Build Coastguard Worker             packet.error);
911*5e7646d2SAndroid Build Coastguard Worker 
912*5e7646d2SAndroid Build Coastguard Worker     return;
913*5e7646d2SAndroid Build Coastguard Worker   }
914*5e7646d2SAndroid Build Coastguard Worker 
915*5e7646d2SAndroid Build Coastguard Worker   debug_printf("DEBUG: community=\"%s\"\n", packet.community);
916*5e7646d2SAndroid Build Coastguard Worker   debug_printf("DEBUG: request-id=%d\n", packet.request_id);
917*5e7646d2SAndroid Build Coastguard Worker   debug_printf("DEBUG: error-status=%d\n", packet.error_status);
918*5e7646d2SAndroid Build Coastguard Worker 
919*5e7646d2SAndroid Build Coastguard Worker   if (packet.error_status && packet.request_id != DEVICE_TYPE)
920*5e7646d2SAndroid Build Coastguard Worker     return;
921*5e7646d2SAndroid Build Coastguard Worker 
922*5e7646d2SAndroid Build Coastguard Worker  /*
923*5e7646d2SAndroid Build Coastguard Worker   * Find a matching device in the cache...
924*5e7646d2SAndroid Build Coastguard Worker   */
925*5e7646d2SAndroid Build Coastguard Worker 
926*5e7646d2SAndroid Build Coastguard Worker   key.addrname = addrname;
927*5e7646d2SAndroid Build Coastguard Worker   device       = (snmp_cache_t *)cupsArrayFind(Devices, &key);
928*5e7646d2SAndroid Build Coastguard Worker 
929*5e7646d2SAndroid Build Coastguard Worker  /*
930*5e7646d2SAndroid Build Coastguard Worker   * Process the message...
931*5e7646d2SAndroid Build Coastguard Worker   */
932*5e7646d2SAndroid Build Coastguard Worker 
933*5e7646d2SAndroid Build Coastguard Worker   switch (packet.request_id)
934*5e7646d2SAndroid Build Coastguard Worker   {
935*5e7646d2SAndroid Build Coastguard Worker     case DEVICE_TYPE :
936*5e7646d2SAndroid Build Coastguard Worker        /*
937*5e7646d2SAndroid Build Coastguard Worker 	* Got the device type response...
938*5e7646d2SAndroid Build Coastguard Worker 	*/
939*5e7646d2SAndroid Build Coastguard Worker 
940*5e7646d2SAndroid Build Coastguard Worker 	if (device)
941*5e7646d2SAndroid Build Coastguard Worker 	{
942*5e7646d2SAndroid Build Coastguard Worker 	  debug_printf("DEBUG: Discarding duplicate device type for \"%s\"...\n",
943*5e7646d2SAndroid Build Coastguard Worker 		       addrname);
944*5e7646d2SAndroid Build Coastguard Worker 	  return;
945*5e7646d2SAndroid Build Coastguard Worker 	}
946*5e7646d2SAndroid Build Coastguard Worker 
947*5e7646d2SAndroid Build Coastguard Worker        /*
948*5e7646d2SAndroid Build Coastguard Worker 	* Add the device and request the device data...
949*5e7646d2SAndroid Build Coastguard Worker 	*/
950*5e7646d2SAndroid Build Coastguard Worker 
951*5e7646d2SAndroid Build Coastguard Worker 	add_cache(&(packet.address), addrname, NULL, NULL, NULL);
952*5e7646d2SAndroid Build Coastguard Worker 
953*5e7646d2SAndroid Build Coastguard Worker 	_cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
954*5e7646d2SAndroid Build Coastguard Worker 	               packet.community, CUPS_ASN1_GET_REQUEST,
955*5e7646d2SAndroid Build Coastguard Worker 		       DEVICE_DESCRIPTION, DescriptionOID);
956*5e7646d2SAndroid Build Coastguard Worker 	_cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
957*5e7646d2SAndroid Build Coastguard Worker 	               packet.community, CUPS_ASN1_GET_REQUEST,
958*5e7646d2SAndroid Build Coastguard Worker 		       DEVICE_ID, DeviceIdOID);
959*5e7646d2SAndroid Build Coastguard Worker 	_cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
960*5e7646d2SAndroid Build Coastguard Worker 	               packet.community, CUPS_ASN1_GET_REQUEST,
961*5e7646d2SAndroid Build Coastguard Worker 		       DEVICE_URI, UriOID);
962*5e7646d2SAndroid Build Coastguard Worker 	_cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
963*5e7646d2SAndroid Build Coastguard Worker 	               packet.community, CUPS_ASN1_GET_REQUEST,
964*5e7646d2SAndroid Build Coastguard Worker 		       DEVICE_LOCATION, LocationOID);
965*5e7646d2SAndroid Build Coastguard Worker 	_cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
966*5e7646d2SAndroid Build Coastguard Worker 	               packet.community, CUPS_ASN1_GET_REQUEST,
967*5e7646d2SAndroid Build Coastguard Worker 		       DEVICE_PRODUCT, LexmarkProductOID);
968*5e7646d2SAndroid Build Coastguard Worker 	_cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
969*5e7646d2SAndroid Build Coastguard Worker 	               packet.community, CUPS_ASN1_GET_REQUEST,
970*5e7646d2SAndroid Build Coastguard Worker 		       DEVICE_PRODUCT, LexmarkProductOID2);
971*5e7646d2SAndroid Build Coastguard Worker 	_cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
972*5e7646d2SAndroid Build Coastguard Worker 	               packet.community, CUPS_ASN1_GET_REQUEST,
973*5e7646d2SAndroid Build Coastguard Worker 		       DEVICE_ID, LexmarkDeviceIdOID);
974*5e7646d2SAndroid Build Coastguard Worker 	_cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
975*5e7646d2SAndroid Build Coastguard Worker 		       packet.community, CUPS_ASN1_GET_REQUEST,
976*5e7646d2SAndroid Build Coastguard Worker 		       DEVICE_ID, RicohDeviceIdOID);
977*5e7646d2SAndroid Build Coastguard Worker 	_cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
978*5e7646d2SAndroid Build Coastguard Worker 	               packet.community, CUPS_ASN1_GET_REQUEST,
979*5e7646d2SAndroid Build Coastguard Worker 		       DEVICE_PRODUCT, XeroxProductOID);
980*5e7646d2SAndroid Build Coastguard Worker 	_cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1,
981*5e7646d2SAndroid Build Coastguard Worker 		       packet.community, CUPS_ASN1_GET_REQUEST,
982*5e7646d2SAndroid Build Coastguard Worker 		       DEVICE_ID, HPDeviceIdOID);
983*5e7646d2SAndroid Build Coastguard Worker         break;
984*5e7646d2SAndroid Build Coastguard Worker 
985*5e7646d2SAndroid Build Coastguard Worker     case DEVICE_DESCRIPTION :
986*5e7646d2SAndroid Build Coastguard Worker 	if (device && packet.object_type == CUPS_ASN1_OCTET_STRING)
987*5e7646d2SAndroid Build Coastguard Worker 	{
988*5e7646d2SAndroid Build Coastguard Worker 	 /*
989*5e7646d2SAndroid Build Coastguard Worker 	  * Update an existing cache entry...
990*5e7646d2SAndroid Build Coastguard Worker 	  */
991*5e7646d2SAndroid Build Coastguard Worker 
992*5e7646d2SAndroid Build Coastguard Worker 	  char	make_model[256];	/* Make and model */
993*5e7646d2SAndroid Build Coastguard Worker 
994*5e7646d2SAndroid Build Coastguard Worker 
995*5e7646d2SAndroid Build Coastguard Worker 	  if (strchr((char *)packet.object_value.string.bytes, ':') &&
996*5e7646d2SAndroid Build Coastguard Worker 	      strchr((char *)packet.object_value.string.bytes, ';'))
997*5e7646d2SAndroid Build Coastguard Worker 	  {
998*5e7646d2SAndroid Build Coastguard Worker 	   /*
999*5e7646d2SAndroid Build Coastguard Worker 	    * Description is the IEEE-1284 device ID...
1000*5e7646d2SAndroid Build Coastguard Worker 	    */
1001*5e7646d2SAndroid Build Coastguard Worker 
1002*5e7646d2SAndroid Build Coastguard Worker             char *ptr;			/* Pointer into device ID */
1003*5e7646d2SAndroid Build Coastguard Worker 
1004*5e7646d2SAndroid Build Coastguard Worker             for (ptr = (char *)packet.object_value.string.bytes; *ptr; ptr ++)
1005*5e7646d2SAndroid Build Coastguard Worker               if (*ptr == '\n')
1006*5e7646d2SAndroid Build Coastguard Worker                 *ptr = ';';		/* A lot of bad printers put a newline */
1007*5e7646d2SAndroid Build Coastguard Worker 	    if (!device->id)
1008*5e7646d2SAndroid Build Coastguard Worker 	      device->id = strdup((char *)packet.object_value.string.bytes);
1009*5e7646d2SAndroid Build Coastguard Worker 
1010*5e7646d2SAndroid Build Coastguard Worker 	    backendGetMakeModel((char *)packet.object_value.string.bytes,
1011*5e7646d2SAndroid Build Coastguard Worker 				make_model, sizeof(make_model));
1012*5e7646d2SAndroid Build Coastguard Worker 
1013*5e7646d2SAndroid Build Coastguard Worker             if (device->info)
1014*5e7646d2SAndroid Build Coastguard Worker 	      free(device->info);
1015*5e7646d2SAndroid Build Coastguard Worker 
1016*5e7646d2SAndroid Build Coastguard Worker 	    device->info = strdup(make_model);
1017*5e7646d2SAndroid Build Coastguard Worker 	  }
1018*5e7646d2SAndroid Build Coastguard Worker 	  else
1019*5e7646d2SAndroid Build Coastguard Worker 	  {
1020*5e7646d2SAndroid Build Coastguard Worker 	   /*
1021*5e7646d2SAndroid Build Coastguard Worker 	    * Description is plain text...
1022*5e7646d2SAndroid Build Coastguard Worker 	    */
1023*5e7646d2SAndroid Build Coastguard Worker 
1024*5e7646d2SAndroid Build Coastguard Worker 	    fix_make_model(make_model, (char *)packet.object_value.string.bytes,
1025*5e7646d2SAndroid Build Coastguard Worker 			   sizeof(make_model));
1026*5e7646d2SAndroid Build Coastguard Worker 
1027*5e7646d2SAndroid Build Coastguard Worker             if (device->info)
1028*5e7646d2SAndroid Build Coastguard Worker 	      free(device->info);
1029*5e7646d2SAndroid Build Coastguard Worker 
1030*5e7646d2SAndroid Build Coastguard Worker 	    device->info = strdup((char *)packet.object_value.string.bytes);
1031*5e7646d2SAndroid Build Coastguard Worker 	  }
1032*5e7646d2SAndroid Build Coastguard Worker 
1033*5e7646d2SAndroid Build Coastguard Worker 	  if (!device->make_and_model)
1034*5e7646d2SAndroid Build Coastguard Worker 	    device->make_and_model = strdup(make_model);
1035*5e7646d2SAndroid Build Coastguard Worker         }
1036*5e7646d2SAndroid Build Coastguard Worker 	break;
1037*5e7646d2SAndroid Build Coastguard Worker 
1038*5e7646d2SAndroid Build Coastguard Worker     case DEVICE_ID :
1039*5e7646d2SAndroid Build Coastguard Worker 	if (device && packet.object_type == CUPS_ASN1_OCTET_STRING &&
1040*5e7646d2SAndroid Build Coastguard Worker 	    (!device->id ||
1041*5e7646d2SAndroid Build Coastguard Worker 	     strlen(device->id) < packet.object_value.string.num_bytes))
1042*5e7646d2SAndroid Build Coastguard Worker 	{
1043*5e7646d2SAndroid Build Coastguard Worker 	 /*
1044*5e7646d2SAndroid Build Coastguard Worker 	  * Update an existing cache entry...
1045*5e7646d2SAndroid Build Coastguard Worker 	  */
1046*5e7646d2SAndroid Build Coastguard Worker 
1047*5e7646d2SAndroid Build Coastguard Worker 	  char	make_model[256];	/* Make and model */
1048*5e7646d2SAndroid Build Coastguard Worker           char *ptr;			/* Pointer into device ID */
1049*5e7646d2SAndroid Build Coastguard Worker 
1050*5e7646d2SAndroid Build Coastguard Worker           for (ptr = (char *)packet.object_value.string.bytes; *ptr; ptr ++)
1051*5e7646d2SAndroid Build Coastguard Worker             if (*ptr == '\n')
1052*5e7646d2SAndroid Build Coastguard Worker               *ptr = ';';		/* A lot of bad printers put a newline */
1053*5e7646d2SAndroid Build Coastguard Worker 	  if (device->id)
1054*5e7646d2SAndroid Build Coastguard Worker 	    free(device->id);
1055*5e7646d2SAndroid Build Coastguard Worker 
1056*5e7646d2SAndroid Build Coastguard Worker 	  device->id = strdup((char *)packet.object_value.string.bytes);
1057*5e7646d2SAndroid Build Coastguard Worker 
1058*5e7646d2SAndroid Build Coastguard Worker 	 /*
1059*5e7646d2SAndroid Build Coastguard Worker 	  * Convert the ID to a make and model string...
1060*5e7646d2SAndroid Build Coastguard Worker 	  */
1061*5e7646d2SAndroid Build Coastguard Worker 
1062*5e7646d2SAndroid Build Coastguard Worker 	  backendGetMakeModel((char *)packet.object_value.string.bytes,
1063*5e7646d2SAndroid Build Coastguard Worker 	                      make_model, sizeof(make_model));
1064*5e7646d2SAndroid Build Coastguard Worker 	  if (device->make_and_model)
1065*5e7646d2SAndroid Build Coastguard Worker 	    free(device->make_and_model);
1066*5e7646d2SAndroid Build Coastguard Worker 
1067*5e7646d2SAndroid Build Coastguard Worker 	  device->make_and_model = strdup(make_model);
1068*5e7646d2SAndroid Build Coastguard Worker 	}
1069*5e7646d2SAndroid Build Coastguard Worker 	break;
1070*5e7646d2SAndroid Build Coastguard Worker 
1071*5e7646d2SAndroid Build Coastguard Worker     case DEVICE_LOCATION :
1072*5e7646d2SAndroid Build Coastguard Worker 	if (device && packet.object_type == CUPS_ASN1_OCTET_STRING &&
1073*5e7646d2SAndroid Build Coastguard Worker 	    !device->location)
1074*5e7646d2SAndroid Build Coastguard Worker 	  device->location = strdup((char *)packet.object_value.string.bytes);
1075*5e7646d2SAndroid Build Coastguard Worker 	break;
1076*5e7646d2SAndroid Build Coastguard Worker 
1077*5e7646d2SAndroid Build Coastguard Worker     case DEVICE_PRODUCT :
1078*5e7646d2SAndroid Build Coastguard Worker 	if (device && packet.object_type == CUPS_ASN1_OCTET_STRING &&
1079*5e7646d2SAndroid Build Coastguard Worker 	    !device->id)
1080*5e7646d2SAndroid Build Coastguard Worker 	{
1081*5e7646d2SAndroid Build Coastguard Worker 	 /*
1082*5e7646d2SAndroid Build Coastguard Worker 	  * Update an existing cache entry...
1083*5e7646d2SAndroid Build Coastguard Worker 	  */
1084*5e7646d2SAndroid Build Coastguard Worker 
1085*5e7646d2SAndroid Build Coastguard Worker           if (!device->info)
1086*5e7646d2SAndroid Build Coastguard Worker 	    device->info = strdup((char *)packet.object_value.string.bytes);
1087*5e7646d2SAndroid Build Coastguard Worker 
1088*5e7646d2SAndroid Build Coastguard Worker           if (device->make_and_model)
1089*5e7646d2SAndroid Build Coastguard Worker 	    free(device->make_and_model);
1090*5e7646d2SAndroid Build Coastguard Worker 
1091*5e7646d2SAndroid Build Coastguard Worker 	  device->make_and_model = strdup((char *)packet.object_value.string.bytes);
1092*5e7646d2SAndroid Build Coastguard Worker 	}
1093*5e7646d2SAndroid Build Coastguard Worker 	break;
1094*5e7646d2SAndroid Build Coastguard Worker 
1095*5e7646d2SAndroid Build Coastguard Worker     case DEVICE_URI :
1096*5e7646d2SAndroid Build Coastguard Worker 	if (device && packet.object_type == CUPS_ASN1_OCTET_STRING &&
1097*5e7646d2SAndroid Build Coastguard Worker 	    !device->uri && packet.object_value.string.num_bytes > 3)
1098*5e7646d2SAndroid Build Coastguard Worker 	{
1099*5e7646d2SAndroid Build Coastguard Worker 	 /*
1100*5e7646d2SAndroid Build Coastguard Worker 	  * Update an existing cache entry...
1101*5e7646d2SAndroid Build Coastguard Worker 	  */
1102*5e7646d2SAndroid Build Coastguard Worker 
1103*5e7646d2SAndroid Build Coastguard Worker           char	scheme[32],		/* URI scheme */
1104*5e7646d2SAndroid Build Coastguard Worker 		userpass[256],		/* Username:password in URI */
1105*5e7646d2SAndroid Build Coastguard Worker 		hostname[256],		/* Hostname in URI */
1106*5e7646d2SAndroid Build Coastguard Worker 		resource[1024];		/* Resource path in URI */
1107*5e7646d2SAndroid Build Coastguard Worker 	  int	port;			/* Port number in URI */
1108*5e7646d2SAndroid Build Coastguard Worker 
1109*5e7646d2SAndroid Build Coastguard Worker 	  if (!strncmp((char *)packet.object_value.string.bytes, "lpr:", 4))
1110*5e7646d2SAndroid Build Coastguard Worker 	  {
1111*5e7646d2SAndroid Build Coastguard Worker 	   /*
1112*5e7646d2SAndroid Build Coastguard Worker 	    * We want "lpd://..." for the URI...
1113*5e7646d2SAndroid Build Coastguard Worker 	    */
1114*5e7646d2SAndroid Build Coastguard Worker 
1115*5e7646d2SAndroid Build Coastguard Worker 	    packet.object_value.string.bytes[2] = 'd';
1116*5e7646d2SAndroid Build Coastguard Worker 	  }
1117*5e7646d2SAndroid Build Coastguard Worker 
1118*5e7646d2SAndroid Build Coastguard Worker           if (httpSeparateURI(HTTP_URI_CODING_ALL,
1119*5e7646d2SAndroid Build Coastguard Worker                               (char *)packet.object_value.string.bytes,
1120*5e7646d2SAndroid Build Coastguard Worker                               scheme, sizeof(scheme),
1121*5e7646d2SAndroid Build Coastguard Worker                               userpass, sizeof(userpass),
1122*5e7646d2SAndroid Build Coastguard Worker                               hostname, sizeof(hostname), &port,
1123*5e7646d2SAndroid Build Coastguard Worker                               resource, sizeof(resource)) >= HTTP_URI_OK)
1124*5e7646d2SAndroid Build Coastguard Worker 	    device->uri = strdup((char *)packet.object_value.string.bytes);
1125*5e7646d2SAndroid Build Coastguard Worker 	}
1126*5e7646d2SAndroid Build Coastguard Worker 	break;
1127*5e7646d2SAndroid Build Coastguard Worker   }
1128*5e7646d2SAndroid Build Coastguard Worker }
1129*5e7646d2SAndroid Build Coastguard Worker 
1130*5e7646d2SAndroid Build Coastguard Worker 
1131*5e7646d2SAndroid Build Coastguard Worker /*
1132*5e7646d2SAndroid Build Coastguard Worker  * 'run_time()' - Return the total running time...
1133*5e7646d2SAndroid Build Coastguard Worker  */
1134*5e7646d2SAndroid Build Coastguard Worker 
1135*5e7646d2SAndroid Build Coastguard Worker static double				/* O - Number of seconds */
run_time(void)1136*5e7646d2SAndroid Build Coastguard Worker run_time(void)
1137*5e7646d2SAndroid Build Coastguard Worker {
1138*5e7646d2SAndroid Build Coastguard Worker   struct timeval	curtime;	/* Current time */
1139*5e7646d2SAndroid Build Coastguard Worker 
1140*5e7646d2SAndroid Build Coastguard Worker 
1141*5e7646d2SAndroid Build Coastguard Worker   gettimeofday(&curtime, NULL);
1142*5e7646d2SAndroid Build Coastguard Worker 
1143*5e7646d2SAndroid Build Coastguard Worker   return (curtime.tv_sec - StartTime.tv_sec +
1144*5e7646d2SAndroid Build Coastguard Worker           0.000001 * (curtime.tv_usec - StartTime.tv_usec));
1145*5e7646d2SAndroid Build Coastguard Worker }
1146*5e7646d2SAndroid Build Coastguard Worker 
1147*5e7646d2SAndroid Build Coastguard Worker 
1148*5e7646d2SAndroid Build Coastguard Worker /*
1149*5e7646d2SAndroid Build Coastguard Worker  * 'scan_devices()' - Scan for devices using SNMP.
1150*5e7646d2SAndroid Build Coastguard Worker  */
1151*5e7646d2SAndroid Build Coastguard Worker 
1152*5e7646d2SAndroid Build Coastguard Worker static void
scan_devices(int ipv4,int ipv6)1153*5e7646d2SAndroid Build Coastguard Worker scan_devices(int ipv4,			/* I - SNMP IPv4 socket */
1154*5e7646d2SAndroid Build Coastguard Worker              int ipv6)			/* I - SNMP IPv6 socket */
1155*5e7646d2SAndroid Build Coastguard Worker {
1156*5e7646d2SAndroid Build Coastguard Worker   int			fd,		/* File descriptor for this address */
1157*5e7646d2SAndroid Build Coastguard Worker 			busy;		/* Are we busy processing something? */
1158*5e7646d2SAndroid Build Coastguard Worker   char			*address,	/* Current address */
1159*5e7646d2SAndroid Build Coastguard Worker 			*community;	/* Current community */
1160*5e7646d2SAndroid Build Coastguard Worker   fd_set		input;		/* Input set for select() */
1161*5e7646d2SAndroid Build Coastguard Worker   struct timeval	timeout;	/* Timeout for select() */
1162*5e7646d2SAndroid Build Coastguard Worker   time_t		endtime;	/* End time for scan */
1163*5e7646d2SAndroid Build Coastguard Worker   http_addrlist_t	*addrs,		/* List of addresses */
1164*5e7646d2SAndroid Build Coastguard Worker 			*addr;		/* Current address */
1165*5e7646d2SAndroid Build Coastguard Worker   snmp_cache_t		*device;	/* Current device */
1166*5e7646d2SAndroid Build Coastguard Worker   char			temp[1024];	/* Temporary address string */
1167*5e7646d2SAndroid Build Coastguard Worker 
1168*5e7646d2SAndroid Build Coastguard Worker 
1169*5e7646d2SAndroid Build Coastguard Worker   gettimeofday(&StartTime, NULL);
1170*5e7646d2SAndroid Build Coastguard Worker 
1171*5e7646d2SAndroid Build Coastguard Worker  /*
1172*5e7646d2SAndroid Build Coastguard Worker   * First send all of the broadcast queries...
1173*5e7646d2SAndroid Build Coastguard Worker   */
1174*5e7646d2SAndroid Build Coastguard Worker 
1175*5e7646d2SAndroid Build Coastguard Worker   for (address = (char *)cupsArrayFirst(Addresses);
1176*5e7646d2SAndroid Build Coastguard Worker        address;
1177*5e7646d2SAndroid Build Coastguard Worker        address = (char *)cupsArrayNext(Addresses))
1178*5e7646d2SAndroid Build Coastguard Worker   {
1179*5e7646d2SAndroid Build Coastguard Worker     if (!strcmp(address, "@LOCAL"))
1180*5e7646d2SAndroid Build Coastguard Worker       addrs = get_interface_addresses(NULL);
1181*5e7646d2SAndroid Build Coastguard Worker     else if (!strncmp(address, "@IF(", 4))
1182*5e7646d2SAndroid Build Coastguard Worker     {
1183*5e7646d2SAndroid Build Coastguard Worker       char	ifname[255];		/* Interface name */
1184*5e7646d2SAndroid Build Coastguard Worker 
1185*5e7646d2SAndroid Build Coastguard Worker       strlcpy(ifname, address + 4, sizeof(ifname));
1186*5e7646d2SAndroid Build Coastguard Worker       if (ifname[0])
1187*5e7646d2SAndroid Build Coastguard Worker         ifname[strlen(ifname) - 1] = '\0';
1188*5e7646d2SAndroid Build Coastguard Worker 
1189*5e7646d2SAndroid Build Coastguard Worker       addrs = get_interface_addresses(ifname);
1190*5e7646d2SAndroid Build Coastguard Worker     }
1191*5e7646d2SAndroid Build Coastguard Worker     else
1192*5e7646d2SAndroid Build Coastguard Worker       addrs = httpAddrGetList(address, AF_UNSPEC, NULL);
1193*5e7646d2SAndroid Build Coastguard Worker 
1194*5e7646d2SAndroid Build Coastguard Worker     if (!addrs)
1195*5e7646d2SAndroid Build Coastguard Worker     {
1196*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "ERROR: Unable to scan \"%s\"!\n", address);
1197*5e7646d2SAndroid Build Coastguard Worker       continue;
1198*5e7646d2SAndroid Build Coastguard Worker     }
1199*5e7646d2SAndroid Build Coastguard Worker 
1200*5e7646d2SAndroid Build Coastguard Worker     for (community = (char *)cupsArrayFirst(Communities);
1201*5e7646d2SAndroid Build Coastguard Worker          community;
1202*5e7646d2SAndroid Build Coastguard Worker 	 community = (char *)cupsArrayNext(Communities))
1203*5e7646d2SAndroid Build Coastguard Worker     {
1204*5e7646d2SAndroid Build Coastguard Worker       debug_printf("DEBUG: Scanning for devices in \"%s\" via \"%s\"...\n",
1205*5e7646d2SAndroid Build Coastguard Worker         	   community, address);
1206*5e7646d2SAndroid Build Coastguard Worker 
1207*5e7646d2SAndroid Build Coastguard Worker       for (addr = addrs; addr; addr = addr->next)
1208*5e7646d2SAndroid Build Coastguard Worker       {
1209*5e7646d2SAndroid Build Coastguard Worker #ifdef AF_INET6
1210*5e7646d2SAndroid Build Coastguard Worker         if (httpAddrFamily(&(addr->addr)) == AF_INET6)
1211*5e7646d2SAndroid Build Coastguard Worker 	  fd = ipv6;
1212*5e7646d2SAndroid Build Coastguard Worker 	else
1213*5e7646d2SAndroid Build Coastguard Worker #endif /* AF_INET6 */
1214*5e7646d2SAndroid Build Coastguard Worker         fd = ipv4;
1215*5e7646d2SAndroid Build Coastguard Worker 
1216*5e7646d2SAndroid Build Coastguard Worker         debug_printf("DEBUG: Sending get request to %s...\n",
1217*5e7646d2SAndroid Build Coastguard Worker 	             httpAddrString(&(addr->addr), temp, sizeof(temp)));
1218*5e7646d2SAndroid Build Coastguard Worker 
1219*5e7646d2SAndroid Build Coastguard Worker         _cupsSNMPWrite(fd, &(addr->addr), CUPS_SNMP_VERSION_1, community,
1220*5e7646d2SAndroid Build Coastguard Worker 	               CUPS_ASN1_GET_REQUEST, DEVICE_TYPE, DeviceTypeOID);
1221*5e7646d2SAndroid Build Coastguard Worker       }
1222*5e7646d2SAndroid Build Coastguard Worker     }
1223*5e7646d2SAndroid Build Coastguard Worker 
1224*5e7646d2SAndroid Build Coastguard Worker     httpAddrFreeList(addrs);
1225*5e7646d2SAndroid Build Coastguard Worker   }
1226*5e7646d2SAndroid Build Coastguard Worker 
1227*5e7646d2SAndroid Build Coastguard Worker  /*
1228*5e7646d2SAndroid Build Coastguard Worker   * Then read any responses that come in over the next 3 seconds...
1229*5e7646d2SAndroid Build Coastguard Worker   */
1230*5e7646d2SAndroid Build Coastguard Worker 
1231*5e7646d2SAndroid Build Coastguard Worker   endtime = time(NULL) + MaxRunTime;
1232*5e7646d2SAndroid Build Coastguard Worker 
1233*5e7646d2SAndroid Build Coastguard Worker   FD_ZERO(&input);
1234*5e7646d2SAndroid Build Coastguard Worker 
1235*5e7646d2SAndroid Build Coastguard Worker   while (time(NULL) < endtime)
1236*5e7646d2SAndroid Build Coastguard Worker   {
1237*5e7646d2SAndroid Build Coastguard Worker     timeout.tv_sec  = 2;
1238*5e7646d2SAndroid Build Coastguard Worker     timeout.tv_usec = 0;
1239*5e7646d2SAndroid Build Coastguard Worker 
1240*5e7646d2SAndroid Build Coastguard Worker     FD_SET(ipv4, &input);
1241*5e7646d2SAndroid Build Coastguard Worker     if (ipv6 >= 0)
1242*5e7646d2SAndroid Build Coastguard Worker       FD_SET(ipv6, &input);
1243*5e7646d2SAndroid Build Coastguard Worker 
1244*5e7646d2SAndroid Build Coastguard Worker     fd = ipv4 > ipv6 ? ipv4 : ipv6;
1245*5e7646d2SAndroid Build Coastguard Worker     if (select(fd + 1, &input, NULL, NULL, &timeout) < 0)
1246*5e7646d2SAndroid Build Coastguard Worker     {
1247*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "ERROR: %.3f select() for %d/%d failed: %s\n", run_time(),
1248*5e7646d2SAndroid Build Coastguard Worker               ipv4, ipv6, strerror(errno));
1249*5e7646d2SAndroid Build Coastguard Worker       break;
1250*5e7646d2SAndroid Build Coastguard Worker     }
1251*5e7646d2SAndroid Build Coastguard Worker 
1252*5e7646d2SAndroid Build Coastguard Worker     busy = 0;
1253*5e7646d2SAndroid Build Coastguard Worker 
1254*5e7646d2SAndroid Build Coastguard Worker     if (FD_ISSET(ipv4, &input))
1255*5e7646d2SAndroid Build Coastguard Worker     {
1256*5e7646d2SAndroid Build Coastguard Worker       read_snmp_response(ipv4);
1257*5e7646d2SAndroid Build Coastguard Worker       busy = 1;
1258*5e7646d2SAndroid Build Coastguard Worker     }
1259*5e7646d2SAndroid Build Coastguard Worker 
1260*5e7646d2SAndroid Build Coastguard Worker     if (ipv6 >= 0 && FD_ISSET(ipv6, &input))
1261*5e7646d2SAndroid Build Coastguard Worker     {
1262*5e7646d2SAndroid Build Coastguard Worker       read_snmp_response(ipv6);
1263*5e7646d2SAndroid Build Coastguard Worker       busy = 1;
1264*5e7646d2SAndroid Build Coastguard Worker     }
1265*5e7646d2SAndroid Build Coastguard Worker 
1266*5e7646d2SAndroid Build Coastguard Worker     if (!busy)
1267*5e7646d2SAndroid Build Coastguard Worker     {
1268*5e7646d2SAndroid Build Coastguard Worker      /*
1269*5e7646d2SAndroid Build Coastguard Worker       * List devices with complete information...
1270*5e7646d2SAndroid Build Coastguard Worker       */
1271*5e7646d2SAndroid Build Coastguard Worker 
1272*5e7646d2SAndroid Build Coastguard Worker       int sent_something = 0;
1273*5e7646d2SAndroid Build Coastguard Worker 
1274*5e7646d2SAndroid Build Coastguard Worker       for (device = (snmp_cache_t *)cupsArrayFirst(Devices);
1275*5e7646d2SAndroid Build Coastguard Worker            device;
1276*5e7646d2SAndroid Build Coastguard Worker 	   device = (snmp_cache_t *)cupsArrayNext(Devices))
1277*5e7646d2SAndroid Build Coastguard Worker         if (!device->sent && device->info && device->make_and_model)
1278*5e7646d2SAndroid Build Coastguard Worker 	{
1279*5e7646d2SAndroid Build Coastguard Worker 	  if (device->uri)
1280*5e7646d2SAndroid Build Coastguard Worker 	    list_device(device);
1281*5e7646d2SAndroid Build Coastguard Worker 	  else
1282*5e7646d2SAndroid Build Coastguard Worker 	    probe_device(device);
1283*5e7646d2SAndroid Build Coastguard Worker 
1284*5e7646d2SAndroid Build Coastguard Worker 	  device->sent = sent_something = 1;
1285*5e7646d2SAndroid Build Coastguard Worker 	}
1286*5e7646d2SAndroid Build Coastguard Worker 
1287*5e7646d2SAndroid Build Coastguard Worker       if (!sent_something)
1288*5e7646d2SAndroid Build Coastguard Worker         break;
1289*5e7646d2SAndroid Build Coastguard Worker     }
1290*5e7646d2SAndroid Build Coastguard Worker   }
1291*5e7646d2SAndroid Build Coastguard Worker 
1292*5e7646d2SAndroid Build Coastguard Worker   debug_printf("DEBUG: %.3f Scan complete!\n", run_time());
1293*5e7646d2SAndroid Build Coastguard Worker }
1294*5e7646d2SAndroid Build Coastguard Worker 
1295*5e7646d2SAndroid Build Coastguard Worker 
1296*5e7646d2SAndroid Build Coastguard Worker /*
1297*5e7646d2SAndroid Build Coastguard Worker  * 'try_connect()' - Try connecting on a port...
1298*5e7646d2SAndroid Build Coastguard Worker  */
1299*5e7646d2SAndroid Build Coastguard Worker 
1300*5e7646d2SAndroid Build Coastguard Worker static int				/* O - 0 on success or -1 on error */
try_connect(http_addr_t * addr,const char * addrname,int port)1301*5e7646d2SAndroid Build Coastguard Worker try_connect(http_addr_t *addr,		/* I - Socket address */
1302*5e7646d2SAndroid Build Coastguard Worker             const char  *addrname,	/* I - Hostname or IP address */
1303*5e7646d2SAndroid Build Coastguard Worker             int         port)		/* I - Port number */
1304*5e7646d2SAndroid Build Coastguard Worker {
1305*5e7646d2SAndroid Build Coastguard Worker   int	fd;				/* Socket */
1306*5e7646d2SAndroid Build Coastguard Worker   int	status;				/* Connection status */
1307*5e7646d2SAndroid Build Coastguard Worker 
1308*5e7646d2SAndroid Build Coastguard Worker 
1309*5e7646d2SAndroid Build Coastguard Worker   debug_printf("DEBUG: %.3f Trying %s://%s:%d...\n", run_time(),
1310*5e7646d2SAndroid Build Coastguard Worker                port == 515 ? "lpd" : "socket", addrname, port);
1311*5e7646d2SAndroid Build Coastguard Worker 
1312*5e7646d2SAndroid Build Coastguard Worker   if ((fd = socket(httpAddrFamily(addr), SOCK_STREAM, 0)) < 0)
1313*5e7646d2SAndroid Build Coastguard Worker   {
1314*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "ERROR: Unable to create socket: %s\n",
1315*5e7646d2SAndroid Build Coastguard Worker             strerror(errno));
1316*5e7646d2SAndroid Build Coastguard Worker     return (-1);
1317*5e7646d2SAndroid Build Coastguard Worker   }
1318*5e7646d2SAndroid Build Coastguard Worker 
1319*5e7646d2SAndroid Build Coastguard Worker   _httpAddrSetPort(addr, port);
1320*5e7646d2SAndroid Build Coastguard Worker 
1321*5e7646d2SAndroid Build Coastguard Worker   alarm(1);
1322*5e7646d2SAndroid Build Coastguard Worker 
1323*5e7646d2SAndroid Build Coastguard Worker   status = connect(fd, (void *)addr, (socklen_t)httpAddrLength(addr));
1324*5e7646d2SAndroid Build Coastguard Worker 
1325*5e7646d2SAndroid Build Coastguard Worker   close(fd);
1326*5e7646d2SAndroid Build Coastguard Worker   alarm(0);
1327*5e7646d2SAndroid Build Coastguard Worker 
1328*5e7646d2SAndroid Build Coastguard Worker   return (status);
1329*5e7646d2SAndroid Build Coastguard Worker }
1330*5e7646d2SAndroid Build Coastguard Worker 
1331*5e7646d2SAndroid Build Coastguard Worker 
1332*5e7646d2SAndroid Build Coastguard Worker /*
1333*5e7646d2SAndroid Build Coastguard Worker  * 'update_cache()' - Update a cached device...
1334*5e7646d2SAndroid Build Coastguard Worker  */
1335*5e7646d2SAndroid Build Coastguard Worker 
1336*5e7646d2SAndroid Build Coastguard Worker static void
update_cache(snmp_cache_t * device,const char * uri,const char * id,const char * make_model)1337*5e7646d2SAndroid Build Coastguard Worker update_cache(snmp_cache_t *device,	/* I - Device */
1338*5e7646d2SAndroid Build Coastguard Worker              const char   *uri,		/* I - Device URI */
1339*5e7646d2SAndroid Build Coastguard Worker 	     const char   *id,		/* I - Device ID */
1340*5e7646d2SAndroid Build Coastguard Worker 	     const char   *make_model)	/* I - Device make and model */
1341*5e7646d2SAndroid Build Coastguard Worker {
1342*5e7646d2SAndroid Build Coastguard Worker   if (device->uri)
1343*5e7646d2SAndroid Build Coastguard Worker     free(device->uri);
1344*5e7646d2SAndroid Build Coastguard Worker 
1345*5e7646d2SAndroid Build Coastguard Worker   device->uri = strdup(uri);
1346*5e7646d2SAndroid Build Coastguard Worker 
1347*5e7646d2SAndroid Build Coastguard Worker   if (id)
1348*5e7646d2SAndroid Build Coastguard Worker   {
1349*5e7646d2SAndroid Build Coastguard Worker     if (device->id)
1350*5e7646d2SAndroid Build Coastguard Worker       free(device->id);
1351*5e7646d2SAndroid Build Coastguard Worker 
1352*5e7646d2SAndroid Build Coastguard Worker     device->id = strdup(id);
1353*5e7646d2SAndroid Build Coastguard Worker   }
1354*5e7646d2SAndroid Build Coastguard Worker 
1355*5e7646d2SAndroid Build Coastguard Worker   if (make_model)
1356*5e7646d2SAndroid Build Coastguard Worker   {
1357*5e7646d2SAndroid Build Coastguard Worker     if (device->make_and_model)
1358*5e7646d2SAndroid Build Coastguard Worker       free(device->make_and_model);
1359*5e7646d2SAndroid Build Coastguard Worker 
1360*5e7646d2SAndroid Build Coastguard Worker     device->make_and_model = strdup(make_model);
1361*5e7646d2SAndroid Build Coastguard Worker   }
1362*5e7646d2SAndroid Build Coastguard Worker 
1363*5e7646d2SAndroid Build Coastguard Worker   list_device(device);
1364*5e7646d2SAndroid Build Coastguard Worker }
1365