source: ogServer-Git/src/ogAdmServer.c @ 06af0c2

Last change on this file since 06af0c2 was 06af0c2, checked in by OpenGnSys Support Team <soporte-og@…>, 4 years ago

#990 Use client broadcast address on WoL

Some universities have computers in a different subnet where the
ogServer is, but ogServer WoL functionality only supported to send
packet to its own subnets. This commit solves this.

Now ogServer sends two WoL packets per client, one with the broadcast
address of the interface indicated in the config file, the other with
the broadcast address calculated with the address and netmask of the
client.

To ensure that the second WoL works correctly you must configure
correctly the IP and netmask of the clients. Also, you have to configure
the network of your organization to route WoL packet to the correct
subnet.

  • Property mode set to 100644
File size: 43.3 KB
Line 
1// *******************************************************************************************************
2// Servicio: ogAdmServer
3// Autor: José Manuel Alonso (E.T.S.I.I.) Universidad de Sevilla
4// Fecha Creación: Marzo-2010
5// Fecha Última modificación: Marzo-2010
6// Nombre del fichero: ogAdmServer.cpp
7// Descripción :Este fichero implementa el servicio de administración general del sistema
8// *******************************************************************************************************
9#include "ogAdmServer.h"
10#include "dbi.h"
11#include "utils.h"
12#include "list.h"
13#include "rest.h"
14#include "client.h"
15#include "json.h"
16#include "schedule.h"
17#include <syslog.h>
18#include <sys/ioctl.h>
19#include <ifaddrs.h>
20#include <sys/types.h>
21#include <sys/stat.h>
22#include <fcntl.h>
23#include <jansson.h>
24#include <time.h>
25
26char usuario[4096]; // Usuario de acceso a la base de datos
27char pasguor[4096]; // Password del usuario
28char datasource[4096]; // Dirección IP del gestor de base de datos
29char catalog[4096]; // Nombre de la base de datos
30char interface[4096]; // Interface name
31char auth_token[4096]; // API token
32char servidoradm[4096]; // Dirección IP del servidor de administración
33char puerto[4096];    // Puerto de comunicación
34
35SOCKETCL tbsockets[MAXIMOS_CLIENTES];
36
37struct og_dbi_config dbi_config = {
38        .user           = usuario,
39        .passwd         = pasguor,
40        .host           = datasource,
41        .database       = catalog,
42};
43
44//________________________________________________________________________________________________________
45//      Función: tomaConfiguracion
46//
47//      Descripción:
48//              Lee el fichero de configuración del servicio
49//      Parámetros:
50//              filecfg : Ruta completa al fichero de configuración
51//      Devuelve:
52//              true: Si el proceso es correcto
53//              false: En caso de ocurrir algún error
54//________________________________________________________________________________________________________
55bool tomaConfiguracion(const char *filecfg)
56{
57        char buf[1024], *line;
58        char *key, *value;
59        FILE *fcfg;
60
61        if (filecfg == NULL || strlen(filecfg) == 0) {
62                syslog(LOG_ERR, "No configuration file has been specified\n");
63                return false;
64        }
65
66        fcfg = fopen(filecfg, "rt");
67        if (fcfg == NULL) {
68                syslog(LOG_ERR, "Cannot open configuration file `%s'\n",
69                       filecfg);
70                return false;
71        }
72
73        servidoradm[0] = '\0'; //inicializar variables globales
74
75        line = fgets(buf, sizeof(buf), fcfg);
76        while (line != NULL) {
77                const char *delim = "=";
78
79                line[strlen(line) - 1] = '\0';
80
81                key = strtok(line, delim);
82                value = strtok(NULL, delim);
83
84                if (!strcmp(str_toupper(key), "SERVIDORADM"))
85                        snprintf(servidoradm, sizeof(servidoradm), "%s", value);
86                else if (!strcmp(str_toupper(key), "PUERTO"))
87                        snprintf(puerto, sizeof(puerto), "%s", value);
88                else if (!strcmp(str_toupper(key), "USUARIO"))
89                        snprintf(usuario, sizeof(usuario), "%s", value);
90                else if (!strcmp(str_toupper(key), "PASSWORD"))
91                        snprintf(pasguor, sizeof(pasguor), "%s", value);
92                else if (!strcmp(str_toupper(key), "DATASOURCE"))
93                        snprintf(datasource, sizeof(datasource), "%s", value);
94                else if (!strcmp(str_toupper(key), "CATALOG"))
95                        snprintf(catalog, sizeof(catalog), "%s", value);
96                else if (!strcmp(str_toupper(key), "INTERFACE"))
97                        snprintf(interface, sizeof(interface), "%s", value);
98                else if (!strcmp(str_toupper(key), "APITOKEN"))
99                        snprintf(auth_token, sizeof(auth_token), "%s", value);
100
101                line = fgets(buf, sizeof(buf), fcfg);
102        }
103
104        fclose(fcfg);
105
106        if (!servidoradm[0]) {
107                syslog(LOG_ERR, "Missing SERVIDORADM in configuration file\n");
108                return false;
109        }
110        if (!puerto[0]) {
111                syslog(LOG_ERR, "Missing PUERTO in configuration file\n");
112                return false;
113        }
114        if (!usuario[0]) {
115                syslog(LOG_ERR, "Missing USUARIO in configuration file\n");
116                return false;
117        }
118        if (!pasguor[0]) {
119                syslog(LOG_ERR, "Missing PASSWORD in configuration file\n");
120                return false;
121        }
122        if (!datasource[0]) {
123                syslog(LOG_ERR, "Missing DATASOURCE in configuration file\n");
124                return false;
125        }
126        if (!catalog[0]) {
127                syslog(LOG_ERR, "Missing CATALOG in configuration file\n");
128                return false;
129        }
130        if (!interface[0])
131                syslog(LOG_ERR, "Missing INTERFACE in configuration file\n");
132
133        return true;
134}
135
136#define OG_CMD_MAXLEN           64
137
138// ________________________________________________________________________________________________________
139// Función: clienteDisponible
140//
141//      Descripción:
142//              Comprueba la disponibilidad del cliente para recibir comandos interactivos
143//      Parametros:
144//              - ip : La ip del cliente a buscar
145//              - idx: (Salida)  Indice que ocupa el cliente, de estar ya registrado
146//      Devuelve:
147//              true: Si el cliente está disponible
148//              false: En caso contrario
149// ________________________________________________________________________________________________________
150bool clienteDisponible(char *ip, int* idx)
151{
152        int estado;
153
154        if (clienteExistente(ip, idx)) {
155                estado = strcmp(tbsockets[*idx].estado, CLIENTE_OCUPADO); // Cliente ocupado
156                if (estado == 0)
157                        return false;
158
159                estado = strcmp(tbsockets[*idx].estado, CLIENTE_APAGADO); // Cliente apagado
160                if (estado == 0)
161                        return false;
162
163                estado = strcmp(tbsockets[*idx].estado, CLIENTE_INICIANDO); // Cliente en proceso de inclusión
164                if (estado == 0)
165                        return false;
166
167                return true; // En caso contrario el cliente está disponible
168        }
169        return false; // Cliente no está registrado en el sistema
170}
171// ________________________________________________________________________________________________________
172// Función: clienteExistente
173//
174//      Descripción:
175//              Comprueba si el cliente está registrado en la tabla de socket del sistema
176//      Parametros:
177//              - ip : La ip del cliente a buscar
178//              - idx:(Salida)  Indice que ocupa el cliente, de estar ya registrado
179//      Devuelve:
180//              true: Si el cliente está registrado
181//              false: En caso contrario
182// ________________________________________________________________________________________________________
183bool clienteExistente(char *ip, int* idx)
184{
185        int i;
186        for (i = 0; i < MAXIMOS_CLIENTES; i++) {
187                if (contieneIP(ip, tbsockets[i].ip)) { // Si existe la IP en la cadena
188                        *idx = i;
189                        return true;
190                }
191        }
192        return false;
193}
194// ________________________________________________________________________________________________________
195// Función: actualizaConfiguracion
196//
197//      Descripción:
198//              Esta función actualiza la base de datos con la configuracion de particiones de un cliente
199//      Parámetros:
200//              - db: Objeto base de datos (ya operativo)
201//              - tbl: Objeto tabla
202//              - cfg: cadena con una Configuración
203//              - ido: Identificador del ordenador cliente
204//      Devuelve:
205//              true: Si el proceso es correcto
206//              false: En caso de ocurrir algún error
207//      Especificaciones:
208//              Los parametros de la configuración son:
209//                      par= Número de partición
210//                      cpt= Codigo o tipo de partición
211//                      sfi= Sistema de ficheros que está implementado en la partición
212//                      soi= Nombre del sistema de ficheros instalado en la partición
213//                      tam= Tamaño de la partición
214// ________________________________________________________________________________________________________
215bool actualizaConfiguracion(struct og_dbi *dbi, char *cfg, int ido)
216{
217        int lon, p, c,i, dato, swu, idsoi, idsfi,k;
218        char *ptrPar[MAXPAR], *ptrCfg[7], *ptrDual[2], tbPar[LONSTD];
219        char *ser, *disk, *par, *cpt, *sfi, *soi, *tam, *uso; // Parametros de configuración.
220        dbi_result result, result_update;
221        const char *msglog;
222
223        lon = 0;
224        p = splitCadena(ptrPar, cfg, '\n');
225        for (i = 0; i < p; i++) {
226                c = splitCadena(ptrCfg, ptrPar[i], '\t');
227
228                // Si la 1ª línea solo incluye el número de serie del equipo; actualizar BD.
229                if (i == 0 && c == 1) {
230                        splitCadena(ptrDual, ptrCfg[0], '=');
231                        ser = ptrDual[1];
232                        if (strlen(ser) > 0) {
233                                // Solo actualizar si número de serie no existía.
234                                result = dbi_conn_queryf(dbi->conn,
235                                                "UPDATE ordenadores SET numserie='%s'"
236                                                " WHERE idordenador=%d AND numserie IS NULL",
237                                                ser, ido);
238                                if (!result) {
239                                        dbi_conn_error(dbi->conn, &msglog);
240                                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
241                                               __func__, __LINE__, msglog);
242                                        return false;
243                                }
244                                dbi_result_free(result);
245                        }
246                        continue;
247                }
248
249                // Distribución de particionado.
250                disk = par = cpt = sfi = soi = tam = uso = NULL;
251
252                splitCadena(ptrDual, ptrCfg[0], '=');
253                disk = ptrDual[1]; // Número de disco
254
255                splitCadena(ptrDual, ptrCfg[1], '=');
256                par = ptrDual[1]; // Número de partición
257
258                k=splitCadena(ptrDual, ptrCfg[2], '=');
259                if(k==2){
260                        cpt = ptrDual[1]; // Código de partición
261                }else{
262                        cpt = (char*)"0";
263                }
264
265                k=splitCadena(ptrDual, ptrCfg[3], '=');
266                if(k==2){
267                        sfi = ptrDual[1]; // Sistema de ficheros
268                        /* Comprueba existencia del s0xistema de ficheros instalado */
269                        idsfi = checkDato(dbi, sfi, "sistemasficheros", "descripcion","idsistemafichero");
270                }
271                else
272                        idsfi=0;
273
274                k=splitCadena(ptrDual, ptrCfg[4], '=');
275                if(k==2){ // Sistema operativo detecdtado
276                        soi = ptrDual[1]; // Nombre del S.O. instalado
277                        /* Comprueba existencia del sistema operativo instalado */
278                        idsoi = checkDato(dbi, soi, "nombresos", "nombreso", "idnombreso");
279                }
280                else
281                        idsoi=0;
282
283                splitCadena(ptrDual, ptrCfg[5], '=');
284                tam = ptrDual[1]; // Tamaño de la partición
285
286                splitCadena(ptrDual, ptrCfg[6], '=');
287                uso = ptrDual[1]; // Porcentaje de uso del S.F.
288
289                lon += sprintf(tbPar + lon, "(%s, %s),", disk, par);
290
291                result = dbi_conn_queryf(dbi->conn,
292                                "SELECT numdisk, numpar, tamano, uso, idsistemafichero, idnombreso"
293                                "  FROM ordenadores_particiones"
294                                " WHERE idordenador=%d AND numdisk=%s AND numpar=%s",
295                                ido, disk, par);
296                if (!result) {
297                        dbi_conn_error(dbi->conn, &msglog);
298                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
299                               __func__, __LINE__, msglog);
300                        return false;
301                }
302                if (!dbi_result_next_row(result)) {
303                        result_update = dbi_conn_queryf(dbi->conn,
304                                        "INSERT INTO ordenadores_particiones(idordenador,numdisk,numpar,codpar,tamano,uso,idsistemafichero,idnombreso,idimagen)"
305                                        " VALUES(%d,%s,%s,0x%s,%s,%s,%d,%d,0)",
306                                        ido, disk, par, cpt, tam, uso, idsfi, idsoi);
307                        if (!result_update) {
308                                dbi_conn_error(dbi->conn, &msglog);
309                                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
310                                       __func__, __LINE__, msglog);
311                                return false;
312                        }
313                        dbi_result_free(result_update);
314
315                } else { // Existe el registro
316                        swu = true; // Se supone que algún dato ha cambiado
317
318                        dato = dbi_result_get_uint(result, "tamano");
319                        if (atoi(tam) == dato) {// Parámetro tamaño igual al almacenado
320                                dato = dbi_result_get_uint(result, "idsistemafichero");
321                                if (idsfi == dato) {// Parámetro sistema de fichero igual al almacenado
322                                        dato = dbi_result_get_uint(result, "idnombreso");
323                                        if (idsoi == dato) {// Parámetro sistema de fichero distinto al almacenado
324                                                swu = false; // Todos los parámetros de la partición son iguales, no se actualiza
325                                        }
326                                }
327                        }
328                        if (swu) { // Hay que actualizar los parámetros de la partición
329                                result_update = dbi_conn_queryf(dbi->conn,
330                                        "UPDATE ordenadores_particiones SET "
331                                        " codpar=0x%s,"
332                                        " tamano=%s,"
333                                        " uso=%s,"
334                                        " idsistemafichero=%d,"
335                                        " idnombreso=%d,"
336                                        " idimagen=0,"
337                                        " idperfilsoft=0,"
338                                        " fechadespliegue=NULL"
339                                        " WHERE idordenador=%d AND numdisk=%s AND numpar=%s",
340                                        cpt, tam, uso, idsfi, idsoi, ido, disk, par);
341                        } else {  // Actualizar porcentaje de uso.
342                                result_update = dbi_conn_queryf(dbi->conn,
343                                        "UPDATE ordenadores_particiones SET "
344                                        " codpar=0x%s,"
345                                        " uso=%s"
346                                        " WHERE idordenador=%d AND numdisk=%s AND numpar=%s",
347                                        cpt, uso, ido, disk, par);
348                        }
349                        if (!result_update) {
350                                dbi_conn_error(dbi->conn, &msglog);
351                                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
352                                       __func__, __LINE__, msglog);
353                                return false;
354                        }
355
356                        dbi_result_free(result_update);
357                }
358                dbi_result_free(result);
359        }
360        lon += sprintf(tbPar + lon, "(0,0)");
361        // Eliminar particiones almacenadas que ya no existen
362        result_update = dbi_conn_queryf(dbi->conn,
363                "DELETE FROM ordenadores_particiones WHERE idordenador=%d AND (numdisk, numpar) NOT IN (%s)",
364                        ido, tbPar);
365        if (!result_update) {
366                dbi_conn_error(dbi->conn, &msglog);
367                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
368                       __func__, __LINE__, msglog);
369                return false;
370        }
371        dbi_result_free(result_update);
372
373        return true;
374}
375// ________________________________________________________________________________________________________
376// Función: checkDato
377//
378//      Descripción:
379//               Esta función comprueba si existe un dato en una tabla y si no es así lo incluye. devuelve en
380//              cualquier caso el identificador del registro existenet o del insertado
381//      Parámetros:
382//              - db: Objeto base de datos (ya operativo)
383//              - tbl: Objeto tabla
384//              - dato: Dato
385//              - tabla: Nombre de la tabla
386//              - nomdato: Nombre del dato en la tabla
387//              - nomidentificador: Nombre del identificador en la tabla
388//      Devuelve:
389//              El identificador del registro existente o el del insertado
390//
391//      Especificaciones:
392//              En caso de producirse algún error se devuelve el valor 0
393// ________________________________________________________________________________________________________
394
395int checkDato(struct og_dbi *dbi, char *dato, const char *tabla,
396                     const char *nomdato, const char *nomidentificador)
397{
398        const char *msglog;
399        int identificador;
400        dbi_result result;
401
402        if (strlen(dato) == 0)
403                return (0); // EL dato no tiene valor
404        result = dbi_conn_queryf(dbi->conn,
405                        "SELECT %s FROM %s WHERE %s ='%s'", nomidentificador,
406                        tabla, nomdato, dato);
407
408        // Ejecuta consulta
409        if (!result) {
410                dbi_conn_error(dbi->conn, &msglog);
411                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
412                       __func__, __LINE__, msglog);
413                return (0);
414        }
415        if (!dbi_result_next_row(result)) { //  Software NO existente
416                dbi_result_free(result);
417
418                result = dbi_conn_queryf(dbi->conn,
419                                "INSERT INTO %s (%s) VALUES('%s')", tabla, nomdato, dato);
420                if (!result) {
421                        dbi_conn_error(dbi->conn, &msglog);
422                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
423                               __func__, __LINE__, msglog);
424                        return (0);
425                }
426                // Recupera el identificador del software
427                identificador = dbi_conn_sequence_last(dbi->conn, NULL);
428        } else {
429                identificador = dbi_result_get_uint(result, nomidentificador);
430        }
431        dbi_result_free(result);
432
433        return (identificador);
434}
435
436// ________________________________________________________________________________________________________
437// Función: Levanta
438//
439//      Descripción:
440//              Enciende ordenadores a través de la red cuyas macs se pasan como parámetro
441//      Parámetros:
442//              - iph: Cadena de direcciones ip separadas por ";"
443//              - mac: Cadena de direcciones mac separadas por ";"
444//              - mar: Método de arranque (1=Broadcast, 2=Unicast)
445//      Devuelve:
446//              true: Si el proceso es correcto
447//              false: En caso de ocurrir algún error
448// ________________________________________________________________________________________________________
449
450bool Levanta(char *ptrIP[], char *ptrMacs[], char *ptrNetmasks[], int lon,
451             char *mar)
452{
453        unsigned int on = 1;
454        struct sockaddr_in local;
455        int i, res;
456        int s;
457
458        /* Creación de socket para envío de magig packet */
459        s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
460        if (s < 0) {
461                syslog(LOG_ERR, "cannot create socket for magic packet\n");
462                return false;
463        }
464        res = setsockopt(s, SOL_SOCKET, SO_BROADCAST, (unsigned int *) &on,
465                         sizeof(on));
466        if (res < 0) {
467                syslog(LOG_ERR, "cannot set broadcast socket\n");
468                return false;
469        }
470        memset(&local, 0, sizeof(local));
471        local.sin_family = AF_INET;
472        local.sin_port = htons(PUERTO_WAKEUP);
473        local.sin_addr.s_addr = htonl(INADDR_ANY);
474
475        for (i = 0; i < lon; i++) {
476                if (!WakeUp(s, ptrIP[i], ptrMacs[i], ptrNetmasks[i], mar)) {
477                        syslog(LOG_ERR, "problem sending magic packet\n");
478                        close(s);
479                        return false;
480                }
481        }
482        close(s);
483        return true;
484}
485
486#define OG_WOL_SEQUENCE         6
487#define OG_WOL_MACADDR_LEN      6
488#define OG_WOL_REPEAT           16
489
490struct wol_msg {
491        char secuencia_FF[OG_WOL_SEQUENCE];
492        char macbin[OG_WOL_REPEAT][OG_WOL_MACADDR_LEN];
493};
494
495static bool wake_up_broadcast(int sd, struct sockaddr_in *client,
496                              const struct wol_msg *msg)
497{
498        struct sockaddr_in *broadcast_addr;
499        struct ifaddrs *ifaddr, *ifa;
500        int ret;
501
502        if (getifaddrs(&ifaddr) < 0) {
503                syslog(LOG_ERR, "cannot get list of addresses\n");
504                return false;
505        }
506
507        client->sin_addr.s_addr = htonl(INADDR_BROADCAST);
508
509        for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
510                if (ifa->ifa_addr == NULL ||
511                    ifa->ifa_addr->sa_family != AF_INET ||
512                    strcmp(ifa->ifa_name, interface) != 0)
513                        continue;
514
515                broadcast_addr =
516                        (struct sockaddr_in *)ifa->ifa_ifu.ifu_broadaddr;
517                client->sin_addr.s_addr = broadcast_addr->sin_addr.s_addr;
518                break;
519        }
520        freeifaddrs(ifaddr);
521
522        ret = sendto(sd, msg, sizeof(*msg), 0,
523                     (struct sockaddr *)client, sizeof(*client));
524        if (ret < 0) {
525                syslog(LOG_ERR, "failed to send broadcast wol\n");
526                return false;
527        }
528
529        return true;
530}
531
532static bool wake_up_unicast(int sd, struct sockaddr_in *client,
533                            const struct wol_msg *msg,
534                            const struct in_addr *addr)
535{
536        int ret;
537
538        client->sin_addr.s_addr = addr->s_addr;
539
540        ret = sendto(sd, msg, sizeof(*msg), 0,
541                     (struct sockaddr *)client, sizeof(*client));
542        if (ret < 0) {
543                syslog(LOG_ERR, "failed to send unicast wol\n");
544                return false;
545        }
546
547        return true;
548}
549
550enum wol_delivery_type {
551        OG_WOL_BROADCAST = 1,
552        OG_WOL_UNICAST = 2
553};
554
555//_____________________________________________________________________________________________________________
556// Función: WakeUp
557//
558//       Descripción:
559//              Enciende el ordenador cuya MAC se pasa como parámetro
560//      Parámetros:
561//              - s : Socket para enviar trama magic packet
562//              - iph : Cadena con la dirección ip
563//              - mac : Cadena con la dirección mac en formato XXXXXXXXXXXX
564//              - mar: Método de arranque (1=Broadcast, 2=Unicast)
565//      Devuelve:
566//              true: Si el proceso es correcto
567//              false: En caso de ocurrir algún error
568//_____________________________________________________________________________________________________________
569//
570bool WakeUp(int s, char* iph, char *mac, char *netmask, char *mar)
571{
572        struct in_addr addr, netmask_addr, broadcast_addr ={};
573        unsigned int macaddr[OG_WOL_MACADDR_LEN];
574        char HDaddress_bin[OG_WOL_MACADDR_LEN];
575        struct sockaddr_in WakeUpCliente;
576        struct wol_msg Trama_WakeUp;
577        bool ret;
578        int i;
579
580        if (inet_aton(iph, &addr) < 0) {
581                syslog(LOG_ERR, "bad IP address\n");
582                return false;
583        }
584
585        if (inet_aton(netmask, &netmask_addr) < 0) {
586                syslog(LOG_ERR, "bad netmask address: %s\n", netmask);
587                return false;
588        }
589
590        broadcast_addr.s_addr = addr.s_addr | ~netmask_addr.s_addr;
591
592        for (i = 0; i < 6; i++) // Primera secuencia de la trama Wake Up (0xFFFFFFFFFFFF)
593                Trama_WakeUp.secuencia_FF[i] = 0xFF;
594
595        sscanf(mac, "%02x%02x%02x%02x%02x%02x",
596               &macaddr[0], &macaddr[1], &macaddr[2],
597               &macaddr[3], &macaddr[4], &macaddr[5]);
598
599        for (i = 0; i < 6; i++)
600                HDaddress_bin[i] = (uint8_t)macaddr[i];
601
602        for (i = 0; i < 16; i++) // Segunda secuencia de la trama Wake Up , repetir 16 veces su la MAC
603                memcpy(&Trama_WakeUp.macbin[i][0], &HDaddress_bin, 6);
604
605        /* Creación de socket del cliente que recibe la trama magic packet */
606        WakeUpCliente.sin_family = AF_INET;
607        WakeUpCliente.sin_port = htons((short) PUERTO_WAKEUP);
608
609        switch (atoi(mar)) {
610        case OG_WOL_BROADCAST:
611                ret = wake_up_broadcast(s, &WakeUpCliente, &Trama_WakeUp);
612                ret &= wake_up_unicast(s, &WakeUpCliente, &Trama_WakeUp,
613                                      &broadcast_addr);
614                break;
615        case OG_WOL_UNICAST:
616                ret = wake_up_unicast(s, &WakeUpCliente, &Trama_WakeUp, &addr);
617                break;
618        default:
619                syslog(LOG_ERR, "unknown wol type\n");
620                ret = false;
621                break;
622        }
623        return ret;
624}
625
626// ________________________________________________________________________________________________________
627// Función: actualizaCreacionImagen
628//
629//      Descripción:
630//              Esta función actualiza la base de datos con el resultado de la creación de una imagen
631//      Parámetros:
632//              - db: Objeto base de datos (ya operativo)
633//              - tbl: Objeto tabla
634//              - idi: Identificador de la imagen
635//              - dsk: Disco de donde se creó
636//              - par: Partición de donde se creó
637//              - cpt: Código de partición
638//              - ipr: Ip del repositorio
639//              - ido: Identificador del ordenador modelo
640//      Devuelve:
641//              true: Si el proceso es correcto
642//              false: En caso de ocurrir algún error
643// ________________________________________________________________________________________________________
644bool actualizaCreacionImagen(struct og_dbi *dbi, char *idi, char *dsk,
645                             char *par, char *cpt, char *ipr, char *ido)
646{
647        const char *msglog;
648        dbi_result result;
649        int idr,ifs;
650
651        /* Toma identificador del repositorio correspondiente al ordenador modelo */
652        result = dbi_conn_queryf(dbi->conn,
653                        "SELECT repositorios.idrepositorio"
654                        "  FROM repositorios"
655                        "  LEFT JOIN ordenadores USING (idrepositorio)"
656                        " WHERE repositorios.ip='%s' AND ordenadores.idordenador=%s", ipr, ido);
657
658        if (!result) {
659                dbi_conn_error(dbi->conn, &msglog);
660                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
661                       __func__, __LINE__, msglog);
662                return false;
663        }
664        if (!dbi_result_next_row(result)) {
665                syslog(LOG_ERR,
666                       "repository does not exist in database (%s:%d)\n",
667                       __func__, __LINE__);
668                dbi_result_free(result);
669                return false;
670        }
671        idr = dbi_result_get_uint(result, "idrepositorio");
672        dbi_result_free(result);
673
674        /* Toma identificador del perfilsoftware */
675        result = dbi_conn_queryf(dbi->conn,
676                        "SELECT idperfilsoft"
677                        "  FROM ordenadores_particiones"
678                        " WHERE idordenador=%s AND numdisk=%s AND numpar=%s", ido, dsk, par);
679
680        if (!result) {
681                dbi_conn_error(dbi->conn, &msglog);
682                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
683                       __func__, __LINE__, msglog);
684                return false;
685        }
686        if (!dbi_result_next_row(result)) {
687                syslog(LOG_ERR,
688                       "software profile does not exist in database (%s:%d)\n",
689                       __func__, __LINE__);
690                dbi_result_free(result);
691                return false;
692        }
693        ifs = dbi_result_get_uint(result, "idperfilsoft");
694        dbi_result_free(result);
695
696        /* Actualizar los datos de la imagen */
697        result = dbi_conn_queryf(dbi->conn,
698                "UPDATE imagenes"
699                "   SET idordenador=%s, numdisk=%s, numpar=%s, codpar=%s,"
700                "       idperfilsoft=%d, idrepositorio=%d,"
701                "       fechacreacion=NOW(), revision=revision+1"
702                " WHERE idimagen=%s", ido, dsk, par, cpt, ifs, idr, idi);
703
704        if (!result) {
705                dbi_conn_error(dbi->conn, &msglog);
706                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
707                       __func__, __LINE__, msglog);
708                return false;
709        }
710        dbi_result_free(result);
711
712        /* Actualizar los datos en el cliente */
713        result = dbi_conn_queryf(dbi->conn,
714                "UPDATE ordenadores_particiones"
715                "   SET idimagen=%s, revision=(SELECT revision FROM imagenes WHERE idimagen=%s),"
716                "       fechadespliegue=NOW()"
717                " WHERE idordenador=%s AND numdisk=%s AND numpar=%s",
718                idi, idi, ido, dsk, par);
719        if (!result) {
720                dbi_conn_error(dbi->conn, &msglog);
721                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
722                       __func__, __LINE__, msglog);
723                return false;
724        }
725        dbi_result_free(result);
726
727        return true;
728}
729
730// ________________________________________________________________________________________________________
731// Función: actualizaRestauracionImagen
732//
733//      Descripción:
734//              Esta función actualiza la base de datos con el resultado de la restauración de una imagen
735//      Parámetros:
736//              - db: Objeto base de datos (ya operativo)
737//              - tbl: Objeto tabla
738//              - idi: Identificador de la imagen
739//              - dsk: Disco de donde se restauró
740//              - par: Partición de donde se restauró
741//              - ido: Identificador del cliente donde se restauró
742//              - ifs: Identificador del perfil software contenido      en la imagen
743//      Devuelve:
744//              true: Si el proceso es correcto
745//              false: En caso de ocurrir algún error
746// ________________________________________________________________________________________________________
747bool actualizaRestauracionImagen(struct og_dbi *dbi, char *idi,
748                                 char *dsk, char *par, char *ido, char *ifs)
749{
750        const char *msglog;
751        dbi_result result;
752
753        /* Actualizar los datos de la imagen */
754        result = dbi_conn_queryf(dbi->conn,
755                        "UPDATE ordenadores_particiones"
756                        "   SET idimagen=%s, idperfilsoft=%s, fechadespliegue=NOW(),"
757                        "       revision=(SELECT revision FROM imagenes WHERE idimagen=%s),"
758                        "       idnombreso=IFNULL((SELECT idnombreso FROM perfilessoft WHERE idperfilsoft=%s),0)"
759                        " WHERE idordenador=%s AND numdisk=%s AND numpar=%s", idi, ifs, idi, ifs, ido, dsk, par);
760
761        if (!result) {
762                dbi_conn_error(dbi->conn, &msglog);
763                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
764                       __func__, __LINE__, msglog);
765                return false;
766        }
767        dbi_result_free(result);
768
769        return true;
770}
771// ________________________________________________________________________________________________________
772// Función: actualizaHardware
773//
774//              Descripción:
775//                      Actualiza la base de datos con la configuracion hardware del cliente
776//              Parámetros:
777//                      - db: Objeto base de datos (ya operativo)
778//                      - tbl: Objeto tabla
779//                      - hrd: cadena con el inventario hardware
780//                      - ido: Identificador del ordenador
781//                      - npc: Nombre del ordenador
782//                      - idc: Identificador del centro o Unidad organizativa
783// ________________________________________________________________________________________________________
784//
785bool actualizaHardware(struct og_dbi *dbi, char *hrd, char *ido, char *npc,
786                       char *idc)
787{
788        const char *msglog;
789        int idtipohardware, idperfilhard;
790        int lon, i, j, aux;
791        bool retval;
792        char *whard;
793        int tbidhardware[MAXHARDWARE];
794        char *tbHardware[MAXHARDWARE],*dualHardware[2], strInt[LONINT], *idhardwares;
795        dbi_result result;
796
797        /* Toma Centro (Unidad Organizativa) */
798        result = dbi_conn_queryf(dbi->conn,
799                                 "SELECT idperfilhard FROM ordenadores WHERE idordenador=%s",
800                                 ido);
801        if (!result) {
802                dbi_conn_error(dbi->conn, &msglog);
803                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
804                       __func__, __LINE__, msglog);
805                return false;
806        }
807        if (!dbi_result_next_row(result)) {
808                syslog(LOG_ERR, "client does not exist in database (%s:%d)\n",
809                       __func__, __LINE__);
810                dbi_result_free(result);
811                return false;
812        }
813        idperfilhard = dbi_result_get_uint(result, "idperfilhard");
814        dbi_result_free(result);
815
816        whard=escaparCadena(hrd); // Codificar comillas simples
817        if(!whard)
818                return false;
819        /* Recorre componentes hardware*/
820        lon = splitCadena(tbHardware, whard, '\n');
821        if (lon > MAXHARDWARE)
822                lon = MAXHARDWARE; // Limita el número de componentes hardware
823        /*
824         for (i=0;i<lon;i++){
825         sprintf(msglog,"Linea de inventario: %s",tbHardware[i]);
826         RegistraLog(msglog,false);
827         }
828         */
829        for (i = 0; i < lon; i++) {
830                splitCadena(dualHardware, rTrim(tbHardware[i]), '=');
831                //sprintf(msglog,"nemonico: %s",dualHardware[0]);
832                //RegistraLog(msglog,false);
833                //sprintf(msglog,"valor: %s",dualHardware[1]);
834                //RegistraLog(msglog,false);
835                result = dbi_conn_queryf(dbi->conn,
836                                         "SELECT idtipohardware,descripcion FROM tipohardwares WHERE nemonico='%s'",
837                                         dualHardware[0]);
838                if (!result) {
839                        dbi_conn_error(dbi->conn, &msglog);
840                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
841                               __func__, __LINE__, msglog);
842                        return false;
843                }
844                if (!dbi_result_next_row(result)) { //  Tipo de Hardware NO existente
845                        dbi_result_free(result);
846                        return false;
847                } else { //  Tipo de Hardware Existe
848                        idtipohardware = dbi_result_get_uint(result, "idtipohardware");
849                        dbi_result_free(result);
850
851                        result = dbi_conn_queryf(dbi->conn,
852                                                 "SELECT idhardware FROM hardwares WHERE idtipohardware=%d AND descripcion='%s'",
853                                                 idtipohardware, dualHardware[1]);
854
855                        if (!result) {
856                                dbi_conn_error(dbi->conn, &msglog);
857                                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
858                                       __func__, __LINE__, msglog);
859                                return false;
860                        }
861
862                        if (!dbi_result_next_row(result)) { //  Hardware NO existente
863                                dbi_result_free(result);
864                                result = dbi_conn_queryf(dbi->conn,
865                                                        "INSERT hardwares (idtipohardware,descripcion,idcentro,grupoid) "
866                                                        " VALUES(%d,'%s',%s,0)", idtipohardware,
867                                                dualHardware[1], idc);
868                                if (!result) {
869                                        dbi_conn_error(dbi->conn, &msglog);
870                                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
871                                               __func__, __LINE__, msglog);
872                                        return false;
873                                }
874
875                                // Recupera el identificador del hardware
876                                tbidhardware[i] = dbi_conn_sequence_last(dbi->conn, NULL);
877                        } else {
878                                tbidhardware[i] = dbi_result_get_uint(result, "idhardware");
879                        }
880                        dbi_result_free(result);
881                }
882        }
883        // Ordena tabla de identificadores para cosultar si existe un pefil con esas especificaciones
884
885        for (i = 0; i < lon - 1; i++) {
886                for (j = i + 1; j < lon; j++) {
887                        if (tbidhardware[i] > tbidhardware[j]) {
888                                aux = tbidhardware[i];
889                                tbidhardware[i] = tbidhardware[j];
890                                tbidhardware[j] = aux;
891                        }
892                }
893        }
894        /* Crea cadena de identificadores de componentes hardware separados por coma */
895        sprintf(strInt, "%d", tbidhardware[lon - 1]); // Pasa a cadena el último identificador que es de mayor longitud
896        aux = strlen(strInt); // Calcula longitud de cadena para reservar espacio a todos los perfiles
897        idhardwares = calloc(1, sizeof(aux) * lon + lon);
898        if (idhardwares == NULL) {
899                syslog(LOG_ERR, "%s:%d OOM\n", __FILE__, __LINE__);
900                return false;
901        }
902        aux = sprintf(idhardwares, "%d", tbidhardware[0]);
903        for (i = 1; i < lon; i++)
904                aux += sprintf(idhardwares + aux, ",%d", tbidhardware[i]);
905
906        if (!cuestionPerfilHardware(dbi, idc, ido, idperfilhard, idhardwares,
907                        npc, tbidhardware, lon)) {
908                syslog(LOG_ERR, "Problem updating client hardware\n");
909                retval=false;
910        } else {
911                retval=true;
912        }
913        free(whard);
914        free(idhardwares);
915
916        return (retval);
917}
918// ________________________________________________________________________________________________________
919// Función: cuestionPerfilHardware
920//
921//              Descripción:
922//                      Comprueba existencia de perfil hardware y actualización de éste para el ordenador
923//              Parámetros:
924//                      - db: Objeto base de datos (ya operativo)
925//                      - tbl: Objeto tabla
926//                      - idc: Identificador de la Unidad organizativa donde se encuentra el cliente
927//                      - ido: Identificador del ordenador
928//                      - tbidhardware: Identificador del tipo de hardware
929//                      - con: Número de componentes detectados para configurar un el perfil hardware
930//                      - npc: Nombre del cliente
931// ________________________________________________________________________________________________________
932bool cuestionPerfilHardware(struct og_dbi *dbi, char *idc, char *ido,
933                int idperfilhardware, char *idhardwares, char *npc, int *tbidhardware,
934                int lon)
935{
936        const char *msglog;
937        dbi_result result;
938        int i;
939        int nwidperfilhard;
940
941        // Busca perfil hard del ordenador que contenga todos los componentes hardware encontrados
942        result = dbi_conn_queryf(dbi->conn,
943                "SELECT idperfilhard FROM"
944                " (SELECT perfileshard_hardwares.idperfilhard as idperfilhard,"
945                "       group_concat(cast(perfileshard_hardwares.idhardware AS char( 11) )"
946                "       ORDER BY perfileshard_hardwares.idhardware SEPARATOR ',' ) AS idhardwares"
947                " FROM  perfileshard_hardwares"
948                " GROUP BY perfileshard_hardwares.idperfilhard) AS temp"
949                " WHERE idhardwares LIKE '%s'", idhardwares);
950
951        if (!result) {
952                dbi_conn_error(dbi->conn, &msglog);
953                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
954                       __func__, __LINE__, msglog);
955                return false;
956        }
957        if (!dbi_result_next_row(result)) {
958                // No existe un perfil hardware con esos componentes de componentes hardware, lo crea
959                dbi_result_free(result);
960                result = dbi_conn_queryf(dbi->conn,
961                                "INSERT perfileshard  (descripcion,idcentro,grupoid)"
962                                " VALUES('Perfil hardware (%s) ',%s,0)", npc, idc);
963                if (!result) {
964                        dbi_conn_error(dbi->conn, &msglog);
965                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
966                               __func__, __LINE__, msglog);
967                        return false;
968                }
969                dbi_result_free(result);
970
971                // Recupera el identificador del nuevo perfil hardware
972                nwidperfilhard = dbi_conn_sequence_last(dbi->conn, NULL);
973
974                // Crea la relación entre perfiles y componenetes hardware
975                for (i = 0; i < lon; i++) {
976                        result = dbi_conn_queryf(dbi->conn,
977                                        "INSERT perfileshard_hardwares  (idperfilhard,idhardware)"
978                                                " VALUES(%d,%d)", nwidperfilhard, tbidhardware[i]);
979                        if (!result) {
980                                dbi_conn_error(dbi->conn, &msglog);
981                                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
982                                       __func__, __LINE__, msglog);
983                                return false;
984                        }
985                        dbi_result_free(result);
986                }
987        } else { // Existe un perfil con todos esos componentes
988                nwidperfilhard = dbi_result_get_uint(result, "idperfilhard");
989                dbi_result_free(result);
990        }
991        if (idperfilhardware != nwidperfilhard) { // No coinciden los perfiles
992                // Actualiza el identificador del perfil hardware del ordenador
993                result = dbi_conn_queryf(dbi->conn,
994                        "UPDATE ordenadores SET idperfilhard=%d"
995                        " WHERE idordenador=%s", nwidperfilhard, ido);
996                if (!result) {
997                        dbi_conn_error(dbi->conn, &msglog);
998                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
999                               __func__, __LINE__, msglog);
1000                        return false;
1001                }
1002                dbi_result_free(result);
1003        }
1004        /* Eliminar Relación de hardwares con Perfiles hardware que quedan húerfanos */
1005        result = dbi_conn_queryf(dbi->conn,
1006                "DELETE FROM perfileshard_hardwares WHERE idperfilhard IN "
1007                " (SELECT idperfilhard FROM perfileshard WHERE idperfilhard NOT IN"
1008                " (SELECT DISTINCT idperfilhard from ordenadores))");
1009        if (!result) {
1010                dbi_conn_error(dbi->conn, &msglog);
1011                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1012                       __func__, __LINE__, msglog);
1013                return false;
1014        }
1015        dbi_result_free(result);
1016
1017        /* Eliminar Perfiles hardware que quedan húerfanos */
1018        result = dbi_conn_queryf(dbi->conn,
1019                        "DELETE FROM perfileshard WHERE idperfilhard NOT IN"
1020                        " (SELECT DISTINCT idperfilhard FROM ordenadores)");
1021        if (!result) {
1022                dbi_conn_error(dbi->conn, &msglog);
1023                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1024                       __func__, __LINE__, msglog);
1025                return false;
1026        }
1027        dbi_result_free(result);
1028
1029        /* Eliminar Relación de hardwares con Perfiles hardware que quedan húerfanos */
1030        result = dbi_conn_queryf(dbi->conn,
1031                        "DELETE FROM perfileshard_hardwares WHERE idperfilhard NOT IN"
1032                        " (SELECT idperfilhard FROM perfileshard)");
1033        if (!result) {
1034                dbi_conn_error(dbi->conn, &msglog);
1035                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1036                       __func__, __LINE__, msglog);
1037                return false;
1038        }
1039        dbi_result_free(result);
1040
1041        return true;
1042}
1043// ________________________________________________________________________________________________________
1044// Función: actualizaSoftware
1045//
1046//      Descripción:
1047//              Actualiza la base de datos con la configuración software del cliente
1048//      Parámetros:
1049//              - db: Objeto base de datos (ya operativo)
1050//              - tbl: Objeto tabla
1051//              - sft: cadena con el inventario software
1052//              - par: Número de la partición
1053//              - ido: Identificador del ordenador del cliente en la tabla
1054//              - npc: Nombre del ordenador
1055//              - idc: Identificador del centro o Unidad organizativa
1056//      Devuelve:
1057//              true: Si el proceso es correcto
1058//              false: En caso de ocurrir algún error
1059//
1060//      Versión 1.1.0: Se incluye el sistema operativo. Autora: Irina Gómez - ETSII Universidad Sevilla
1061// ________________________________________________________________________________________________________
1062bool actualizaSoftware(struct og_dbi *dbi, char *sft, char *par,char *ido,
1063                       char *npc, char *idc)
1064{
1065        int i, j, lon, aux, idperfilsoft, idnombreso;
1066        bool retval;
1067        char *wsft;
1068        int tbidsoftware[MAXSOFTWARE];
1069        char *tbSoftware[MAXSOFTWARE], strInt[LONINT], *idsoftwares;
1070        const char *msglog;
1071        dbi_result result;
1072
1073        /* Toma Centro (Unidad Organizativa) y perfil software */
1074        result = dbi_conn_queryf(dbi->conn,
1075                "SELECT idperfilsoft,numpar"
1076                " FROM ordenadores_particiones"
1077                " WHERE idordenador=%s", ido);
1078        if (!result) {
1079                dbi_conn_error(dbi->conn, &msglog);
1080                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1081                       __func__, __LINE__, msglog);
1082                return false;
1083        }
1084        idperfilsoft = 0; // Por defecto se supone que el ordenador no tiene aún detectado el perfil software
1085        while (dbi_result_next_row(result)) {
1086                aux = dbi_result_get_uint(result, "numpar");
1087                if (aux == atoi(par)) { // Se encuentra la partición
1088                        idperfilsoft = dbi_result_get_uint(result, "idperfilsoft");
1089                        break;
1090                }
1091        }
1092        dbi_result_free(result);
1093        wsft=escaparCadena(sft); // Codificar comillas simples
1094        if(!wsft)
1095                return false;
1096
1097        /* Recorre componentes software*/
1098        lon = splitCadena(tbSoftware, wsft, '\n');
1099
1100        if (lon == 0)
1101                return true; // No hay lineas que procesar
1102        if (lon > MAXSOFTWARE)
1103                lon = MAXSOFTWARE; // Limita el número de componentes software
1104
1105        idnombreso = 0;
1106        for (i = 0; i < lon; i++) {
1107                // Primera línea es el sistema operativo: se obtiene identificador
1108                if (i == 0) {
1109                        idnombreso = checkDato(dbi, rTrim(tbSoftware[i]), "nombresos", "nombreso", "idnombreso");
1110                        continue;
1111                }
1112
1113                result = dbi_conn_queryf(dbi->conn,
1114                                "SELECT idsoftware FROM softwares WHERE descripcion ='%s'",
1115                                rTrim(tbSoftware[i]));
1116                if (!result) {
1117                        dbi_conn_error(dbi->conn, &msglog);
1118                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1119                               __func__, __LINE__, msglog);
1120                        return false;
1121                }
1122
1123                if (!dbi_result_next_row(result)) {
1124                        dbi_result_free(result);
1125                        result = dbi_conn_queryf(dbi->conn,
1126                                                "INSERT INTO softwares (idtiposoftware,descripcion,idcentro,grupoid)"
1127                                                " VALUES(2,'%s',%s,0)", tbSoftware[i], idc);
1128                        if (!result) { // Error al insertar
1129                                dbi_conn_error(dbi->conn, &msglog);
1130                                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1131                                       __func__, __LINE__, msglog);
1132                                return false;
1133                        }
1134
1135                        // Recupera el identificador del software
1136                        tbidsoftware[i] = dbi_conn_sequence_last(dbi->conn, NULL);
1137                } else {
1138                        tbidsoftware[i] = dbi_result_get_uint(result, "idsoftware");
1139                }
1140                dbi_result_free(result);
1141        }
1142
1143        // Ordena tabla de identificadores para cosultar si existe un pefil con esas especificaciones
1144
1145        for (i = 0; i < lon - 1; i++) {
1146                for (j = i + 1; j < lon; j++) {
1147                        if (tbidsoftware[i] > tbidsoftware[j]) {
1148                                aux = tbidsoftware[i];
1149                                tbidsoftware[i] = tbidsoftware[j];
1150                                tbidsoftware[j] = aux;
1151                        }
1152                }
1153        }
1154        /* Crea cadena de identificadores de componentes software separados por coma */
1155        sprintf(strInt, "%d", tbidsoftware[lon - 1]); // Pasa a cadena el último identificador que es de mayor longitud
1156        aux = strlen(strInt); // Calcula longitud de cadena para reservar espacio a todos los perfiles
1157        idsoftwares = calloc(1, (sizeof(aux)+1) * lon + lon);
1158        if (idsoftwares == NULL) {
1159                syslog(LOG_ERR, "%s:%d OOM\n", __FILE__, __LINE__);
1160                return false;
1161        }
1162        aux = sprintf(idsoftwares, "%d", tbidsoftware[0]);
1163        for (i = 1; i < lon; i++)
1164                aux += sprintf(idsoftwares + aux, ",%d", tbidsoftware[i]);
1165
1166        // Comprueba existencia de perfil software y actualización de éste para el ordenador
1167        if (!cuestionPerfilSoftware(dbi, idc, ido, idperfilsoft, idnombreso, idsoftwares,
1168                        npc, par, tbidsoftware, lon)) {
1169                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1170                       __func__, __LINE__, msglog);
1171                retval=false;
1172        } else {
1173                retval=true;
1174        }
1175        free(wsft);
1176        free(idsoftwares);
1177
1178        return retval;
1179}
1180// ________________________________________________________________________________________________________
1181// Función: CuestionPerfilSoftware
1182//
1183//      Parámetros:
1184//              - db: Objeto base de datos (ya operativo)
1185//              - tbl: Objeto tabla
1186//              - idcentro: Identificador del centro en la tabla
1187//              - ido: Identificador del ordenador del cliente en la tabla
1188//              - idnombreso: Identificador del sistema operativo
1189//              - idsoftwares: Cadena con los identificadores de componentes software separados por comas
1190//              - npc: Nombre del ordenador del cliente
1191//              - particion: Número de la partición
1192//              - tbidsoftware: Array con los identificadores de componentes software
1193//              - lon: Número de componentes
1194//      Devuelve:
1195//              true: Si el proceso es correcto
1196//              false: En caso de ocurrir algún error
1197//
1198//      Versión 1.1.0: Se incluye el sistema operativo. Autora: Irina Gómez - ETSII Universidad Sevilla
1199//_________________________________________________________________________________________________________
1200bool cuestionPerfilSoftware(struct og_dbi *dbi, char *idc, char *ido,
1201                            int idperfilsoftware, int idnombreso,
1202                            char *idsoftwares, char *npc, char *par,
1203                            int *tbidsoftware, int lon)
1204{
1205        int i, nwidperfilsoft;
1206        const char *msglog;
1207        dbi_result result;
1208
1209        // Busca perfil soft del ordenador que contenga todos los componentes software encontrados
1210        result = dbi_conn_queryf(dbi->conn,
1211                "SELECT idperfilsoft FROM"
1212                " (SELECT perfilessoft_softwares.idperfilsoft as idperfilsoft,"
1213                "       group_concat(cast(perfilessoft_softwares.idsoftware AS char( 11) )"
1214                "       ORDER BY perfilessoft_softwares.idsoftware SEPARATOR ',' ) AS idsoftwares"
1215                " FROM  perfilessoft_softwares"
1216                " GROUP BY perfilessoft_softwares.idperfilsoft) AS temp"
1217                " WHERE idsoftwares LIKE '%s'", idsoftwares);
1218
1219        if (!result) {
1220                dbi_conn_error(dbi->conn, &msglog);
1221                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1222                       __func__, __LINE__, msglog);
1223                return false;
1224        }
1225        if (!dbi_result_next_row(result)) { // No existe un perfil software con esos componentes de componentes software, lo crea
1226                dbi_result_free(result);
1227                result = dbi_conn_queryf(dbi->conn,
1228                                "INSERT perfilessoft  (descripcion, idcentro, grupoid, idnombreso)"
1229                                " VALUES('Perfil Software (%s, Part:%s) ',%s,0,%i)", npc, par, idc,idnombreso);
1230                if (!result) {
1231                        dbi_conn_error(dbi->conn, &msglog);
1232                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1233                               __func__, __LINE__, msglog);
1234                        return false;
1235                }
1236
1237                dbi_result_free(result);
1238                // Recupera el identificador del nuevo perfil software
1239                nwidperfilsoft = dbi_conn_sequence_last(dbi->conn, NULL);
1240
1241                // Crea la relación entre perfiles y componenetes software
1242                for (i = 0; i < lon; i++) {
1243                        result = dbi_conn_queryf(dbi->conn,
1244                                                "INSERT perfilessoft_softwares (idperfilsoft,idsoftware)"
1245                                                " VALUES(%d,%d)", nwidperfilsoft, tbidsoftware[i]);
1246                        if (!result) {
1247                                dbi_conn_error(dbi->conn, &msglog);
1248                                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1249                                       __func__, __LINE__, msglog);
1250                                return false;
1251                        }
1252                        dbi_result_free(result);
1253                }
1254        } else { // Existe un perfil con todos esos componentes
1255                nwidperfilsoft = dbi_result_get_uint(result, "idperfilsoft");
1256                dbi_result_free(result);
1257        }
1258
1259        if (idperfilsoftware != nwidperfilsoft) { // No coinciden los perfiles
1260                // Actualiza el identificador del perfil software del ordenador
1261                result = dbi_conn_queryf(dbi->conn,
1262                                "UPDATE ordenadores_particiones SET idperfilsoft=%d,idimagen=0"
1263                                " WHERE idordenador=%s AND numpar=%s", nwidperfilsoft, ido, par);
1264                if (!result) { // Error al insertar
1265                        dbi_conn_error(dbi->conn, &msglog);
1266                        syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1267                               __func__, __LINE__, msglog);
1268                        return false;
1269                }
1270                dbi_result_free(result);
1271        }
1272
1273        /* DEPURACIÓN DE PERFILES SOFTWARE */
1274
1275         /* Eliminar Relación de softwares con Perfiles software que quedan húerfanos */
1276        result = dbi_conn_queryf(dbi->conn,
1277                "DELETE FROM perfilessoft_softwares WHERE idperfilsoft IN "\
1278                " (SELECT idperfilsoft FROM perfilessoft WHERE idperfilsoft NOT IN"\
1279                " (SELECT DISTINCT idperfilsoft from ordenadores_particiones) AND idperfilsoft NOT IN"\
1280                " (SELECT DISTINCT idperfilsoft from imagenes))");
1281        if (!result) {
1282                dbi_conn_error(dbi->conn, &msglog);
1283                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1284                       __func__, __LINE__, msglog);
1285                return false;
1286        }
1287        dbi_result_free(result),
1288        /* Eliminar Perfiles software que quedan húerfanos */
1289        result = dbi_conn_queryf(dbi->conn,
1290                "DELETE FROM perfilessoft WHERE idperfilsoft NOT IN"
1291                " (SELECT DISTINCT idperfilsoft from ordenadores_particiones)"\
1292                " AND  idperfilsoft NOT IN"\
1293                " (SELECT DISTINCT idperfilsoft from imagenes)");
1294        if (!result) {
1295                dbi_conn_error(dbi->conn, &msglog);
1296                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1297                       __func__, __LINE__, msglog);
1298                return false;
1299        }
1300        dbi_result_free(result),
1301
1302        /* Eliminar Relación de softwares con Perfiles software que quedan húerfanos */
1303        result = dbi_conn_queryf(dbi->conn,
1304                        "DELETE FROM perfilessoft_softwares WHERE idperfilsoft NOT IN"
1305                        " (SELECT idperfilsoft from perfilessoft)");
1306        if (!result) {
1307                dbi_conn_error(dbi->conn, &msglog);
1308                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
1309                       __func__, __LINE__, msglog);
1310                return false;
1311        }
1312        dbi_result_free(result);
1313
1314        return true;
1315}
Note: See TracBrowser for help on using the repository browser.