source: admin/Sources/Services/ogAdmBoot/sources/ogAdmBoot.cpp @ de734df

918-git-images-111dconfigfileconfigure-oglivegit-imageslgromero-new-oglivemainmaint-cronmount-efivarfsmultivmmultivm-ogboot-installerogClonningEngineogboot-installer-jenkinsoglive-ipv6test-python-scriptsticket-301ticket-50ticket-50-oldticket-577ticket-585ticket-611ticket-612ticket-693ticket-700ubu24tplunification2use-local-agent-oglivevarios-instalacionwebconsole3
Last change on this file since de734df was 3ec149c, checked in by alonso <alonso@…>, 15 years ago

git-svn-id: https://opengnsys.es/svn/trunk@1314 a21b9725-9963-47de-94b9-378ad31fedc9

  • Property mode set to 100644
File size: 43.9 KB
Line 
1// ********************************************************************************************************
2// Servicio: ogAdmBoot
3// Autor: José Manuel Alonso (E.T.S.I.I.) Universidad de Sevilla
4// Fecha Creación: Julio-2010
5// Fecha Última modificación: Julio-2010
6// Nombre del fichero: ogAdmBoot.cpp
7// Descripción :Este fichero implementa el servicio dhcp y tftp propios del sistema
8// ********************************************************************************************************
9#include "ogAdmBoot.h"
10#include "ogAdmLib.c"
11//________________________________________________________________________________________________________
12//      Función: tomaConfiguracion
13//
14//      Descripción:
15//              Lee el fichero de configuración del servicio
16//      Parámetros:
17//              filecfg : Ruta completa al fichero de configuración
18//      Devuelve:
19//              TRUE: Si el proceso es correcto
20//              FALSE: En caso de ocurrir algún error
21//________________________________________________________________________________________________________
22BOOLEAN tomaConfiguracion(char* filecfg)
23{
24        char modulo[] = "tomaConfiguracion()";
25
26        if (filecfg == NULL || strlen(filecfg) == 0) {
27                errorLog(modulo, 1, FALSE); // Fichero de configuración del servicio vacío
28                return (FALSE);
29        }
30        FILE *fcfg;
31        long lSize;
32        char * buffer, *lineas[MAXPRM], *dualparametro[2];
33        int i, numlin, resul;
34
35        fcfg = fopen(filecfg, "rt");
36        if (fcfg == NULL) {
37                errorLog(modulo, 2, FALSE); // No existe fichero de configuración del servicio
38                return (FALSE);
39        }
40
41        fseek(fcfg, 0, SEEK_END);
42        lSize = ftell(fcfg); // Obtiene tamaño del fichero.
43        rewind(fcfg);
44        buffer = (char*) reservaMemoria(lSize+1); // Toma memoria para el buffer de lectura.
45        if (buffer == NULL) { // No hay memoria suficiente para el buffer
46                errorLog(modulo, 3, FALSE);
47                return (FALSE);
48        }
49        fread(buffer, 1, lSize, fcfg); // Lee contenido del fichero
50        buffer[lSize]=(char) NULL;
51        fclose(fcfg);
52
53        IPlocal[0] = (char) NULL; //inicializar variables globales
54        usuario[0] = (char) NULL;
55        pasguor[0] = (char) NULL;
56        datasource[0] = (char) NULL;
57        catalog[0] = (char) NULL;
58        router[0] = (char) NULL;
59        mascara[0] = (char) NULL;
60
61        numlin = splitCadena(lineas, buffer, '\n');
62        for (i = 0; i < numlin; i++) {
63                splitCadena(dualparametro, lineas[i], '=');
64                resul = strcmp(StrToUpper(dualparametro[0]), "IPLOCAL");
65                if (resul == 0)
66                        strcpy(IPlocal, dualparametro[1]);
67                resul = strcmp(StrToUpper(dualparametro[0]), "USUARIO");
68                if (resul == 0)
69                        strcpy(usuario, dualparametro[1]);
70                resul = strcmp(StrToUpper(dualparametro[0]), "PASSWORD");
71                if (resul == 0)
72                        strcpy(pasguor, dualparametro[1]);
73                resul = strcmp(StrToUpper(dualparametro[0]), "DATASOURCE");
74                if (resul == 0)
75                        strcpy(datasource, dualparametro[1]);
76                resul = strcmp(StrToUpper(dualparametro[0]), "CATALOG");
77                if (resul == 0)
78                        strcpy(catalog, dualparametro[1]);
79                resul = strcmp(StrToUpper(dualparametro[0]), "ROUTER");
80                if (resul == 0)
81                        strcpy(router, dualparametro[1]);
82                resul = strcmp(StrToUpper(dualparametro[0]), "MASCARA");
83                if (resul == 0)
84                        strcpy(mascara, dualparametro[1]);
85        }
86        if (IPlocal[0] == (char) NULL) {
87                errorLog(modulo, 4, FALSE); // Falta parámetro IPLOCAL
88                return (FALSE);
89        }
90        if (usuario[0] == (char) NULL) {
91                errorLog(modulo, 6, FALSE); // Falta parámetro USUARIO
92                return (FALSE);
93        }
94        if (pasguor[0] == (char) NULL) {
95                errorLog(modulo, 7, FALSE); // Falta parámetro PASSWORD
96                return (FALSE);
97        }
98        if (datasource[0] == (char) NULL) {
99                errorLog(modulo, 8, FALSE); // Falta parámetro DATASOURCE
100                return (FALSE);
101        }
102        if (catalog[0] == (char) NULL) {
103                errorLog(modulo, 9, FALSE); // Falta parámetro CATALOG
104                return (FALSE);
105        }
106        return (TRUE);
107}
108// _____________________________________________________________________________________________________________
109// Función: ServicioDHCP
110//
111//              Descripción:
112//                      Esta hebra implementa el servicio DHCP
113// _____________________________________________________________________________________________________________
114
115LPVOID ServicioDHCP(LPVOID ipl)
116{
117        SOCKET socket_s; // Socket donde escucha el servidor
118        struct TramaDhcpBootp * trmInfo;
119        struct sockaddr_in local;
120        int ret,resul;
121        BOOLEAN bOpt;
122        pthread_t hThread;
123        char modulo[]="ServicioDHCP()";
124                       
125        socket_s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); // Crea socket para UDP
126        if (socket_s == SOCKET_ERROR){
127                errorLog(modulo,61, TRUE);
128                return(FALSE);
129        }
130        local.sin_addr.s_addr = htonl(INADDR_ANY); // selecciona interface
131        local.sin_family = AF_INET;     
132        local.sin_port = htons(PUERTODHCPORIGEN); // Puerto
133
134        // Enlaza socket
135        if (bind(socket_s,(struct sockaddr *)&local,sizeof(local)) == SOCKET_ERROR){
136                errorLog(modulo,62, TRUE);
137                return(FALSE);
138        }
139       
140        bOpt=TRUE; // Pone el socket en modo "soportar Broadcast"
141        ret=setsockopt(socket_s,SOL_SOCKET,SO_BROADCAST,(char *)&bOpt,sizeof(bOpt));
142        if (ret == SOCKET_ERROR){
143                errorLog(modulo,48, TRUE);
144                return(FALSE);
145    }
146        while(true){
147                trmInfo = (struct  TramaDhcpBootp*)malloc(sizeof(struct  TramaDhcpBootp)); // Crea estructura de control para hebra
148        if (trmInfo == NULL){
149                errorLog(modulo,64, FALSE);
150                        return(FALSE);
151        }
152                // Inicializa parámetros
153                memset(trmInfo,0,sizeof(struct  TramaDhcpBootp));
154                trmInfo->sockaddrsize = sizeof(trmInfo->cliente);
155                trmInfo->sck=socket_s;
156                // Espera tramas DHCP
157                ret = recvfrom(trmInfo->sck,(char *)&trmInfo->pckDchp, sizeof(trmInfo->pckDchp),0,(struct sockaddr *)&trmInfo->cliente, &trmInfo->sockaddrsize);
158                if (ret == SOCKET_ERROR){
159                errorLog(modulo,65, TRUE);
160                        return(FALSE);
161                }
162                else{
163                        if (ret>0){
164                                        resul=pthread_create(&hThread,NULL,GestionaServicioDHCP,(LPVOID)trmInfo);
165                                        if(resul!=0){
166                                        errorLog(modulo,66,TRUE);
167                                        return(FALSE);
168                                }
169                                pthread_detach(hThread);       
170                        }
171                }
172        }
173        close(socket_s);
174}
175// _____________________________________________________________________________________________________________
176// Función: ServicioBOOTP
177//
178//              Descripción:
179//                      Esta hebra implementa el servicio BOOTP
180// _____________________________________________________________________________________________________________
181
182LPVOID ServicioBOOTP(LPVOID iplocal)
183{
184        SOCKET socket_s; // Socket donde escucha el servidor
185        struct TramaDhcpBootp * trmInfo;
186        struct sockaddr_in local;
187        int ret,resul;
188        pthread_t hThread;
189        char modulo[]="ServicioBOOTP()";
190       
191        socket_s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); // Crea socket para UDP
192        if (socket_s == SOCKET_ERROR){
193                errorLog(modulo,67, TRUE);
194                return(FALSE);
195        }
196        local.sin_addr.s_addr = htonl(INADDR_ANY); // selecciona interface
197        local.sin_family = AF_INET;     
198        local.sin_port = htons(PUERTOBOOTPORIGEN); // Puerto
199
200        // Enlaza socket
201        if (bind(socket_s,(struct sockaddr *)&local,sizeof(local)) == SOCKET_ERROR){
202                errorLog(modulo,68, TRUE);
203                return(FALSE);
204        }
205        while(true){
206                trmInfo = (struct  TramaDhcpBootp*)malloc(sizeof(struct  TramaDhcpBootp)); // Crea estructura de control para hebra
207        if (trmInfo == NULL){
208                errorLog(modulo,69, FALSE);
209                    return(FALSE);
210        }
211                // Inicializa parámetros
212                memset(trmInfo,0,sizeof(struct  TramaDhcpBootp));
213                trmInfo->sockaddrsize = sizeof(trmInfo->cliente);
214                trmInfo->sck=socket_s;
215                // Espera tramas BOOTP
216                ret = recvfrom(trmInfo->sck,(char *)&trmInfo->pckDchp, sizeof(trmInfo->pckDchp),0,(struct sockaddr *)&trmInfo->cliente, &trmInfo->sockaddrsize);
217
218                if (ret == SOCKET_ERROR){
219                errorLog(modulo,70, TRUE);
220                        return(FALSE);
221                }
222                else{
223                        if (ret>0){
224                                        resul=pthread_create(&hThread,NULL,GestionaServicioBOOTP,(LPVOID)trmInfo);
225                                        if(resul!=0){
226                                        errorLog(modulo,71, TRUE);
227                                        return(FALSE);
228                                }
229                                pthread_detach(hThread);                                       
230                        }
231                }
232        }
233        close(socket_s);
234}
235// _____________________________________________________________________________________________________________
236// Función: ServicioTFTP
237//
238//              Descripción:
239//                      Esta hebra implementa el servicio TFTP
240// _____________________________________________________________________________________________________________
241
242LPVOID ServicioTFTP(LPVOID ipl)
243{
244        SOCKET socket_s; // Socket donde escucha el servidor
245        struct TramaTftp * trmInfo;
246        struct sockaddr_in local;
247        pthread_t hThread;
248        int ret,resul;
249        char modulo[]="ServicioTFTP()";
250
251        socket_s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); // Crea socket para UDP
252        if (socket_s == SOCKET_ERROR){
253                errorLog(modulo,72, TRUE);
254        return(FALSE);
255        }
256        local.sin_addr.s_addr = htonl(INADDR_ANY); // selecciona interface
257        local.sin_family = AF_INET;     
258        local.sin_port = htons(PUERTOTFTPORIGEN); // Puerto
259
260        // Enlaza socket
261        if (bind(socket_s,(struct sockaddr *)&local,sizeof(local)) == SOCKET_ERROR){
262                errorLog(modulo,73, TRUE);
263        return(FALSE);
264        }
265        while(true){
266                trmInfo = (struct  TramaTftp*)malloc(sizeof(struct  TramaTftp)); // Crea estructura de control para hebra
267        if (trmInfo == NULL){
268                errorLog(modulo,74, FALSE);
269                    return(FALSE);
270        }
271                memset(trmInfo,0,sizeof(struct  TramaTftp));
272                trmInfo->sockaddrsize = sizeof(trmInfo->cliente);
273                // Espera tramas TFTP
274                ret = recvfrom(socket_s,(char *)&trmInfo->pckTftp, sizeof(trmInfo->pckTftp),0,(struct sockaddr *)&trmInfo->cliente,&trmInfo->sockaddrsize);
275                if (ret == SOCKET_ERROR){
276                        errorLog(modulo,75, TRUE);
277                        return(FALSE);
278                }
279                else{
280                        if (ret>0){
281                                resul=pthread_create(&hThread,NULL,GestionaServicioTFTP,(LPVOID)trmInfo);
282                                if(resul!=0){
283                                        errorLog(modulo,76, TRUE);
284                                return(FALSE);
285                        }
286                        pthread_detach(hThread);
287                        }
288                }
289               
290        }
291        close(socket_s);
292}
293//________________________________________________________________________________________________________
294//      Función: GestionaServicioDHCP
295//
296//      Descripción:
297//              Gestiona la conexiónn con un cliente que sea Hidra para el servicio DHCP
298//      Parámetros:
299//              lpParam: Puntero a la estructura de control para la conversacion DHCP
300//      Devuelve:
301//              TRUE: Si el proceso es correcto
302//              FALSE: En caso de ocurrir algún error
303//________________________________________________________________________________________________________
304LPVOID GestionaServicioDHCP(LPVOID lpParam)
305{
306        struct TramaDhcpBootp * trmInfo=(struct TramaDhcpBootp *)lpParam;
307        char IPCliente[16]; // Ip del cliente
308        char MACCliente[16]; // Mac del cliente
309
310        if(!OpcionesPresentes(trmInfo->pckDchp.magiccookie)) // Comprueba que existen opciones en la trama Dhcp
311                return(false);
312        strcpy(IPCliente,inet_ntoa(trmInfo->cliente.sin_addr));
313        if(strcmp(IPCliente,"0.0.0.0")!=0){ // El cliente tiene una IP concreta distinta de 0.0.0.0
314                if(!ClienteExistente(trmInfo,IPCliente,1)){ // Comprueba que se trata de un cliente Hidra
315                        free(trmInfo);
316                        return(false);
317                }
318        }
319        else{
320                sprintf(MACCliente,"%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x",(unsigned int)trmInfo->pckDchp.chaddr[0],(unsigned int)trmInfo->pckDchp.chaddr[1],(unsigned int)trmInfo->pckDchp.chaddr[2],(unsigned int)trmInfo->pckDchp.chaddr[3],(unsigned int)trmInfo->pckDchp.chaddr[4],(unsigned int)trmInfo->pckDchp.chaddr[5]);
321                if(!ClienteExistente(trmInfo,MACCliente,0)){ // Comprueba que se trata de un cliente Hidra (Por la Mac)
322                        free(trmInfo);
323                        return(false);
324                }
325        }
326        if(OpcionPXEClient(&trmInfo->pckDchp)) // Comprueba que sea un cliente PXE
327                ProcesaTramaClientePXE(trmInfo); // Procesa DHCP para el protocolo PXE
328        else
329                ProcesaTramaClienteDHCP(trmInfo); // Procesa DHCP de cliente Windows o Linux
330
331        free(trmInfo);
332        return(false);
333}
334//_______________________________________________________________________________________________________________
335//
336// Gestiona la conexion con un cliente que sea Hidra para el servicio BOOTP
337// Parámetros:
338//              lpParam: Puntero a la estructura de control para la conversacion BOOTP
339//_______________________________________________________________________________________________________________
340LPVOID GestionaServicioBOOTP(LPVOID lpParam)
341{
342        struct TramaDhcpBootp * trmInfo=(struct TramaDhcpBootp *)lpParam;
343        char IPCliente[16]; // Ip del cliente
344
345        if(!OpcionesPresentes(trmInfo->pckDchp.magiccookie)) // Comprueba que existen opciones en la trama Dhcp
346                return(false);
347
348        strcpy(IPCliente,inet_ntoa(trmInfo->cliente.sin_addr));
349        if(!ClienteExistente(trmInfo,IPCliente,1)) // Comprueba que se trata de un cliente Hidra
350                return(false);
351
352        if(OpcionPXEClient(&trmInfo->pckDchp)) // Comprueba que sea un cliente PXE
353                ProcesaTramaClienteBOOTP(trmInfo); // Procesa DHCP para el protocolo PXE
354
355        free(trmInfo);
356        return(trmInfo);
357}
358//_______________________________________________________________________________________________________________
359//
360// Comprueba si la IP del cliente está en la base de datos de Hidra
361// Parámetros:
362//              trmInfo: Puntero a la estructura de control de la conversacin DHCP
363//              ipmac: IP o MAC del cliente que ha abierto la hebra
364//              sw: Si vale 1 o 2 o 3 el parámetro anterior ser una IP en caso contrario ser una MAC
365//
366//      Devuelve:
367//              true: Si el cliente est en la base de datos
368//              false: En caso contrario
369//
370//  Comentarios:
371//              Slo se procesarn mensages dhcp de clientes hidra.
372//_______________________________________________________________________________________________________________
373int ClienteExistente(struct TramaDhcpBootp *trmInfo,char* ipmac,int sw)
374{
375        char sqlstr[1000],ErrStr[200]; 
376        Database db;
377        Table tbl;
378        char wrouter[LONPRM];
379        char wmascara[LONPRM];
380        /////////////////////////////////////////////////////////////////////////
381        // ACCESO atnico A TRAVEZ DE OBJETO MUTEX a este trozo de cnigo
382        pthread_mutex_lock(&guardia);
383       
384        // Abre conexion con base de datos
385        if(!db.Open(usuario,pasguor,datasource,catalog)){ // error de conexion
386                db.GetErrorErrStr(ErrStr);
387                return(false);
388        }       
389       
390        if(sw==1 || sw==2){ // Bsqueda por IP
391                sprintf(sqlstr,"SELECT ip,router,mascara FROM ordenadores WHERE ip='%s' ",ipmac);
392        }
393        else{ // Bsqueda por MAC
394                sprintf(sqlstr,"SELECT ip,router,mascara FROM ordenadores WHERE mac='%s' ",ipmac);
395        }
396        if(!db.Execute(sqlstr,tbl)){ // Error al leer
397                db.GetErrorErrStr(ErrStr);
398                db.Close();
399                pthread_mutex_unlock(&guardia);
400                return(false);
401        }
402
403        if(tbl.ISEOF()){ // No existe el cliente
404                db.Close();
405                pthread_mutex_unlock(&guardia);
406                return(false);
407        }
408        if(sw==1 || sw==0){ // Sólo para las tramas dhcp PXE y BOOTP
409                if(!tbl.Get("ip",trmInfo->bdIP)){ // Incorpora la IP a asignar al cliente a la estructura de control
410                        tbl.GetErrorErrStr(ErrStr); // error al acceder al registro
411                        db.Close();
412                        pthread_mutex_unlock(&guardia);
413                        return(false);
414                }       
415                if(!tbl.Get("router",wrouter)){ // Toma la configuración router del cliente
416                        tbl.GetErrorErrStr(ErrStr); // error al acceder al registro
417                        db.Close();
418                        pthread_mutex_unlock(&guardia);
419                        return(false);
420                }
421                if(strlen(wrouter)>0)
422                        strcpy(oProuter,wrouter);
423                else
424                        strcpy(oProuter,router);
425
426                if(!tbl.Get("mascara",wmascara)){ // Toma la configuración router del cliente
427                        tbl.GetErrorErrStr(ErrStr); // error al acceder al registro
428                        db.Close();
429                        pthread_mutex_unlock(&guardia);
430                        return(false);
431                }
432                if(strlen(wmascara)>0)
433                        strcpy(oPmascara,wmascara);
434                else
435                        strcpy(oPmascara,mascara);
436        }
437        db.Close();
438        pthread_mutex_unlock(&guardia);
439        ////////////////////////////////////////////////////////////////////////////////
440        return(true);
441}
442//_______________________________________________________________________________________________________________
443//
444// Comprueba que existen opciones en el mensage dhcp analizando la magic cookie
445// Parámetros:
446//              mc: Puntero al primer elemento de la magic cookie (primer campo de las opciones)
447//
448//      Devuelve:
449//              true: Si esta presenta el valor 99..130.83.99
450//              false: En caso contrario
451//_______________________________________________________________________________________________________________
452int OpcionesPresentes(unsigned char *mc)
453{
454        if(mc[0]!=0x63) return(false);
455        if(mc[1]!=0x82) return(false);
456        if(mc[2]!=0x53) return(false);
457        if(mc[3]!=0x63) return(false);
458
459        // Magic Cookie presente
460        return(true);
461}
462//_______________________________________________________________________________________________________________
463//
464// Busca una determinada opción dentro de la trama dhcp
465// Parámetros:
466//              dhcp_packet: Puntero a la estructura que contiene el mensaje dhcp
467//              codop: Cdigo de la opción a buscar
468//
469//      Devuelve:
470//              Si existe, un puntero al primer elemento de la estructura de la opción (codigo,longitud,valor)
471//              en caso contrario devuelve null
472//_______________________________________________________________________________________________________________
473unsigned char * BuscaOpcion(dhcp_packet* tDhcp,unsigned char codop)
474{
475        unsigned char wcodop;
476        unsigned char wlongitud;
477        unsigned char *ptrOp,*ptrDhcp;
478
479        ptrDhcp=(unsigned char*)tDhcp; // Se toma el puntero al principio del mensage
480        ptrOp=(unsigned char*)&tDhcp->options[0]; // Se toma el puntero a las opciones
481
482        while(ptrOp-ptrDhcp<DHCP_OPTION_LEN-4){
483                wcodop = ptrOp[0];
484                if(wcodop==DHCP_PAD)
485                        ptrOp++;
486                else{
487                        if(wcodop==DHCP_END) // Fin de la cadena de opciones, no se encontr la opción
488                                return(NULL);
489                        else{
490                               
491                                if (wcodop == codop) // Encuentra la opción
492                                        return(ptrOp); // Devuelve el puntero a la estructura variable opción
493                                else{
494                                        wlongitud = ptrOp[1];
495                                        ptrOp+=wlongitud+2; // Avanza hasta la prxima opción
496                                }
497                        }
498                }
499        }
500        return(NULL);
501}
502//_______________________________________________________________________________________________________________
503//
504// Comprueba si el mensaje recibido proviene de un cliente PXE
505// Parámetros:
506//              dhcp_packet: Puntero a la estructura que contiene el mensaje dhcp
507//
508//      Devuelve:
509//              true: Si el mensaje lo ha enviado un cliente PXE
510//              false: En caso contrario
511//_______________________________________________________________________________________________________________
512int OpcionPXEClient(dhcp_packet* tDhcp)
513{
514        if(!BuscaOpcion(tDhcp,DHCP_CLASS_IDENTIFIER))
515                return(false);
516        else
517                return(true);
518}
519//_______________________________________________________________________________________________________________
520//
521// Procesa un mensaje DHCP recibido que proviene de un cliente PXE
522// Parámetros:
523//              trmInfo: Puntero a la estructura de control de la conversacin DHCP
524//_______________________________________________________________________________________________________________
525void ProcesaTramaClientePXE(struct TramaDhcpBootp* trmInfo)
526{
527        unsigned char codop;
528        unsigned char longitud;
529        unsigned char *ptrOp;
530        unsigned char *msgDhcp;
531        char modulo[]="ProcesaTramaClientePXE()";
532
533        ptrOp=BuscaOpcion(&trmInfo->pckDchp,DHCP_MESSAGE_TYPE); // Puntero a la opción tipo de mensaje
534        if(!ptrOp){ // No existe la opción DHCP
535                errorLog(modulo,77, FALSE);
536                return;
537        }
538        codop = ptrOp[0];
539        longitud=ptrOp[1];
540        msgDhcp=ptrOp+2; // Puntero al dato tipo de mensaje
541        switch(*msgDhcp){
542                case DHCPDISCOVER:
543                        dhcpDISCOVER_PXE(trmInfo);
544                        break;
545                case DHCPREQUEST:
546                        dhcpREQUEST_PXE(trmInfo);
547                        break;
548        }
549}
550//_______________________________________________________________________________________________________________
551//
552// Procesa un mensaje BOOTP recibido que proviene de un cliente PXE
553// Parámetros:
554//              trmInfo: Puntero a la estructura de control de la conversacin BOOTP
555//_______________________________________________________________________________________________________________
556void ProcesaTramaClienteBOOTP(struct TramaDhcpBootp* trmInfo)
557{
558        unsigned char codop;
559        unsigned char longitud;
560        unsigned char *ptrOp;
561        unsigned char *msgDhcp;
562        char modulo[]="ProcesaTramaClienteBOOTP()";
563
564        ptrOp=BuscaOpcion(&trmInfo->pckDchp,DHCP_MESSAGE_TYPE); // Puntero a la opción tipo de mensaje
565        if(!ptrOp){ // No existe la opción DHCP
566                errorLog(modulo,77, FALSE);
567                return;
568        }
569        codop = ptrOp[0];
570        longitud=ptrOp[1];
571        msgDhcp=ptrOp+2; // Puntero al dato tipo de mensaje
572        switch(*msgDhcp){
573                case DHCPREQUEST:
574                        bootpREQUEST_PXE(trmInfo);
575                        break;
576        }
577}
578//_______________________________________________________________________________________________________________
579//
580// Gestiona la conexion con un cliente que sea Hidra para el servicio TFTP
581// Parámetros:
582//              lpParam: Puntero a la estructura de control para la conversacion TFTP
583//_______________________________________________________________________________________________________________
584LPVOID GestionaServicioTFTP(LPVOID lpParam)
585{
586        struct TramaTftp * trmInfo=(struct TramaTftp *)lpParam;
587        char IPCliente[16]; // Ip del cliente
588
589        strcpy(IPCliente,inet_ntoa(trmInfo->cliente.sin_addr));
590        if(!ClienteExistente((struct TramaDhcpBootp*)trmInfo,IPCliente,2)) // Comprueba que se trata de un cliente Hidra
591                return(false);
592
593        // Inicializa parámetros
594        trmInfo->sockaddrsize = sizeof(trmInfo->cliente);
595        trmInfo->sck=TomaSocketUser();
596        if(trmInfo->sck==INVALID_SOCKET) return(false); // Ha habido algn problama para crear el socket de usuario
597
598        trmInfo->currentopCode=0x0000;  // Cdigo de operación para detectar errores de secuencia
599        trmInfo->bloquesize=512;                // Tamao de bloque por defecto 512
600        trmInfo->tsize=0;                               // Tamao del fichero
601        trmInfo->interval=0;                    // Intervalo
602
603        ProcesaTramaClienteTFTP(trmInfo); // Procesa TFTP para el protocolo PXE
604        close(trmInfo->sck);
605        free(trmInfo);
606        return(trmInfo);
607}
608//_______________________________________________________________________________________________________________
609//
610// Procesa un mensaje TFTP recibido que proviene de un cliente PXE
611// Parámetros:
612//              trmInfo: Puntero a la estructura de control de la conversacin TFTP
613//_______________________________________________________________________________________________________________
614void ProcesaTramaClienteTFTP(struct TramaTftp* trmInfo)
615{
616        char *ptr;
617        int bloque,lon,ret;
618        char tam[20];
619        struct tftppacket_ack* ptrack;
620        char modulo[]="ProcesaTramaClienteTFTP()";
621       
622        while(true){
623                switch(ntohs(trmInfo->pckTftp.opcode)){
624                        case TFTPRRQ: // Read Request
625                                if(trmInfo->currentopCode!=0x0000) return; // Error en la secuencia de operaciones
626                                if(!PeticionFichero(trmInfo)) return;
627                                fseek(trmInfo->fileboot,0,SEEK_SET);
628                                trmInfo->pckTftp.opcode= htons(TFTPOACK);
629                                trmInfo->currentopCode=TFTPOACK;
630                                ptr=&trmInfo->pckTftp.buffer[0];
631                                if(trmInfo->tsize>0){ // opción tsize
632                                        strcpy(ptr,"tsize");
633                                        ptr+=strlen(ptr)+1;
634                                        //itoa(trmInfo->tsize,tam,10);
635                                        sprintf(tam,"%d",trmInfo->tsize);
636                                        strcpy(ptr,tam);
637                                        ptr+=strlen(ptr)+1;
638                                        *ptr=0x00;
639                                }
640                                else{
641                                        if(trmInfo->bloquesize>0){ // opción blksize
642                                                strcpy(ptr,"blksize");
643                                                ptr+=strlen(ptr)+1;
644                                                //itoa(trmInfo->bloquesize,tam,10);
645                                                sprintf(tam,"%d",trmInfo->bloquesize);
646                                                strcpy(ptr,tam);
647                                                ptr+=strlen(ptr)+1;
648                                                *ptr=0x00;
649                                        }
650                                        else
651                                                trmInfo->bloquesize=512;
652                                }
653
654                                lon=ptr-(char*)&trmInfo->pckTftp;
655                                //ret=connect(trmInfo->sck,(struct sockaddr*)&trmInfo->cliente,trmInfo->sockaddrsize);
656                                //if (ret == SOCKET_ERROR){
657                                //      RegistraLog("***connect() fallo:",true);
658                                //      return;
659                                //}
660                                ret=sendto(trmInfo->sck,(char*)&trmInfo->pckTftp,lon,0,(struct sockaddr*)&trmInfo->cliente,trmInfo->sockaddrsize);
661                                //ret=send(trmInfo->sck,(char*)&trmInfo->pckTftp,lon,0);
662                                if (ret == SOCKET_ERROR){
663                                        errorLog(modulo,26, TRUE);
664                                        return;
665                                }
666                                break;
667
668                        case TFTPACK: //
669                                if(trmInfo->currentopCode!=TFTPOACK && trmInfo->currentopCode!=TFTPDATA) return; // Error en la secuencia de operaciones
670                                ptrack=(struct tftppacket_ack*)&trmInfo->pckTftp;
671                                bloque=ntohs(ptrack->block);
672                                trmInfo->currentopCode=TFTPDATA;
673                                ptrack->opcode=htons(TFTPDATA);
674                                bloque++;
675                                ptrack->block=htons(bloque);
676                                trmInfo->numblock=bloque;
677                                lon=fread(ptrack->buffer,1,trmInfo->bloquesize,trmInfo->fileboot);
678                                //ret=connect(trmInfo->sck,(struct sockaddr*)&trmInfo->cliente,trmInfo->sockaddrsize);
679                                //if (ret == SOCKET_ERROR){
680                                //      RegistraLog("***connect() fallo:",true);
681                                //      return;
682                                //}
683                                ret=sendto(trmInfo->sck,(char*)&trmInfo->pckTftp,lon+4,0,(struct sockaddr*)&trmInfo->cliente,trmInfo->sockaddrsize);
684                                //ret=send(trmInfo->sck,(char*)&trmInfo->pckTftp,lon+4,0);
685                                if (ret == SOCKET_ERROR){
686                                        errorLog(modulo,26, TRUE);
687                                        return;
688                                }
689                                if(lon==0)
690                                        return; // Fin de la trama tftp
691                                break;                                 
692                        case TFTPERROR:
693                                errorLog(modulo,78, TRUE);
694                }
695                ret = recvfrom(trmInfo->sck,(char *)&trmInfo->pckTftp, sizeof(trmInfo->pckTftp),0,(struct sockaddr *)&trmInfo->cliente,&trmInfo->sockaddrsize);
696                if (ret == SOCKET_ERROR){
697                        errorLog(modulo,79, TRUE);
698                        return;
699                }
700                else
701                        if(ret==0) break;
702         }
703         return;
704}
705//_______________________________________________________________________________________________________________
706//
707// Procesa un mensaje Tftp de peticin de fichero. Recupera datos de tamao de bloque y otros parámetros
708//      para gestionar la conversacin.
709//
710//      Parámetros:
711//              trmInfo: Puntero a la estructura de control de la conversacin TFTP
712//_______________________________________________________________________________________________________________
713int PeticionFichero(struct TramaTftp* trmInfo)
714{
715        char *ptr;
716        char nomfile[250];
717
718        if(strncmp(trmInfo->pckTftp.buffer,"pxelinux.cfg",12)==0)
719                strcpy(nomfile,"default");
720        else
721                strcpy(nomfile,trmInfo->pckTftp.buffer);
722       
723        trmInfo->currentopCode=ntohs(trmInfo->pckTftp.opcode); // Guarda código de operación
724        // Localiza parámetros
725        ptr=&trmInfo->pckTftp.buffer[0];
726        ptr+=strlen(ptr)+1; // Avanza al campo siguiente al del nombre de fichero
727        if(!strcmp(ptr,"octet")){       // Modo de apertura
728                //trmInfo->fileboot=fopen(trmInfo->pckTftp.buffer,"rb");
729                trmInfo->fileboot=fopen(nomfile,"rb");
730        }
731        else{
732                //trmInfo->fileboot=fopen(trmInfo->pckTftp.buffer,"rt");
733                trmInfo->fileboot=fopen(nomfile,"rt");         
734        }
735        if(trmInfo->fileboot==NULL)
736                return(false); // No existe el fichero boot
737        ptr+=strlen(ptr)+1; // Paso al parámetro siguiente
738        while(*ptr){
739                if(strcmp(ptr,"blksize")==0){   // parámetro blksize
740                        ptr+=strlen(ptr) + 1;
741                        trmInfo->bloquesize=atoi(ptr);
742                        if(trmInfo->bloquesize<512) trmInfo->bloquesize=512;
743                        if(trmInfo->bloquesize>MAXBLOCK) trmInfo->bloquesize=512;
744                        ptr+=strlen(ptr) + 1;
745                }
746                else{
747                        if(strcmp(ptr,"tsize")==0){     // parámetro tsize
748                                ptr+=strlen(ptr) + 1;
749                                fseek(trmInfo->fileboot,0,SEEK_END);
750                                trmInfo->tsize=ftell(trmInfo->fileboot);
751                                ptr+=strlen(ptr) + 1;
752                        }
753                        else{
754                                if(strcmp(ptr,"interval")==0){  // Tamao de los bloques
755                                        ptr+=strlen(ptr) + 1;
756                                        trmInfo->interval=atoi(ptr);
757                                        ptr+=strlen(ptr) + 1;
758                                }
759                                else
760                                        return(false);
761                        }
762               
763                }
764        }
765        return(true);
766}
767//_______________________________________________________________________________________________________________
768//
769// Procesa un mensaje recibido que proviene de un cliente Hidra pero no en el momento de arranque con PXE
770// sino cuando arranca con algn S.O. como (Windows oLinux)
771//
772//      Parámetros:
773//              trmInfo: Puntero a la estructura de control de la conversacin DHCP
774//_______________________________________________________________________________________________________________
775void ProcesaTramaClienteDHCP(struct TramaDhcpBootp* trmInfo)
776{
777        unsigned char codop;
778        unsigned char longitud;
779        unsigned char *ptrOp;
780        unsigned char *msgDhcp;
781        int ret;
782        char modulo[]="ProcesaTramaClienteDHCP()";
783
784        while(true){
785                ptrOp=BuscaOpcion(&trmInfo->pckDchp,DHCP_MESSAGE_TYPE); // Puntero a la opción tipo de mensaje
786                if(!ptrOp){ // No existe la opción DHCP
787                        errorLog(modulo,77, FALSE);
788                        return;
789                }
790                codop = ptrOp[0];
791                longitud=ptrOp[1];
792                msgDhcp=ptrOp+2; // Puntero al dato tipo de mensaje
793
794                switch(*msgDhcp){
795                        case DHCPDISCOVER:
796                                dhcpDISCOVER_PXE(trmInfo);
797                                break;
798                        case DHCPREQUEST:
799                                dhcpREQUEST_PXE(trmInfo);
800                                break;
801                }
802                ret = recvfrom(trmInfo->sck,(char *)&trmInfo->pckDchp, sizeof(trmInfo->pckDchp),0,(struct sockaddr *)&trmInfo->cliente,&trmInfo->sockaddrsize);
803                if (ret == SOCKET_ERROR){
804                        errorLog(modulo,80, TRUE);
805                }
806                else
807                        if(ret==0) break;
808         }
809}
810//_______________________________________________________________________________________________________________
811//
812// Rellena el campo IP asignada(yiaddr) al cliente dentro del mensaje DHCP
813//
814//      Parámetros:
815//              trmInfo: Puntero a la estructura de control de la conversacin DHCP
816//_______________________________________________________________________________________________________________
817void RellenaIPCLiente(struct TramaDhcpBootp* trmInfo)
818{
819        unsigned long aux;
820
821        aux=inet_addr(trmInfo->bdIP); // Ip para el cliente
822        memcpy((void*)&trmInfo->pckDchp.yiaddr,&aux,sizeof(aux));
823}
824//_______________________________________________________________________________________________________________
825//
826// Rellena el campo IP del servidor(siaddr) dentro del mensaje DHCP
827//
828//      Parámetros:
829//              trmInfo: Puntero a la estructura de control de la conversacin DHCP
830//_______________________________________________________________________________________________________________
831void RellenaIPServidor(struct TramaDhcpBootp* trmInfo)
832{
833        unsigned long aux;
834
835        aux=inet_addr(IPlocal); // Ip del servidor
836        memcpy(&trmInfo->pckDchp.siaddr,&aux,sizeof(aux));
837}
838//_______________________________________________________________________________________________________________
839//
840// Rellena el campo nombre del servidor boot dentro del mensaje BOOTP
841//
842//      Parámetros:
843//              trmInfo: Puntero a la estructura de control de la conversacin BOOTP
844//_______________________________________________________________________________________________________________
845void RellenaNombreServidorBoot(struct TramaDhcpBootp* trmInfo)
846{
847        char aux[100];
848
849        strcpy(aux,"Hidra 2.0 PXE Boot Server");
850        memcpy(&trmInfo->pckDchp.sname,&aux,25);
851}
852//_______________________________________________________________________________________________________________
853//
854// Rellena el campo nombre del fichero boot dentro del mensaje BOOTP
855//
856//      Parámetros:
857//              trmInfo: Puntero a la estructura de control de la conversacin BOOTP
858//_______________________________________________________________________________________________________________
859void RellenaNombreFicheroBoot(struct TramaDhcpBootp* trmInfo)
860{
861        char aux[100];
862
863        strcpy(aux,"pxelinux.0");
864        memcpy(&trmInfo->pckDchp.file,&aux,25);
865}
866//_______________________________________________________________________________________________________________
867//
868// Procesa un mensaje DHCPDISCOVER
869//
870//      Parámetros:
871//              trmInfo: Puntero a la estructura de control de la conversacin DHCP
872//
873//      Devuelve:
874//              true: Si el mensaje se procesa correctamente
875//              false: En caso contrario
876//_______________________________________________________________________________________________________________
877void dhcpDISCOVER_PXE(struct TramaDhcpBootp* trmInfo)
878{
879        unsigned char *ptrOp,*ptrDhcp;
880        int lon,ret;
881        char modulo[]="dhcpDISCOVER_PXE()";
882
883        ptrDhcp=(unsigned char*)&trmInfo->pckDchp; // Se toma el puntero al principio del mensage
884        ptrOp=(unsigned char*)&trmInfo->pckDchp.options[0]; // Se toma el puntero a las opciones
885        lon=ptrOp-ptrDhcp; //Longitud del mensaje sin las opciones ni la magic coockie
886
887        RellenaIPCLiente(trmInfo);
888        RellenaIPServidor(trmInfo);
889        *ptrOp='\0'; //Borra opciones del mensaje recibido para colocar las nuevas
890       
891
892        AdjDHCPOFFER(&ptrOp,&lon);                      // Genera opción de Mensaje (0x35) dhcp valor 1
893        AdjSERVERIDENTIFIER(&ptrOp,&lon);       // Genera opción de Mensaje (0x36) Dhcp
894        AdjLEASETIME(&ptrOp,&lon);                      // Genera opción de Mensaje (0x33) Dhcp
895        AdjSUBNETMASK(&ptrOp,&lon);                     // Genera opción de Mensaje (0x01) Dhcp
896        AdjROUTERS(&ptrOp,&lon);                        // Genera opción de Mensaje (0x03) Dhcp
897        AdjCLASSIDENTIFIER(&ptrOp,&lon);        // Genera opción de Mensaje (0x3c) Dhcp
898        *ptrOp=DHCP_END;
899        lon++;
900        trmInfo->pckDchp.op=DHCPOFFER;
901        //MandaRespuesta(&trmInfo->pckDchp,htonl(INADDR_BROADCAST),lon,htons(PUERTODHCPDESTINO));
902        trmInfo->cliente.sin_addr.s_addr=htonl(INADDR_BROADCAST);
903        ret=sendto(trmInfo->sck,(char*)&trmInfo->pckDchp,lon,0,(struct sockaddr*)&trmInfo->cliente,trmInfo->sockaddrsize);
904        if (ret == SOCKET_ERROR){
905                errorLog(modulo,26, TRUE);
906        }
907}
908//_______________________________________________________________________________________________________________
909//
910// Procesa un mensaje DHCPREQUEST (DHCP)
911//
912//      Parámetros:
913//              trmInfo: Puntero a la estructura de control para la conversacin DHCP
914//
915//      Devuelve:
916//              true: Si el mensaje se procesa correctamente
917//              false: En caso contrario
918//_______________________________________________________________________________________________________________
919void dhcpREQUEST_PXE(struct TramaDhcpBootp* trmInfo)
920{
921        unsigned char * ptrOp,*ptrDhcp;
922        struct dhcp_opcion;
923        int lon,ret;
924        char modulo[]="dhcpREQUEST_PXE()";
925
926        ptrDhcp=(unsigned char*)&trmInfo->pckDchp; // Se toma el puntero al principio del mensage
927        ptrOp=(unsigned char*)&trmInfo->pckDchp.options[0]; // Se toma el puntero a las opciones
928        lon=ptrOp-ptrDhcp; //Longitud del mensaje sin las opciones ni la magic coockie
929
930        RellenaIPCLiente(trmInfo);
931        RellenaIPServidor(trmInfo);
932        *ptrOp='\0'; //Borra opciones del mensaje recibido para colocar las nuevas
933
934        AdjDHCPACK(&ptrOp,&lon);                        // Ge           db.Close();nera opción de Mensaje (0x35) dhcp valor 5
935        AdjSERVERIDENTIFIER(&ptrOp,&lon);       // Genera opción de Mensaje (0x36) Dhcp
936        AdjLEASETIME(&ptrOp,&lon);                      // Genera opción de Mensaje (0x33) Dhcp
937        AdjSUBNETMASK(&ptrOp,&lon);                     // Genera opción de Mensaje (0x01) Dhcp
938        AdjROUTERS(&ptrOp,&lon);                        // Genera opción de Mensaje (0x03) Dhcp
939        AdjCLASSIDENTIFIER(&ptrOp,&lon);        // Genera opción de Mensaje (0x3c) Dhcp
940
941        *ptrOp=DHCP_END;
942        lon++;
943
944        trmInfo->pckDchp.op=DHCPOFFER;
945        //MandaRespuesta(&trmInfo->pckDchp,htonl(INADDR_BROADCAST),lon,htons(PUERTODHCPDESTINO));
946        trmInfo->cliente.sin_addr.s_addr=htonl(INADDR_BROADCAST);
947        ret=sendto(trmInfo->sck,(char*)&trmInfo->pckDchp,lon,0,(struct sockaddr*)&trmInfo->cliente,trmInfo->sockaddrsize);
948        if (ret == SOCKET_ERROR){
949                errorLog(modulo,26, TRUE);
950        }
951}
952//_______________________________________________________________________________________________________________
953//
954// Procesa un mensaje DHCPREQUEST (BOOTP)
955//
956//      Parámetros:
957//              trmInfo: Puntero a la estructura de control para la conversacin BOOTP
958//
959//      Devuelve:
960//              true: Si el mensaje se procesa correctamente
961//              false: En caso contrario
962//_______________________________________________________________________________________________________________
963void bootpREQUEST_PXE(struct TramaDhcpBootp* trmInfo)
964{
965        unsigned char * ptrOp,*ptrDhcp;
966        struct dhcp_opcion;
967        int lon,ret;
968        unsigned long aux;
969        char modulo[]="bootpREQUEST_PXE()";
970
971        ptrDhcp=(unsigned char*)&trmInfo->pckDchp; // Se toma el puntero al principio del mensage
972        ptrOp=(unsigned char*)&trmInfo->pckDchp.options[0]; // Se toma el puntero a las opciones
973        lon=ptrOp-ptrDhcp; //Longitud del mensaje sin las opciones ni la magic coockie
974
975        aux=inet_addr("0.0.0.0"); // Borra Ip del cliente ( No se porqu pero en la trama aparece as)
976        memcpy(&trmInfo->pckDchp.ciaddr,&aux,4);
977        RellenaNombreServidorBoot(trmInfo);
978        RellenaNombreFicheroBoot(trmInfo);
979
980        *ptrOp='\0'; //Borra opciones del mensaje recibido para colocar las nuevas
981
982        AdjDHCPACK(&ptrOp,&lon);                        // Genera opción de Mensaje (0x35) dhcp valor 5
983        AdjSERVERIDENTIFIER(&ptrOp,&lon);       // Genera opción de Mensaje (0x36) Dhcp
984        AdjBOOTSIZE(&ptrOp,&lon);                       // Genera opción de Mensaje (0x0D) Dhcp
985        AdjCLASSIDENTIFIER(&ptrOp,&lon);        // Genera opción de Mensaje (0x3c) Dhcp
986
987        *ptrOp=DHCP_END;
988        lon++;
989
990        trmInfo->pckDchp.op=DHCPOFFER;
991        //ret=connect(trmInfo->sck,(struct sockaddr*)&trmInfo->cliente,trmInfo->sockaddrsize);
992        //if (ret == SOCKET_ERROR){
993        //      RegistraLog("***connect() fallo:",true);
994        //      return;
995        //}
996        //ret=send(trmInfo->sck,(char*)&trmInfo->pckDchp,lon,0);
997        ret=sendto(trmInfo->sck,(char*)&trmInfo->pckDchp,lon,0,(struct sockaddr*)&trmInfo->cliente,trmInfo->sockaddrsize);     
998        if (ret == SOCKET_ERROR){
999                errorLog(modulo,26,TRUE);
1000                return;
1001        }
1002}
1003//_______________________________________________________________________________________________________________
1004//
1005// Genera una opción del tipo 0x35(53) con el valor "Dhcp Offer" valor 2
1006//
1007//      Devuelve:
1008//              Una estructura de opciones de dhcp(codigo,longitud,dato) con la opciones de Mensaje dhcp Offer
1009//_______________________________________________________________________________________________________________
1010void AdjDHCPOFFER(unsigned char* *ptrOp,int*lon)
1011{
1012        **ptrOp=DHCP_MESSAGE_TYPE;
1013        *ptrOp+=1;
1014        **ptrOp=1;
1015        *ptrOp+=1;
1016        **ptrOp=DHCPOFFER;
1017        *ptrOp+=1;
1018        *lon+=3;
1019}
1020//_______________________________________________________________________________________________________________
1021//
1022// Genera una opción del tipo 0x35(53) con el valor "Dhcp Ack" valor 5
1023//
1024//      Devuelve:
1025//              Una estructura de opciones de dhcp(codigo,longitud,dato) con la opciones de Mensaje dhcp Ack
1026//_______________________________________________________________________________________________________________
1027void AdjDHCPACK(unsigned char** ptrOp,int*lon)
1028
1029{
1030        **ptrOp=DHCP_MESSAGE_TYPE;
1031        *ptrOp+=1;
1032        **ptrOp=1;
1033        *ptrOp+=1;
1034        **ptrOp=DHCPACK;
1035        *ptrOp+=1;
1036        *lon+=3;
1037}
1038//_______________________________________________________________________________________________________________
1039//
1040// Genera una opción del tipo 0x03(3) con la IP del router
1041//
1042//      Devuelve:
1043//              Una estructura de opciones de dhcp(codigo,longitud,dato) con la opciones de Ip del Routers
1044//_______________________________________________________________________________________________________________
1045void AdjROUTERS(unsigned char** ptrOp,int*lon)
1046{
1047        unsigned long aux;
1048        aux=inet_addr(oProuter); // Router
1049
1050        **ptrOp=DHCP_ROUTERS;
1051        *ptrOp+=1;
1052        **ptrOp=4;
1053        *ptrOp+=1;
1054        memcpy(*ptrOp,&aux,4); // Copia la Ip del router en la estructura
1055        *ptrOp+=4;
1056        *lon+=6;
1057
1058}
1059//_______________________________________________________________________________________________________________
1060//
1061// Genera una opción del tipo 0x01(1) con la mascara de red
1062//
1063//      Devuelve:
1064//              Una estructura de opciones de dhcp(codigo,longitud,dato) con la opciones de mscara de red
1065//_______________________________________________________________________________________________________________
1066void AdjSUBNETMASK(unsigned char** ptrOp,int*lon)
1067{
1068        unsigned long aux;
1069        aux=inet_addr(oPmascara); // Mascara de red
1070
1071        **ptrOp=DHCP_SUBNET_MASK;
1072        *ptrOp+=1;
1073        **ptrOp=4;
1074        *ptrOp+=1;
1075        memcpy(*ptrOp,&aux,4); // Copia la máscara de red
1076        *ptrOp+=4;
1077        *lon+=6;
1078}
1079//_______________________________________________________________________________________________________________
1080//
1081// Genera una opción del tipo 0x3c(60) con el literal "PXECLient" para clientes PXE
1082//
1083//      Devuelve:
1084//              Una estructura de opciones de dhcp(codigo,longitud,dato) con la opciones de clase de cliente
1085//_______________________________________________________________________________________________________________
1086void AdjCLASSIDENTIFIER(unsigned char** ptrOp,int*lon)
1087{
1088        **ptrOp=DHCP_CLASS_IDENTIFIER;
1089        *ptrOp+=1;
1090        **ptrOp=9;
1091        *ptrOp+=1;
1092        memcpy(*ptrOp,"PXEClient",9); // Copia el literal PXClient
1093        *ptrOp+=9;
1094        *lon+=11;
1095}
1096//_______________________________________________________________________________________________________________
1097//
1098// Genera una opción del tipo 0x36(54) con la IP del servidor
1099//
1100//      Devuelve:
1101//              Una estructura de opciones de dhcp(codigo,longitud,dato) con la opciones de Ip del servidor
1102//_______________________________________________________________________________________________________________
1103void AdjSERVERIDENTIFIER(unsigned char** ptrOp,int*lon)
1104{
1105        unsigned long aux;
1106        aux=inet_addr(IPlocal); // Ip del servidor
1107
1108        **ptrOp=DHCP_SERVER_IDENTIFIER;
1109        *ptrOp+=1;
1110        **ptrOp=4;
1111        *ptrOp+=1;
1112        memcpy(*ptrOp,&aux,4); // Copia la Ip del ervidor en la estructura
1113        *ptrOp+=4;
1114        *lon+=6;
1115
1116}
1117//_______________________________________________________________________________________________________________
1118//
1119// Genera una opción del tipo 0x33(51) con el tiempo de "lease" de la IP
1120//
1121//      Devuelve:
1122//              Una estructura de opciones de dhcp(codigo,longitud,dato) con la opciones del "Lease Time"
1123//_______________________________________________________________________________________________________________
1124void AdjLEASETIME(unsigned char** ptrOp,int*lon)
1125{
1126        unsigned long aux;
1127        aux=0x00006054; // tiempo en segundos
1128
1129        **ptrOp=DHCP_LEASE_TIME;
1130        *ptrOp+=1;
1131        **ptrOp=4;
1132        *ptrOp+=1;
1133        memcpy(*ptrOp,&aux,4); // Copia el lease time en la estructura
1134        *ptrOp+=4;
1135        *lon+=6;
1136}
1137//_______________________________________________________________________________________________________________
1138//
1139// Genera una opción del tipo 0x0D(13) con el tiempo tamao del fichero boot
1140//
1141//      Devuelve:
1142//              Una estructura de opciones de dhcp(codigo,longitud,dato) con la opciones del "Lease Time"
1143//_______________________________________________________________________________________________________________
1144void AdjBOOTSIZE(unsigned char** ptrOp,int*lon)
1145{
1146        unsigned short aux;
1147        aux=0x0402; // Tamao en bytes
1148
1149        **ptrOp=DHCP_BOOT_SIZE;
1150        *ptrOp+=1;
1151        **ptrOp=2;
1152        *ptrOp+=1;
1153        memcpy(*ptrOp,&aux,2); // Copia el tamao en la estructura
1154        *ptrOp+=2;
1155        *lon+=4;
1156}
1157//_______________________________________________________________________________________________________________
1158//
1159// Crea un socket en un puerto determinado para la conversacin de las distintas hebras
1160//
1161//_______________________________________________________________________________________________________________
1162SOCKET TomaSocketUser()
1163{
1164        SOCKET socket_c; // Socket para hebras (UDP)
1165    struct sockaddr_in cliente;
1166        int ret,puerto;
1167        BOOLEAN bOpt;
1168        char modulo[]="TomaSocketUser()";
1169
1170        socket_c = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); // Crea socket para UDP
1171
1172        if (socket_c == SOCKET_ERROR){
1173                errorLog(modulo,81,TRUE);
1174        return(false);
1175        }
1176        cliente.sin_addr.s_addr = htonl(INADDR_ANY); // selecciona interface
1177        cliente.sin_family = AF_INET;
1178        puerto=PUERTOMINUSER;
1179        while(puerto<PUERTOMAXUSER){ // Busca puerto libre
1180                cliente.sin_port = htons(puerto); // Puerto asignado
1181                if (bind(socket_c,(struct sockaddr *)&cliente,sizeof(cliente)) == SOCKET_ERROR)
1182                        puerto++;
1183                else
1184                        break;
1185        }
1186        if(puerto>=PUERTOMAXUSER){ // No hay puertos libres
1187                errorLog(modulo,63, TRUE);
1188                return(INVALID_SOCKET);
1189        }
1190
1191        bOpt=TRUE; // Pone el socket en modo "soportar Broadcast"
1192        ret=setsockopt(socket_c,SOL_SOCKET,SO_BROADCAST,(char *)&bOpt,sizeof(bOpt));
1193        if (ret == SOCKET_ERROR){
1194                errorLog(modulo,48, TRUE);
1195                return(INVALID_SOCKET);
1196    }
1197        return(socket_c);
1198}
1199//_______________________________________________________________________________________________________________
1200void Pinta(dhcp_packet* tdp)
1201{
1202        return;
1203        printf("\nop = %d  htype = %d  hlen = %d  hops = %d",tdp -> op, tdp -> htype, tdp -> hlen, tdp -> hops);
1204        //printf ("\nxid = %x  secs = %d  flags = %x",tdp -> xid, tdp -> secs, tdp -> flags);
1205        printf ("\nciaddr = %s", inet_ntoa (tdp -> ciaddr));
1206        printf ("\nyiaddr = %s", inet_ntoa (tdp -> yiaddr));
1207        printf ("\nsiaddr = %s", inet_ntoa (tdp -> siaddr));
1208        printf ("\ngiaddr = %s", inet_ntoa (tdp -> giaddr));
1209        printf ("\nchaddr = %x:%x:%x:%x:%x:%x",((unsigned char *)(tdp -> chaddr)) [0],((unsigned char *)(tdp -> chaddr)) [1],((unsigned char *)(tdp -> chaddr)) [2],((unsigned char *)(tdp -> chaddr)) [3],((unsigned char *)(tdp -> chaddr)) [4],((unsigned char *)(tdp -> chaddr)) [5]);
1210        printf ("\nfilename = %s", tdp -> file);
1211        printf ("\nserver_name = %s", tdp -> sname);
1212
1213        printf ("\n\n");
1214}
1215//***************************************************************************************************************
1216// PROGRAMA PRINCIPAL
1217//***************************************************************************************************************
1218int main(int argc, char **argv)
1219{
1220        pthread_t hThreadDHCP,hThreadBOOTP,hThreadTFTP;
1221        int resul;
1222        char modulo[] = "main()";
1223       
1224        /*--------------------------------------------------------------------------------------------------------
1225                Validación de parámetros de ejecución y lectura del fichero de configuración del servicio
1226         ---------------------------------------------------------------------------------------------------------*/
1227        if (!validacionParametros(argc, argv,4)) // Valida parámetros de ejecución
1228                exit(EXIT_FAILURE);
1229
1230        if (!tomaConfiguracion(szPathFileCfg)) { // Toma parametros de configuracion
1231                exit(EXIT_FAILURE);
1232        }
1233       
1234        infoLog(1); // Inicio de sesión
1235       
1236        // Hebra servicio DHCP ---------------------------------
1237        resul=pthread_create(&hThreadDHCP,NULL,ServicioDHCP,(LPVOID)IPlocal);
1238        if(resul!=0){
1239                errorLog(modulo, 58, TRUE);
1240                exit(EXIT_FAILURE);
1241    }
1242    pthread_detach(hThreadDHCP);
1243   
1244 
1245        // Hebra servicio BOOTP  ---------------------------------
1246        resul=pthread_create(&hThreadBOOTP,NULL,ServicioBOOTP,(LPVOID)IPlocal);
1247        if(resul!=0){
1248                errorLog(modulo,59,TRUE);
1249                exit(EXIT_FAILURE);
1250    }
1251    pthread_detach(hThreadBOOTP);
1252   
1253        // Hebra servicio TFTP  ----------------------------------
1254        resul=pthread_create(&hThreadTFTP,NULL,ServicioTFTP,(LPVOID)IPlocal);
1255        if(resul!=0){
1256                errorLog(modulo,60,TRUE);
1257                exit(EXIT_FAILURE);
1258    }
1259    pthread_detach(hThreadTFTP);
1260   
1261    while (true)
1262        sleep(1000);
1263       
1264}
Note: See TracBrowser for help on using the repository browser.