1 /*
2  * swinst_rpm.c:
3  *     hrSWInstalledTable data access:
4  */
5 #include <net-snmp/net-snmp-config.h>
6 #include <net-snmp/net-snmp-features.h>
7 
8 #include <stdio.h>
9 #ifdef HAVE_STDLIB_H
10 #include <stdlib.h>
11 #endif
12 #ifdef HAVE_UNISTD_H
13 #include <unistd.h>
14 #endif
15 #ifdef HAVE_SYS_TYPES_H
16 #include <sys/types.h>
17 #endif
18 #ifdef HAVE_STRING_H
19 #include <string.h>
20 #else
21 #include <strings.h>
22 #endif
23 #ifdef HAVE_FCNTL_H
24 #include <fcntl.h>
25 #endif
26 
27 #ifdef HAVE_RPM_RPMLIB_H
28 #include <rpm/rpmlib.h>
29 #endif
30 #ifdef HAVE_RPM_RPMLIB_H
31 #include <rpm/header.h>
32 #endif
33 #ifdef HAVE_RPMGETPATH		/* HAVE_RPM_RPMMACRO_H */
34 #include <rpm/rpmmacro.h>
35 #endif
36 #ifdef HAVE_RPM_RPMTS_H
37 #include <rpm/rpmts.h>
38 #include <rpm/rpmdb.h>
39 #endif
40 
41 #include <net-snmp/net-snmp-includes.h>
42 #include <net-snmp/agent/net-snmp-agent-includes.h>
43 #include <net-snmp/library/container.h>
44 #include <net-snmp/library/snmp_debug.h>
45 #include <net-snmp/data_access/swinst.h>
46 #include "swinst_private.h"
47 
48 netsnmp_feature_require(date_n_time);
49 
50    /*
51     * Location of RPM package directory.
52     * Used for:
53     *    - reporting hrSWInstalledLast* objects
54     *    - detecting when the cached contents are out of date.
55     */
56 char pkg_directory[SNMP_MAXPATH];
57 
58 /* ---------------------------------------------------------------------
59  */
60 void
netsnmp_swinst_arch_init(void)61 netsnmp_swinst_arch_init(void)
62 {
63     char        *rpmdbpath = NULL;
64     const char  *dbpath;
65     struct stat  stat_buf;
66 
67 #ifdef HAVE_RPMGETPATH
68     rpmReadConfigFiles( NULL, NULL );
69     rpmdbpath = rpmGetPath( "%{_dbpath}", NULL );
70     dbpath = rpmdbpath;
71 #else
72     dbpath = "/var/lib/rpm";   /* Most likely */
73 #endif
74 
75     snprintf( pkg_directory, SNMP_MAXPATH, "%s/Packages", dbpath );
76     SNMP_FREE(rpmdbpath);
77     dbpath = NULL;
78     if (-1 == stat( pkg_directory, &stat_buf )) {
79         snmp_log(LOG_ERR, "Can't find directory of RPM packages");
80         pkg_directory[0] = '\0';
81     }
82 }
83 
84 void
netsnmp_swinst_arch_shutdown(void)85 netsnmp_swinst_arch_shutdown(void)
86 {
87      /* Nothing to do */
88      return;
89 }
90 
91 /* ---------------------------------------------------------------------
92  */
93 int
netsnmp_swinst_arch_load(netsnmp_container * container,u_int flags)94 netsnmp_swinst_arch_load( netsnmp_container *container, u_int flags)
95 {
96     rpmts                 ts;
97 
98     rpmdbMatchIterator    mi;
99     Header                h;
100 #if HAVE_HEADERGET
101     const char           *g;
102     rpmtd                 td_name, td_version, td_release, td_group, td_time;
103 #else
104     char                 *n, *v, *r, *g;
105     int32_t              *t;
106 #endif
107     time_t                install_time;
108     size_t                date_len;
109     int                   i = 1;
110     netsnmp_swinst_entry *entry;
111 
112 #if HAVE_HEADERGET
113     td_name = rpmtdNew();
114     td_version = rpmtdNew();
115     td_release = rpmtdNew();
116     td_group = rpmtdNew();
117     td_time = rpmtdNew();
118 #endif
119     ts = rpmtsCreate();
120     rpmtsSetVSFlags( ts, (_RPMVSF_NOSIGNATURES|_RPMVSF_NODIGESTS));
121 
122     mi = rpmtsInitIterator( ts, RPMDBI_PACKAGES, NULL, 0);
123     if (mi == NULL)
124 	NETSNMP_LOGONCE((LOG_ERR, "rpmdbOpen() failed\n"));
125 
126     while (NULL != (h = rpmdbNextIterator( mi )))
127     {
128         const u_char *dt;
129 
130         entry = netsnmp_swinst_entry_create( i++ );
131         if (NULL == entry)
132             continue;   /* error already logged by function */
133         CONTAINER_INSERT(container, entry);
134 
135         h = headerLink( h );
136 #if HAVE_HEADERGET
137         headerGet(h, RPMTAG_NAME, td_name, HEADERGET_EXT);
138         headerGet(h, RPMTAG_VERSION, td_version, HEADERGET_EXT);
139         headerGet(h, RPMTAG_RELEASE, td_release, HEADERGET_EXT);
140         headerGet(h, RPMTAG_GROUP, td_group, HEADERGET_EXT);
141         headerGet(h, RPMTAG_INSTALLTIME, td_time, HEADERGET_EXT);
142         entry->swName_len = snprintf( entry->swName, sizeof(entry->swName),
143                                       "%s-%s-%s", rpmtdGetString(td_name),
144                                       rpmtdGetString(td_version),
145                                       rpmtdGetString(td_release));
146         install_time = rpmtdGetNumber(td_time);
147         g = rpmtdGetString(td_group);
148 #else
149         headerGetEntry( h, RPMTAG_NAME,        NULL, (void**)&n, NULL);
150         headerGetEntry( h, RPMTAG_VERSION,     NULL, (void**)&v, NULL);
151         headerGetEntry( h, RPMTAG_RELEASE,     NULL, (void**)&r, NULL);
152         headerGetEntry( h, RPMTAG_GROUP,       NULL, (void**)&g, NULL);
153         headerGetEntry( h, RPMTAG_INSTALLTIME, NULL, (void**)&t, NULL);
154         entry->swName_len = snprintf( entry->swName, sizeof(entry->swName),
155                                       "%s-%s-%s", n, v, r);
156         install_time = *t;
157 #endif
158         entry->swType = (g && NULL != strstr( g, "System Environment"))
159                         ? 2      /* operatingSystem */
160                         : 4;     /*  application    */
161         if (entry->swName_len > sizeof(entry->swName))
162             entry->swName_len = sizeof(entry->swName);
163 
164         dt = date_n_time( &install_time, &date_len );
165         if (date_len != 8 && date_len != 11) {
166             snmp_log(LOG_ERR, "Bogus length from date_n_time for %s", entry->swName);
167             entry->swDate_len = 0;
168         }
169         else {
170             entry->swDate_len = date_len;
171             memcpy(entry->swDate, dt, entry->swDate_len);
172         }
173 
174 #if HAVE_HEADERGET
175         rpmtdFreeData(td_name);
176         rpmtdFreeData(td_version);
177         rpmtdFreeData(td_release);
178         rpmtdFreeData(td_group);
179         rpmtdFreeData(td_time);
180 #endif
181         headerFree( h );
182     }
183     rpmdbFreeIterator( mi );
184     rpmtsFree( ts );
185 #if HAVE_HEADERGET
186     rpmtdFree(td_name);
187     rpmtdFree(td_version);
188     rpmtdFree(td_release);
189     rpmtdFree(td_group);
190     rpmtdFree(td_time);
191 #endif
192 
193     DEBUGMSGTL(("swinst:load:arch", "loaded %d entries\n",
194                 (int)CONTAINER_SIZE(container)));
195 
196     return 0;
197 }
198