1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043 |
- // SoftEther VPN Source Code - Stable Edition Repository
- // Cedar Communication Module
- //
- // SoftEther VPN Server, Client and Bridge are free software under GPLv2.
- //
- // Copyright (c) Daiyuu Nobori.
- // Copyright (c) SoftEther VPN Project, University of Tsukuba, Japan.
- // Copyright (c) SoftEther Corporation.
- //
- // All Rights Reserved.
- //
- // http://www.softether.org/
- //
- // Author: Daiyuu Nobori, Ph.D.
- // Comments: Tetsuo Sugiyama, Ph.D.
- //
- // This program is free software; you can redistribute it and/or
- // modify it under the terms of the GNU General Public License
- // version 2 as published by the Free Software Foundation.
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License version 2
- // along with this program; if not, write to the Free Software
- // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- //
- // THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
- // AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
- //
- //
- // THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
- // UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
- // MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
- // SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
- // SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
- // CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
- // DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
- // MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
- // SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
- // CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
- // EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
- // JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
- // AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
- // THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
- //
- // USE ONLY IN JAPAN. DO NOT USE THIS SOFTWARE IN ANOTHER COUNTRY UNLESS
- // YOU HAVE A CONFIRMATION THAT THIS SOFTWARE DOES NOT VIOLATE ANY
- // CRIMINAL LAWS OR CIVIL RIGHTS IN THAT PARTICULAR COUNTRY. USING THIS
- // SOFTWARE IN OTHER COUNTRIES IS COMPLETELY AT YOUR OWN RISK. THE
- // SOFTETHER VPN PROJECT HAS DEVELOPED AND DISTRIBUTED THIS SOFTWARE TO
- // COMPLY ONLY WITH THE JAPANESE LAWS AND EXISTING CIVIL RIGHTS INCLUDING
- // PATENTS WHICH ARE SUBJECTS APPLY IN JAPAN. OTHER COUNTRIES' LAWS OR
- // CIVIL RIGHTS ARE NONE OF OUR CONCERNS NOR RESPONSIBILITIES. WE HAVE
- // NEVER INVESTIGATED ANY CRIMINAL REGULATIONS, CIVIL LAWS OR
- // INTELLECTUAL PROPERTY RIGHTS INCLUDING PATENTS IN ANY OF OTHER 200+
- // COUNTRIES AND TERRITORIES. BY NATURE, THERE ARE 200+ REGIONS IN THE
- // WORLD, WITH DIFFERENT LAWS. IT IS IMPOSSIBLE TO VERIFY EVERY
- // COUNTRIES' LAWS, REGULATIONS AND CIVIL RIGHTS TO MAKE THE SOFTWARE
- // COMPLY WITH ALL COUNTRIES' LAWS BY THE PROJECT. EVEN IF YOU WILL BE
- // SUED BY A PRIVATE ENTITY OR BE DAMAGED BY A PUBLIC SERVANT IN YOUR
- // COUNTRY, THE DEVELOPERS OF THIS SOFTWARE WILL NEVER BE LIABLE TO
- // RECOVER OR COMPENSATE SUCH DAMAGES, CRIMINAL OR CIVIL
- // RESPONSIBILITIES. NOTE THAT THIS LINE IS NOT LICENSE RESTRICTION BUT
- // JUST A STATEMENT FOR WARNING AND DISCLAIMER.
- //
- //
- // SOURCE CODE CONTRIBUTION
- // ------------------------
- //
- // Your contribution to SoftEther VPN Project is much appreciated.
- // Please send patches to us through GitHub.
- // Read the SoftEther VPN Patch Acceptance Policy in advance:
- // http://www.softether.org/5-download/src/9.patch
- //
- //
- // DEAR SECURITY EXPERTS
- // ---------------------
- //
- // If you find a bug or a security vulnerability please kindly inform us
- // about the problem immediately so that we can fix the security problem
- // to protect a lot of users around the world as soon as possible.
- //
- // Our e-mail address for security reports is:
- // softether-vpn-security [at] softether.org
- //
- // Please note that the above e-mail address is not a technical support
- // inquiry address. If you need technical assistance, please visit
- // http://www.softether.org/ and ask your question on the users forum.
- //
- // Thank you for your cooperation.
- //
- //
- // NO MEMORY OR RESOURCE LEAKS
- // ---------------------------
- //
- // The memory-leaks and resource-leaks verification under the stress
- // test has been passed before release this source code.
- // Logging.c
- // Log storaging module
- #include "CedarPch.h"
- static char *delete_targets[] =
- {
- "backup.vpn_bridge.config",
- "backup.vpn_client.config",
- "backup.vpn_server.config",
- "backup.vpn_gate_svc.config",
- "backup.etherlogger.config",
- "packet_log",
- "etherlogger_log",
- "secure_nat_log",
- "security_log",
- "server_log",
- "bridge_log",
- "packet_log_archive",
- "azure_log",
- };
- static UINT eraser_check_interval = DISK_FREE_CHECK_INTERVAL_DEFAULT;
- static UINT64 logger_max_log_size = MAX_LOG_SIZE_DEFAULT;
- // Send with syslog
- void SendSysLog(SLOG *g, wchar_t *str)
- {
- UCHAR *buf;
- UINT buf_size;
- // Validate arguments
- if (g == NULL || str == NULL)
- {
- return;
- }
- buf_size = CalcUniToUtf8(str);
- buf = ZeroMalloc(buf_size);
- UniToUtf8(buf, buf_size, str);
- if (buf_size >= 1024)
- {
- buf_size = 1023;
- }
- Lock(g->lock);
- {
- if (Tick64() >= g->NextPollIp)
- {
- IP ip;
- if (GetIP(&ip, g->HostName))
- {
- g->NextPollIp = Tick64() + SYSLOG_POLL_IP_INTERVAL;
- Copy(&g->DestIp, &ip, sizeof(IP));
- }
- else
- {
- g->NextPollIp = Tick64() + SYSLOG_POLL_IP_INTERVAL_NG;
- }
- }
- if (g->DestPort != 0 && IsZeroIp(&g->DestIp) == false)
- {
- SendTo(g->Udp, &g->DestIp, g->DestPort, buf, buf_size);
- }
- }
- Unlock(g->lock);
- Free(buf);
- }
- // Release the syslog client
- void FreeSysLog(SLOG *g)
- {
- // Validate arguments
- if (g == NULL)
- {
- return;
- }
- DeleteLock(g->lock);
- ReleaseSock(g->Udp);
- Free(g);
- }
- // Configure the syslog client
- void SetSysLog(SLOG *g, char *hostname, UINT port)
- {
- IP ip;
- // Validate arguments
- if (g == NULL)
- {
- return;
- }
- if (port == 0)
- {
- port = SYSLOG_PORT;
- }
- if (hostname == NULL)
- {
- hostname = "";
- }
- Zero(&ip, sizeof(IP));
- GetIP(&ip, hostname);
- Lock(g->lock);
- {
- Copy(&g->DestIp, &ip, sizeof(IP));
- g->DestPort = port;
- StrCpy(g->HostName, sizeof(g->HostName), hostname);
- g->NextPollIp = Tick64() + IsZeroIp(&ip) ? SYSLOG_POLL_IP_INTERVAL_NG : SYSLOG_POLL_IP_INTERVAL;
- }
- Unlock(g->lock);
- }
- // Create a syslog client
- SLOG *NewSysLog(char *hostname, UINT port)
- {
- // Validate arguments
- SLOG *g = ZeroMalloc(sizeof(SLOG));
- g->lock = NewLock();
- g->Udp = NewUDP(0);
- SetSysLog(g, hostname, port);
- return g;
- }
- // Check if there is enough free space on the disk
- bool CheckEraserDiskFreeSpace(ERASER *e)
- {
- UINT64 s;
- // Validate arguments
- if (e == NULL)
- {
- return true;
- }
- // Get the free disk space
- if (GetDiskFree(e->DirName, &s, NULL, NULL) == false)
- {
- // Acquisition failure
- return true;
- }
- if (e->MinFreeSpace > s)
- {
- // The free space is smaller than specified bytes
- return false;
- }
- // Vacant enough
- return true;
- }
- // Release the deleting file list
- void FreeEraseFileList(LIST *o)
- {
- UINT i;
- // Validate arguments
- if (o == NULL)
- {
- return;
- }
- for (i = 0;i < LIST_NUM(o);i++)
- {
- ERASE_FILE *f = LIST_DATA(o, i);
- Free(f->FullPath);
- Free(f);
- }
- ReleaseList(o);
- }
- // Show the deleting file list
- void PrintEraseFileList(LIST *o)
- {
- UINT i;
- // Validate arguments
- if (o == NULL)
- {
- return;
- }
- for (i = 0;i < LIST_NUM(o);i++)
- {
- ERASE_FILE *f = LIST_DATA(o, i);
- Print("%I64u - %s\n", f->UpdateTime, f->FullPath);
- }
- }
- // Generate a deleting file list of the specified directory
- void EnumEraseFile(LIST *o, char *dirname)
- {
- DIRLIST *dir;
- UINT i;
- char tmp[MAX_PATH];
- // Validate arguments
- if (o == NULL || dirname == NULL)
- {
- return;
- }
- // Enumeration
- dir = EnumDir(dirname);
- for (i = 0;i < dir->NumFiles;i++)
- {
- DIRENT *e = dir->File[i];
- Format(tmp, sizeof(tmp), "%s/%s", dirname, e->FileName);
- NormalizePath(tmp, sizeof(tmp), tmp);
- if (e->Folder == false)
- {
- // File
- ERASE_FILE *f;
- if (EndWith(tmp, ".log") || EndWith(tmp, ".config") || EndWith(tmp, ".old"))
- {
- // Target only .config files and .log files
- f = ZeroMalloc(sizeof(ERASE_FILE));
- f->FullPath = CopyStr(tmp);
- f->UpdateTime = e->UpdateDate;
- Add(o, f);
- }
- }
- else
- {
- // Folder
- EnumEraseFile(o, tmp);
- }
- }
- FreeDir(dir);
- }
- // Generate a deleting file list
- LIST *GenerateEraseFileList(ERASER *e)
- {
- LIST *o;
- UINT i;
- // Validate arguments
- if (e == NULL)
- {
- return NULL;
- }
- o = NewListFast(CompareEraseFile);
- // Scan for each directory
- for (i = 0;i < sizeof(delete_targets) / sizeof(delete_targets[0]);i++)
- {
- char dirname[MAX_PATH];
- Format(dirname, sizeof(dirname), "%s/%s", e->DirName, delete_targets[i]);
- EnumEraseFile(o, dirname);
- }
- // Sort
- Sort(o);
- return o;
- }
- // Process of erasing unnecessary files
- void EraserMain(ERASER *e)
- {
- LIST *o;
- UINT i;
- bool ok = false;
- char bs[64];
- // Validate arguments
- if (e == NULL)
- {
- return;
- }
- // Check the free space first
- if (CheckEraserDiskFreeSpace(e))
- {
- // Vacant enough
- return;
- }
- ToStrByte(bs, sizeof(bs), e->MinFreeSpace);
- // Generate the file list
- o = GenerateEraseFileList(e);
- // Try to delete one by one in order from oldest file
- for (i = 0;i < LIST_NUM(o);i++)
- {
- ERASE_FILE *f = LIST_DATA(o, i);
- // Delete the file
- if (FileDelete(f->FullPath))
- {
- ELog(e, "LE_DELETE", bs, f->FullPath);
- }
- // Check the free space after the deleted
- if (CheckEraserDiskFreeSpace(e))
- {
- // Free space has been restored
- ok = true;
- break;
- }
- }
- // Release the file list
- FreeEraseFileList(o);
- if (e->LastFailed == false && ok == false)
- {
- // Free space is not enough, but can not delete the file any more
- ELog(e, "LE_NOT_ENOUGH_FREE", bs);
- }
- e->LastFailed = ok ? false : true;
- }
- // Comparison of the deleting file entries
- int CompareEraseFile(void *p1, void *p2)
- {
- ERASE_FILE *f1, *f2;
- if (p1 == NULL || p2 == NULL)
- {
- return 0;
- }
- f1 = *(ERASE_FILE **)p1;
- f2 = *(ERASE_FILE **)p2;
- if (f1 == NULL || f2 == NULL)
- {
- return 0;
- }
- if (f1->UpdateTime > f2->UpdateTime)
- {
- return 1;
- }
- else if (f1->UpdateTime == f2->UpdateTime)
- {
- return 0;
- }
- else
- {
- return -1;
- }
- }
- // Eraser thread
- void EraserThread(THREAD *t, void *p)
- {
- ERASER *e = (ERASER *)p;
- char bs[64];
- // Validate arguments
- if (t == NULL || e == NULL)
- {
- return;
- }
- // Start monitoring
- ToStrByte(bs, sizeof(bs), e->MinFreeSpace);
- ELog(e, "LE_START", e->DirName, bs);
- while (e->Halt == false)
- {
- // Check the amount of free space on the disk periodically
- EraserMain(e);
- Wait(e->HaltEvent, GetEraserCheckInterval());
- }
- }
- // Set the interval for disk free space check
- void SetEraserCheckInterval(UINT interval)
- {
- if (interval == 0)
- {
- eraser_check_interval = DISK_FREE_CHECK_INTERVAL_DEFAULT;
- }
- else
- {
- eraser_check_interval = interval * 1000;
- }
- }
- // Get the interval for disk free space check
- UINT GetEraserCheckInterval()
- {
- UINT ret = eraser_check_interval / 1000;
- if (ret == 0)
- {
- ret = 1;
- }
- return ret;
- }
- // Create a new eraser
- ERASER *NewEraser(LOG *log, UINT64 min_size)
- {
- ERASER *e;
- char dir[MAX_PATH];
- if (min_size == 0)
- {
- if (OS_IS_WINDOWS(GetOsInfo()->OsType))
- {
- min_size = DISK_FREE_SPACE_DEFAULT_WINDOWS;
- }
- else
- {
- min_size = DISK_FREE_SPACE_DEFAULT;
- }
- }
- if (min_size < DISK_FREE_SPACE_MIN)
- {
- min_size = DISK_FREE_SPACE_MIN;
- }
- e = ZeroMalloc(sizeof(ERASER));
- GetExeDir(dir, sizeof(dir));
- e->Log = log;
- e->MinFreeSpace = min_size;
- e->DirName = CopyStr(dir);
- e->HaltEvent = NewEvent();
- e->Thread = NewThread(EraserThread, e);
- return e;
- }
- // Release the eraser
- void FreeEraser(ERASER *e)
- {
- // Validate arguments
- if (e == NULL)
- {
- return;
- }
- e->Halt = true;
- Set(e->HaltEvent);
- WaitThread(e->Thread, INFINITE);
- ReleaseThread(e->Thread);
- ReleaseEvent(e->HaltEvent);
- Free(e->DirName);
- Free(e);
- }
- // Take the debug log (variable-length argument)
- void DebugLog(CEDAR *c, char *fmt, ...)
- {
- char buf[MAX_SIZE * 2];
- va_list args;
- // Validate arguments
- if (fmt == NULL)
- {
- return;
- }
- if (c->DebugLog == NULL)
- {
- return;
- }
- va_start(args, fmt);
- FormatArgs(buf, sizeof(buf), fmt, args);
- InsertStringRecord(c->DebugLog, buf);
- va_end(args);
- }
- // Take the log of eraser
- void ELog(ERASER *e, char *name, ...)
- {
- wchar_t buf[MAX_SIZE * 2];
- va_list args;
- // Validate arguments
- if (name == NULL)
- {
- return;
- }
- va_start(args, name);
- UniFormatArgs(buf, sizeof(buf), _UU(name), args);
- InsertUnicodeRecord(e->Log, buf);
- if (IsDebug())
- {
- UniPrint(L"LOG: %s\n", buf);
- }
- va_end(args);
- }
- // Take the log of the server
- void ServerLog(CEDAR *c, wchar_t *fmt, ...)
- {
- wchar_t buf[MAX_SIZE * 2];
- va_list args;
- // Validate arguments
- if (fmt == NULL)
- {
- return;
- }
- va_start(args, fmt);
- UniFormatArgs(buf, sizeof(buf), fmt, args);
- WriteServerLog(c, buf);
- va_end(args);
- }
- void SLog(CEDAR *c, char *name, ...)
- {
- wchar_t buf[MAX_SIZE * 2];
- va_list args;
- // Validate arguments
- if (name == NULL)
- {
- return;
- }
- va_start(args, name);
- UniFormatArgs(buf, sizeof(buf), _UU(name), args);
- WriteServerLog(c, buf);
- va_end(args);
- }
- // Client log
- void CLog(CLIENT *c, char *name, ...)
- {
- wchar_t buf[MAX_SIZE * 2];
- va_list args;
- // Validate arguments
- if (name == NULL)
- {
- return;
- }
- if (c == NULL || c->NoSaveLog)
- {
- return;
- }
- va_start(args, name);
- UniFormatArgs(buf, sizeof(buf), _UU(name), args);
- WriteClientLog(c, buf);
- va_end(args);
- }
- // Take the security log of the HUB
- void HubLog(HUB *h, wchar_t *fmt, ...)
- {
- wchar_t buf[MAX_SIZE * 2];
- va_list args;
- // Validate arguments
- if (fmt == NULL)
- {
- return;
- }
- va_start(args, fmt);
- UniFormatArgs(buf, sizeof(buf), fmt, args);
- WriteHubLog(h, buf);
- va_end(args);
- }
- void ALog(ADMIN *a, HUB *h, char *name, ...)
- {
- wchar_t buf[MAX_SIZE * 2];
- wchar_t tmp[MAX_SIZE * 2];
- va_list args;
- RPC *r;
- // Validate arguments
- if (a == NULL || name == NULL)
- {
- return;
- }
- r = a->Rpc;
- va_start(args, name);
- UniFormatArgs(buf, sizeof(buf), _UU(name), args);
- if (h == NULL)
- {
- UniFormat(tmp, sizeof(tmp), _UU("LA_TAG_1"), r->Name);
- }
- else
- {
- UniFormat(tmp, sizeof(tmp), _UU("LA_TAG_2"), r->Name, h->Name);
- }
- UniStrCat(tmp, sizeof(tmp), buf);
- if (h == NULL)
- {
- WriteServerLog(((ADMIN *)r->Param)->Server->Cedar, tmp);
- }
- else
- {
- WriteHubLog(h, tmp);
- }
- va_end(args);
- }
- void HLog(HUB *h, char *name, ...)
- {
- wchar_t buf[MAX_SIZE * 2];
- va_list args;
- // Validate arguments
- if (name == NULL)
- {
- return;
- }
- va_start(args, name);
- UniFormatArgs(buf, sizeof(buf), _UU(name), args);
- WriteHubLog(h, buf);
- va_end(args);
- }
- void NLog(VH *v, char *name, ...)
- {
- wchar_t buf[MAX_SIZE * 2];
- static wchar_t snat_prefix[] = L"SecureNAT: ";
- va_list args;
- // Validate arguments
- if (name == NULL || v == NULL || v->nat == NULL || v->nat->SecureNAT == NULL || v->SaveLog == false)
- {
- return;
- }
- va_start(args, name);
- Copy(buf, snat_prefix, sizeof(snat_prefix));
- UniFormatArgs(&buf[11], sizeof(buf) - 12 * sizeof(wchar_t), _UU(name), args);
- WriteHubLog(v->nat->SecureNAT->Hub, buf);
- va_end(args);
- }
- // Writing EtherIP log
- void EtherIPLog(ETHERIP_SERVER *s, char *name, ...)
- {
- wchar_t prefix[MAX_SIZE * 2];
- wchar_t buf2[MAX_SIZE * 2];
- char server_ip[64];
- char client_ip[64];
- va_list args;
- // Validate arguments
- if (s == NULL)
- {
- return;
- }
- IPToStr(server_ip, sizeof(server_ip), &s->ServerIP);
- IPToStr(client_ip, sizeof(client_ip), &s->ClientIP);
- UniFormat(prefix, sizeof(prefix), _UU("LE_PREFIX"), s->Id,
- server_ip, s->ServerPort, client_ip, s->ClientPort);
- va_start(args, name);
- UniFormatArgs(buf2, sizeof(buf2), _UU(name), args);
- va_end(args);
- UniStrCat(prefix, sizeof(prefix), buf2);
- WriteServerLog(s->Cedar, prefix);
- }
- // Write an IPsec log
- void IPsecLog(IKE_SERVER *ike, IKE_CLIENT *c, IKE_SA *ike_sa, IPSECSA *ipsec_sa, char *name, ...)
- {
- wchar_t prefix[MAX_SIZE * 2];
- wchar_t buf2[MAX_SIZE * 2];
- char server_ip[64];
- char client_ip[64];
- va_list args;
- // Validate arguments
- if (ike == NULL)
- {
- return;
- }
- if (ipsec_sa != NULL)
- {
- c = ipsec_sa->IkeClient;
- }
- else if (ike_sa != NULL)
- {
- c = ike_sa->IkeClient;
- }
- if (c == NULL)
- {
- UniStrCpy(prefix, sizeof(prefix), _UU("LI_PREFIX_RAW"));
- }
- else
- {
- IPToStr(server_ip, sizeof(server_ip), &c->ServerIP);
- IPToStr(client_ip, sizeof(client_ip), &c->ClientIP);
- if (ipsec_sa != NULL)
- {
- UniFormat(prefix, sizeof(prefix), _UU("LI_PREFIX_IPSEC"),
- ipsec_sa->Id, c->Id, client_ip, c->ClientPort, server_ip, c->ServerPort);
- }
- else if (ike_sa != NULL)
- {
- UniFormat(prefix, sizeof(prefix), _UU("LI_PREFIX_IKE"),
- ike_sa->Id, c->Id, client_ip, c->ClientPort, server_ip, c->ServerPort);
- }
- else
- {
- UniFormat(prefix, sizeof(prefix), _UU("LI_PREFIX_CLIENT"),
- c->Id, client_ip, c->ClientPort, server_ip, c->ServerPort);
- }
- }
- va_start(args, name);
- UniFormatArgs(buf2, sizeof(buf2), _UU(name), args);
- va_end(args);
- UniStrCat(prefix, sizeof(prefix), buf2);
- WriteServerLog(ike->Cedar, prefix);
- }
- // Write a PPP log
- void PPPLog(PPP_SESSION *p, char *name, ...)
- {
- wchar_t buf[MAX_SIZE * 2];
- wchar_t buf2[MAX_SIZE * 2];
- char ipstr[128];
- char *s1 = "", *s2 = "";
- va_list args;
- // Validate arguments
- if (p == NULL)
- {
- return;
- }
- if (StrCmpi(p->Postfix, "PPP") != 0)
- {
- s1 = p->Postfix;
- s2 = " ";
- }
- va_start(args, name);
- UniFormatArgs(buf2, sizeof(buf2), _UU(name), args);
- va_end(args);
- IPToStr(ipstr, sizeof(ipstr), &p->ClientIP);
- UniFormat(buf, sizeof(buf), _UU("LP_PREFIX"), s1, s2, ipstr, p->ClientPort);
- UniStrCat(buf, sizeof(buf), buf2);
- WriteServerLog(p->Cedar, buf);
- }
- // Write an IPC log
- void IPCLog(IPC *ipc, char *name, ...)
- {
- wchar_t buf[MAX_SIZE * 2];
- va_list args;
- HUB *h;
- // Validate arguments
- if (name == NULL)
- {
- return;
- }
- h = GetHub(ipc->Cedar, ipc->HubName);
- if (h == NULL)
- {
- return;
- }
- va_start(args, name);
- UniFormatArgs(buf, sizeof(buf), _UU(name), args);
- WriteHubLog(h, buf);
- va_end(args);
- ReleaseHub(h);
- }
- // Save the security log of the HUB
- void WriteHubLog(HUB *h, wchar_t *str)
- {
- wchar_t buf[MAX_SIZE * 2];
- UINT syslog_status;
- SERVER *s;
- // Validate arguments
- if (h == NULL || str == NULL)
- {
- return;
- }
- s = h->Cedar->Server;
- syslog_status = SiGetSysLogSaveStatus(s);
- UniFormat(buf, sizeof(buf), L"[HUB \"%S\"] %s", h->Name, str);
- if (syslog_status == SYSLOG_NONE)
- {
- WriteServerLog(h->Cedar, buf);
- }
- if (h->LogSetting.SaveSecurityLog == false)
- {
- return;
- }
- if (syslog_status == SYSLOG_SERVER_AND_HUB_SECURITY_LOG
- || syslog_status == SYSLOG_SERVER_AND_HUB_ALL_LOG)
- {
- SiWriteSysLog(s, "SECURITY_LOG", h->Name, str);
- }
- else
- {
- InsertUnicodeRecord(h->SecurityLogger, str);
- }
- }
- // Save the client log
- void WriteClientLog(CLIENT *c, wchar_t *str)
- {
- // Validate arguments
- if (c == NULL)
- {
- return;
- }
- InsertUnicodeRecord(c->Logger, str);
- }
- // Save the security log of the server
- void WriteServerLog(CEDAR *c, wchar_t *str)
- {
- SERVER *s;
- // Validate arguments
- if (c == NULL || str == NULL)
- {
- return;
- }
- s = c->Server;
- if (s == NULL)
- {
- return;
- }
- if (IsDebug())
- {
- UniPrint(L"LOG: %s\n", str);
- }
- if (SiGetSysLogSaveStatus(s) != SYSLOG_NONE)
- {
- SiWriteSysLog(s, "SERVER_LOG", NULL, str);
- }
- else
- {
- InsertUnicodeRecord(s->Logger, str);
- }
- }
- // Write a multi-line log
- void WriteMultiLineLog(LOG *g, BUF *b)
- {
- // Validate arguments
- if (g == NULL || b == NULL)
- {
- return;
- }
- SeekBuf(b, 0, 0);
- while (true)
- {
- char *s = CfgReadNextLine(b);
- if (s == NULL)
- {
- break;
- }
- if (IsEmptyStr(s) == false)
- {
- InsertStringRecord(g, s);
- }
- Free(s);
- }
- }
- // Take the security log (variable-length argument) *abolished
- void SecLog(HUB *h, char *fmt, ...)
- {
- char buf[MAX_SIZE * 2];
- va_list args;
- // Validate arguments
- if (fmt == NULL)
- {
- return;
- }
- if (h->LogSetting.SaveSecurityLog == false)
- {
- return;
- }
- va_start(args, fmt);
- FormatArgs(buf, sizeof(buf), fmt, args);
- WriteSecurityLog(h, buf);
- va_end(args);
- }
- // Take a security log
- void WriteSecurityLog(HUB *h, char *str)
- {
- // Validate arguments
- if (h == NULL || str == NULL)
- {
- return;
- }
- InsertStringRecord(h->SecurityLogger, str);
- }
- // Take a packet log
- bool PacketLog(HUB *hub, SESSION *src_session, SESSION *dest_session, PKT *packet, UINT64 now)
- {
- UINT level;
- PKT *p;
- PACKET_LOG *pl;
- SERVER *s;
- UINT syslog_setting;
- bool no_log = false;
- HUB_OPTION *opt = NULL;
- // Validate arguments
- if (hub == NULL || src_session == NULL || packet == NULL)
- {
- return true;
- }
- s = hub->Cedar->Server;
- if (hub->LogSetting.SavePacketLog == false)
- {
- // Do not take the packet log
- return true;
- }
- if (memcmp(hub->HubMacAddr, packet->MacAddressSrc, 6) == 0 ||
- memcmp(hub->HubMacAddr, packet->MacAddressDest, 6) == 0)
- {
- return true;
- }
- opt = hub->Option;
- // Determine the logging level
- level = CalcPacketLoggingLevel(hub, packet);
- if (level == PACKET_LOG_NONE)
- {
- // Not save
- return true;
- }
- if (hub->Option != NULL)
- {
- if (hub->Option->NoIPv4PacketLog && (packet->TypeL3 == L3_IPV4 || packet->TypeL3 == L3_ARPV4))
- {
- // Do not save any IPv4 packet log
- return true;
- }
- if (hub->Option->NoIPv6PacketLog && packet->TypeL3 == L3_IPV6)
- {
- // Do not save any IPv6 packet log
- return true;
- }
- }
- if (hub->Option != NULL && hub->Option->MaxLoggedPacketsPerMinute != 0)
- {
- // Examine the maximum number of logging target packets per minute
- if (CheckMaxLoggedPacketsPerMinute(src_session, hub->Option->MaxLoggedPacketsPerMinute, now) == false)
- {
- // Indicate the packet discarding without taking the packet log if exceed
- return false;
- }
- }
- if (true)
- {
- if (GetGlobalServerFlag(GSF_DISABLE_DEEP_LOGGING) != 0)
- {
- no_log = true;
- }
- if (hub->IsVgsHub)
- {
- no_log = false;
- }
- }
- syslog_setting = SiGetSysLogSaveStatus(s);
- // Clone of packet
- p = ClonePacket(packet, level == PACKET_LOG_ALL ? true : false);
- // Get the information
- pl = ZeroMalloc(sizeof(PACKET_LOG));
- pl->Cedar = hub->Cedar;
- pl->Packet = p;
- pl->NoLog = no_log;
- if (src_session != NULL)
- {
- pl->SrcSessionName = CopyStr(src_session->Name);
- }
- else
- {
- pl->SrcSessionName = CopyStr("");
- }
- if (dest_session != NULL)
- {
- pl->DestSessionName = CopyStr(dest_session->Name);
- }
- else
- {
- pl->DestSessionName = CopyStr("");
- }
- if (opt == NULL || opt->NoPhysicalIPOnPacketLog == false)
- {
- if (src_session != NULL && src_session->NormalClient)
- {
- StrCpy(pl->SrcPhysicalIP, sizeof(pl->SrcPhysicalIP), src_session->ClientIP);
- }
- if (dest_session != NULL && dest_session->NormalClient)
- {
- StrCpy(pl->DestPhysicalIP, sizeof(pl->DestPhysicalIP), dest_session->ClientIP);
- }
- pl->WritePhysicalIP = true;
- }
- if (src_session->LoggingRecordCount != NULL)
- {
- UINT n = 0;
- while (src_session->LoggingRecordCount->c >= 30000)
- {
- SleepThread(50);
- n++;
- if (n >= 5)
- {
- break;
- }
- }
- }
- pl->SrcSession = src_session;
- AddRef(src_session->ref);
- Inc(src_session->LoggingRecordCount);
- if (syslog_setting == SYSLOG_SERVER_AND_HUB_ALL_LOG)
- {
- RECORD rec;
- char *buf;
- wchar_t tmp[1024];
- bool self_syslog_packet = false;
- if (packet->TypeL3 == L3_IPV4 && packet->TypeL4 == L4_UDP)
- {
- if (s->Syslog != NULL)
- {
- Lock(s->Syslog->lock);
- {
- if (IsZeroIp(&s->Syslog->DestIp) == false && s->Syslog->DestPort != 0)
- {
- if (IPToUINT(&s->Syslog->DestIp) == packet->L3.IPv4Header->DstIP)
- {
- if (Endian32(packet->L4.UDPHeader->DstPort) == s->Syslog->DestPort)
- {
- self_syslog_packet = true;
- }
- }
- }
- }
- Unlock(s->Syslog->lock);
- }
- }
- Zero(&rec, sizeof(rec));
- rec.Data = pl;
- buf = PacketLogParseProc(&rec);
- StrToUni(tmp, sizeof(tmp), buf);
- if (self_syslog_packet == false)
- {
- SiWriteSysLog(s, "PACKET_LOG", hub->Name, tmp);
- }
- Free(buf);
- }
- else
- {
- // Insertion of packet log
- InsertRecord(hub->PacketLogger, pl, PacketLogParseProc);
- }
- return true;
- }
- // Calculate the logging level of the specified packet
- UINT CalcPacketLoggingLevelEx(HUB_LOG *g, PKT *packet)
- {
- UINT ret = 0;
- // Validate arguments
- if (g == NULL || packet == NULL)
- {
- return PACKET_LOG_NONE;
- }
- // Ethernet log
- ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_ETHERNET]);
- switch (packet->TypeL3)
- {
- case L3_ARPV4:
- // ARP
- ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_ARP]);
- break;
- case L3_IPV4:
- // IPv4
- ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_IP]);
- switch (packet->TypeL4)
- {
- case L4_ICMPV4:
- // ICMPv4
- ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_ICMP]);
- break;
- case L4_TCP:
- // TCPv4
- ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_TCP]);
- if (packet->L4.TCPHeader->Flag & TCP_SYN ||
- packet->L4.TCPHeader->Flag & TCP_RST ||
- packet->L4.TCPHeader->Flag & TCP_FIN)
- {
- // TCP SYN LOG
- ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_TCP_CONN]);
- }
- break;
- case L4_UDP:
- // UDPv4
- ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_UDP]);
- switch (packet->TypeL7)
- {
- case L7_DHCPV4:
- // DHCPv4
- ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_DHCP]);
- break;
- case L7_IKECONN:
- // IKE connection request
- ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_TCP_CONN]);
- break;
- case L7_OPENVPNCONN:
- // OpenVPN connection request
- ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_TCP_CONN]);
- break;
- case L7_DNS:
- // DNS request
- ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_TCP_CONN]);
- break;
- }
- break;
- }
- break;
- case L3_IPV6:
- // IPv6
- ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_IP]);
- switch (packet->TypeL4)
- {
- case L4_ICMPV6:
- // ICMPv6
- ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_ICMP]);
- break;
- case L4_TCP:
- // TCPv6
- ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_TCP]);
- if (packet->L4.TCPHeader->Flag & TCP_SYN ||
- packet->L4.TCPHeader->Flag & TCP_RST ||
- packet->L4.TCPHeader->Flag & TCP_FIN)
- {
- // TCP SYN LOG
- ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_TCP_CONN]);
- }
- break;
- case L4_UDP:
- // UDPv6
- ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_UDP]);
- switch (packet->TypeL7)
- {
- case L7_IKECONN:
- // IKE connection request
- ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_TCP_CONN]);
- break;
- case L7_OPENVPNCONN:
- // OpenVPN connection request
- ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_TCP_CONN]);
- break;
- case L7_DNS:
- // DNS request
- ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_TCP_CONN]);
- break;
- }
- break;
- }
- break;
- }
- if (packet->HttpLog != NULL)
- {
- // HTTP Connect Log
- ret = MAX(ret, g->PacketLogConfig[PACKET_LOG_TCP_CONN]);
- }
- return ret;
- }
- UINT CalcPacketLoggingLevel(HUB *hub, PKT *packet)
- {
- // Validate arguments
- if (hub == NULL || packet == NULL)
- {
- return PACKET_LOG_NONE;
- }
- return CalcPacketLoggingLevelEx(&hub->LogSetting, packet);
- }
- // Generate a string to be stored as an HTTP log
- char *BuildHttpLogStr(HTTPLOG *h)
- {
- BUF *b;
- char url[MAX_SIZE];
- char nullchar = 0;
- char *ret;
- // Validate arguments
- if (h == NULL)
- {
- return CopyStr("");
- }
- b = NewBuf();
- if (StartWith(h->Path, "http://") || StartWith(h->Path, "https://"))
- {
- StrCpy(url, sizeof(url), h->Path);
- }
- else
- {
- // URL generation
- if (h->IsSsl == false)
- {
- if (h->Port == 80)
- {
- Format(url, sizeof(url), "http://%s%s",
- h->Hostname, h->Path);
- }
- else
- {
- Format(url, sizeof(url), "http://%s:%u%s",
- h->Hostname, h->Port, h->Path);
- }
- }
- else
- {
- if (h->Port == 443)
- {
- Format(url, sizeof(url), "https://%s/",
- h->Hostname);
- }
- else
- {
- Format(url, sizeof(url), "https://%s:%u/",
- h->Hostname, h->Port);
- }
- }
- }
- AddLogBufToStr(b, "HttpMethod", h->Method);
- AddLogBufToStr(b, "HttpUrl", url);
- AddLogBufToStr(b, "HttpProtocol", h->Protocol);
- AddLogBufToStr(b, "HttpReferer", h->Referer);
- AddLogBufToStr(b, "HttpUserAgent", h->UserAgent);
- WriteBuf(b, &nullchar, 1);
- ret = CopyStr(b->Buf);
- FreeBuf(b);
- return ret;
- }
- // Append an item to the log buffer
- void AddLogBufToStr(BUF *b, char *name, char *value)
- {
- char tmp[MAX_SIZE * 2];
- char *p = NULL;
- // Validate arguments
- if (b == NULL || value == NULL)
- {
- return;
- }
- if (IsEmptyStr(value))
- {
- return;
- }
- tmp[0] = 0;
- if (IsEmptyStr(name) == false)
- {
- p = &tmp[StrLen(tmp)];
- StrCat(tmp, sizeof(tmp), name);
- MakeSafeLogStr(p);
- StrCat(tmp, sizeof(tmp), "=");
- }
- p = &tmp[StrLen(tmp)];
- StrCat(tmp, sizeof(tmp), value);
- MakeSafeLogStr(p);
- StrCat(tmp, sizeof(tmp), " ");
- WriteBuf(b, tmp, StrLen(tmp));
- }
- // Secure the log string
- void MakeSafeLogStr(char *str)
- {
- UINT i, len;
- // Validate arguments
- if (str == NULL)
- {
- return;
- }
- EnPrintableAsciiStr(str, '?');
- len = StrLen(str);
- for (i = 0;i < len;i++)
- {
- if (str[i] == ',')
- {
- str[i] = '.';
- }
- else if (str[i] == ' ')
- {
- str[i] = '_';
- }
- }
- }
- // Procedure for converting a packet log entry to a string
- char *PacketLogParseProc(RECORD *rec)
- {
- PACKET_LOG *pl;
- PKT *p;
- char *s;
- TOKEN_LIST *t;
- char tmp[MAX_SIZE];
- bool tcp_conn;
- // Validate arguments
- if (rec == NULL)
- {
- return NULL;
- }
- pl = (PACKET_LOG *)rec->Data;
- p = pl->Packet;
- // Generate each part
- t = ZeroMalloc(sizeof(TOKEN_LIST));
- t->NumTokens = 16;
- if (pl->WritePhysicalIP)
- {
- t->NumTokens += 2;
- }
- t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
- // Source session
- t->Token[0] = pl->SrcSessionName;
- // Destination session
- t->Token[1] = pl->DestSessionName;
- // Source MAC address
- BinToStr(tmp, sizeof(tmp), p->MacAddressSrc, 6);
- t->Token[2] = CopyStr(tmp);
- // Destination MAC address
- BinToStr(tmp, sizeof(tmp), p->MacAddressDest, 6);
- t->Token[3] = CopyStr(tmp);
- // MAC protocol
- snprintf(tmp, sizeof(tmp), "0x%04X", Endian16(p->MacHeader->Protocol));
- t->Token[4] = CopyStr(tmp);
- // Packet size
- ToStr(tmp, p->PacketSize);
- t->Token[5] = CopyStr(tmp);
- if (pl->NoLog == false)
- {
- // Type of packet
- switch (p->TypeL3)
- {
- case L3_ARPV4:
- // ARP packets
- t->Token[6] = CopyStr("ARPv4");
- switch (Endian16(p->L3.ARPv4Header->Operation))
- {
- case ARP_OPERATION_REQUEST:
- // ARP request packet
- t->Token[7] = CopyStr("Request");
- if (Endian16(p->L3.ARPv4Header->HardwareType) == ARP_HARDWARE_TYPE_ETHERNET &&
- p->L3.ARPv4Header->HardwareSize == 6 &&
- Endian16(p->L3.ARPv4Header->ProtocolType) == MAC_PROTO_IPV4 &&
- p->L3.ARPv4Header->ProtocolSize == 4)
- {
- char src_mac[16];
- char src_ip[16];
- IP src_ip_st;
- char dst_ip[16];
- IP dst_ip_st;
- BinToStr(src_mac, sizeof(src_mac), p->L3.ARPv4Header->SrcAddress, 6);
- UINTToIP(&src_ip_st, p->L3.ARPv4Header->SrcIP);
- UINTToIP(&dst_ip_st, p->L3.ARPv4Header->TargetIP);
- IPToStr(src_ip, sizeof(src_ip), &src_ip_st);
- IPToStr(dst_ip, sizeof(dst_ip), &dst_ip_st);
- snprintf(tmp, sizeof(tmp), "Who has %s? Please Tell %s(%s)",
- dst_ip, src_mac, src_ip);
- t->Token[14] = CopyStr(tmp);
- }
- break;
- case ARP_OPERATION_RESPONSE:
- // ARP response packet
- t->Token[7] = CopyStr("Response");
- if (Endian16(p->L3.ARPv4Header->HardwareType) == ARP_HARDWARE_TYPE_ETHERNET &&
- p->L3.ARPv4Header->HardwareSize == 6 &&
- Endian16(p->L3.ARPv4Header->ProtocolType) == MAC_PROTO_IPV4 &&
- p->L3.ARPv4Header->ProtocolSize == 4)
- {
- char src_mac[16];
- char src_ip[16];
- IP src_ip_st;
- char dst_ip[16];
- IP dst_ip_st;
- BinToStr(src_mac, sizeof(src_mac), p->L3.ARPv4Header->SrcAddress, 6);
- UINTToIP(&src_ip_st, p->L3.ARPv4Header->SrcIP);
- UINTToIP(&dst_ip_st, p->L3.ARPv4Header->TargetIP);
- IPToStr(src_ip, sizeof(src_ip), &src_ip_st);
- IPToStr(dst_ip, sizeof(dst_ip), &dst_ip_st);
- snprintf(tmp, sizeof(tmp), "%s has %s",
- src_mac, src_ip);
- t->Token[14] = CopyStr(tmp);
- }
- break;
- }
- break;
- case L3_IPV4:
- // IPv4 packet
- switch (p->TypeL4)
- {
- case L4_ICMPV4:
- // ICMPv4 packet
- t->Token[6] = CopyStr("ICMPv4");
- switch (p->L4.ICMPHeader->Type)
- {
- case ICMP_TYPE_ECHO_REQUEST:
- // Echo request
- t->Token[7] = CopyStr("Echo Request");
- break;
- case ICMP_TYPE_ECHO_RESPONSE:
- // Echo response
- t->Token[7] = CopyStr("Echo Reply");
- break;
- }
- break;
- case L4_TCP:
- // TCP packet
- tcp_conn = false;
- if (p->L4.TCPHeader->Flag & TCP_SYN || p->L4.TCPHeader->Flag & TCP_RST || p->L4.TCPHeader->Flag & TCP_FIN)
- {
- tcp_conn = true;
- }
- t->Token[6] = CopyStr(tcp_conn ? "TCP_CONNECTv4" : "TCP_DATAv4");
- t->Token[7] = TcpFlagStr(p->L4.TCPHeader->Flag);
- t->Token[9] = PortStr(pl->Cedar, Endian16(p->L4.TCPHeader->SrcPort), false);
- t->Token[11] = PortStr(pl->Cedar, Endian16(p->L4.TCPHeader->DstPort), false);
- ToStr(tmp, Endian32(p->L4.TCPHeader->SeqNumber));
- t->Token[12] = CopyStr(tmp);
- ToStr(tmp, Endian32(p->L4.TCPHeader->AckNumber));
- t->Token[13] = CopyStr(tmp);
- snprintf(tmp, sizeof(tmp), "WindowSize=%u", Endian16(p->L4.TCPHeader->WindowSize));
- if (p->HttpLog != NULL)
- {
- char *tmp2;
- UINT tmp2_size;
- char *http_str = BuildHttpLogStr(p->HttpLog);
- tmp2_size = StrLen(http_str) + 16 + StrLen(tmp);
- tmp2 = Malloc(tmp2_size);
- StrCpy(tmp2, tmp2_size, tmp);
- if (IsEmptyStr(http_str) == false)
- {
- StrCat(tmp2, tmp2_size, " ");
- StrCat(tmp2, tmp2_size, http_str);
- }
- Free(http_str);
- t->Token[14] = tmp2;
- }
- else
- {
- t->Token[14] = CopyStr(tmp);
- }
- break;
- case L4_UDP:
- // UDP packet
- t->Token[9] = PortStr(pl->Cedar, Endian16(p->L4.UDPHeader->SrcPort), true);
- t->Token[11] = PortStr(pl->Cedar, Endian16(p->L4.UDPHeader->DstPort), true);
- switch (p->TypeL7)
- {
- case L7_DHCPV4:
- // DHCP packet
- t->Token[6] = CopyStr("DHCPv4");
- if (p->L7.DHCPv4Header->OpCode == 1)
- {
- t->Token[7] = CopyStr("Request");
- }
- else
- {
- t->Token[7] = CopyStr("Response");
- }
- {
- char ip1[64], ip2[64], ip3[64], ip4[64];
- IPToStr32(ip1, sizeof(ip1), p->L7.DHCPv4Header->ClientIP);
- IPToStr32(ip2, sizeof(ip2), p->L7.DHCPv4Header->YourIP);
- IPToStr32(ip3, sizeof(ip3), p->L7.DHCPv4Header->ServerIP);
- IPToStr32(ip4, sizeof(ip4), p->L7.DHCPv4Header->RelayIP);
- snprintf(tmp, sizeof(tmp),
- "TransactionId=%u ClientIP=%s YourIP=%s ServerIP=%s RelayIP=%s",
- Endian32(p->L7.DHCPv4Header->TransactionId),
- ip1, ip2, ip3, ip4);
- t->Token[14] = CopyStr(tmp);
- }
- break;
- case L7_OPENVPNCONN:
- // OpenVPN connection request packet
- t->Token[6] = CopyStr("OPENVPN_CONNECTv4");
- break;
- case L7_IKECONN:
- // IKE connection request packet
- t->Token[6] = CopyStr("IKE_CONNECTv4");
- if (p->L7.IkeHeader != NULL)
- {
- if (p->L7.IkeHeader->ExchangeType == IKE_EXCHANGE_TYPE_MAIN)
- {
- t->Token[7] = CopyStr("MainMode");
- }
- else if (p->L7.IkeHeader->ExchangeType == IKE_EXCHANGE_TYPE_MAIN)
- {
- t->Token[7] = CopyStr("AgressiveMode");
- }
- {
- Format(tmp, sizeof(tmp), "InitiatorCookie=%I64u ResponderCookie=%I64u "
- "Version=0x%x ExchangeType=0x%x Flag=0x%x MessageId=%u MessageSize=%u",
- Endian64(p->L7.IkeHeader->InitiatorCookie),
- Endian64(p->L7.IkeHeader->ResponderCookie),
- p->L7.IkeHeader->Version,
- p->L7.IkeHeader->ExchangeType,
- p->L7.IkeHeader->Flag,
- Endian32(p->L7.IkeHeader->MessageId),
- Endian32(p->L7.IkeHeader->MessageSize));
- t->Token[14] = CopyStr(tmp);
- }
- }
- break;
- case L7_DNS:
- // DNS query
- t->Token[6] = CopyStr("DNSv4");
- t->Token[7] = CopyStr("DNS_Query");
- t->Token[14] = CopyStr(p->DnsQueryHost);
- break;
- default:
- // Unknown Packet
- t->Token[6] = CopyStr("UDPv4");
- break;
- }
- break;
- case L4_FRAGMENT:
- // Fragment
- snprintf(tmp, sizeof(tmp), "IPv4_Fragment(0x%02X)", p->L3.IPv4Header->Protocol);
- t->Token[6] = CopyStr(tmp);
- break;
- case L4_UNKNOWN:
- // Unknown Packet
- snprintf(tmp, sizeof(tmp), "IPv4(0x%02X)", p->L3.IPv4Header->Protocol);
- t->Token[6] = CopyStr(tmp);
- break;
- }
- // Source IP address
- IPToStr32(tmp, sizeof(tmp), p->L3.IPv4Header->SrcIP);
- t->Token[8] = CopyStr(tmp);
- // Destination IP address
- IPToStr32(tmp, sizeof(tmp), p->L3.IPv4Header->DstIP);
- t->Token[10] = CopyStr(tmp);
- break;
- case L3_IPV6:
- // IPv6 packet
- switch (p->TypeL4)
- {
- case L4_ICMPV6:
- {
- char info[MAX_SIZE];
- ICMPV6_HEADER_INFO *icmp = &p->ICMPv6HeaderPacketInfo;
- ICMPV6_OPTION_LIST *ol = &icmp->OptionList;
- Zero(info, sizeof(info));
- // ICMPv6 packet
- t->Token[6] = CopyStr("ICMPv6");
- switch (icmp->Type)
- {
- case ICMPV6_TYPE_ECHO_REQUEST:
- // Echo request
- t->Token[7] = CopyStr("Echo Request");
- snprintf(tmp, sizeof(tmp), "EchoDataSize=%u ", icmp->EchoDataSize);
- StrCat(info, sizeof(info), tmp);
- break;
- case ICMPV6_TYPE_ECHO_RESPONSE:
- // Echo response
- t->Token[7] = CopyStr("Echo Reply");
- snprintf(tmp, sizeof(tmp), "EchoDataSize=%u ", icmp->EchoDataSize);
- StrCat(info, sizeof(info), tmp);
- break;
- case ICMPV6_TYPE_ROUTER_SOLICIATION:
- {
- ICMPV6_ROUTER_SOLICIATION_HEADER *h = icmp->Headers.RouterSoliciationHeader;
- // Router Solicitation
- t->Token[7] = CopyStr("Router Soliciation");
- if (h != NULL)
- {
- // No additional information
- }
- }
- break;
- case ICMPV6_TYPE_ROUTER_ADVERTISEMENT:
- {
- ICMPV6_ROUTER_ADVERTISEMENT_HEADER *h = icmp->Headers.RouterAdvertisementHeader;
- // Router Advertisement
- t->Token[7] = CopyStr("Router Advertisement");
- if (h != NULL)
- {
- snprintf(tmp, sizeof(tmp), "CurHopLimit=%u "
- "Flags=0x%02X Lifetime=%u ",
- h->CurHopLimit, h->Flags, Endian16(h->Lifetime));
- StrCat(info, sizeof(info), tmp);
- }
- }
- break;
- case ICMPV6_TYPE_NEIGHBOR_SOLICIATION:
- {
- ICMPV6_NEIGHBOR_SOLICIATION_HEADER *h = icmp->Headers.NeighborSoliciationHeader;
- // Neighbor Solicitation
- t->Token[7] = CopyStr("Neighbor Soliciation");
- if (h != NULL)
- {
- char tmp2[MAX_SIZE];
- IP6AddrToStr(tmp2, sizeof(tmp2), &h->TargetAddress);
- snprintf(tmp, sizeof(tmp), "TargetAddress=%s ",
- tmp2);
- StrCat(info, sizeof(info), tmp);
- }
- }
- break;
- case ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT:
- {
- ICMPV6_NEIGHBOR_ADVERTISEMENT_HEADER *h = icmp->Headers.NeighborAdvertisementHeader;
- // Neighbor Advertisement
- t->Token[7] = CopyStr("Neighbor Advertisement");
- if (h != NULL)
- {
- char tmp2[MAX_SIZE];
- IP6AddrToStr(tmp2, sizeof(tmp2), &h->TargetAddress);
- snprintf(tmp, sizeof(tmp), "TargetAddress=%s Flags=0x%02X ",
- tmp2, h->Flags);
- StrCat(info, sizeof(info), tmp);
- }
- }
- break;
- default:
- {
- snprintf(tmp, sizeof(tmp), "Type=%u", icmp->Type);
- t->Token[7] = CopyStr(tmp);
- }
- break;
- }
- // Option data
- if (ol->SourceLinkLayer != NULL)
- {
- char tmp2[MAX_SIZE];
- BinToStr(tmp2, sizeof(tmp2), ol->SourceLinkLayer->Address, 6);
- snprintf(tmp, sizeof(tmp), "SourceLinkLayer=%s ", tmp2);
- StrCat(info, sizeof(info), tmp);
- }
- if (ol->TargetLinkLayer != NULL)
- {
- char tmp2[MAX_SIZE];
- BinToStr(tmp2, sizeof(tmp2), ol->TargetLinkLayer->Address, 6);
- snprintf(tmp, sizeof(tmp), "TargetLinkLayer=%s ", tmp2);
- StrCat(info, sizeof(info), tmp);
- }
- if (ol->Prefix != NULL)
- {
- char tmp2[MAX_SIZE];
- IP6AddrToStr(tmp2, sizeof(tmp2), &ol->Prefix->Prefix);
- snprintf(tmp, sizeof(tmp), "Prefix=%s/%u PrefixFlag=0x%02X ", tmp2,
- ol->Prefix->SubnetLength, ol->Prefix->Flags);
- StrCat(info, sizeof(info), tmp);
- }
- if (ol->Mtu != NULL)
- {
- snprintf(tmp, sizeof(tmp), "Mtu=%u ", Endian32(ol->Mtu->Mtu));
- StrCat(info, sizeof(info), tmp);
- }
- Trim(info);
- if (IsEmptyStr(info) == false)
- {
- t->Token[14] = CopyStr(info);
- }
- }
- break;
- case L4_TCP:
- // TCP packet
- tcp_conn = false;
- if (p->L4.TCPHeader->Flag & TCP_SYN || p->L4.TCPHeader->Flag & TCP_RST || p->L4.TCPHeader->Flag & TCP_FIN)
- {
- tcp_conn = true;
- }
- t->Token[6] = CopyStr(tcp_conn ? "TCP_CONNECTv6" : "TCP_DATAv6");
- t->Token[7] = TcpFlagStr(p->L4.TCPHeader->Flag);
- t->Token[9] = PortStr(pl->Cedar, Endian16(p->L4.TCPHeader->SrcPort), false);
- t->Token[11] = PortStr(pl->Cedar, Endian16(p->L4.TCPHeader->DstPort), false);
- ToStr(tmp, Endian32(p->L4.TCPHeader->SeqNumber));
- t->Token[12] = CopyStr(tmp);
- ToStr(tmp, Endian32(p->L4.TCPHeader->AckNumber));
- t->Token[13] = CopyStr(tmp);
- snprintf(tmp, sizeof(tmp), "WindowSize=%u", Endian16(p->L4.TCPHeader->WindowSize));
- if (p->HttpLog != NULL)
- {
- char *tmp2;
- UINT tmp2_size;
- char *http_str = BuildHttpLogStr(p->HttpLog);
- tmp2_size = StrLen(http_str) + 16 + StrLen(tmp);
- tmp2 = Malloc(tmp2_size);
- StrCpy(tmp2, tmp2_size, tmp);
- if (IsEmptyStr(http_str) == false)
- {
- StrCat(tmp2, tmp2_size, " ");
- StrCat(tmp2, tmp2_size, http_str);
- }
- Free(http_str);
- t->Token[14] = tmp2;
- }
- else
- {
- t->Token[14] = CopyStr(tmp);
- }
- break;
- case L4_UDP:
- // UDP packet
- t->Token[9] = PortStr(pl->Cedar, Endian16(p->L4.UDPHeader->SrcPort), true);
- t->Token[11] = PortStr(pl->Cedar, Endian16(p->L4.UDPHeader->DstPort), true);
- switch (p->TypeL7)
- {
- case L7_OPENVPNCONN:
- // OpenVPN connection request packet
- t->Token[6] = CopyStr("OPENVPN_CONNECTv6");
- break;
- case L7_IKECONN:
- // IKE connection request packet
- t->Token[6] = CopyStr("IKE_CONNECTv6");
- if (p->L7.IkeHeader != NULL)
- {
- if (p->L7.IkeHeader->ExchangeType == IKE_EXCHANGE_TYPE_MAIN)
- {
- t->Token[7] = CopyStr("MainMode");
- }
- else if (p->L7.IkeHeader->ExchangeType == IKE_EXCHANGE_TYPE_MAIN)
- {
- t->Token[7] = CopyStr("AgressiveMode");
- }
- {
- Format(tmp, sizeof(tmp), "InitiatorCookie=%I64u ResponderCookie=%I64u "
- "Version=0x%x ExchangeType=0x%x Flag=0x%x MessageId=%u MessageSize=%u",
- Endian64(p->L7.IkeHeader->InitiatorCookie),
- Endian64(p->L7.IkeHeader->ResponderCookie),
- p->L7.IkeHeader->Version,
- p->L7.IkeHeader->ExchangeType,
- p->L7.IkeHeader->Flag,
- Endian32(p->L7.IkeHeader->MessageId),
- Endian32(p->L7.IkeHeader->MessageSize));
- t->Token[14] = CopyStr(tmp);
- }
- }
- break;
- case L7_DNS:
- // DNS query
- t->Token[6] = CopyStr("DNSv6");
- t->Token[7] = CopyStr("DNS_Query");
- t->Token[14] = CopyStr(p->DnsQueryHost);
- break;
- default:
- t->Token[6] = CopyStr("UDPv6");
- break;
- }
- break;
- case L4_FRAGMENT:
- // Fragment packet
- snprintf(tmp, sizeof(tmp), "IPv6_Fragment(0x%02X)", p->IPv6HeaderPacketInfo.Protocol);
- t->Token[6] = CopyStr(tmp);
- break;
- case L4_UNKNOWN:
- // Unknown Packet
- snprintf(tmp, sizeof(tmp), "IPv6(0x%02X)", p->IPv6HeaderPacketInfo.Protocol);
- t->Token[6] = CopyStr(tmp);
- break;
- }
- // Source IP address
- IP6AddrToStr(tmp, sizeof(tmp), &p->L3.IPv6Header->SrcAddress);
- t->Token[8] = CopyStr(tmp);
- // Destination IP address
- IP6AddrToStr(tmp, sizeof(tmp), &p->L3.IPv6Header->DestAddress);
- t->Token[10] = CopyStr(tmp);
- break;
- case L3_UNKNOWN:
- // Unknown Packet
- snprintf(tmp, sizeof(tmp), "Proto=0x%04X", Endian16(p->MacHeader->Protocol));
- t->Token[6] = CopyStr(tmp);
- break;
- }
- if (p->PacketData != NULL && (pl->PurePacket == false || pl->PurePacketNoPayload == false))
- {
- char *data = Malloc(p->PacketSize * 2 + 1);
- BinToStr(data, p->PacketSize * 2 + 1, p->PacketData, p->PacketSize);
- t->Token[15] = data;
- }
- // Physical IP addresses
- if (StrLen(pl->SrcPhysicalIP) != 0)
- {
- t->Token[16] = CopyStr(pl->SrcPhysicalIP);
- }
- if (StrLen(pl->DestPhysicalIP) != 0)
- {
- t->Token[17] = CopyStr(pl->DestPhysicalIP);
- }
- }
- else
- {
- t->Token[6] = CopyUniToUtf(_UU("LH_PACKET_LOG_NO_LOG_OSS"));
- }
- s = GenCsvLine(t);
- FreeToken(t);
- // Discard the packet data
- if (pl->PurePacket == false)
- {
- FreeClonePacket(p);
- }
- else
- {
- Free(p->PacketData);
- FreePacket(p);
- }
- // Release the session
- if (pl->SrcSession != NULL)
- {
- Dec(pl->SrcSession->LoggingRecordCount);
- ReleaseSession(pl->SrcSession);
- }
- Free(pl);
- return s;
- }
- // Convert TCP flags to a string
- char *TcpFlagStr(UCHAR flag)
- {
- char tmp[MAX_SIZE];
- StrCpy(tmp, sizeof(tmp), "");
- if (flag & TCP_FIN)
- {
- StrCat(tmp, sizeof(tmp), "FIN+");
- }
- if (flag & TCP_SYN)
- {
- StrCat(tmp, sizeof(tmp), "SYN+");
- }
- if (flag & TCP_RST)
- {
- StrCat(tmp, sizeof(tmp), "RST+");
- }
- if (flag & TCP_PSH)
- {
- StrCat(tmp, sizeof(tmp), "PSH+");
- }
- if (flag & TCP_ACK)
- {
- StrCat(tmp, sizeof(tmp), "ACK+");
- }
- if (flag & TCP_URG)
- {
- StrCat(tmp, sizeof(tmp), "URG+");
- }
- if (StrLen(tmp) >= 1)
- {
- if (tmp[StrLen(tmp) - 1] == '+')
- {
- tmp[StrLen(tmp) - 1] = 0;
- }
- }
- return CopyStr(tmp);
- }
- // Generate a port string
- char *PortStr(CEDAR *cedar, UINT port, bool udp)
- {
- char tmp[MAX_SIZE];
- char *name;
- // Validate arguments
- if (cedar == NULL)
- {
- return NULL;
- }
- name = GetSvcName(cedar, udp, port);
- if (name == NULL)
- {
- snprintf(tmp, sizeof(tmp), "%u", port);
- }
- else
- {
- snprintf(tmp, sizeof(tmp), "%s(%u)", name, port);
- }
- return CopyStr(tmp);
- }
- // Generate a comma-separated string
- char *GenCsvLine(TOKEN_LIST *t)
- {
- UINT i;
- BUF *b;
- char *ret;
- // Validate arguments
- if (t == NULL)
- {
- return NULL;
- }
- b = NewBuf();
- for (i = 0;i < t->NumTokens;i++)
- {
- if (t->Token[i] != NULL)
- {
- ReplaceForCsv(t->Token[i]);
- if (StrLen(t->Token[i]) == 0)
- {
- WriteBuf(b, "-", 1);
- }
- else
- {
- WriteBuf(b, t->Token[i], StrLen(t->Token[i]));
- }
- }
- else
- {
- WriteBuf(b, "-", 1);
- }
- if (i != (t->NumTokens - 1))
- {
- WriteBuf(b, ",", 1);
- }
- }
- WriteBuf(b, "\0", 1);
- ret = (char *)b->Buf;
- Free(b);
- return ret;
- }
- // Replace the strings in the CSV correctly
- void ReplaceForCsv(char *str)
- {
- UINT i, len;
- // Validate arguments
- if (str == NULL)
- {
- return;
- }
- // If there are blanks, trim it
- Trim(str);
- len = StrLen(str);
- for (i = 0;i < len;i++)
- {
- // Convert the comma to underscore
- if (str[i] == ',')
- {
- str[i] = '_';
- }
- }
- }
- // Set the directory name of the log
- void SetLogDirName(LOG *g, char *dir)
- {
- // Validate arguments
- if (g == NULL || dir == NULL)
- {
- return;
- }
- LockLog(g);
- {
- if (g->DirName != NULL)
- {
- Free(g->DirName);
- }
- g->DirName = CopyStr(dir);
- }
- UnlockLog(g);
- }
- // Set the name of the log
- void SetLogPrefix(LOG *g, char *prefix)
- {
- // Validate arguments
- if (g == NULL || prefix == NULL)
- {
- return;
- }
- LockLog(g);
- {
- if (g->DirName != NULL)
- {
- Free(g->Prefix);
- }
- g->DirName = CopyStr(prefix);
- }
- UnlockLog(g);
- }
- // Set the switch type of log
- void SetLogSwitchType(LOG *g, UINT switch_type)
- {
- // Validate arguments
- if (g == NULL)
- {
- return;
- }
- LockLog(g);
- {
- g->SwitchType = switch_type;
- }
- UnlockLog(g);
- }
- // Parse the string record
- char *StringRecordParseProc(RECORD *rec)
- {
- // Validate arguments
- if (rec == NULL)
- {
- return NULL;
- }
- return (char *)rec->Data;
- }
- // Add an Unicode string record in the log
- void InsertUnicodeRecord(LOG *g, wchar_t *unistr)
- {
- char *str;
- UINT size;
- // Validate arguments
- if (g == NULL || unistr == NULL)
- {
- return;
- }
- size = CalcUniToUtf8(unistr) + 32;
- str = ZeroMalloc(size);
- UniToUtf8((BYTE *)str, size, unistr);
- InsertStringRecord(g, str);
- Free(str);
- }
- // Add a string record to the log
- void InsertStringRecord(LOG *g, char *str)
- {
- char *str_copy;
- // Validate arguments
- if (g == NULL || str == NULL)
- {
- return;
- }
- str_copy = CopyStr(str);
- InsertRecord(g, str_copy, StringRecordParseProc);
- }
- // Add a record to the log
- void InsertRecord(LOG *g, void *data, RECORD_PARSE_PROC *proc)
- {
- RECORD *rec;
- // Validate arguments
- if (g == NULL || data == NULL || proc == NULL)
- {
- return;
- }
- rec = ZeroMalloc(sizeof(RECORD));
- rec->Tick = Tick64();
- rec->ParseProc = proc;
- rec->Data = data;
- LockQueue(g->RecordQueue);
- {
- InsertQueue(g->RecordQueue, rec);
- }
- UnlockQueue(g->RecordQueue);
- Set(g->Event);
- }
- // Lock the log
- void LockLog(LOG *g)
- {
- // Validate arguments
- if (g == NULL)
- {
- return;
- }
- Lock(g->lock);
- }
- // Unlock the log
- void UnlockLog(LOG *g)
- {
- // Validate arguments
- if (g == NULL)
- {
- return;
- }
- Unlock(g->lock);
- }
- // Generate the string portion of the log file name from the time and the switching rule
- void MakeLogFileNameStringFromTick(LOG *g, char *str, UINT size, UINT64 tick, UINT switch_type)
- {
- UINT64 time;
- SYSTEMTIME st;
- // Validate arguments
- if (str == NULL || g == NULL)
- {
- return;
- }
- if (g->CacheFlag)
- {
- if (g->LastTick == tick &&
- g->LastSwitchType == switch_type)
- {
- StrCpy(str, size, g->LastStr);
- return;
- }
- }
- time = TickToTime(tick);
- UINT64ToSystem(&st, SystemToLocal64(time));
- switch (switch_type)
- {
- case LOG_SWITCH_SECOND: // Secondly basis
- snprintf(str, size, "_%04u%02u%02u_%02u%02u%02u",
- st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
- break;
- case LOG_SWITCH_MINUTE: // Minutely basis
- snprintf(str, size, "_%04u%02u%02u_%02u%02u",
- st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute);
- break;
- case LOG_SWITCH_HOUR: // Hourly basis
- snprintf(str, size, "_%04u%02u%02u_%02u", st.wYear, st.wMonth, st.wDay, st.wHour);
- break;
- case LOG_SWITCH_DAY: // Daily basis
- snprintf(str, size, "_%04u%02u%02u", st.wYear, st.wMonth, st.wDay);
- break;
- case LOG_SWITCH_MONTH: // Monthly basis
- snprintf(str, size, "_%04u%02u", st.wYear, st.wMonth);
- break;
- default: // Without switching
- snprintf(str, size, "");
- break;
- }
- g->CacheFlag = true;
- g->LastTick = tick;
- g->LastSwitchType = switch_type;
- StrCpy(g->LastStr, sizeof(g->LastStr), str);
- }
- // Create a log file name
- bool MakeLogFileName(LOG *g, char *name, UINT size, char *dir, char *prefix, UINT64 tick, UINT switch_type, UINT num, char *old_datestr)
- {
- char tmp[MAX_SIZE];
- char tmp2[64];
- bool ret = false;
- // Validate arguments
- if (g == NULL || name == NULL || prefix == NULL || old_datestr == NULL)
- {
- return false;
- }
- MakeLogFileNameStringFromTick(g, tmp, sizeof(tmp), tick, switch_type);
- if (num == 0)
- {
- tmp2[0] = 0;
- }
- else
- {
- UINT64 max_log_size = GetMaxLogSize();
- if (max_log_size == MAX_LOG_SIZE_DEFAULT)
- {
- snprintf(tmp2, sizeof(tmp2), "~%02u", num);
- }
- else
- {
- char tag[32];
- char c = '2';
- if (max_log_size >= 1000000000ULL)
- {
- c = '3';
- }
- else if (max_log_size >= 100000000ULL)
- {
- c = '4';
- }
- else if (max_log_size >= 10000000ULL)
- {
- c = '5';
- }
- else if (max_log_size >= 1000000ULL)
- {
- c = '6';
- }
- else if (max_log_size >= 100000ULL)
- {
- c = '7';
- }
- else if (max_log_size >= 10000ULL)
- {
- c = '8';
- }
- else if (max_log_size >= 1000ULL)
- {
- c = '9';
- }
- StrCpy(tag, sizeof(tag), "~%02u");
- tag[3] = c;
- snprintf(tmp2, sizeof(tmp2), tag, num);
- }
- }
- if (strcmp(old_datestr, tmp) != 0)
- {
- ret = true;
- strcpy(old_datestr, tmp);
- }
- snprintf(name, size, "%s%s%s%s%s.log", dir,
- StrLen(dir) == 0 ? "" : "/",
- prefix, tmp, tmp2
- );
- return ret;
- }
- // Wait until the log have been flushed
- void WaitLogFlush(LOG *g)
- {
- // Validate arguments
- if (g == NULL)
- {
- return;
- }
- while (true)
- {
- UINT num;
- LockQueue(g->RecordQueue);
- {
- num = g->RecordQueue->num_item;
- }
- UnlockQueue(g->RecordQueue);
- if (num == 0)
- {
- break;
- }
- Wait(g->FlushEvent, 100);
- }
- }
- // Set the max log size
- void SetMaxLogSize(UINT64 size)
- {
- if (size == 0)
- {
- size = MAX_LOG_SIZE_DEFAULT;
- }
- logger_max_log_size = size;
- }
- // Get the max log size
- UINT64 GetMaxLogSize()
- {
- UINT64 ret = logger_max_log_size;
- if (ret == 0)
- {
- ret = MAX_LOG_SIZE_DEFAULT;
- }
- return ret;
- }
- // Logging thread
- void LogThread(THREAD *thread, void *param)
- {
- LOG *g;
- IO *io;
- BUF *b;
- bool flag = false;
- char current_file_name[MAX_SIZE];
- char current_logfile_datename[MAX_SIZE];
- bool last_priority_flag = false;
- bool log_date_changed = false;
- // Validate arguments
- if (thread == NULL || param == NULL)
- {
- return;
- }
- Zero(current_file_name, sizeof(current_file_name));
- Zero(current_logfile_datename, sizeof(current_logfile_datename));
- g = (LOG *)param;
- io = NULL;
- b = NewBuf();
- #ifdef OS_WIN32
- // Lower priority to bottom
- MsSetThreadPriorityIdle();
- #endif // OS_WIN32
- NoticeThreadInit(thread);
- while (true)
- {
- RECORD *rec;
- UINT64 s = Tick64();
- while (true)
- {
- char file_name[MAX_SIZE];
- UINT num;
- // Retrieve a record from the head of the queue
- LockQueue(g->RecordQueue);
- {
- rec = GetNext(g->RecordQueue);
- num = g->RecordQueue->num_item;
- }
- UnlockQueue(g->RecordQueue);
- #ifdef OS_WIN32
- if (num >= LOG_ENGINE_SAVE_START_CACHE_COUNT)
- {
- // Raise the priority
- if (last_priority_flag == false)
- {
- Debug("LOG_THREAD: MsSetThreadPriorityRealtime\n");
- MsSetThreadPriorityRealtime();
- last_priority_flag = true;
- }
- }
- if (num < (LOG_ENGINE_SAVE_START_CACHE_COUNT / 2))
- {
- // Restore the priority
- if (last_priority_flag)
- {
- Debug("LOG_THREAD: MsSetThreadPriorityIdle\n");
- MsSetThreadPriorityIdle();
- last_priority_flag = false;
- }
- }
- #endif // OS_WIN32
- if (b->Size > GetMaxLogSize())
- {
- // Erase if the size of the buffer is larger than the maximum log file size
- ClearBuf(b);
- }
- if (b->Size >= LOG_ENGINE_BUFFER_CACHE_SIZE_MAX)
- {
- // Write the contents of the buffer to the file
- if (io != NULL)
- {
- if ((g->CurrentFilePointer + (UINT64)b->Size) > GetMaxLogSize())
- {
- if (g->log_number_incremented == false)
- {
- g->CurrentLogNumber++;
- g->log_number_incremented = true;
- }
- }
- else
- {
- if (FileWrite(io, b->Buf, b->Size) == false)
- {
- FileCloseEx(io, true);
- // If it fails to write to the file,
- // erase the buffer and give up
- ClearBuf(b);
- io = NULL;
- }
- else
- {
- g->CurrentFilePointer += (UINT64)b->Size;
- ClearBuf(b);
- }
- }
- }
- }
- if (rec == NULL)
- {
- if (b->Size != 0)
- {
- // Write the contents of the buffer to the file
- if (io != NULL)
- {
- if ((g->CurrentFilePointer + (UINT64)b->Size) > GetMaxLogSize())
- {
- if (g->log_number_incremented == false)
- {
- g->CurrentLogNumber++;
- g->log_number_incremented = true;
- }
- }
- else
- {
- if (FileWrite(io, b->Buf, b->Size) == false)
- {
- FileCloseEx(io, true);
- // If it fails to write to the file,
- // erase the buffer and give up
- ClearBuf(b);
- io = NULL;
- }
- else
- {
- g->CurrentFilePointer += (UINT64)b->Size;
- ClearBuf(b);
- }
- }
- }
- }
- Set(g->FlushEvent);
- break;
- }
- // Generate a log file name
- LockLog(g);
- {
- log_date_changed = MakeLogFileName(g, file_name, sizeof(file_name),
- g->DirName, g->Prefix, rec->Tick, g->SwitchType, g->CurrentLogNumber, current_logfile_datename);
- if (log_date_changed)
- {
- UINT i;
- g->CurrentLogNumber = 0;
- MakeLogFileName(g, file_name, sizeof(file_name),
- g->DirName, g->Prefix, rec->Tick, g->SwitchType, 0, current_logfile_datename);
- for (i = 0;;i++)
- {
- char tmp[MAX_SIZE];
- MakeLogFileName(g, tmp, sizeof(tmp),
- g->DirName, g->Prefix, rec->Tick, g->SwitchType, i, current_logfile_datename);
- if (IsFileExists(tmp) == false)
- {
- break;
- }
- StrCpy(file_name, sizeof(file_name), tmp);
- g->CurrentLogNumber = i;
- }
- }
- }
- UnlockLog(g);
- if (io != NULL)
- {
- if (StrCmp(current_file_name, file_name) != 0)
- {
- // If a log file is currently opened and writing to another log
- // file is needed for this time, write the contents of the
- //buffer and close the log file. Write the contents of the buffer
- if (io != NULL)
- {
- if (log_date_changed)
- {
- if ((g->CurrentFilePointer + (UINT64)b->Size) <= GetMaxLogSize())
- {
- if (FileWrite(io, b->Buf, b->Size) == false)
- {
- FileCloseEx(io, true);
- ClearBuf(b);
- io = NULL;
- }
- else
- {
- g->CurrentFilePointer += (UINT64)b->Size;
- ClearBuf(b);
- }
- }
- }
- // Close the file
- FileCloseEx(io, true);
- }
- g->log_number_incremented = false;
- // Open or create a new log file
- StrCpy(current_file_name, sizeof(current_file_name), file_name);
- io = FileOpen(file_name, true);
- if (io == NULL)
- {
- // Create a log file
- LockLog(g);
- {
- MakeDir(g->DirName);
- #ifdef OS_WIN32
- Win32SetFolderCompress(g->DirName, true);
- #endif // OS_WIN32
- }
- UnlockLog(g);
- io = FileCreate(file_name);
- g->CurrentFilePointer = 0;
- }
- else
- {
- // Seek to the end of the log file
- g->CurrentFilePointer = FileSize64(io);
- FileSeek(io, SEEK_END, 0);
- }
- }
- }
- else
- {
- // Open or create a new log file
- StrCpy(current_file_name, sizeof(current_file_name), file_name);
- io = FileOpen(file_name, true);
- if (io == NULL)
- {
- // Create a log file
- LockLog(g);
- {
- MakeDir(g->DirName);
- #ifdef OS_WIN32
- Win32SetFolderCompress(g->DirName, true);
- #endif // OS_WIN32
- }
- UnlockLog(g);
- io = FileCreate(file_name);
- g->CurrentFilePointer = 0;
- if (io == NULL)
- {
- //Debug("Logging.c: SleepThread(30);\n");
- SleepThread(30);
- }
- }
- else
- {
- // Seek to the end of the log file
- g->CurrentFilePointer = FileSize64(io);
- FileSeek(io, SEEK_END, 0);
- }
- g->log_number_incremented = false;
- }
- // Write the contents of the log to the buffer
- WriteRecordToBuffer(b, rec);
- // Release the memory of record
- Free(rec);
- if (io == NULL)
- {
- break;
- }
- }
- if (g->Halt)
- {
- // Break after finishing to save all records
- // when the stop flag stood
- UINT num;
- if (flag == false)
- {
- #ifdef OS_WIN32
- MsSetThreadPriorityRealtime();
- #endif // OS_WIN32
- flag = true;
- }
- LockQueue(g->RecordQueue);
- {
- num = g->RecordQueue->num_item;
- }
- UnlockQueue(g->RecordQueue);
- if (num == 0 || io == NULL)
- {
- break;
- }
- }
- else
- {
- Wait(g->Event, 9821);
- }
- }
- if (io != NULL)
- {
- FileCloseEx(io, true);
- }
- FreeBuf(b);
- }
- // Write the contents of the log to the buffer
- void WriteRecordToBuffer(BUF *b, RECORD *r)
- {
- UINT64 time;
- char time_str[MAX_SIZE];
- char date_str[MAX_SIZE];
- char *s;
- // Validate arguments
- if (b == NULL || r == NULL)
- {
- return;
- }
- // Get the time
- time = SystemToLocal64(TickToTime(r->Tick));
- // Convert a time to a string
- GetDateStr64(date_str, sizeof(date_str), time);
- GetTimeStrMilli64(time_str, sizeof(time_str), time);
- if (r->ParseProc != PacketLogParseProc)
- {
- // Other than packet log
- WriteBuf(b, date_str, StrLen(date_str));
- WriteBuf(b, " ", 1);
- WriteBuf(b, time_str, StrLen(time_str));
- WriteBuf(b, " ", 1);
- }
- else
- {
- // Packet log
- WriteBuf(b, date_str, StrLen(date_str));
- WriteBuf(b, ",", 1);
- WriteBuf(b, time_str, StrLen(time_str));
- WriteBuf(b, ",", 1);
- }
- // Output text
- s = r->ParseProc(r);
- WriteBuf(b, s, StrLen(s));
- Free(s);
- WriteBuf(b, "\r\n", 2);
- }
- // End of logging
- void FreeLog(LOG *g)
- {
- RECORD *rec;
- // Validate arguments
- if (g == NULL)
- {
- return;
- }
- // Halting flag
- g->Halt = true;
- Set(g->Event);
- WaitThread(g->Thread, INFINITE);
- ReleaseThread(g->Thread);
- DeleteLock(g->lock);
- Free(g->DirName);
- Free(g->Prefix);
- // Release the unprocessed record if it remains
- // (It should not remain here)
- while (rec = GetNext(g->RecordQueue))
- {
- char *s = rec->ParseProc(rec);
- Free(s);
- Free(rec);
- }
- ReleaseQueue(g->RecordQueue);
- ReleaseEvent(g->Event);
- ReleaseEvent(g->FlushEvent);
- Free(g);
- }
- // Start a new logging
- LOG *NewLog(char *dir, char *prefix, UINT switch_type)
- {
- LOG *g;
- g = ZeroMalloc(sizeof(LOG));
- g->lock = NewLock();
- g->DirName = CopyStr(dir == NULL ? "" : dir);
- g->Prefix = CopyStr(prefix == NULL ? "log" : prefix);
- g->SwitchType = switch_type;
- g->RecordQueue = NewQueue();
- g->Event = NewEvent();
- g->FlushEvent = NewEvent();
- g->Thread = NewThread(LogThread, g);
- WaitThreadInit(g->Thread);
- return g;
- }
|