// read configuration either from INI file (if it exists) or from the registry int DHCPReadConfig ( ) { int Ark; char szBuf[128]; memset (& sParamDHCP, 0, sizeof sParamDHCP); sParamDHCP.nLease = DHCP_DEFAULT_LEASE_TIME; for (Ark=0 ; Ark<SizeOfTab (tDHCPd32Entry) ; Ark++) ReadKey ( TFTPD32_DHCP_KEY, tDHCPd32Entry [Ark].szEntry, tDHCPd32Entry [Ark].pValue, tDHCPd32Entry [Ark].nBufSize, tDHCPd32Entry [Ark].nType, szTftpd32IniFile ); // custom items for (Ark=0 ; Ark < SizeOfTab (sParamDHCP.t) ; Ark++) { wsprintf (szBuf, "%s%d", KEY_DHCP_USER_OPTION_NB, Ark+1); ReadKey (TFTPD32_DHCP_KEY, szBuf, & sParamDHCP.t[Ark].nAddOption, sizeof sParamDHCP.t[Ark].nAddOption, REG_DWORD, szTftpd32IniFile); wsprintf (szBuf, "%s%d", KEY_DHCP_USER_OPTION_VALUE, Ark+1); ReadKey (TFTPD32_DHCP_KEY, szBuf, sParamDHCP.t[Ark].szAddOption, sizeof sParamDHCP.t[Ark].szAddOption, REG_SZ, szTftpd32IniFile); } if ( sParamDHCP.nPoolSize!=0 ) { tFirstIP = malloc (sParamDHCP.nPoolSize * sizeof *tFirstIP[0]) ; tMAC = malloc (sParamDHCP.nPoolSize * sizeof *tMAC[0]) ; if (tFirstIP == NULL || tMAC == NULL ) { SVC_ERROR ("Can not allocate memory"); return FALSE; } LoadLeases (); } if (sParamDHCP.nLease==0) { sParamDHCP.nLease=DHCP_DEFAULT_LEASE_TIME; LOG (12, "%d, Lease time not specified, set to 2 days", GetCurrentThreadId ()); } // compatability 3 -> 4 if (sParamDHCP.szWins[0]==0 && sParamDHCP.szDns1[0]!=0) { lstrcpy (sParamDHCP.szWins, sParamDHCP.szDns1); LOG (0, "WINS server copied from DNS servers"); } return TRUE; } // DHCPReadConfig
///////////////////////////////////////// // Dir window callback LRESULT CALLBACK ShDirProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { static const int tTabs[] = { 90, 125 }; struct S_DirectoryContent *pDir = (struct S_DirectoryContent *) lParam; HWND hLBWnd = GetDlgItem (hWnd, IDC_LB_SHDIR); int Ark; switch (message) { case WM_INITDIALOG : // Set the window name to either tftpd32 or tftpd64 SetWindowText (hWnd, TFTPD_DIR_TITLE); ListBox_SetTabStops ( hLBWnd, SizeOfTab(tTabs), tTabs ); ListBox_ResetContent ( hLBWnd ); for ( Ark=0 ; Ark < pDir->nb ; Ark++ ) ListBox_AddString ( hLBWnd, pDir->ent[Ark].file_descr ); CenterChildWindow (hWnd, CCW_INSIDE | CCW_VISIBLE); // If GUI is in remote mode, deactivate Explorer Button if ( IsGuiConnectedToRemoteService () ) Button_Enable (GetDlgItem (hWnd, IDC_SD_EXPLORER), FALSE); break; case WM_COMMAND : Handle_VM_Command (hWnd, wParam, lParam); break; case WM_CLOSE : case WM_DESTROY : EndDialog (hWnd, 0); break; } // switch return FALSE; } // ShDirProc
///////////////////////////////////////////////////////// // Read settings : // Parse the settings table and call ReadKey ///////////////////////////////////////////////////////// BOOL Tftpd32ReadSettings (void) { int Ark, Rc=TRUE; char szCurDir[_MAX_PATH]; for (Ark=0 ; Ark< SizeOfTab (tTftpd32Entry) ; Ark++) ReadKey ( TFTPD32_MAIN_KEY, tTftpd32Entry[Ark].szEntry, tTftpd32Entry[Ark].pValue, tTftpd32Entry[Ark].nBufSize, tTftpd32Entry[Ark].nType, szTftpd32IniFile ); if (sSettings.uServices == TFTPD32_NONE) sSettings.uServices = TFTPD32_ALL_SERVICES; // field WorkingDirectory : // try env variable then szBaseDir and current dir if ( GetEnvironmentVariable (TFTP_DIR, szCurDir, sizeof szCurDir) != 0 && IsValidDirectory ( szCurDir ) ) GetFullPathName ( szCurDir, sizeof sSettings.szWorkingDirectory, sSettings.szWorkingDirectory, NULL ); else if ( IsValidDirectory ( sSettings.szBaseDirectory ) ) GetFullPathName ( sSettings.szBaseDirectory, sizeof sSettings.szWorkingDirectory, sSettings.szWorkingDirectory, NULL ); else GetCurrentDirectory ( sizeof sSettings.szWorkingDirectory, sSettings.szWorkingDirectory ); // release for the Australian Department of defence #ifdef BAE_SYSTEMS_LEN_WHITE sSettings.uServices = TFTPD32_TFTP_SERVER; #endif return Rc; } // Tftpd32ReadSettings
/////////////////////////////////////////////// // Tab control has changed : hide/show controls LRESULT TR_ChangeTabControl (HWND hDlgWnd) { HWND hTabWnd = GetDlgItem (hDlgWnd, IDC_TAB_OPTION); DWORD nCurOnglet = TabCtrl_GetCurSel (hTabWnd); DWORD Ark; DWORD TabMask; TC_ITEM TabCtrlItem; // get the selected tab id if (nCurOnglet != (DWORD)-1) { TabCtrlItem.mask = TCIF_PARAM ; TabCtrl_GetItem (hTabWnd, nCurOnglet, & TabCtrlItem); TabMask = MakeMask (TabCtrlItem.lParam); } else TabMask = TAB_NONE; // according to TabMask and tResize table hide/display controls for (Ark=0 ; Ark<SizeOfTab(tResize) ; Ark++) ShowWindow (GetDlgItem (hDlgWnd, tResize[Ark].idCtrl), (tResize[Ark].mView & TabMask) ? SW_SHOW : SW_HIDE); // DHCP tab has been selected : display the settings if (TabMask == TAB_DHCP_SERVER) { Gui_LoadDHCPConfig (hDlgWnd); } return TabCtrlItem.lParam ; } // ChangeTabControl
// Save configuration either in INI file (if it exists) or in registry int DHCPSaveConfig ( const struct S_DHCP_Param *pNewParamDHCP ) { INT Ark; char szBuf[64]; // allocate new array, but keep pointers if ( sParamDHCP.nPoolSize!=pNewParamDHCP->nPoolSize ) { tFirstIP = realloc (tFirstIP, sizeof (tFirstIP[0]) * pNewParamDHCP->nPoolSize); tMAC = realloc (tMAC, sizeof (tMAC[0]) * pNewParamDHCP->nPoolSize); // do not complain if pool is empty if (pNewParamDHCP->nPoolSize!=0 && (tFirstIP==NULL || tMAC==NULL) ) { SVC_ERROR ("Can not allocate memory"); return FALSE; } } nAllocatedIP = min (nAllocatedIP, pNewParamDHCP->nPoolSize); sParamDHCP = *pNewParamDHCP; for (Ark=0 ; Ark<SizeOfTab (tDHCPd32Entry) ; Ark++) AsyncSaveKey ( TFTPD32_DHCP_KEY, tDHCPd32Entry [Ark].szEntry, tDHCPd32Entry [Ark].pValue, tDHCPd32Entry [Ark].nBufSize, tDHCPd32Entry [Ark].nType, szTftpd32IniFile ); // custom items for (Ark=0 ; Ark < SizeOfTab (sParamDHCP.t) ; Ark++) { wsprintf (szBuf, "%s%d", KEY_DHCP_USER_OPTION_NB, Ark+1); AsyncSaveKey (TFTPD32_DHCP_KEY, szBuf, & sParamDHCP.t[Ark].nAddOption, sizeof sParamDHCP.t[Ark].nAddOption, REG_DWORD, szTftpd32IniFile); wsprintf (szBuf, "%s%d", KEY_DHCP_USER_OPTION_VALUE, Ark+1); AsyncSaveKey (TFTPD32_DHCP_KEY, szBuf, sParamDHCP.t[Ark].szAddOption, sizeof sParamDHCP.t[Ark].szAddOption, REG_SZ, szTftpd32IniFile); } return TRUE; } // DHCPSaveConfig
/////////////////////////////////////////////// // Resize the main window --> resize each control int TR_ResizeWindow (HWND hDlgWnd, BOOL bInit) { static BOOL bConvert2Physique=FALSE; DWORD Ark; RECT RClient; SIZE SClient; int InflateX, InflateY; // tenth // at first call : convert logical data to physical if (! bConvert2Physique) { bConvert2Physique = TRUE; for (Ark=0 ; Ark<SizeOfTab(tResize) ; Ark++) MapDialogRect (hDlgWnd, (LPRECT) & tResize[Ark].x); MapDialogRect (hDlgWnd, & SizeInit); MapDialogRect (hDlgWnd, & RectMinMax); MapDialogRect (hDlgWnd, & RectTftpClient); } if (bInit) MoveWindow (hDlgWnd, SizeInit.left, SizeInit.top, SizeInit.right, SizeInit.bottom, FALSE); // get window size and calculate the inflate rate GetWindowRect (hDlgWnd, & RClient); SClient.cx = RClient.right - RClient.left; SClient.cy = RClient.bottom - RClient.top; InflateX = 10 * ( SClient.cx - (SizeInit.right - SizeInit.left) ); InflateY = 10 * ( SClient.cy - (SizeInit.bottom - SizeInit.top) ); for (Ark=0 ; Ark<SizeOfTab(tResize) ; Ark++) { MoveWindow (GetDlgItem (hDlgWnd, tResize[Ark].idCtrl), tResize[Ark].x + (tResize[Ark].dx * InflateX) / 100, tResize[Ark].y + (tResize[Ark].dy * InflateY) / 100, tResize[Ark].width + (tResize[Ark].dwidth * InflateX) / 100, tResize[Ark].height+ (tResize[Ark].dheight * InflateY) / 100, TRUE); } InvalidateRect (hDlgWnd, NULL, FALSE); return Ark; } //TR_ResizeWindow
/* ----------------------------------------------------- */ int Skt4uInit (void) { int Ark; if (! bInitDone) /* Aucune socket ouverte */ { for (Ark=0 ; Ark<SizeOfTab(HistoSocket) ; Ark++) HistoSocket[Ark].skt = INVALID_SOCKET; bInitDone=TRUE; } #ifdef WINDOWS /* liberation des sockets appartenant a des taches mortes */ else { for (Ark=0 ; Ark<SizeOfTab(HistoSocket) ; Ark++) if ( HistoSocket[Ark].skt!=INVALID_SOCKET && !IsTask(HistoSocket[Ark].hTask) ) TcpClose (& HistoSocket[Ark].skt); } /* InitDone */ #endif return TCP4U_SUCCESS; } /* Skt4wInit */
///////////////////////////////////////////////////////// // Save Settings into ini file/registry ///////////////////////////////////////////////////////// BOOL Tftpd32SaveSettings (void) { int Ark, Rc; for (Ark=0, Rc=TRUE ; Rc && Ark< SizeOfTab (tTftpd32Entry) ; Ark++) Rc = AsyncSaveKey ( TFTPD32_MAIN_KEY, tTftpd32Entry[Ark].szEntry, tTftpd32Entry[Ark].pValue, tTftpd32Entry[Ark].nBufSize, tTftpd32Entry[Ark].nType, szTftpd32IniFile ); if (! Rc) REG_ERROR(); return Rc; } // Tftpd32SaveSettings
/*###################################################################### *## *## NAME: HttpSendAdditionnalHeader *## *## PURPOSE: Send a http 1.0 general-header *## *####################################################################*/ static int HttpSendAdditionnalHeader(SOCKET CSock) { int Ark; int Rc; static LPCSTR szAdditionnalStrings[] = { "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*", "User-Agent: Http4u by Ph. Jounin and L. Le Bras", "", }; Tcp4uLog (LOG4U_INTERN, "HttpSendAdditionnalHeader"); /* sending request, if successful send Request Header */ for (Rc=TCP4U_SUCCESS,Ark=0 ; Rc==TCP4U_SUCCESS && Ark<SizeOfTab(szAdditionnalStrings); Ark++) Rc = TnSend (CSock, szAdditionnalStrings[Ark], FALSE, DO_NOT_LOG); return Rc==TCP4U_SUCCESS ? HTTP4U_SUCCESS : HTTP4U_TCP_FAILED; } /* END HttpSendAdditionnalHeader */
/* -------------------------------------------------------------- */ int API4U SmtpSendRcpt (SOCKET CSock, LPCSTR szTo, LPSTR szBuffer, UINT uBufSize) { LPCSTR pTo = szTo; LPSTR qCmd = NULL; int Rc = SMTP4U_SUCCESS; int Ark; Tcp4uLog (LOG4U_PROC, "SmtpSendRcpt"); while (*pTo!=0 && Rc==SMTP4U_SUCCESS) { /* constructs the beginning of the command */ Strcpy (szBuffer, SmtpProto[_SMTP4U_RCPTTO].szCmd); qCmd = szBuffer + Strlen (SmtpProto[_SMTP4U_RCPTTO].szCmd); /* get the first recipient from the pTo line */ for (Ark=0 ; pTo[Ark]!=0 && pTo[Ark]!=SMTP4U_SEPARATOR ; Ark++) qCmd[Ark] = pTo[Ark]; qCmd[Ark]=0; /* skip spaces and affect pTo the next recipient */ while (pTo[Ark]==SMTP4U_SEPARATOR || pTo[Ark]==' ' || pTo[Ark]=='\t') Ark++; pTo += Ark; /* send the RCPT string */ Rc = TnProtoExchange (CSock, /* used socket */ szBuffer, szBuffer, uBufSize, TnReadMultiLine, /* recv function */ SmtpProto[_SMTP4U_RCPTTO].tAnswer, SizeOfTab(SmtpProto[_SMTP4U_RCPTTO].tAnswer), TRUE, /* sensitive compare */ SMTP4U_DEFTIMEOUT, HFILE_ERROR); } /* until either error or no more recipient */ Tcp4uLog (LOG4U_EXIT, "SmtpSendRcpt"); return Rc<TN_SUCCESS ? SMTP4U_DATAERROR : Rc ; } /* SmtpSendRcpt */
/* ------------------------------------------------------------------ */ int Skt4uCleanup (void) { int Ark; if (bInitDone) { /* blocking call ? */ if (WSAIsBlocking()) { WSACancelBlockingCall (); return TCP4U_ERROR; } else { /* TcpClose (&s) force s a -1 -> pas besoin de UnrcdSkt */ for (Ark=0 ; Ark<SizeOfTab(HistoSocket) ; Ark++) if ( HistoSocket[Ark].hTask == GetCurrentTask () && HistoSocket[Ark].skt != INVALID_SOCKET ) TcpClose (& HistoSocket[Ark].skt); WSACleanup (); } /* requete non bloquante */ } /* bInitDone */ return TCP4U_SUCCESS; } /* Skt4wCleanup */
/* ------------------------------------------------------------------ */ static int FindSocketIdx (SOCKET s) { int Ark; for (Ark=0 ; Ark<SizeOfTab(HistoSocket) && s!=HistoSocket[Ark].skt ; Ark++); return Ark<SizeOfTab(HistoSocket) ? Ark : INVALID_INDEX; } /* FindSocketIdx */
////////////////////////////////////////////////////////////////////////////////////////////// // fill DHCP fields ////////////////////////////////////////////////////////////////////////////////////////////// int DHCPOptionsReply (struct dhcp_packet *pDhcpPkt, int nDhcpType) { unsigned char *pOpt = (unsigned char *) (pDhcpPkt->options + (sizeof DHCP_OPTIONS_COOKIE - 1)); HANDLE hFile; struct in_addr *pNearest; int Ark, Evan; char sz[256]; static struct S_DhcpOptions sDhcpOpt [] = // 0 for unspecified { DHO_DHCP_MESSAGE_TYPE, 1, ~TFTPD32_NONE, DHO_DHCP_SERVER_IDENTIFIER, 4, ~TFTPD32_NONE, DHO_SUBNET_MASK, 4, ~TFTPD32_NONE, DHO_ROUTERS, 4, ~TFTPD32_NONE, DHO_DOMAIN_NAME_SERVERS, 4, ~TFTPD32_NONE, DHO_LOG_SERVERS, 4, TFTPD32_SYSLOG_SERVER, DHO_NETBIOS_NAME_SERVERS, 4, ~TFTPD32_NONE, DHO_DHCP_LEASE_TIME, 4, ~TFTPD32_NONE, DHO_DHCP_RENEWAL_TIME, 4, ~TFTPD32_NONE, DHO_DHCP_REBINDING_TIME, 4, ~TFTPD32_NONE, DHO_BOOT_SIZE, 0, TFTPD32_TFTP_SERVER, DHO_DOMAIN_NAME, 0, ~TFTPD32_NONE, DHO_CUSTOM, 0, ~TFTPD32_NONE, DHO_END, 0, ~TFTPD32_NONE, }; //Always pack the magic cookie again, just in case it was corrupted *(DWORD*)(pDhcpPkt->options) = * (DWORD*) DHCP_OPTIONS_COOKIE; // pNearest points on the "good" LAN interface pNearest = FindNearestServerAddress (&pDhcpPkt->yiaddr, & sParamDHCP.dwMask, FALSE); //HACK -- If we are the bootp server, we are also the tftpserver if (sSettings.uServices & TFTPD32_TFTP_SERVER) pDhcpPkt->siaddr = *pNearest; // Next server (TFTP server is enabled) for (Ark=0 ; Ark<SizeOfTab(sDhcpOpt) ; Ark++) { // skip if linked to a service which is not started (change suggested by Colin) if (! (sSettings.uServices & sDhcpOpt[Ark].nServices)) continue; if (sDhcpOpt[Ark].nLen!=0) { *pOpt++ = (unsigned char) sDhcpOpt[Ark].nDHCPOpt ; *pOpt++ = (unsigned char) sDhcpOpt[Ark].nLen; } switch (sDhcpOpt[Ark].nDHCPOpt) { case DHO_DHCP_MESSAGE_TYPE : * pOpt = (unsigned char) nDhcpType ; break ; case DHO_LOG_SERVERS : // fallthrough case DHO_DHCP_SERVER_IDENTIFIER : * (DWORD *) pOpt = pNearest->s_addr; break ; case DHO_SUBNET_MASK : * (DWORD *) pOpt = sParamDHCP.dwMask.s_addr; break ; case DHO_ROUTERS : * (DWORD *) pOpt = (sParamDHCP.dwGateway.s_addr == 0xffffffff ? pDhcpPkt->yiaddr.s_addr : sParamDHCP.dwGateway.s_addr); break ; case DHO_NETBIOS_NAME_SERVERS : case DHO_DOMAIN_NAME_SERVERS : * (DWORD *) pOpt = sParamDHCP.dwDns.s_addr; break; case DHO_DHCP_LEASE_TIME : * (DWORD *) pOpt = htonl (sParamDHCP.nLease * 60); break ; case DHO_DHCP_RENEWAL_TIME : case DHO_DHCP_REBINDING_TIME : * (DWORD *) pOpt = htonl (sParamDHCP.nLease/2 * 60); break ; case DHO_BOOT_SIZE : // translate $IP$ and $MAC$ from boot file name TranslateExp (sParamDHCP.szBootFile, sz, pDhcpPkt->yiaddr, pDhcpPkt->chaddr); hFile = CreateFile(sz, // open the file GENERIC_READ, // open for reading FILE_SHARE_READ, // share for reading NULL, // no security OPEN_EXISTING, // existing file only FILE_ATTRIBUTE_NORMAL, // normal file NULL); // no attr. template if (hFile != INVALID_HANDLE_VALUE) { *pOpt++ = DHO_BOOT_SIZE ; *pOpt++ = sizeof (unsigned short); * (unsigned short *) pOpt = htons ( (unsigned short) (1+GetFileSize (hFile, NULL) / 512) ) ; pOpt += sizeof (unsigned short); CloseHandle( hFile ) ; // close the file } break; case DHO_DOMAIN_NAME : if (sParamDHCP.szDomainName[0]!=0) { *pOpt++ = DHO_DOMAIN_NAME; *pOpt = lstrlen (sParamDHCP.szDomainName); memcpy (pOpt+1, sParamDHCP.szDomainName, *pOpt); pOpt += 1+*pOpt; } break; case DHO_CUSTOM : // Manage custom options for (Evan=0 ; Evan < SizeOfTab (sParamDHCP.t) ; Evan++) if (sParamDHCP.t[Evan].nAddOption != 0) { *pOpt++ = (unsigned char) sParamDHCP.t[Evan].nAddOption; *pOpt = TranslateParam2Value (pOpt+1, 64, sParamDHCP.t[Evan].szAddOption, pDhcpPkt->yiaddr, pDhcpPkt->chaddr); pOpt += 1+*pOpt; } break; case DHO_END : *pOpt++ = DHO_END; *pOpt++ = DHO_PAD; *pOpt++ = DHO_PAD; break; } // switch option pOpt += sDhcpOpt[Ark].nLen ; // points on next field } // for all option return (int) (pOpt - (unsigned char*) pDhcpPkt); } // DHCPOptionsReply
///////////////////////////// // Fenetre Background gestion des appels TCP // LRESULT CALLBACK TftpClientProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { DWORD nbWrt; struct tftphdr *tpr, *tps; time_t dNow; int Ark; HWND hCBWnd, hParentWnd; time (&dNow); switch (message) { ///////////////////////// // Message Windows case WM_INITCLIENT : // only one client transfer available hTftpClientSemaphore = CreateSemaphore(NULL, 1, 1, TFTP_CLIENT_SEMAPHORE); hTftpClientWnd = hWnd; hParentWnd = GetParent (hWnd); EnableWindow (GetDlgItem (hParentWnd, IDC_CLIENT_BREAK_BUTTON), FALSE); SetDlgItemText (hParentWnd, IDC_CLIENT_BLOCK, ""); // populate combo with proposed block sizes hCBWnd = GetDlgItem (hParentWnd, IDC_CB_DATASEG); for (Ark=0 ; Ark<SizeOfTab (tBlkSize); Ark++) ComboBox_AddString (hCBWnd, tBlkSize[Ark].szBlkSize); ComboBox_SetCurSel (hCBWnd, 0); // uncheck "Send full path to server" SendDlgItemMessage (hParentWnd, IDC_CLIENT_FULL_PATH, BM_SETCHECK, BST_UNCHECKED, 0); // edittext IDC_CLIENT_FILE will accept dropped file (works only because it is on the top in Z-Order DragAcceptFiles (GetDlgItem (hParentWnd, IDC_CLIENT_LOCALFILE), TRUE); // fEditBoxProc = (WNDPROC) SetWindowLong (GetDlgItem (hParentWnd, IDC_CLIENT_LOCALFILE), GWL_WNDPROC, (LONG) TftpClientFileNameProc); fEditBoxProc = (WNDPROC) SetWindowLongPtr (GetDlgItem (hParentWnd, IDC_CLIENT_LOCALFILE), GWLP_WNDPROC, (LONG_PTR) TftpClientFileNameProc); // SetWindowLong (GetDlgItem (hParentWnd, IDC_CLIENT_FILE), GWL_USERDATA, (LONG) TftpClientFileNameProc); SetWindowLongPtr (GetDlgItem (hParentWnd, IDC_CLIENT_LOCALFILE), GWLP_USERDATA, (LONG_PTR) TftpClientFileNameProc); break; case WM_CLOSE : LogToMonitor ("GUI: Closing Tftp Client"); CloseHandle (hTftpClientSemaphore); CloseHandle (sTC.hFile); closesocket (sTC.s); break; case WM_COMMAND : Handle_VM_Command (hWnd, wParam, lParam); break; case WM_TIMER : KillTimer(hWnd, wParam); PostMessage (hWnd, wParam, 0, (LPARAM) -1); // pour pas confondre break; ////////////////////// // Download : fichier envoyé par le serveur case WM_CLIENT_DATA : // WSAAsyncSelect (sTC.s, hWnd, 0, 0); A SUPPRIMER KillTimer(hWnd, wParam); if (sTC.bBreak) return FALSE; sTC.nRcvd = 0; // On est reveillé par un message reçu tpr = (struct tftphdr *) sTC.BufRcv; if (WSAGETSELECTEVENT(lParam) == FD_READ) { if (! UdpRecv ()) return BadEndOfTransfer ("Error in Recv.\nError code is %d (%s)", WSAGetLastError (), LastErrorText() ); // parcours des codes retours switch (htons (tpr->th_opcode)) { case TFTP_ERROR : return BadEndOfTransfer ("Server stops the transfer.\nError #%d: %s", htons (tpr->th_code), tpr->th_msg); case TFTP_OACK : if (sTC.nCount==0) TftpProcessOACK (); break; case TFTP_DATA : // a data packet has been received. Check #block if ( htons (tpr->th_block) == (unsigned short) (sTC.nCount+1) ) { if ( !WriteFile (sTC.hFile, tpr->th_data, sTC.nRcvd - TFTP_DATA_HEADERSIZE, & nbWrt, NULL) || sTC.nRcvd-TFTP_DATA_HEADERSIZE!=nbWrt) return BadEndOfTransfer ("Error in writing file.\nError code is %d (%s)", GetLastError(), LastErrorText()); sTC.nCount++; sTC.nRetransmit = 0; // prepare Ack block tps = (struct tftphdr *) sTC.BufSnd; tps->th_opcode = htons (TFTP_ACK), tps->th_block = htons ((unsigned short) sTC.nCount); sTC.nToSend = TFTP_DATA_HEADERSIZE; // compute MD5 MD5Update (& sTC.m.ctx, tpr->th_data, nbWrt); } break; default : return BadEndOfTransfer ("Server sent illegal opcode %d", htons (tpr->th_opcode)); } // switch opcode } // il y a un message à recevoir // La comparaison marche si le paquet est le bon ou une répétition du précédent message if ( htons (tpr->th_block) == (unsigned short) sTC.nCount) { if (sTC.nRetransmit) sTC.nTotRetrans ++; if (sTC.nRetransmit++ > TFTP_RETRANSMIT) return BadEndOfTransfer ("Timeout waiting block #%d", sTC.nCount+1); send (sTC.s, sTC.BufSnd, sTC.nToSend, 0); SetTimer (hWnd, WM_CLIENT_DATA, sTC.dwTimeout, NULL); } // sTC.nRcvd ne peut être inférieur que si on a reçu un block if ( htons (tpr->th_opcode)==TFTP_DATA && sTC.nRcvd!=0 && sTC.nRcvd < sTC.nPktSize + TFTP_DATA_HEADERSIZE) return TransferOK (dNow); Statistics (dNow); break; //////////////////////// // Upload : server sends ACK case WM_CLIENT_ACK : KillTimer(hWnd, wParam); if (sTC.bBreak || sTC.s==INVALID_SOCKET) return FALSE; // socket not closed by StopTransfer tpr = (struct tftphdr *) sTC.BufRcv; if ( WSAGETSELECTEVENT(lParam) == FD_READ ) { if (! UdpRecv ()) return BadEndOfTransfer ("Error in Recv.\nError code is %d (%s)", WSAGetLastError (), LastErrorText() ); switch (htons (tpr->th_opcode)) { case TFTP_ERROR : return BadEndOfTransfer ("Server stops the transfer.\nError #%d: %s", htons (tpr->th_code), tpr->th_msg); case TFTP_OACK : if (sTC.nCount!=0) break; // ignore message TftpProcessOACK (); tpr->th_block = htons(0); // pour passer en dessous // Fall through case TFTP_ACK : if ( htons (tpr->th_block) == (unsigned short) sTC.nCount ) { // prepare Data block tps = (struct tftphdr *) sTC.BufSnd; if ( !ReadFile (sTC.hFile, tps->th_data, sTC.nPktSize, & sTC.nRcvd, NULL) ) { if (sTC.nToSend == TFTP_DATA_HEADERSIZE + sTC.nPktSize) // file was exactly N * PkSize return TransferOK (dNow); else return BadEndOfTransfer ("Error in reading file.\nError code is %d (%s)", GetLastError(), LastErrorText()); } if (sTC.nRcvd == 0) // EOF { if (sTC.nToSend < TFTP_DATA_HEADERSIZE + sTC.nPktSize) return TransferOK (dNow); } sTC.nCount++; sTC.nRetransmit = 0; tps->th_opcode = htons (TFTP_DATA), tps->th_block = htons ((unsigned short) sTC.nCount); sTC.nToSend = TFTP_DATA_HEADERSIZE + sTC.nRcvd; // compute MD5 MD5Update (& sTC.m.ctx, tps->th_data, sTC.nRcvd); } break; default : return BadEndOfTransfer ("Server sent illegal opcode %d", htons (tpr->th_opcode)); } // switch opcode } // il y a un message à recevoir // Timeout or ack of previous block else if ( htons (tpr->th_block) == (unsigned short) (sTC.nCount-1) ) { if (sTC.nRetransmit) sTC.nTotRetrans ++; if (sTC.nRetransmit++ > TFTP_RETRANSMIT) return BadEndOfTransfer ("Timeout while waiting ack block #%d", sTC.nCount); // une possibilité : on est au dernier message et le serveur TFTP n'a pas acquitté // --> on renvoie, mais sur Timeout, on signale un transfert OK if (sTC.nToSend < TFTP_DATA_HEADERSIZE + sTC.nPktSize && sTC.nRetransmit<TFTP_RETRANSMIT) return TransferOK (dNow); } send (sTC.s, sTC.BufSnd, sTC.nToSend, 0); SetTimer (hWnd, WM_CLIENT_ACK, sTC.dwTimeout, NULL); Statistics (dNow); break; } // switch message return DefWindowProc (hWnd, message, wParam, lParam); } // TftpProc
/////////////////////////////////////////////// // Initthe Tab control int TR_InitTabControl (HWND hDlgWnd) { TC_ITEM TabCtrlItem; HWND hTabWnd = GetDlgItem (hDlgWnd, IDC_TAB_OPTION); int nOnglet, Ark; static const struct S_TabCtrlData { int tab; char *name; int mask; int service; // TRUE if tab is the GUI of a service } tTabCtrlData [] = { ONGLET_TFTP_SERVER, "Tftp 服务器" , TFTPD32_TFTP_SERVER, TRUE, ONGLET_TFTP_CLIENT, "Tftp 客户端", TFTPD32_TFTP_CLIENT, FALSE, ONGLET_DHCP_SERVER, "DHCP 服务器", TFTPD32_DHCP_SERVER, TRUE, ONGLET_SYSLOG_SERVER, "系统日志服务器", TFTPD32_SYSLOG_SERVER, TRUE, ONGLET_SNTP_SERVER, "SNTP 服务器", TFTPD32_SNTP_SERVER, TRUE, ONGLET_DNS_SERVER, "DNS 服务器", TFTPD32_DNS_SERVER, TRUE, ONGLET_EVENTS_VIEWER, "日志查看器", TFTPD32_ALL_SERVICES, FALSE, }; // tTabCtrlData // Ordonated list of the Client Controls static const int tTftpClientCtrl [] = { IDC_CLIENT_HOST, IDC_CLIENT_PORT, IDC_CLIENT_LOCALFILE, IDC_CLIENT_REMOTEFILE, IDC_CLIENT_GET_BUTTON, IDC_CLIENT_SEND_BUTTON }; // Create tabs and add them label // code is really not optimized, but it is working // and since it is called only once... TabCtrlItem.mask = TCIF_TEXT | TCIF_PARAM ; for ( nOnglet = 0; nOnglet < SizeOfTab (tTabCtrlData) ; nOnglet++ ) { // for local tabs (tftp client & event viewer use the settings) // for remote services use the report sent by the console // and saved into sGuiSettings.uRunningServices if ( tTabCtrlData[nOnglet].mask & (tTabCtrlData[nOnglet].service ? sGuiSettings.uRunningServices : sGuiSettings.uServices) ) { TabCtrlItem.pszText = tTabCtrlData[nOnglet].name; TabCtrlItem.lParam = tTabCtrlData[nOnglet].tab ; TabCtrl_InsertItem(hTabWnd, nOnglet, (LPARAM) & TabCtrlItem); } // tab should be displayed } // all tabs TR_ResizeWindow(hDlgWnd, TRUE); // First available tab is selected TabCtrl_SetCurSel (hTabWnd, 0); TR_ChangeTabControl (hDlgWnd); // Place Tab ctrl at bottom of Z-order and all client control at top // Local File control will then accept drag an drop // (set also the other windows just to ease navigation with TAB) SetWindowPos (hTabWnd, HWND_BOTTOM, 0,0,0,0, SWP_NOMOVE|SWP_NOSIZE); for ( Ark=SizeOfTab (tTftpClientCtrl) ; Ark>0 ; Ark-- ) SetWindowPos ( GetDlgItem (hDlgWnd, tTftpClientCtrl [Ark-1]), HWND_TOP, 0,0,0,0, SWP_NOMOVE|SWP_NOSIZE ); return TRUE; } // InitTabControl
int API4U SmtpSendMessage (LPCSTR szFrom, LPCSTR szTo, LPCSTR szMessage, LPCSTR szHost, LPCSTR szLocalDomain) { int Rc; SOCKET CSock=INVALID_SOCKET; unsigned short usPort = SMTP4U_DEFPORT; char szBuf[2048]; /* overflow is not handled */ #define XX_RETURN(x) { \ TcpClose (& CSock); \ Tcp4uLog (LOG4U_HIPROC, "exit SmtpSendMessage"); \ return (x); } Tcp4uLog (LOG4U_HIPROC, "SmtpSendMessage"); /* Ok search for SMTP server */ Rc = TcpConnect(& CSock, szHost, "smtp", & usPort); if (Rc!=TCP4U_SUCCESS) XX_RETURN (SMTP4U_CANTCONNECT); /* waits for incoming frame */ Rc = TnProtoExchange (CSock, /* used socket */ NULL, /* no frame to be sent */ szBuf, sizeof szBuf, TnReadMultiLine, /* recv function */ SmtpProto[_SMTP4U_CONNECT].tAnswer, SizeOfTab(SmtpProto[_SMTP4U_CONNECT].tAnswer), TRUE, /* sensitive compare */ SMTP4U_DEFTIMEOUT, HFILE_ERROR); if (Rc != SMTP4U_SUCCESS) XX_RETURN (Rc<TN_SUCCESS ? SMTP4U_DATAERROR : Rc); /* sends the hello command */ Sprintf (szBuf, SmtpProto[_SMTP4U_HELO].szCmd, szLocalDomain==NULL ? "" : szLocalDomain); Rc = TnProtoExchange (CSock, /* used socket */ szBuf, /* no frame to be sent */ szBuf, sizeof szBuf, TnReadMultiLine, /* recv function */ SmtpProto[_SMTP4U_HELO].tAnswer, SizeOfTab(SmtpProto[_SMTP4U_HELO].tAnswer), TRUE, /* sensitive compare */ SMTP4U_DEFTIMEOUT, HFILE_ERROR); if (Rc != SMTP4U_SUCCESS) XX_RETURN (Rc<TN_SUCCESS ? SMTP4U_DATAERROR : Rc); /* sends the Mail From */ Sprintf (szBuf, SmtpProto[_SMTP4U_MAILFROM].szCmd, szFrom); Rc = TnProtoExchange (CSock, /* used socket */ szBuf, /* no frame to be sent */ szBuf, sizeof szBuf, TnReadMultiLine, /* recv function */ SmtpProto[_SMTP4U_MAILFROM].tAnswer, SizeOfTab(SmtpProto[_SMTP4U_MAILFROM].tAnswer), TRUE, /* sensitive compare */ SMTP4U_DEFTIMEOUT, HFILE_ERROR); if (Rc != SMTP4U_SUCCESS) XX_RETURN (Rc<TN_SUCCESS ? SMTP4U_DATAERROR : Rc); /* Rcpt command is handled by the SmtpSendRcpt function*/ Rc = SmtpSendRcpt (CSock, szTo, szBuf, sizeof szBuf); if (Rc!=SMTP4U_SUCCESS) XX_RETURN (Rc); /* sends the Data command */ Rc = TnProtoExchange (CSock, /* used socket */ SmtpProto[_SMTP4U_DATA].szCmd, szBuf, sizeof szBuf, TnReadMultiLine, /* recv function */ SmtpProto[_SMTP4U_DATA].tAnswer, SizeOfTab(SmtpProto[_SMTP4U_DATA].tAnswer), TRUE, /* sensitive compare */ SMTP4U_DEFTIMEOUT, HFILE_ERROR); if (Rc != SMTP4U_SUCCESS) XX_RETURN (Rc<TN_SUCCESS ? SMTP4U_DATAERROR : Rc); /* Sends the data using TnSendMultiLine */ TnSendMultiLine (CSock, SMTP4U_STDHEADER, TRUE, HFILE_ERROR); Rc = TnSendMultiLine (CSock, szMessage, TRUE, HFILE_ERROR); if (Rc<TN_SUCCESS) XX_RETURN (SMTP4U_DATAERROR); /* sends the End of Data command */ Rc = TnProtoExchange (CSock, /* used socket */ SmtpProto[_SMTP4U_ENDOFDATA].szCmd, szBuf, sizeof szBuf, TnReadMultiLine, /* recv function */ SmtpProto[_SMTP4U_ENDOFDATA].tAnswer, SizeOfTab(SmtpProto[_SMTP4U_ENDOFDATA].tAnswer), TRUE, /* sensitive compare */ SMTP4U_DEFTIMEOUT, HFILE_ERROR); if (Rc != SMTP4U_SUCCESS) XX_RETURN (Rc<TN_SUCCESS ? SMTP4U_DATAERROR : Rc); /* and Quit properly */ Rc = TnProtoExchange (CSock, /* used socket */ SmtpProto[_SMTP4U_QUIT].szCmd, szBuf, sizeof szBuf, TnReadMultiLine, /* recv function */ SmtpProto[_SMTP4U_QUIT].tAnswer, SizeOfTab(SmtpProto[_SMTP4U_QUIT].tAnswer), TRUE, /* sensitive compare */ SMTP4U_DEFTIMEOUT, HFILE_ERROR); XX_RETURN (Rc<TN_SUCCESS ? SMTP4U_DATAERROR : Rc); #undef XX_RETURN } /* SmtpSendMessage */
int ProcessDHCPMessage (struct dhcp_packet *pDhcpPkt, int *pSize) { unsigned char *p=NULL; struct LL_IP *pCurIP=NULL, *pProposedIP=NULL; // Thanks Sam Leitch ! int Ark, nDhcpType = 0; struct in_addr sRequestedAddr; DWORD sStaticIP; if (IsDHCP (*pDhcpPkt)) { // search DHCP message type p = DHCPSearchOptionsField (pDhcpPkt->options, DHO_DHCP_MESSAGE_TYPE, NULL); if (p!=NULL) nDhcpType = *p; } if (pDhcpPkt->yiaddr.s_addr!=INADDR_ANY && pDhcpPkt->yiaddr.s_addr!=INADDR_NONE ) return FALSE ; // address already assigned // the tab has one undef raw for (Ark=0 ; Ark<SizeOfTab(tDHCPType)-1 && nDhcpType!=tDHCPType[Ark].nType ; Ark++) ; LOG (5, "Rcvd %s Msg for IP %s, Mac %s", tDHCPType[Ark].sType, inet_ntoa (pDhcpPkt->ciaddr), haddrtoa(pDhcpPkt->chaddr, pDhcpPkt->hlen,':')); // if (sParamDHCP.nPoolSize==0) return FALSE; // no allocation pool --> listen only switch (nDhcpType) { case 0 : // BootP if(sParamDHCP.nIgnoreBootp) { LOG (5, "Ignoring Bootp request"); break; } case DHCPDISCOVER : sStaticIP = DHCP_StaticAssignation (pDhcpPkt); if (sStaticIP != INADDR_NONE) { LOG (0, "%s: statically assigned to address %s", haddrtoa(pDhcpPkt->chaddr, pDhcpPkt->hlen,':'), inet_ntoa (* (struct in_addr *) & sStaticIP) ); pDhcpPkt->yiaddr.s_addr = sStaticIP; } else { p = DHCPSearchOptionsField (pDhcpPkt->options, DHO_DHCP_REQUESTED_ADDRESS, NULL); if (p!=NULL) { pDhcpPkt->ciaddr = * (struct in_addr *) p; LOG (5, "Client requested address %s", inet_ntoa (pDhcpPkt->ciaddr)); } pProposedIP = DHCP_IPAllocate (nDhcpType, & pDhcpPkt->ciaddr, pDhcpPkt->chaddr, pDhcpPkt->hlen); if (pProposedIP == NULL) { LOG (1, "no more address or address previously allocated by another server"); return FALSE; } pDhcpPkt->yiaddr.s_addr = pProposedIP->dwIP.s_addr; LOG (2, "%s: proposed address %s", IsDHCP(*pDhcpPkt) ? "DHCP" : "BOOTP", inet_ntoa (pProposedIP->dwIP) ); //If this is a bootp, there is no other response from the client. //Since we don't want leases expiring (or being mistaken for unAcked DHCP offers), //set renewed to a distant time if(nDhcpType == 0 && sStaticIP == INADDR_NONE) // patched by Rolf Offermanns ForceRenewTime(pProposedIP, 0x66666666); // fixed by Sam Leitch } // dynamically assigned address // populate the packet to be returned pDhcpPkt->op = BOOTREPLY; // translate $IP$ and $MAC$ from boot file name TranslateExp (sParamDHCP.szBootFile, pDhcpPkt->file, pDhcpPkt->yiaddr, pDhcpPkt->chaddr); *pSize = DHCPOptionsReply (pDhcpPkt, DHCPOFFER); break ; //NJW Changed how requests are handled to mimic linux -- requests are responded to even if we didn't originally allocate, but only if the requested address is in our pool range case DHCPREQUEST : {BOOL bSERVER = FALSE; // TRUE if Tftpd32 has assigned this address // Static Allocation ? // search field REQUEST ADDR in options sStaticIP = DHCP_StaticAssignation (pDhcpPkt); if (sStaticIP != INADDR_NONE) { // populate the packet to be returned pDhcpPkt->op = BOOTREPLY; pDhcpPkt->yiaddr.s_addr = sStaticIP; // translate $IP$ and $MAC$ from boot file name TranslateExp (sParamDHCP.szBootFile, pDhcpPkt->file, pDhcpPkt->yiaddr, pDhcpPkt->chaddr); *pSize = DHCPOptionsReply (pDhcpPkt, DHCPACK); break; } // has tftpd32 dinamically assigned this address pCurIP = DHCPSearchByMacAddress (pDhcpPkt->chaddr, pDhcpPkt->hlen); if (pCurIP==NULL) return FALSE; // not attributed by Tftpd32 --> do not answer // search field REQUEST ADDR in options // if specified should fit database p = DHCPSearchOptionsField (pDhcpPkt->options, DHO_DHCP_REQUESTED_ADDRESS, NULL); if (p!=NULL) { pDhcpPkt->ciaddr = * (struct in_addr *) p; } if(AddrFitsPool(&pDhcpPkt->ciaddr)) { //Look up the address, if it's not found, or the owner is this macaddr, //or the lease was expired, allow the serving. BOOL wasexpired = FALSE; pProposedIP = DHCPSearchByIP(&pDhcpPkt->ciaddr, &wasexpired); bSERVER = !pProposedIP || wasexpired || (0 == memcmp(pProposedIP->sMacAddr, pDhcpPkt->chaddr, 6)); } if (bSERVER) { pProposedIP = DHCP_IPAllocate (nDhcpType, & pDhcpPkt->ciaddr, pDhcpPkt->chaddr, pDhcpPkt->hlen); if (pProposedIP == NULL) { LOG (1, "no more addresses or address previously allocated by another server"); return FALSE; } if (pProposedIP->tAllocated==0) SetAllocTime(pProposedIP); SetRenewTime(pProposedIP); LOG (5, "Previously allocated address %s acked", inet_ntoa (pProposedIP->dwIP)); // populate the packet to be returned pDhcpPkt->op = BOOTREPLY; pDhcpPkt->yiaddr.s_addr = pProposedIP->dwIP.s_addr; TranslateExp (sParamDHCP.szBootFile, pDhcpPkt->file, pDhcpPkt->yiaddr, pDhcpPkt->chaddr); *pSize = DHCPOptionsReply (pDhcpPkt, DHCPACK); } else { LOG (5, "Client requested address %s which was not allocated by tftpd32 and is either outside our pool or is used by someone else", inet_ntoa (pDhcpPkt->ciaddr) ); return FALSE ; // do not answer } } // Block for bSERVER declaration break; case DHCPDECLINE : // search current item and its precedent pCurIP = DHCPSearchByMacAddress (pDhcpPkt->chaddr, pDhcpPkt->hlen); if (pCurIP!=NULL) { p = DHCPSearchOptionsField (pDhcpPkt->options, DHO_DHCP_REQUESTED_ADDRESS, NULL); if (p!=NULL) { sRequestedAddr.s_addr = * (DWORD *) p; if ( pCurIP->dwIP.s_addr==sRequestedAddr.s_addr) { DHCPDestroyItem (pCurIP); LOG (5, "item destroyed"); } } } //The decline is sent when an address is already in use. Do an ARP and //add a lease for the in-use address { ULONG mac[2]; ULONG maclen = 6; // search field REQUEST ADDR in options // if specified should fit database p = DHCPSearchOptionsField (pDhcpPkt->options, DHO_DHCP_REQUESTED_ADDRESS, NULL); if (p!=NULL) { pDhcpPkt->ciaddr = * (struct in_addr *) p; } if(NO_ERROR == SendARP(pDhcpPkt->ciaddr.s_addr, 0, mac, &maclen)) { pProposedIP = DHCP_IPAllocate (nDhcpType, & pDhcpPkt->ciaddr, (unsigned char*)mac, maclen); if (pProposedIP) { if (pProposedIP->tAllocated==0) SetAllocTime(pProposedIP); ForceRenewTime(pProposedIP, 0x66666666); //Give a bootp lease, since the device may not do dhcp LOG (5, "Added lease for existing address %s", inet_ntoa (pProposedIP->dwIP)); } } } break; case DHCPRELEASE : // do not destroy the item but mark it free pCurIP = DHCPSearchByMacAddress (pDhcpPkt->chaddr, pDhcpPkt->hlen); if (pCurIP!=NULL) // then mac address found in table { ZeroAllocTime(pCurIP); ZeroRenewTime(pCurIP); LOG (5, "item %s released", haddrtoa(pDhcpPkt->chaddr, pDhcpPkt->hlen,':') ); } break; } // switch type DHCPScan(); // answer only to BootP, Request or discover msg return (nDhcpType==0 || nDhcpType==DHCPDISCOVER || nDhcpType==DHCPREQUEST); } // ProcessDHCPMessage