1265 lines
44 KiB
C++
1265 lines
44 KiB
C++
// ********************************************************************************************************
|
|
// Servicio: ogAdmBoot
|
|
// Autor: José Manuel Alonso (E.T.S.I.I.) Universidad de Sevilla
|
|
// Fecha Creación: Julio-2010
|
|
// Fecha Última modificación: Julio-2010
|
|
// Nombre del fichero: ogAdmBoot.cpp
|
|
// Descripción :Este fichero implementa el servicio dhcp y tftp propios del sistema
|
|
// ********************************************************************************************************
|
|
#include "ogAdmBoot.h"
|
|
#include "ogAdmLib.c"
|
|
//________________________________________________________________________________________________________
|
|
// Función: tomaConfiguracion
|
|
//
|
|
// Descripción:
|
|
// Lee el fichero de configuración del servicio
|
|
// Parámetros:
|
|
// filecfg : Ruta completa al fichero de configuración
|
|
// Devuelve:
|
|
// TRUE: Si el proceso es correcto
|
|
// FALSE: En caso de ocurrir algún error
|
|
//________________________________________________________________________________________________________
|
|
BOOLEAN tomaConfiguracion(char* filecfg)
|
|
{
|
|
char modulo[] = "tomaConfiguracion()";
|
|
|
|
if (filecfg == NULL || strlen(filecfg) == 0) {
|
|
errorLog(modulo, 1, FALSE); // Fichero de configuración del servicio vacío
|
|
return (FALSE);
|
|
}
|
|
FILE *fcfg;
|
|
long lSize;
|
|
char * buffer, *lineas[MAXPRM], *dualparametro[2];
|
|
int i, numlin, resul;
|
|
|
|
fcfg = fopen(filecfg, "rt");
|
|
if (fcfg == NULL) {
|
|
errorLog(modulo, 2, FALSE); // No existe fichero de configuración del servicio
|
|
return (FALSE);
|
|
}
|
|
|
|
fseek(fcfg, 0, SEEK_END);
|
|
lSize = ftell(fcfg); // Obtiene tamaño del fichero.
|
|
rewind(fcfg);
|
|
buffer = (char*) reservaMemoria(lSize+1); // Toma memoria para el buffer de lectura.
|
|
if (buffer == NULL) { // No hay memoria suficiente para el buffer
|
|
errorLog(modulo, 3, FALSE);
|
|
return (FALSE);
|
|
}
|
|
fread(buffer, 1, lSize, fcfg); // Lee contenido del fichero
|
|
buffer[lSize]=(char) NULL;
|
|
fclose(fcfg);
|
|
|
|
IPlocal[0] = (char) NULL; //inicializar variables globales
|
|
usuario[0] = (char) NULL;
|
|
pasguor[0] = (char) NULL;
|
|
datasource[0] = (char) NULL;
|
|
catalog[0] = (char) NULL;
|
|
router[0] = (char) NULL;
|
|
mascara[0] = (char) NULL;
|
|
|
|
numlin = splitCadena(lineas, buffer, '\n');
|
|
for (i = 0; i < numlin; i++) {
|
|
splitCadena(dualparametro, lineas[i], '=');
|
|
resul = strcmp(StrToUpper(dualparametro[0]), "IPLOCAL");
|
|
if (resul == 0)
|
|
strcpy(IPlocal, dualparametro[1]);
|
|
resul = strcmp(StrToUpper(dualparametro[0]), "USUARIO");
|
|
if (resul == 0)
|
|
strcpy(usuario, dualparametro[1]);
|
|
resul = strcmp(StrToUpper(dualparametro[0]), "PASSWORD");
|
|
if (resul == 0)
|
|
strcpy(pasguor, dualparametro[1]);
|
|
resul = strcmp(StrToUpper(dualparametro[0]), "DATASOURCE");
|
|
if (resul == 0)
|
|
strcpy(datasource, dualparametro[1]);
|
|
resul = strcmp(StrToUpper(dualparametro[0]), "CATALOG");
|
|
if (resul == 0)
|
|
strcpy(catalog, dualparametro[1]);
|
|
resul = strcmp(StrToUpper(dualparametro[0]), "ROUTER");
|
|
if (resul == 0)
|
|
strcpy(router, dualparametro[1]);
|
|
resul = strcmp(StrToUpper(dualparametro[0]), "MASCARA");
|
|
if (resul == 0)
|
|
strcpy(mascara, dualparametro[1]);
|
|
}
|
|
if (IPlocal[0] == (char) NULL) {
|
|
errorLog(modulo, 4, FALSE); // Falta parámetro IPLOCAL
|
|
return (FALSE);
|
|
}
|
|
if (usuario[0] == (char) NULL) {
|
|
errorLog(modulo, 6, FALSE); // Falta parámetro USUARIO
|
|
return (FALSE);
|
|
}
|
|
if (pasguor[0] == (char) NULL) {
|
|
errorLog(modulo, 7, FALSE); // Falta parámetro PASSWORD
|
|
return (FALSE);
|
|
}
|
|
if (datasource[0] == (char) NULL) {
|
|
errorLog(modulo, 8, FALSE); // Falta parámetro DATASOURCE
|
|
return (FALSE);
|
|
}
|
|
if (catalog[0] == (char) NULL) {
|
|
errorLog(modulo, 9, FALSE); // Falta parámetro CATALOG
|
|
return (FALSE);
|
|
}
|
|
return (TRUE);
|
|
}
|
|
// _____________________________________________________________________________________________________________
|
|
// Función: ServicioDHCP
|
|
//
|
|
// Descripción:
|
|
// Esta hebra implementa el servicio DHCP
|
|
// _____________________________________________________________________________________________________________
|
|
|
|
LPVOID ServicioDHCP(LPVOID ipl)
|
|
{
|
|
SOCKET socket_s; // Socket donde escucha el servidor
|
|
struct TramaDhcpBootp * trmInfo;
|
|
struct sockaddr_in local;
|
|
int ret,resul;
|
|
BOOLEAN bOpt;
|
|
pthread_t hThread;
|
|
char modulo[]="ServicioDHCP()";
|
|
|
|
socket_s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); // Crea socket para UDP
|
|
if (socket_s == SOCKET_ERROR){
|
|
errorLog(modulo,61, TRUE);
|
|
return(FALSE);
|
|
}
|
|
local.sin_addr.s_addr = htonl(INADDR_ANY); // selecciona interface
|
|
local.sin_family = AF_INET;
|
|
local.sin_port = htons(PUERTODHCPORIGEN); // Puerto
|
|
|
|
// Enlaza socket
|
|
if (bind(socket_s,(struct sockaddr *)&local,sizeof(local)) == SOCKET_ERROR){
|
|
errorLog(modulo,62, TRUE);
|
|
return(FALSE);
|
|
}
|
|
|
|
bOpt=TRUE; // Pone el socket en modo "soportar Broadcast"
|
|
ret=setsockopt(socket_s,SOL_SOCKET,SO_BROADCAST,(char *)&bOpt,sizeof(bOpt));
|
|
if (ret == SOCKET_ERROR){
|
|
errorLog(modulo,48, TRUE);
|
|
return(FALSE);
|
|
}
|
|
while(true){
|
|
trmInfo = (struct TramaDhcpBootp*)malloc(sizeof(struct TramaDhcpBootp)); // Crea estructura de control para hebra
|
|
if (trmInfo == NULL){
|
|
errorLog(modulo,64, FALSE);
|
|
return(FALSE);
|
|
}
|
|
// Inicializa parámetros
|
|
memset(trmInfo,0,sizeof(struct TramaDhcpBootp));
|
|
trmInfo->sockaddrsize = sizeof(trmInfo->cliente);
|
|
trmInfo->sck=socket_s;
|
|
// Espera tramas DHCP
|
|
ret = recvfrom(trmInfo->sck,(char *)&trmInfo->pckDchp, sizeof(trmInfo->pckDchp),0,(struct sockaddr *)&trmInfo->cliente, &trmInfo->sockaddrsize);
|
|
if (ret == SOCKET_ERROR){
|
|
errorLog(modulo,65, TRUE);
|
|
return(FALSE);
|
|
}
|
|
else{
|
|
if (ret>0){
|
|
resul=pthread_create(&hThread,NULL,GestionaServicioDHCP,(LPVOID)trmInfo);
|
|
if(resul!=0){
|
|
errorLog(modulo,66,TRUE);
|
|
return(FALSE);
|
|
}
|
|
pthread_detach(hThread);
|
|
}
|
|
}
|
|
}
|
|
close(socket_s);
|
|
}
|
|
// _____________________________________________________________________________________________________________
|
|
// Función: ServicioBOOTP
|
|
//
|
|
// Descripción:
|
|
// Esta hebra implementa el servicio BOOTP
|
|
// _____________________________________________________________________________________________________________
|
|
|
|
LPVOID ServicioBOOTP(LPVOID iplocal)
|
|
{
|
|
SOCKET socket_s; // Socket donde escucha el servidor
|
|
struct TramaDhcpBootp * trmInfo;
|
|
struct sockaddr_in local;
|
|
int ret,resul;
|
|
pthread_t hThread;
|
|
char modulo[]="ServicioBOOTP()";
|
|
|
|
socket_s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); // Crea socket para UDP
|
|
if (socket_s == SOCKET_ERROR){
|
|
errorLog(modulo,67, TRUE);
|
|
return(FALSE);
|
|
}
|
|
local.sin_addr.s_addr = htonl(INADDR_ANY); // selecciona interface
|
|
local.sin_family = AF_INET;
|
|
local.sin_port = htons(PUERTOBOOTPORIGEN); // Puerto
|
|
|
|
// Enlaza socket
|
|
if (bind(socket_s,(struct sockaddr *)&local,sizeof(local)) == SOCKET_ERROR){
|
|
errorLog(modulo,68, TRUE);
|
|
return(FALSE);
|
|
}
|
|
while(true){
|
|
trmInfo = (struct TramaDhcpBootp*)malloc(sizeof(struct TramaDhcpBootp)); // Crea estructura de control para hebra
|
|
if (trmInfo == NULL){
|
|
errorLog(modulo,69, FALSE);
|
|
return(FALSE);
|
|
}
|
|
// Inicializa parámetros
|
|
memset(trmInfo,0,sizeof(struct TramaDhcpBootp));
|
|
trmInfo->sockaddrsize = sizeof(trmInfo->cliente);
|
|
trmInfo->sck=socket_s;
|
|
// Espera tramas BOOTP
|
|
ret = recvfrom(trmInfo->sck,(char *)&trmInfo->pckDchp, sizeof(trmInfo->pckDchp),0,(struct sockaddr *)&trmInfo->cliente, &trmInfo->sockaddrsize);
|
|
|
|
if (ret == SOCKET_ERROR){
|
|
errorLog(modulo,70, TRUE);
|
|
return(FALSE);
|
|
}
|
|
else{
|
|
if (ret>0){
|
|
resul=pthread_create(&hThread,NULL,GestionaServicioBOOTP,(LPVOID)trmInfo);
|
|
if(resul!=0){
|
|
errorLog(modulo,71, TRUE);
|
|
return(FALSE);
|
|
}
|
|
pthread_detach(hThread);
|
|
}
|
|
}
|
|
}
|
|
close(socket_s);
|
|
}
|
|
// _____________________________________________________________________________________________________________
|
|
// Función: ServicioTFTP
|
|
//
|
|
// Descripción:
|
|
// Esta hebra implementa el servicio TFTP
|
|
// _____________________________________________________________________________________________________________
|
|
|
|
LPVOID ServicioTFTP(LPVOID ipl)
|
|
{
|
|
SOCKET socket_s; // Socket donde escucha el servidor
|
|
struct TramaTftp * trmInfo;
|
|
struct sockaddr_in local;
|
|
pthread_t hThread;
|
|
int ret,resul;
|
|
char modulo[]="ServicioTFTP()";
|
|
|
|
socket_s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); // Crea socket para UDP
|
|
if (socket_s == SOCKET_ERROR){
|
|
errorLog(modulo,72, TRUE);
|
|
return(FALSE);
|
|
}
|
|
local.sin_addr.s_addr = htonl(INADDR_ANY); // selecciona interface
|
|
local.sin_family = AF_INET;
|
|
local.sin_port = htons(PUERTOTFTPORIGEN); // Puerto
|
|
|
|
// Enlaza socket
|
|
if (bind(socket_s,(struct sockaddr *)&local,sizeof(local)) == SOCKET_ERROR){
|
|
errorLog(modulo,73, TRUE);
|
|
return(FALSE);
|
|
}
|
|
while(true){
|
|
trmInfo = (struct TramaTftp*)malloc(sizeof(struct TramaTftp)); // Crea estructura de control para hebra
|
|
if (trmInfo == NULL){
|
|
errorLog(modulo,74, FALSE);
|
|
return(FALSE);
|
|
}
|
|
memset(trmInfo,0,sizeof(struct TramaTftp));
|
|
trmInfo->sockaddrsize = sizeof(trmInfo->cliente);
|
|
// Espera tramas TFTP
|
|
ret = recvfrom(socket_s,(char *)&trmInfo->pckTftp, sizeof(trmInfo->pckTftp),0,(struct sockaddr *)&trmInfo->cliente,&trmInfo->sockaddrsize);
|
|
if (ret == SOCKET_ERROR){
|
|
errorLog(modulo,75, TRUE);
|
|
return(FALSE);
|
|
}
|
|
else{
|
|
if (ret>0){
|
|
resul=pthread_create(&hThread,NULL,GestionaServicioTFTP,(LPVOID)trmInfo);
|
|
if(resul!=0){
|
|
errorLog(modulo,76, TRUE);
|
|
return(FALSE);
|
|
}
|
|
pthread_detach(hThread);
|
|
}
|
|
}
|
|
|
|
}
|
|
close(socket_s);
|
|
}
|
|
//________________________________________________________________________________________________________
|
|
// Función: GestionaServicioDHCP
|
|
//
|
|
// Descripción:
|
|
// Gestiona la conexiónn con un cliente que sea Hidra para el servicio DHCP
|
|
// Parámetros:
|
|
// lpParam: Puntero a la estructura de control para la conversacion DHCP
|
|
// Devuelve:
|
|
// TRUE: Si el proceso es correcto
|
|
// FALSE: En caso de ocurrir algún error
|
|
//________________________________________________________________________________________________________
|
|
LPVOID GestionaServicioDHCP(LPVOID lpParam)
|
|
{
|
|
struct TramaDhcpBootp * trmInfo=(struct TramaDhcpBootp *)lpParam;
|
|
char IPCliente[16]; // Ip del cliente
|
|
char MACCliente[16]; // Mac del cliente
|
|
|
|
if(!OpcionesPresentes(trmInfo->pckDchp.magiccookie)) // Comprueba que existen opciones en la trama Dhcp
|
|
return(false);
|
|
strcpy(IPCliente,inet_ntoa(trmInfo->cliente.sin_addr));
|
|
if(strcmp(IPCliente,"0.0.0.0")!=0){ // El cliente tiene una IP concreta distinta de 0.0.0.0
|
|
if(!ClienteExistente(trmInfo,IPCliente,1)){ // Comprueba que se trata de un cliente Hidra
|
|
free(trmInfo);
|
|
return(false);
|
|
}
|
|
}
|
|
else{
|
|
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]);
|
|
if(!ClienteExistente(trmInfo,MACCliente,0)){ // Comprueba que se trata de un cliente Hidra (Por la Mac)
|
|
free(trmInfo);
|
|
return(false);
|
|
}
|
|
}
|
|
if(OpcionPXEClient(&trmInfo->pckDchp)) // Comprueba que sea un cliente PXE
|
|
ProcesaTramaClientePXE(trmInfo); // Procesa DHCP para el protocolo PXE
|
|
else
|
|
ProcesaTramaClienteDHCP(trmInfo); // Procesa DHCP de cliente Windows o Linux
|
|
|
|
free(trmInfo);
|
|
return(false);
|
|
}
|
|
//_______________________________________________________________________________________________________________
|
|
//
|
|
// Gestiona la conexion con un cliente que sea Hidra para el servicio BOOTP
|
|
// Parámetros:
|
|
// lpParam: Puntero a la estructura de control para la conversacion BOOTP
|
|
//_______________________________________________________________________________________________________________
|
|
LPVOID GestionaServicioBOOTP(LPVOID lpParam)
|
|
{
|
|
struct TramaDhcpBootp * trmInfo=(struct TramaDhcpBootp *)lpParam;
|
|
char IPCliente[16]; // Ip del cliente
|
|
|
|
if(!OpcionesPresentes(trmInfo->pckDchp.magiccookie)) // Comprueba que existen opciones en la trama Dhcp
|
|
return(false);
|
|
|
|
strcpy(IPCliente,inet_ntoa(trmInfo->cliente.sin_addr));
|
|
if(!ClienteExistente(trmInfo,IPCliente,1)) // Comprueba que se trata de un cliente Hidra
|
|
return(false);
|
|
|
|
if(OpcionPXEClient(&trmInfo->pckDchp)) // Comprueba que sea un cliente PXE
|
|
ProcesaTramaClienteBOOTP(trmInfo); // Procesa DHCP para el protocolo PXE
|
|
|
|
free(trmInfo);
|
|
return(trmInfo);
|
|
}
|
|
//_______________________________________________________________________________________________________________
|
|
//
|
|
// Comprueba si la IP del cliente está en la base de datos de Hidra
|
|
// Parámetros:
|
|
// trmInfo: Puntero a la estructura de control de la conversacin DHCP
|
|
// ipmac: IP o MAC del cliente que ha abierto la hebra
|
|
// sw: Si vale 1 o 2 o 3 el parámetro anterior ser una IP en caso contrario ser una MAC
|
|
//
|
|
// Devuelve:
|
|
// true: Si el cliente est en la base de datos
|
|
// false: En caso contrario
|
|
//
|
|
// Comentarios:
|
|
// Slo se procesarn mensages dhcp de clientes hidra.
|
|
//_______________________________________________________________________________________________________________
|
|
int ClienteExistente(struct TramaDhcpBootp *trmInfo,char* ipmac,int sw)
|
|
{
|
|
char sqlstr[1000],ErrStr[200];
|
|
Database db;
|
|
Table tbl;
|
|
char wrouter[LONPRM];
|
|
char wmascara[LONPRM];
|
|
/////////////////////////////////////////////////////////////////////////
|
|
// ACCESO atnico A TRAVEZ DE OBJETO MUTEX a este trozo de cnigo
|
|
pthread_mutex_lock(&guardia);
|
|
|
|
// Abre conexion con base de datos
|
|
if(!db.Open(usuario,pasguor,datasource,catalog)){ // error de conexion
|
|
db.GetErrorErrStr(ErrStr);
|
|
return(false);
|
|
}
|
|
|
|
if(sw==1 || sw==2){ // Bsqueda por IP
|
|
sprintf(sqlstr,"SELECT ip,router,mascara FROM ordenadores WHERE ip='%s' ",ipmac);
|
|
}
|
|
else{ // Bsqueda por MAC
|
|
sprintf(sqlstr,"SELECT ip,router,mascara FROM ordenadores WHERE mac='%s' ",ipmac);
|
|
}
|
|
if(!db.Execute(sqlstr,tbl)){ // Error al leer
|
|
db.GetErrorErrStr(ErrStr);
|
|
db.Close();
|
|
pthread_mutex_unlock(&guardia);
|
|
return(false);
|
|
}
|
|
|
|
if(tbl.ISEOF()){ // No existe el cliente
|
|
db.Close();
|
|
pthread_mutex_unlock(&guardia);
|
|
return(false);
|
|
}
|
|
if(sw==1 || sw==0){ // Sólo para las tramas dhcp PXE y BOOTP
|
|
if(!tbl.Get("ip",trmInfo->bdIP)){ // Incorpora la IP a asignar al cliente a la estructura de control
|
|
tbl.GetErrorErrStr(ErrStr); // error al acceder al registro
|
|
db.Close();
|
|
pthread_mutex_unlock(&guardia);
|
|
return(false);
|
|
}
|
|
if(!tbl.Get("router",wrouter)){ // Toma la configuración router del cliente
|
|
tbl.GetErrorErrStr(ErrStr); // error al acceder al registro
|
|
db.Close();
|
|
pthread_mutex_unlock(&guardia);
|
|
return(false);
|
|
}
|
|
if(strlen(wrouter)>0)
|
|
strcpy(oProuter,wrouter);
|
|
else
|
|
strcpy(oProuter,router);
|
|
|
|
if(!tbl.Get("mascara",wmascara)){ // Toma la configuración router del cliente
|
|
tbl.GetErrorErrStr(ErrStr); // error al acceder al registro
|
|
db.Close();
|
|
pthread_mutex_unlock(&guardia);
|
|
return(false);
|
|
}
|
|
if(strlen(wmascara)>0)
|
|
strcpy(oPmascara,wmascara);
|
|
else
|
|
strcpy(oPmascara,mascara);
|
|
}
|
|
db.Close();
|
|
pthread_mutex_unlock(&guardia);
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
return(true);
|
|
}
|
|
//_______________________________________________________________________________________________________________
|
|
//
|
|
// Comprueba que existen opciones en el mensage dhcp analizando la magic cookie
|
|
// Parámetros:
|
|
// mc: Puntero al primer elemento de la magic cookie (primer campo de las opciones)
|
|
//
|
|
// Devuelve:
|
|
// true: Si esta presenta el valor 99..130.83.99
|
|
// false: En caso contrario
|
|
//_______________________________________________________________________________________________________________
|
|
int OpcionesPresentes(unsigned char *mc)
|
|
{
|
|
if(mc[0]!=0x63) return(false);
|
|
if(mc[1]!=0x82) return(false);
|
|
if(mc[2]!=0x53) return(false);
|
|
if(mc[3]!=0x63) return(false);
|
|
|
|
// Magic Cookie presente
|
|
return(true);
|
|
}
|
|
//_______________________________________________________________________________________________________________
|
|
//
|
|
// Busca una determinada opción dentro de la trama dhcp
|
|
// Parámetros:
|
|
// dhcp_packet: Puntero a la estructura que contiene el mensaje dhcp
|
|
// codop: Cdigo de la opción a buscar
|
|
//
|
|
// Devuelve:
|
|
// Si existe, un puntero al primer elemento de la estructura de la opción (codigo,longitud,valor)
|
|
// en caso contrario devuelve null
|
|
//_______________________________________________________________________________________________________________
|
|
unsigned char * BuscaOpcion(dhcp_packet* tDhcp,unsigned char codop)
|
|
{
|
|
unsigned char wcodop;
|
|
unsigned char wlongitud;
|
|
unsigned char *ptrOp,*ptrDhcp;
|
|
|
|
ptrDhcp=(unsigned char*)tDhcp; // Se toma el puntero al principio del mensage
|
|
ptrOp=(unsigned char*)&tDhcp->options[0]; // Se toma el puntero a las opciones
|
|
|
|
while(ptrOp-ptrDhcp<DHCP_OPTION_LEN-4){
|
|
wcodop = ptrOp[0];
|
|
if(wcodop==DHCP_PAD)
|
|
ptrOp++;
|
|
else{
|
|
if(wcodop==DHCP_END) // Fin de la cadena de opciones, no se encontr la opción
|
|
return(NULL);
|
|
else{
|
|
|
|
if (wcodop == codop) // Encuentra la opción
|
|
return(ptrOp); // Devuelve el puntero a la estructura variable opción
|
|
else{
|
|
wlongitud = ptrOp[1];
|
|
ptrOp+=wlongitud+2; // Avanza hasta la prxima opción
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return(NULL);
|
|
}
|
|
//_______________________________________________________________________________________________________________
|
|
//
|
|
// Comprueba si el mensaje recibido proviene de un cliente PXE
|
|
// Parámetros:
|
|
// dhcp_packet: Puntero a la estructura que contiene el mensaje dhcp
|
|
//
|
|
// Devuelve:
|
|
// true: Si el mensaje lo ha enviado un cliente PXE
|
|
// false: En caso contrario
|
|
//_______________________________________________________________________________________________________________
|
|
int OpcionPXEClient(dhcp_packet* tDhcp)
|
|
{
|
|
if(!BuscaOpcion(tDhcp,DHCP_CLASS_IDENTIFIER))
|
|
return(false);
|
|
else
|
|
return(true);
|
|
}
|
|
//_______________________________________________________________________________________________________________
|
|
//
|
|
// Procesa un mensaje DHCP recibido que proviene de un cliente PXE
|
|
// Parámetros:
|
|
// trmInfo: Puntero a la estructura de control de la conversacin DHCP
|
|
//_______________________________________________________________________________________________________________
|
|
void ProcesaTramaClientePXE(struct TramaDhcpBootp* trmInfo)
|
|
{
|
|
unsigned char codop;
|
|
unsigned char longitud;
|
|
unsigned char *ptrOp;
|
|
unsigned char *msgDhcp;
|
|
char modulo[]="ProcesaTramaClientePXE()";
|
|
|
|
ptrOp=BuscaOpcion(&trmInfo->pckDchp,DHCP_MESSAGE_TYPE); // Puntero a la opción tipo de mensaje
|
|
if(!ptrOp){ // No existe la opción DHCP
|
|
errorLog(modulo,77, FALSE);
|
|
return;
|
|
}
|
|
codop = ptrOp[0];
|
|
longitud=ptrOp[1];
|
|
msgDhcp=ptrOp+2; // Puntero al dato tipo de mensaje
|
|
switch(*msgDhcp){
|
|
case DHCPDISCOVER:
|
|
dhcpDISCOVER_PXE(trmInfo);
|
|
break;
|
|
case DHCPREQUEST:
|
|
dhcpREQUEST_PXE(trmInfo);
|
|
break;
|
|
}
|
|
}
|
|
//_______________________________________________________________________________________________________________
|
|
//
|
|
// Procesa un mensaje BOOTP recibido que proviene de un cliente PXE
|
|
// Parámetros:
|
|
// trmInfo: Puntero a la estructura de control de la conversacin BOOTP
|
|
//_______________________________________________________________________________________________________________
|
|
void ProcesaTramaClienteBOOTP(struct TramaDhcpBootp* trmInfo)
|
|
{
|
|
unsigned char codop;
|
|
unsigned char longitud;
|
|
unsigned char *ptrOp;
|
|
unsigned char *msgDhcp;
|
|
char modulo[]="ProcesaTramaClienteBOOTP()";
|
|
|
|
ptrOp=BuscaOpcion(&trmInfo->pckDchp,DHCP_MESSAGE_TYPE); // Puntero a la opción tipo de mensaje
|
|
if(!ptrOp){ // No existe la opción DHCP
|
|
errorLog(modulo,77, FALSE);
|
|
return;
|
|
}
|
|
codop = ptrOp[0];
|
|
longitud=ptrOp[1];
|
|
msgDhcp=ptrOp+2; // Puntero al dato tipo de mensaje
|
|
switch(*msgDhcp){
|
|
case DHCPREQUEST:
|
|
bootpREQUEST_PXE(trmInfo);
|
|
break;
|
|
}
|
|
}
|
|
//_______________________________________________________________________________________________________________
|
|
//
|
|
// Gestiona la conexion con un cliente que sea Hidra para el servicio TFTP
|
|
// Parámetros:
|
|
// lpParam: Puntero a la estructura de control para la conversacion TFTP
|
|
//_______________________________________________________________________________________________________________
|
|
LPVOID GestionaServicioTFTP(LPVOID lpParam)
|
|
{
|
|
struct TramaTftp * trmInfo=(struct TramaTftp *)lpParam;
|
|
char IPCliente[16]; // Ip del cliente
|
|
|
|
strcpy(IPCliente,inet_ntoa(trmInfo->cliente.sin_addr));
|
|
if(!ClienteExistente((struct TramaDhcpBootp*)trmInfo,IPCliente,2)) // Comprueba que se trata de un cliente Hidra
|
|
return(false);
|
|
|
|
// Inicializa parámetros
|
|
trmInfo->sockaddrsize = sizeof(trmInfo->cliente);
|
|
trmInfo->sck=TomaSocketUser();
|
|
if(trmInfo->sck==INVALID_SOCKET) return(false); // Ha habido algn problama para crear el socket de usuario
|
|
|
|
trmInfo->currentopCode=0x0000; // Cdigo de operación para detectar errores de secuencia
|
|
trmInfo->bloquesize=512; // Tamao de bloque por defecto 512
|
|
trmInfo->tsize=0; // Tamao del fichero
|
|
trmInfo->interval=0; // Intervalo
|
|
|
|
ProcesaTramaClienteTFTP(trmInfo); // Procesa TFTP para el protocolo PXE
|
|
close(trmInfo->sck);
|
|
free(trmInfo);
|
|
return(trmInfo);
|
|
}
|
|
//_______________________________________________________________________________________________________________
|
|
//
|
|
// Procesa un mensaje TFTP recibido que proviene de un cliente PXE
|
|
// Parámetros:
|
|
// trmInfo: Puntero a la estructura de control de la conversacin TFTP
|
|
//_______________________________________________________________________________________________________________
|
|
void ProcesaTramaClienteTFTP(struct TramaTftp* trmInfo)
|
|
{
|
|
char *ptr;
|
|
int bloque,lon,ret;
|
|
char tam[20];
|
|
struct tftppacket_ack* ptrack;
|
|
char modulo[]="ProcesaTramaClienteTFTP()";
|
|
|
|
while(true){
|
|
switch(ntohs(trmInfo->pckTftp.opcode)){
|
|
case TFTPRRQ: // Read Request
|
|
if(trmInfo->currentopCode!=0x0000) return; // Error en la secuencia de operaciones
|
|
if(!PeticionFichero(trmInfo)) return;
|
|
fseek(trmInfo->fileboot,0,SEEK_SET);
|
|
trmInfo->pckTftp.opcode= htons(TFTPOACK);
|
|
trmInfo->currentopCode=TFTPOACK;
|
|
ptr=&trmInfo->pckTftp.buffer[0];
|
|
if(trmInfo->tsize>0){ // opción tsize
|
|
strcpy(ptr,"tsize");
|
|
ptr+=strlen(ptr)+1;
|
|
//itoa(trmInfo->tsize,tam,10);
|
|
sprintf(tam,"%d",trmInfo->tsize);
|
|
strcpy(ptr,tam);
|
|
ptr+=strlen(ptr)+1;
|
|
*ptr=0x00;
|
|
}
|
|
else{
|
|
if(trmInfo->bloquesize>0){ // opción blksize
|
|
strcpy(ptr,"blksize");
|
|
ptr+=strlen(ptr)+1;
|
|
//itoa(trmInfo->bloquesize,tam,10);
|
|
sprintf(tam,"%d",trmInfo->bloquesize);
|
|
strcpy(ptr,tam);
|
|
ptr+=strlen(ptr)+1;
|
|
*ptr=0x00;
|
|
}
|
|
else
|
|
trmInfo->bloquesize=512;
|
|
}
|
|
|
|
lon=ptr-(char*)&trmInfo->pckTftp;
|
|
//ret=connect(trmInfo->sck,(struct sockaddr*)&trmInfo->cliente,trmInfo->sockaddrsize);
|
|
//if (ret == SOCKET_ERROR){
|
|
// RegistraLog("***connect() fallo:",true);
|
|
// return;
|
|
//}
|
|
ret=sendto(trmInfo->sck,(char*)&trmInfo->pckTftp,lon,0,(struct sockaddr*)&trmInfo->cliente,trmInfo->sockaddrsize);
|
|
//ret=send(trmInfo->sck,(char*)&trmInfo->pckTftp,lon,0);
|
|
if (ret == SOCKET_ERROR){
|
|
errorLog(modulo,26, TRUE);
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case TFTPACK: //
|
|
if(trmInfo->currentopCode!=TFTPOACK && trmInfo->currentopCode!=TFTPDATA) return; // Error en la secuencia de operaciones
|
|
ptrack=(struct tftppacket_ack*)&trmInfo->pckTftp;
|
|
bloque=ntohs(ptrack->block);
|
|
trmInfo->currentopCode=TFTPDATA;
|
|
ptrack->opcode=htons(TFTPDATA);
|
|
bloque++;
|
|
ptrack->block=htons(bloque);
|
|
trmInfo->numblock=bloque;
|
|
lon=fread(ptrack->buffer,1,trmInfo->bloquesize,trmInfo->fileboot);
|
|
//ret=connect(trmInfo->sck,(struct sockaddr*)&trmInfo->cliente,trmInfo->sockaddrsize);
|
|
//if (ret == SOCKET_ERROR){
|
|
// RegistraLog("***connect() fallo:",true);
|
|
// return;
|
|
//}
|
|
ret=sendto(trmInfo->sck,(char*)&trmInfo->pckTftp,lon+4,0,(struct sockaddr*)&trmInfo->cliente,trmInfo->sockaddrsize);
|
|
//ret=send(trmInfo->sck,(char*)&trmInfo->pckTftp,lon+4,0);
|
|
if (ret == SOCKET_ERROR){
|
|
errorLog(modulo,26, TRUE);
|
|
return;
|
|
}
|
|
if(lon==0)
|
|
return; // Fin de la trama tftp
|
|
break;
|
|
case TFTPERROR:
|
|
errorLog(modulo,78, TRUE);
|
|
}
|
|
ret = recvfrom(trmInfo->sck,(char *)&trmInfo->pckTftp, sizeof(trmInfo->pckTftp),0,(struct sockaddr *)&trmInfo->cliente,&trmInfo->sockaddrsize);
|
|
if (ret == SOCKET_ERROR){
|
|
errorLog(modulo,79, TRUE);
|
|
return;
|
|
}
|
|
else
|
|
if(ret==0) break;
|
|
}
|
|
return;
|
|
}
|
|
//_______________________________________________________________________________________________________________
|
|
//
|
|
// Procesa un mensaje Tftp de peticin de fichero. Recupera datos de tamao de bloque y otros parámetros
|
|
// para gestionar la conversacin.
|
|
//
|
|
// Parámetros:
|
|
// trmInfo: Puntero a la estructura de control de la conversacin TFTP
|
|
//_______________________________________________________________________________________________________________
|
|
int PeticionFichero(struct TramaTftp* trmInfo)
|
|
{
|
|
char *ptr;
|
|
char nomfile[250];
|
|
|
|
if(strncmp(trmInfo->pckTftp.buffer,"pxelinux.cfg",12)==0)
|
|
strcpy(nomfile,"default");
|
|
else
|
|
strcpy(nomfile,trmInfo->pckTftp.buffer);
|
|
|
|
trmInfo->currentopCode=ntohs(trmInfo->pckTftp.opcode); // Guarda código de operación
|
|
// Localiza parámetros
|
|
ptr=&trmInfo->pckTftp.buffer[0];
|
|
ptr+=strlen(ptr)+1; // Avanza al campo siguiente al del nombre de fichero
|
|
if(!strcmp(ptr,"octet")){ // Modo de apertura
|
|
//trmInfo->fileboot=fopen(trmInfo->pckTftp.buffer,"rb");
|
|
trmInfo->fileboot=fopen(nomfile,"rb");
|
|
}
|
|
else{
|
|
//trmInfo->fileboot=fopen(trmInfo->pckTftp.buffer,"rt");
|
|
trmInfo->fileboot=fopen(nomfile,"rt");
|
|
}
|
|
if(trmInfo->fileboot==NULL)
|
|
return(false); // No existe el fichero boot
|
|
ptr+=strlen(ptr)+1; // Paso al parámetro siguiente
|
|
while(*ptr){
|
|
if(strcmp(ptr,"blksize")==0){ // parámetro blksize
|
|
ptr+=strlen(ptr) + 1;
|
|
trmInfo->bloquesize=atoi(ptr);
|
|
if(trmInfo->bloquesize<512) trmInfo->bloquesize=512;
|
|
if(trmInfo->bloquesize>MAXBLOCK) trmInfo->bloquesize=512;
|
|
ptr+=strlen(ptr) + 1;
|
|
}
|
|
else{
|
|
if(strcmp(ptr,"tsize")==0){ // parámetro tsize
|
|
ptr+=strlen(ptr) + 1;
|
|
fseek(trmInfo->fileboot,0,SEEK_END);
|
|
trmInfo->tsize=ftell(trmInfo->fileboot);
|
|
ptr+=strlen(ptr) + 1;
|
|
}
|
|
else{
|
|
if(strcmp(ptr,"interval")==0){ // Tamao de los bloques
|
|
ptr+=strlen(ptr) + 1;
|
|
trmInfo->interval=atoi(ptr);
|
|
ptr+=strlen(ptr) + 1;
|
|
}
|
|
else
|
|
return(false);
|
|
}
|
|
|
|
}
|
|
}
|
|
return(true);
|
|
}
|
|
//_______________________________________________________________________________________________________________
|
|
//
|
|
// Procesa un mensaje recibido que proviene de un cliente Hidra pero no en el momento de arranque con PXE
|
|
// sino cuando arranca con algn S.O. como (Windows oLinux)
|
|
//
|
|
// Parámetros:
|
|
// trmInfo: Puntero a la estructura de control de la conversacin DHCP
|
|
//_______________________________________________________________________________________________________________
|
|
void ProcesaTramaClienteDHCP(struct TramaDhcpBootp* trmInfo)
|
|
{
|
|
unsigned char codop;
|
|
unsigned char longitud;
|
|
unsigned char *ptrOp;
|
|
unsigned char *msgDhcp;
|
|
int ret;
|
|
char modulo[]="ProcesaTramaClienteDHCP()";
|
|
|
|
while(true){
|
|
ptrOp=BuscaOpcion(&trmInfo->pckDchp,DHCP_MESSAGE_TYPE); // Puntero a la opción tipo de mensaje
|
|
if(!ptrOp){ // No existe la opción DHCP
|
|
errorLog(modulo,77, FALSE);
|
|
return;
|
|
}
|
|
codop = ptrOp[0];
|
|
longitud=ptrOp[1];
|
|
msgDhcp=ptrOp+2; // Puntero al dato tipo de mensaje
|
|
|
|
switch(*msgDhcp){
|
|
case DHCPDISCOVER:
|
|
dhcpDISCOVER_PXE(trmInfo);
|
|
break;
|
|
case DHCPREQUEST:
|
|
dhcpREQUEST_PXE(trmInfo);
|
|
break;
|
|
}
|
|
ret = recvfrom(trmInfo->sck,(char *)&trmInfo->pckDchp, sizeof(trmInfo->pckDchp),0,(struct sockaddr *)&trmInfo->cliente,&trmInfo->sockaddrsize);
|
|
if (ret == SOCKET_ERROR){
|
|
errorLog(modulo,80, TRUE);
|
|
}
|
|
else
|
|
if(ret==0) break;
|
|
}
|
|
}
|
|
//_______________________________________________________________________________________________________________
|
|
//
|
|
// Rellena el campo IP asignada(yiaddr) al cliente dentro del mensaje DHCP
|
|
//
|
|
// Parámetros:
|
|
// trmInfo: Puntero a la estructura de control de la conversacin DHCP
|
|
//_______________________________________________________________________________________________________________
|
|
void RellenaIPCLiente(struct TramaDhcpBootp* trmInfo)
|
|
{
|
|
unsigned long aux;
|
|
|
|
aux=inet_addr(trmInfo->bdIP); // Ip para el cliente
|
|
memcpy((void*)&trmInfo->pckDchp.yiaddr,&aux,sizeof(aux));
|
|
}
|
|
//_______________________________________________________________________________________________________________
|
|
//
|
|
// Rellena el campo IP del servidor(siaddr) dentro del mensaje DHCP
|
|
//
|
|
// Parámetros:
|
|
// trmInfo: Puntero a la estructura de control de la conversacin DHCP
|
|
//_______________________________________________________________________________________________________________
|
|
void RellenaIPServidor(struct TramaDhcpBootp* trmInfo)
|
|
{
|
|
unsigned long aux;
|
|
|
|
aux=inet_addr(IPlocal); // Ip del servidor
|
|
memcpy(&trmInfo->pckDchp.siaddr,&aux,sizeof(aux));
|
|
}
|
|
//_______________________________________________________________________________________________________________
|
|
//
|
|
// Rellena el campo nombre del servidor boot dentro del mensaje BOOTP
|
|
//
|
|
// Parámetros:
|
|
// trmInfo: Puntero a la estructura de control de la conversacin BOOTP
|
|
//_______________________________________________________________________________________________________________
|
|
void RellenaNombreServidorBoot(struct TramaDhcpBootp* trmInfo)
|
|
{
|
|
char aux[100];
|
|
|
|
strcpy(aux,"Hidra 2.0 PXE Boot Server");
|
|
memcpy(&trmInfo->pckDchp.sname,&aux,25);
|
|
}
|
|
//_______________________________________________________________________________________________________________
|
|
//
|
|
// Rellena el campo nombre del fichero boot dentro del mensaje BOOTP
|
|
//
|
|
// Parámetros:
|
|
// trmInfo: Puntero a la estructura de control de la conversacin BOOTP
|
|
//_______________________________________________________________________________________________________________
|
|
void RellenaNombreFicheroBoot(struct TramaDhcpBootp* trmInfo)
|
|
{
|
|
char aux[100];
|
|
|
|
strcpy(aux,"pxelinux.0");
|
|
memcpy(&trmInfo->pckDchp.file,&aux,25);
|
|
}
|
|
//_______________________________________________________________________________________________________________
|
|
//
|
|
// Procesa un mensaje DHCPDISCOVER
|
|
//
|
|
// Parámetros:
|
|
// trmInfo: Puntero a la estructura de control de la conversacin DHCP
|
|
//
|
|
// Devuelve:
|
|
// true: Si el mensaje se procesa correctamente
|
|
// false: En caso contrario
|
|
//_______________________________________________________________________________________________________________
|
|
void dhcpDISCOVER_PXE(struct TramaDhcpBootp* trmInfo)
|
|
{
|
|
unsigned char *ptrOp,*ptrDhcp;
|
|
int lon,ret;
|
|
char modulo[]="dhcpDISCOVER_PXE()";
|
|
|
|
ptrDhcp=(unsigned char*)&trmInfo->pckDchp; // Se toma el puntero al principio del mensage
|
|
ptrOp=(unsigned char*)&trmInfo->pckDchp.options[0]; // Se toma el puntero a las opciones
|
|
lon=ptrOp-ptrDhcp; //Longitud del mensaje sin las opciones ni la magic coockie
|
|
|
|
RellenaIPCLiente(trmInfo);
|
|
RellenaIPServidor(trmInfo);
|
|
*ptrOp='\0'; //Borra opciones del mensaje recibido para colocar las nuevas
|
|
|
|
|
|
AdjDHCPOFFER(&ptrOp,&lon); // Genera opción de Mensaje (0x35) dhcp valor 1
|
|
AdjSERVERIDENTIFIER(&ptrOp,&lon); // Genera opción de Mensaje (0x36) Dhcp
|
|
AdjLEASETIME(&ptrOp,&lon); // Genera opción de Mensaje (0x33) Dhcp
|
|
AdjSUBNETMASK(&ptrOp,&lon); // Genera opción de Mensaje (0x01) Dhcp
|
|
AdjROUTERS(&ptrOp,&lon); // Genera opción de Mensaje (0x03) Dhcp
|
|
AdjCLASSIDENTIFIER(&ptrOp,&lon); // Genera opción de Mensaje (0x3c) Dhcp
|
|
*ptrOp=DHCP_END;
|
|
lon++;
|
|
trmInfo->pckDchp.op=DHCPOFFER;
|
|
//MandaRespuesta(&trmInfo->pckDchp,htonl(INADDR_BROADCAST),lon,htons(PUERTODHCPDESTINO));
|
|
trmInfo->cliente.sin_addr.s_addr=htonl(INADDR_BROADCAST);
|
|
ret=sendto(trmInfo->sck,(char*)&trmInfo->pckDchp,lon,0,(struct sockaddr*)&trmInfo->cliente,trmInfo->sockaddrsize);
|
|
if (ret == SOCKET_ERROR){
|
|
errorLog(modulo,26, TRUE);
|
|
}
|
|
}
|
|
//_______________________________________________________________________________________________________________
|
|
//
|
|
// Procesa un mensaje DHCPREQUEST (DHCP)
|
|
//
|
|
// Parámetros:
|
|
// trmInfo: Puntero a la estructura de control para la conversacin DHCP
|
|
//
|
|
// Devuelve:
|
|
// true: Si el mensaje se procesa correctamente
|
|
// false: En caso contrario
|
|
//_______________________________________________________________________________________________________________
|
|
void dhcpREQUEST_PXE(struct TramaDhcpBootp* trmInfo)
|
|
{
|
|
unsigned char * ptrOp,*ptrDhcp;
|
|
struct dhcp_opcion;
|
|
int lon,ret;
|
|
char modulo[]="dhcpREQUEST_PXE()";
|
|
|
|
ptrDhcp=(unsigned char*)&trmInfo->pckDchp; // Se toma el puntero al principio del mensage
|
|
ptrOp=(unsigned char*)&trmInfo->pckDchp.options[0]; // Se toma el puntero a las opciones
|
|
lon=ptrOp-ptrDhcp; //Longitud del mensaje sin las opciones ni la magic coockie
|
|
|
|
RellenaIPCLiente(trmInfo);
|
|
RellenaIPServidor(trmInfo);
|
|
*ptrOp='\0'; //Borra opciones del mensaje recibido para colocar las nuevas
|
|
|
|
AdjDHCPACK(&ptrOp,&lon); // Ge db.Close();nera opción de Mensaje (0x35) dhcp valor 5
|
|
AdjSERVERIDENTIFIER(&ptrOp,&lon); // Genera opción de Mensaje (0x36) Dhcp
|
|
AdjLEASETIME(&ptrOp,&lon); // Genera opción de Mensaje (0x33) Dhcp
|
|
AdjSUBNETMASK(&ptrOp,&lon); // Genera opción de Mensaje (0x01) Dhcp
|
|
AdjROUTERS(&ptrOp,&lon); // Genera opción de Mensaje (0x03) Dhcp
|
|
AdjCLASSIDENTIFIER(&ptrOp,&lon); // Genera opción de Mensaje (0x3c) Dhcp
|
|
|
|
*ptrOp=DHCP_END;
|
|
lon++;
|
|
|
|
trmInfo->pckDchp.op=DHCPOFFER;
|
|
//MandaRespuesta(&trmInfo->pckDchp,htonl(INADDR_BROADCAST),lon,htons(PUERTODHCPDESTINO));
|
|
trmInfo->cliente.sin_addr.s_addr=htonl(INADDR_BROADCAST);
|
|
ret=sendto(trmInfo->sck,(char*)&trmInfo->pckDchp,lon,0,(struct sockaddr*)&trmInfo->cliente,trmInfo->sockaddrsize);
|
|
if (ret == SOCKET_ERROR){
|
|
errorLog(modulo,26, TRUE);
|
|
}
|
|
}
|
|
//_______________________________________________________________________________________________________________
|
|
//
|
|
// Procesa un mensaje DHCPREQUEST (BOOTP)
|
|
//
|
|
// Parámetros:
|
|
// trmInfo: Puntero a la estructura de control para la conversacin BOOTP
|
|
//
|
|
// Devuelve:
|
|
// true: Si el mensaje se procesa correctamente
|
|
// false: En caso contrario
|
|
//_______________________________________________________________________________________________________________
|
|
void bootpREQUEST_PXE(struct TramaDhcpBootp* trmInfo)
|
|
{
|
|
unsigned char * ptrOp,*ptrDhcp;
|
|
struct dhcp_opcion;
|
|
int lon,ret;
|
|
unsigned long aux;
|
|
char modulo[]="bootpREQUEST_PXE()";
|
|
|
|
ptrDhcp=(unsigned char*)&trmInfo->pckDchp; // Se toma el puntero al principio del mensage
|
|
ptrOp=(unsigned char*)&trmInfo->pckDchp.options[0]; // Se toma el puntero a las opciones
|
|
lon=ptrOp-ptrDhcp; //Longitud del mensaje sin las opciones ni la magic coockie
|
|
|
|
aux=inet_addr("0.0.0.0"); // Borra Ip del cliente ( No se porqu pero en la trama aparece as)
|
|
memcpy(&trmInfo->pckDchp.ciaddr,&aux,4);
|
|
RellenaNombreServidorBoot(trmInfo);
|
|
RellenaNombreFicheroBoot(trmInfo);
|
|
|
|
*ptrOp='\0'; //Borra opciones del mensaje recibido para colocar las nuevas
|
|
|
|
AdjDHCPACK(&ptrOp,&lon); // Genera opción de Mensaje (0x35) dhcp valor 5
|
|
AdjSERVERIDENTIFIER(&ptrOp,&lon); // Genera opción de Mensaje (0x36) Dhcp
|
|
AdjBOOTSIZE(&ptrOp,&lon); // Genera opción de Mensaje (0x0D) Dhcp
|
|
AdjCLASSIDENTIFIER(&ptrOp,&lon); // Genera opción de Mensaje (0x3c) Dhcp
|
|
|
|
*ptrOp=DHCP_END;
|
|
lon++;
|
|
|
|
trmInfo->pckDchp.op=DHCPOFFER;
|
|
//ret=connect(trmInfo->sck,(struct sockaddr*)&trmInfo->cliente,trmInfo->sockaddrsize);
|
|
//if (ret == SOCKET_ERROR){
|
|
// RegistraLog("***connect() fallo:",true);
|
|
// return;
|
|
//}
|
|
//ret=send(trmInfo->sck,(char*)&trmInfo->pckDchp,lon,0);
|
|
ret=sendto(trmInfo->sck,(char*)&trmInfo->pckDchp,lon,0,(struct sockaddr*)&trmInfo->cliente,trmInfo->sockaddrsize);
|
|
if (ret == SOCKET_ERROR){
|
|
errorLog(modulo,26,TRUE);
|
|
return;
|
|
}
|
|
}
|
|
//_______________________________________________________________________________________________________________
|
|
//
|
|
// Genera una opción del tipo 0x35(53) con el valor "Dhcp Offer" valor 2
|
|
//
|
|
// Devuelve:
|
|
// Una estructura de opciones de dhcp(codigo,longitud,dato) con la opciones de Mensaje dhcp Offer
|
|
//_______________________________________________________________________________________________________________
|
|
void AdjDHCPOFFER(unsigned char* *ptrOp,int*lon)
|
|
{
|
|
**ptrOp=DHCP_MESSAGE_TYPE;
|
|
*ptrOp+=1;
|
|
**ptrOp=1;
|
|
*ptrOp+=1;
|
|
**ptrOp=DHCPOFFER;
|
|
*ptrOp+=1;
|
|
*lon+=3;
|
|
}
|
|
//_______________________________________________________________________________________________________________
|
|
//
|
|
// Genera una opción del tipo 0x35(53) con el valor "Dhcp Ack" valor 5
|
|
//
|
|
// Devuelve:
|
|
// Una estructura de opciones de dhcp(codigo,longitud,dato) con la opciones de Mensaje dhcp Ack
|
|
//_______________________________________________________________________________________________________________
|
|
void AdjDHCPACK(unsigned char** ptrOp,int*lon)
|
|
|
|
{
|
|
**ptrOp=DHCP_MESSAGE_TYPE;
|
|
*ptrOp+=1;
|
|
**ptrOp=1;
|
|
*ptrOp+=1;
|
|
**ptrOp=DHCPACK;
|
|
*ptrOp+=1;
|
|
*lon+=3;
|
|
}
|
|
//_______________________________________________________________________________________________________________
|
|
//
|
|
// Genera una opción del tipo 0x03(3) con la IP del router
|
|
//
|
|
// Devuelve:
|
|
// Una estructura de opciones de dhcp(codigo,longitud,dato) con la opciones de Ip del Routers
|
|
//_______________________________________________________________________________________________________________
|
|
void AdjROUTERS(unsigned char** ptrOp,int*lon)
|
|
{
|
|
unsigned long aux;
|
|
aux=inet_addr(oProuter); // Router
|
|
|
|
**ptrOp=DHCP_ROUTERS;
|
|
*ptrOp+=1;
|
|
**ptrOp=4;
|
|
*ptrOp+=1;
|
|
memcpy(*ptrOp,&aux,4); // Copia la Ip del router en la estructura
|
|
*ptrOp+=4;
|
|
*lon+=6;
|
|
|
|
}
|
|
//_______________________________________________________________________________________________________________
|
|
//
|
|
// Genera una opción del tipo 0x01(1) con la mascara de red
|
|
//
|
|
// Devuelve:
|
|
// Una estructura de opciones de dhcp(codigo,longitud,dato) con la opciones de mscara de red
|
|
//_______________________________________________________________________________________________________________
|
|
void AdjSUBNETMASK(unsigned char** ptrOp,int*lon)
|
|
{
|
|
unsigned long aux;
|
|
aux=inet_addr(oPmascara); // Mascara de red
|
|
|
|
**ptrOp=DHCP_SUBNET_MASK;
|
|
*ptrOp+=1;
|
|
**ptrOp=4;
|
|
*ptrOp+=1;
|
|
memcpy(*ptrOp,&aux,4); // Copia la máscara de red
|
|
*ptrOp+=4;
|
|
*lon+=6;
|
|
}
|
|
//_______________________________________________________________________________________________________________
|
|
//
|
|
// Genera una opción del tipo 0x3c(60) con el literal "PXECLient" para clientes PXE
|
|
//
|
|
// Devuelve:
|
|
// Una estructura de opciones de dhcp(codigo,longitud,dato) con la opciones de clase de cliente
|
|
//_______________________________________________________________________________________________________________
|
|
void AdjCLASSIDENTIFIER(unsigned char** ptrOp,int*lon)
|
|
{
|
|
**ptrOp=DHCP_CLASS_IDENTIFIER;
|
|
*ptrOp+=1;
|
|
**ptrOp=9;
|
|
*ptrOp+=1;
|
|
memcpy(*ptrOp,"PXEClient",9); // Copia el literal PXClient
|
|
*ptrOp+=9;
|
|
*lon+=11;
|
|
}
|
|
//_______________________________________________________________________________________________________________
|
|
//
|
|
// Genera una opción del tipo 0x36(54) con la IP del servidor
|
|
//
|
|
// Devuelve:
|
|
// Una estructura de opciones de dhcp(codigo,longitud,dato) con la opciones de Ip del servidor
|
|
//_______________________________________________________________________________________________________________
|
|
void AdjSERVERIDENTIFIER(unsigned char** ptrOp,int*lon)
|
|
{
|
|
unsigned long aux;
|
|
aux=inet_addr(IPlocal); // Ip del servidor
|
|
|
|
**ptrOp=DHCP_SERVER_IDENTIFIER;
|
|
*ptrOp+=1;
|
|
**ptrOp=4;
|
|
*ptrOp+=1;
|
|
memcpy(*ptrOp,&aux,4); // Copia la Ip del ervidor en la estructura
|
|
*ptrOp+=4;
|
|
*lon+=6;
|
|
|
|
}
|
|
//_______________________________________________________________________________________________________________
|
|
//
|
|
// Genera una opción del tipo 0x33(51) con el tiempo de "lease" de la IP
|
|
//
|
|
// Devuelve:
|
|
// Una estructura de opciones de dhcp(codigo,longitud,dato) con la opciones del "Lease Time"
|
|
//_______________________________________________________________________________________________________________
|
|
void AdjLEASETIME(unsigned char** ptrOp,int*lon)
|
|
{
|
|
unsigned long aux;
|
|
aux=0x00006054; // tiempo en segundos
|
|
|
|
**ptrOp=DHCP_LEASE_TIME;
|
|
*ptrOp+=1;
|
|
**ptrOp=4;
|
|
*ptrOp+=1;
|
|
memcpy(*ptrOp,&aux,4); // Copia el lease time en la estructura
|
|
*ptrOp+=4;
|
|
*lon+=6;
|
|
}
|
|
//_______________________________________________________________________________________________________________
|
|
//
|
|
// Genera una opción del tipo 0x0D(13) con el tiempo tamao del fichero boot
|
|
//
|
|
// Devuelve:
|
|
// Una estructura de opciones de dhcp(codigo,longitud,dato) con la opciones del "Lease Time"
|
|
//_______________________________________________________________________________________________________________
|
|
void AdjBOOTSIZE(unsigned char** ptrOp,int*lon)
|
|
{
|
|
unsigned short aux;
|
|
aux=0x0402; // Tamao en bytes
|
|
|
|
**ptrOp=DHCP_BOOT_SIZE;
|
|
*ptrOp+=1;
|
|
**ptrOp=2;
|
|
*ptrOp+=1;
|
|
memcpy(*ptrOp,&aux,2); // Copia el tamao en la estructura
|
|
*ptrOp+=2;
|
|
*lon+=4;
|
|
}
|
|
//_______________________________________________________________________________________________________________
|
|
//
|
|
// Crea un socket en un puerto determinado para la conversacin de las distintas hebras
|
|
//
|
|
//_______________________________________________________________________________________________________________
|
|
SOCKET TomaSocketUser()
|
|
{
|
|
SOCKET socket_c; // Socket para hebras (UDP)
|
|
struct sockaddr_in cliente;
|
|
int ret,puerto;
|
|
BOOLEAN bOpt;
|
|
char modulo[]="TomaSocketUser()";
|
|
|
|
socket_c = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); // Crea socket para UDP
|
|
|
|
if (socket_c == SOCKET_ERROR){
|
|
errorLog(modulo,81,TRUE);
|
|
return(false);
|
|
}
|
|
cliente.sin_addr.s_addr = htonl(INADDR_ANY); // selecciona interface
|
|
cliente.sin_family = AF_INET;
|
|
puerto=PUERTOMINUSER;
|
|
while(puerto<PUERTOMAXUSER){ // Busca puerto libre
|
|
cliente.sin_port = htons(puerto); // Puerto asignado
|
|
if (bind(socket_c,(struct sockaddr *)&cliente,sizeof(cliente)) == SOCKET_ERROR)
|
|
puerto++;
|
|
else
|
|
break;
|
|
}
|
|
if(puerto>=PUERTOMAXUSER){ // No hay puertos libres
|
|
errorLog(modulo,63, TRUE);
|
|
return(INVALID_SOCKET);
|
|
}
|
|
|
|
bOpt=TRUE; // Pone el socket en modo "soportar Broadcast"
|
|
ret=setsockopt(socket_c,SOL_SOCKET,SO_BROADCAST,(char *)&bOpt,sizeof(bOpt));
|
|
if (ret == SOCKET_ERROR){
|
|
errorLog(modulo,48, TRUE);
|
|
return(INVALID_SOCKET);
|
|
}
|
|
return(socket_c);
|
|
}
|
|
//_______________________________________________________________________________________________________________
|
|
void Pinta(dhcp_packet* tdp)
|
|
{
|
|
return;
|
|
printf("\nop = %d htype = %d hlen = %d hops = %d",tdp -> op, tdp -> htype, tdp -> hlen, tdp -> hops);
|
|
//printf ("\nxid = %x secs = %d flags = %x",tdp -> xid, tdp -> secs, tdp -> flags);
|
|
printf ("\nciaddr = %s", inet_ntoa (tdp -> ciaddr));
|
|
printf ("\nyiaddr = %s", inet_ntoa (tdp -> yiaddr));
|
|
printf ("\nsiaddr = %s", inet_ntoa (tdp -> siaddr));
|
|
printf ("\ngiaddr = %s", inet_ntoa (tdp -> giaddr));
|
|
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]);
|
|
printf ("\nfilename = %s", tdp -> file);
|
|
printf ("\nserver_name = %s", tdp -> sname);
|
|
|
|
printf ("\n\n");
|
|
}
|
|
//***************************************************************************************************************
|
|
// PROGRAMA PRINCIPAL
|
|
//***************************************************************************************************************
|
|
int main(int argc, char **argv)
|
|
{
|
|
pthread_t hThreadDHCP,hThreadBOOTP,hThreadTFTP;
|
|
int resul;
|
|
char modulo[] = "main()";
|
|
|
|
/*--------------------------------------------------------------------------------------------------------
|
|
Validación de parámetros de ejecución y lectura del fichero de configuración del servicio
|
|
---------------------------------------------------------------------------------------------------------*/
|
|
if (!validacionParametros(argc, argv,4)) // Valida parámetros de ejecución
|
|
exit(EXIT_FAILURE);
|
|
|
|
if (!tomaConfiguracion(szPathFileCfg)) { // Toma parametros de configuracion
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
infoLog(1); // Inicio de sesión
|
|
|
|
// Hebra servicio DHCP ---------------------------------
|
|
resul=pthread_create(&hThreadDHCP,NULL,ServicioDHCP,(LPVOID)IPlocal);
|
|
if(resul!=0){
|
|
errorLog(modulo, 58, TRUE);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
pthread_detach(hThreadDHCP);
|
|
|
|
|
|
// Hebra servicio BOOTP ---------------------------------
|
|
resul=pthread_create(&hThreadBOOTP,NULL,ServicioBOOTP,(LPVOID)IPlocal);
|
|
if(resul!=0){
|
|
errorLog(modulo,59,TRUE);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
pthread_detach(hThreadBOOTP);
|
|
|
|
// Hebra servicio TFTP ----------------------------------
|
|
resul=pthread_create(&hThreadTFTP,NULL,ServicioTFTP,(LPVOID)IPlocal);
|
|
if(resul!=0){
|
|
errorLog(modulo,60,TRUE);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
pthread_detach(hThreadTFTP);
|
|
|
|
while (true)
|
|
sleep(1000);
|
|
|
|
}
|