12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996 |
- /***************************************************************************
- * *
- * _____ ____ *
- * | __ \ / __ \ _ _ _____ *
- * | | \ \ / / \_\ | | | | _ \ *
- * | | \ \| | | | | | |_| | *
- * | | | || | | | | | ___/ *
- * | | / /| | __ | | | | _ \ *
- * | |__/ / \ \__/ / | |___| | |_| | *
- * |_____/ \____/ |_____|_|_____/ *
- * *
- * Wiimms source code library *
- * *
- ***************************************************************************
- * *
- * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> *
- * *
- ***************************************************************************
- * *
- * This library is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This library 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. *
- * *
- * See file gpl-2.0.txt or http://www.gnu.org/licenses/gpl-2.0.txt *
- * *
- ***************************************************************************/
- #define _GNU_SOURCE 1
- #include <string.h>
- #include <netdb.h>
- #include <errno.h>
- #include <unistd.h>
- #include <errno.h>
- #include <poll.h>
- #include <signal.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/un.h>
- #include <netinet/in.h>
- #include <stddef.h>
- #include <ifaddrs.h>
- #include "dclib-network.h"
- #include "dclib-punycode.h"
- ///////////////////////////////////////////////////////////////////////////////
- #ifdef __APPLE__
- #ifndef SOCK_NONBLOCK
- #define SOCK_NONBLOCK 0
- #endif
- #endif
- #ifndef POLLRDHUP
- #define POLLRDHUP 0
- #endif
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// host name support ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- bool ResolveHost
- (
- // returns TRUE, if a hostname is detected
- // if result is FALSE => check host->filename
- NetworkHost_t *host, // valid pointer to NetworkHost_t
- bool init_host, // true: initialize 'host'
- ccp name, // name to analyze
- int default_port, // use this as port, if no other is found
- bool check_filename, // true: check for unix filename
- bool store_name // true: setup 'host->name'
- )
- {
- return ResolveHostMem( host, init_host, MemByString(name),
- default_port, check_filename, store_name );
- }
- ///////////////////////////////////////////////////////////////////////////////
- bool ResolveHostMem
- (
- // returns TRUE, if a hostname is detected
- // if result is FALSE => check host->filename
- NetworkHost_t *host, // valid pointer to NetworkHost_t
- bool init_host, // true: initialize 'host'
- mem_t name, // name to analyze
- int default_port, // use this as port, if no other is found
- bool check_filename, // true: check for unix filename
- bool store_name // true: setup 'host->name'
- )
- {
- Setup_ConnectTCP_Hook(false);
- DASSERT(host);
- if (!init_host)
- FREE((char*)host->name);
- InitializeHost(host);
- host->port = default_port;
- if (check_filename)
- {
- mem_t res = CheckUnixSocketPathMem(name,0);
- host->filename = res.ptr;
- if (host->filename)
- return false;
- }
- char buf[1000];
- ccp ptr = name.ptr;
- ccp end = ptr + name.len;
- if ( ptr < end
- && ( *ptr >= 'a' && *ptr <= 'z' || *ptr >= 'A' && *ptr <= 'Z' ))
- {
- while ( ptr < end
- && ( *ptr >= 'a' && *ptr <= 'z'
- || *ptr >= 'A' && *ptr <= 'Z'
- || *ptr >= '0' && *ptr <= '9'
- || *ptr == '_' || *ptr == '-'
- ))
- {
- ptr++;
- }
- uint len = ptr - name.ptr;
- if ( len && len < sizeof(buf) && ptr+1 < end && *ptr == ':' && ptr[1] == '/' )
- {
- memcpy(buf,name.ptr,len);
- buf[len] = 0;
- struct servent *s = getservbyname(buf,0);
- if (s)
- {
- const int port = ntohs(s->s_port);
- if ( port > 0 )
- host->port = port;
- }
- ptr += 2;
- if ( *ptr == '/' )
- ptr++;
- name = BehindMem(name,ptr);
- check_filename = false;
- }
- else
- ptr = name.ptr;
- }
- while ( ptr < end
- && ( *ptr >= 'a' && *ptr <= 'z'
- || *ptr >= 'A' && *ptr <= 'Z'
- || *ptr >= '0' && *ptr <= '9'
- || *ptr == '_' || *ptr == '-' || *ptr == '.'
- ))
- {
- ptr++;
- }
- uint len = ptr - name.ptr;
- if ( len > 0 && len < sizeof(buf) )
- {
- memcpy(buf,name.ptr,len);
- buf[len] = 0;
- if (store_name)
- host->name = MEMDUP(buf,len);
- struct hostent *h = gethostbyname(buf);
- if ( h && h->h_addrtype == AF_INET && h->h_length == 4 )
- {
- host->ip4 = ntohl(*(u32*)h->h_addr_list[0]);
- host->ip4_valid = true;
- }
- if ( ptr < end && *ptr == ':' )
- {
- ccp pptr = ptr+1;
- if ( pptr < end && *pptr >= '0' && *pptr <= '9' )
- {
- char *end;
- const uint port = strtoul(pptr,&end,10);
- if ( port <= 0xffff && end > pptr )
- {
- host->port = port;
- ptr = end;
- }
- }
- else
- {
- ccp pstart = pptr;
- while ( pptr < end
- && ( *pptr >= 'a' && *pptr <= 'z'
- || *pptr >= 'A' && *pptr <= 'Z'
- || *pptr >= '0' && *pptr <= '9'
- || *pptr == '_' || *pptr == '-'
- ))
- {
- pptr++;
- }
- len = pptr - pstart;
- if ( len > 0 && len < sizeof(buf) )
- {
- memcpy(buf,pstart,len);
- buf[len] = 0;
- struct servent *s = getservbyname(buf,0);
- if (s)
- {
- const int port = ntohs(s->s_port);
- if ( port > 0 )
- host->port = port;
- ptr = pptr;
- }
- }
- }
- }
- host->sa.sin_family = AF_INET;
- host->sa.sin_addr.s_addr = htonl(host->ip4);
- host->sa.sin_port = htons(host->port);
- }
- if ( *ptr && check_filename )
- {
- host->filename = name.ptr;
- host->ip4_valid = false;
- }
- host->not_scanned = BehindMem(name,ptr);
- return host->ip4_valid;
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// enum PrintModeIP_t ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- PrintModeIP_t ScanPrintModeIP ( PrintModeIP_t base, ccp arg )
- {
- if (arg)
- {
- bool neg = false;
- while (*arg)
- {
- PrintModeIP_t val = 0;
- PrintModeIP_t mask = 0;
- switch(*arg++)
- {
- case '-': neg = !neg; break;
- case 'n': val = PMIP_NEVER; mask = PMIP_M_BITS; break;
- case 'r': val = PMIP_RELEVANT; mask = PMIP_M_BITS; break;
- case 'i': val = PMIP_IF_SET; mask = PMIP_M_BITS; break;
- case 'a': val = PMIP_ALWAYS; mask = PMIP_M_BITS; break;
- case 'p': val = PMIP_PORT; break;
- case 's': val = PMIP_SERVICE; break;
- case 'm': val = PMIP_MASK; break;
- case 'b': val = PMIP_BRACKETS; break;
- case 'f': val = PMIP_FULL_IPV6; break;
- case '0': val = PMIP_0DOTS; mask = PMIP_M_DOTS; break;
- case '1': val = PMIP_1DOT; mask = PMIP_M_DOTS; break;
- case '2': val = PMIP_2DOTS; mask = PMIP_M_DOTS; break;
- case '3': val = PMIP_3DOTS; mask = PMIP_M_DOTS; break;
- }
- if (mask) // ignore 'neg'
- {
- base = base & ~mask | val;
- neg = false;
- }
- else if (val)
- {
- if (neg)
- base &= ~val;
- else
- base |= val;
- neg = false;
- }
- }
- }
- return base;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ccp PrintPrintModeIP ( PrintModeIP_t val, bool align )
- {
- char buf[20], *dest = buf;
- DASSERT( PMIP_M_BITS == 3 );
- *dest++ = "nria"[ val & PMIP_M_BITS ];
- if ( val & PMIP_PORT ) *dest++ = 'p'; else if (align) *dest++ = '-';
- if ( val & PMIP_SERVICE ) *dest++ = 's'; else if (align) *dest++ = '-';
- if ( val & PMIP_MASK ) *dest++ = 'm'; else if (align) *dest++ = '-';
- if ( val & PMIP_BRACKETS ) *dest++ = 'b'; else if (align) *dest++ = '-';
- if ( val & PMIP_FULL_IPV6 ) *dest++ = 'f'; else if (align) *dest++ = '-';
- if ( val & PMIP_0DOTS )
- *dest++ = '0';
- else if ( val & PMIP_1DOT )
- *dest++ = '1';
- else if ( val & PMIP_2DOTS )
- *dest++ = '2';
- else if (align)
- *dest++ = '3';
- DASSERT( dest < buf+sizeof(buf) );
- return CopyCircBuf0(buf,dest-buf);
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// enum IPClass_t ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- ccp GetIPClassColor ( const ColorSet_t *colset, IPClass_t ipc )
- {
- if ( !colset || !colset->colorize )
- return "";
- switch (ipc)
- {
- case IPCL_INVALID: return colset->b_red;
- case IPCL_LOOPBACK: return colset->b_cyan;
- case IPCL_LOCAL: return colset->b_green;
- case IPCL_STANDARD: return colset->reset;
- case IPCL_SPECIAL: return colset->b_yellow;
- default: return colset->b_magenta;
- }
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// struct SplitIP_t ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- bool SplitIP ( SplitIP_t *sip, ccp addr )
- {
- DASSERT(sip);
- memset(sip,0,sizeof(*sip));
- if (!addr)
- return false;
- while ( isblank((int)*addr) )
- addr++;
- int bits = -1;
- ccp slash = strchr(addr,'/');
- if (slash)
- {
- if (strchr(slash,'.'))
- {
- // is there a netmask?
- struct in_addr inp;
- if (inet_aton(slash+1,&inp))
- {
- const int bits2 = Count1Bits32(inp.s_addr);
- const ipv4_t mask = GetIP4Mask(bits2);
- if ( mask == inp.s_addr )
- bits = bits2;
- }
- }
- if ( bits < 0 )
- {
- const int val = strtol(slash+1,0,10);
- if ( val >= 0 && val <= 128 )
- bits = val;
- }
- }
- ccp have_port = 0;
- if ( *addr == '[' )
- {
- ccp close = strchr(++addr,']');
- if (!close)
- return false;
- StringCopySM(sip->name,sizeof(sip->name),addr,close-addr);
- if ( close[1] == ':' )
- have_port = close+2;
- }
- else
- {
- char *end_name = slash
- ? StringCopySM(sip->name,sizeof(sip->name),addr,slash-addr)
- : StringCopyS(sip->name,sizeof(sip->name),addr);
- if ( end_name > sip->name && end_name[-1] == '.' )
- {
- // remove trailing point if not a valid IPv4 (domains only)
- if ( CheckIP4(sip->name,end_name-sip->name) <= CIP4_INVALID )
- *--end_name = 0;
- }
- ccp point = strchr(sip->name,'.');
- if (point)
- {
- char *colon = strchr(point,':');
- if (colon)
- {
- *colon++ = 0;
- have_port = colon;
- }
- }
- }
- if (!*sip->name)
- return false;
- if (have_port)
- {
- if ( *have_port >= '0' && *have_port <= '9' )
- {
- const uint port = strtol(have_port,0,10);
- if ( port <= 0xffff )
- sip->port = port;
- }
- else
- {
- char serv[100];
- if (slash)
- {
- StringCopySM(serv,sizeof(serv),have_port,slash-have_port);
- have_port = serv;
- }
- struct servent result_buf;
- struct servent *result = 0;
- char buf[1000];
- if ( !getservbyname_r(have_port,0,&result_buf,buf,sizeof(buf),&result) && result )
- sip->port = ntohs(result->s_port);
- }
- }
- sip->bits = bits;
- return true;
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// struct NamesIP_t ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- struct ip_names_list_t
- {
- int offset;
- char name[8];
- };
- //-----------------------------------------------------------------------------
- #undef RECORD
- #define RECORD(v) { offsetof(NamesIP_t,v), #v },
- static const struct ip_names_list_t ip_names_list[] =
- {
- RECORD(binaddr)
- RECORD(ipvers)
- RECORD(addr1)
- RECORD(addr2)
- RECORD(bits)
- RECORD(mask1)
- RECORD(mask2)
- {-1,""}
- };
- #undef RECORD
- #undef GET_NAME_IP_PTR
- #define GET_NAME_IP_PTR(nip,offset) ((ccp*)( (char*)(nip)+offset ))
- ///////////////////////////////////////////////////////////////////////////////
- void SetupNamesIP ( NamesIP_t *dest, const NamesIP_t *src )
- {
- if (!dest)
- return;
- if (src)
- {
- for ( const struct ip_names_list_t *in = ip_names_list; in->offset >= 0; in++ )
- {
- ccp *s = GET_NAME_IP_PTR(src,in->offset);
- ccp *d = GET_NAME_IP_PTR(dest,in->offset);
- *d = *s && **s ? *s : in->name;
- }
- }
- else
- {
- for ( const struct ip_names_list_t *in = ip_names_list; in->offset >= 0; in++ )
- {
- ccp *d = GET_NAME_IP_PTR(dest,in->offset);
- *d = in->name;
- }
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- void SetupNamesByListIP ( NamesIP_t *dest, const exmem_list_t *src )
- {
- if (!dest)
- return;
- // [[2do]] ??? qqq
- }
- ///////////////////////////////////////////////////////////////////////////////
- ccp PrintNamesIP ( const NamesIP_t *nip )
- {
- return nip
- ? PrintCircBuf("ba=%s, iv=%s, a1=%s, a2=%s, b=%s, m1=%s, m2=%s\n",
- nip->binaddr, nip->ipvers, nip->addr1, nip->addr2,
- nip->bits, nip->mask1, nip->mask2 )
- : 0;
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// struct BinIP_t ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- BinIP_t GetIPMask ( const BinIP_t *src )
- {
- BinIP_t res = {0};
- if (src)
- {
- if ( src->ipvers == 4 )
- res.ip4 = GetIP4Mask(src->bits);
- else if ( src->ipvers == 6 )
- res.ip6 = GetIP6Mask(src->bits);
- else
- goto abort;
- res.ipvers = src->ipvers;
- res.bits = src->bits;
- }
- abort:
- return res;
- }
- ///////////////////////////////////////////////////////////////////////////////
- void ApplyIPMask ( BinIP_t *bip )
- {
- if (bip)
- {
- BinIP_t mask = GetIPMask(bip);
- bip->ip6_64[0] &= mask.ip6_64[0];
- bip->ip6_64[1] &= mask.ip6_64[1];
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- IPClass_t GetIPClassBIP ( const BinIP_t * bip )
- {
- struct ip4_tab
- {
- ipv4_t addr;
- ipv4_t mask;
- IPClass_t ipc;
- };
- static const struct ip4_tab ip4_tab[] =
- {
- { 0x00000000, 0xffffffff, IPCL_INVALID }, // 0.0.0.0
- { 0x7f000000, 0xff000000, IPCL_LOOPBACK }, // 127.0.0.0/8
- { 0x0a000000, 0xff000000, IPCL_LOCAL }, // 10.0.0.0/8
- { 0xac100000, 0xfff00000, IPCL_LOCAL }, // 172.16.0.0/12
- { 0xc0a80000, 0xffff0000, IPCL_LOCAL }, // 192.168.0.0/16
- { 0xa9fe0000, 0xffff0000, IPCL_LOCAL }, // 169.254.0.0/16
- { 0xe0000000, 0xe0000000, IPCL_SPECIAL }, // 224.0.0.0/3
- { 0,0,IPCL__N },
- };
- struct ip6_tab
- {
- IPClass_t ipc;
- ccp name;
- ipv6_t addr;
- ipv6_t mask;
- };
- static struct ip6_tab ip6_tab[] =
- {
- { IPCL_INVALID, "::" },
- { IPCL_LOOPBACK, "::1" },
- { IPCL_LOCAL, "fe80::/10" },
- { IPCL_SPECIAL, "f00::/8" },
- { 0,0 },
- };
- if (bip)
- {
- if ( bip->ipvers == 4 )
- {
- const ipv4_t addr = ntohl(bip->ip4);
- for ( const struct ip4_tab *ptr = ip4_tab; ptr->ipc < IPCL__N; ptr++ )
- if ( ( addr & ptr->mask ) == ptr->addr )
- return ptr->ipc;
- return IPCL_STANDARD;
- }
- else if ( bip->ipvers == 6 )
- {
- ipv6_t addr;
- memcpy(&addr,bip->ip6_64,sizeof(addr));
- PRINT0("> %016llx.%016llx\n",ntoh64(addr.v64[0]),ntoh64(addr.v64[1]));
- static bool init_done = false;
- if (!init_done)
- {
- init_done = true;
- ManageIP_t mip = {{0}};
- for ( struct ip6_tab *ptr = ip6_tab; ptr->name; ptr++ )
- {
- ScanMIP(&mip,ptr->name);
- memcpy(&ptr->addr,mip.bin.ip6_64,sizeof(ptr->addr));
- ptr->mask = GetIP6Mask(mip.bin.bits);
- }
- ResetMIP(&mip);
- }
- for ( struct ip6_tab *ptr = ip6_tab; ptr->name; ptr++ )
- {
- PRINT0(" %016llx.%016llx / %016llx.%016llx : %s\n",
- ntoh64(ptr->addr.v64[0]), ntoh64(ptr->addr.v64[1]),
- ntoh64(ptr->mask.v64[0]), ntoh64(ptr->mask.v64[1]),
- ptr->name );
- if ( ( addr.v64[0] & ptr->mask.v64[0] ) == ptr->addr.v64[0]
- && ( addr.v64[1] & ptr->mask.v64[1] ) == ptr->addr.v64[1] )
- {
- return ptr->ipc;
- }
- }
- return IPCL_STANDARD;
- }
- }
- return IPCL_INVALID;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ccp PrintBIP ( const BinIP_t * bip )
- {
- ccp res;
- int bitlen = 32;
- char buf[INET6_ADDRSTRLEN+1];
- switch ( bip ? bip->ipvers : 0 )
- {
- case 4:
- res = inet_ntop(AF_INET,&bip->ip4,buf,sizeof(buf));
- break;
- case 6:
- res = inet_ntop(AF_INET6,bip->ip6_32,buf,sizeof(buf));
- bitlen = 128;
- break;
- default:
- res = 0;
- break;
- }
- if (!res)
- return 0;
- return bip->bits < bitlen
- ? PrintCircBuf("%s/%u",res,bip->bits)
- : CopyCircBuf(res,strlen(res)+1);
- }
- ///////////////////////////////////////////////////////////////////////////////
- bool IsSameBIP ( const BinIP_t *a1, const BinIP_t *a2, uint use_mask )
- {
- if ( a1 && a2 && a1->ipvers == a2->ipvers )
- {
- int bits;
- switch ( use_mask & 3 )
- {
- case 1: bits = a1->bits; break;
- case 2: bits = a2->bits; break;
- case 3: bits = a1->bits < a2->bits ? a1->bits : a2->bits; break;
- default: bits = 128; break;
- }
- if ( a1->ipvers == 4 )
- {
- ipv4_t mask = GetIP4Mask(bits);
- return ( a1->ip4 & mask ) == ( a2->ip4 & mask );
- }
- else if ( a1->ipvers == 6 )
- {
- ipv6_t mask = GetIP6Mask(bits);
- return !( ( a1->ip6.v64[0] ^ a2->ip6.v64[0] ) & mask.v64[0] )
- && !( ( a1->ip6.v64[1] ^ a2->ip6.v64[1] ) & mask.v64[1] );
- }
- }
- return false;
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// struct BinIPList_t ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- void ResetBIL ( BinIPList_t *bil )
- {
- if (bil)
- {
- ClearBIL(bil);
- FREE(bil->list);
- InitializeBIL(bil);
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- void ClearBIL ( BinIPList_t *bil )
- {
- if (bil)
- {
- BinIPItem_t *it = bil->list;
- for ( int i = 0; i < bil->used; i++, it++ )
- {
- FreeString(it->name);
- it->name = 0;
- }
- bil->used = 0;
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- void SetSizeBIL ( BinIPList_t *bil, int size )
- {
- DASSERT(bil);
- if ( size < 0 )
- size = 0;
- if ( bil->used > size )
- {
- for ( int i = size; i < bil->used; i++ )
- {
- BinIPItem_t *it = bil->list + i;
- FreeString(it->name);
- }
- bil->used = size;
- }
- if ( bil->size != size )
- {
- bil->size = size;
- bil->list = REALLOC( bil->list, size * sizeof(*bil->list) );
- }
- DASSERT( !bil->size || bil->list );
- DASSERT( bil->used <= bil->size );
- }
- ///////////////////////////////////////////////////////////////////////////////
- void SetMinSizeBIL ( BinIPList_t *bil, int min_size )
- {
- DASSERT(bil);
- if ( min_size > bil->size )
- {
- const int good_size = bil->size / 8 + 10;
- if ( min_size < good_size )
- min_size = good_size;
- SetSizeBIL(bil,min_size);
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- BinIPItem_t * CreateItemBIL ( BinIPList_t *bil, int n_item )
- {
- DASSERT(bil);
- if ( n_item < 0 )
- n_item = 0;
- SetMinSizeBIL(bil,bil->used+n_item);
- BinIPItem_t *res = bil->list + bil->used;
- if ( n_item > 0 )
- memset( res, 0, n_item * sizeof(*res) );
- bil->used += n_item;
- DASSERT( !bil->size || bil->list );
- DASSERT( bil->used <= bil->size );
- return res;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- #if 0
- BinIPItem_t * InsertBIL ( BinIPList_t *bil, int index, ccp key, CopyMode_t copy_mode )
- {
- DASSERT(bil);
- // ???
- return 0;
- }
- #endif
- ///////////////////////////////////////////////////////////////////////////////
- #if 0
- BinIPItem_t * InsertByKeyBIL ( BinIPList_t *bil, ccp key, CopyMode_t copy_mode )
- {
- DASSERT(bil);
- // ???
- return 0;
- }
- #endif
- ///////////////////////////////////////////////////////////////////////////////
- #if 0
- int FindIndexBIL ( const BinIPList_t *bil, ccp key )
- {
- DASSERT(bil);
- // ???
- return 0;
- }
- #endif
- ///////////////////////////////////////////////////////////////////////////////
- BinIPIterate_t FindAddressBIL ( const BinIPList_t *bil, BinIP_t *addr, uint use_mask )
- {
- BinIPIterate_t iter;
- if ( bil && bil->used && addr && addr->ipvers )
- {
- iter.valid = true;
- iter.bil = bil;
- iter.cur = bil->list - 1;
- iter.addr = *addr;
- iter.use_mask = use_mask;
- FindNextAddressBIL(&iter);
- }
- else
- memset(&iter,0,sizeof(iter));
- return iter;
- }
- //-----------------------------------------------------------------------------
- void FindNextAddressBIL ( BinIPIterate_t *iter )
- {
- if ( iter && iter->valid && iter->bil && iter->cur )
- {
- for ( uint idx = iter->cur + 1 - iter->bil->list; idx < iter->bil->used; idx++ )
- {
- BinIPItem_t *it = iter->bil->list + idx;
- if (IsSameBIP(&it->bip,&iter->addr,iter->use_mask))
- {
- iter->cur = it;
- return;
- }
- }
- }
- iter->valid = false;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- BinIP_t GetBIPBySA ( sockaddr_t *addr, sockaddr_t *mask )
- {
- BinIP_t res = {0};
- if (addr)
- {
- if ( addr->sa_family == AF_INET )
- {
- res.ipvers = 4;
- res.bits = GetBitsBySA(mask,32);
- res.ip4 = ((sockaddr_in4_t*)addr)->sin_addr.s_addr;
- }
- else if ( addr->sa_family == AF_INET6 )
- {
- res.ipvers = 6;
- res.bits = GetBitsBySA(mask,128);
- memcpy(&res.ip6,&((sockaddr_in6_t*)addr)->sin6_addr,sizeof(res.ip6));
- }
- }
- return res;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- uint ScanInterfaceAddresses ( BinIPList_t *bil, bool init_bil )
- {
- DASSERT(bil);
- if (init_bil)
- InitializeBIL(bil);
- else
- ClearBIL(bil);
- struct ifaddrs *ifaddr;
- if (getifaddrs(&ifaddr))
- return -1;
- for ( const struct ifaddrs *ifa = ifaddr; ifa; ifa = ifa->ifa_next )
- {
- BinIP_t temp = GetBIPBySA(ifa->ifa_addr,ifa->ifa_netmask);
- if (temp.ipvers)
- {
- BinIPItem_t *it = CreateItemBIL(bil,1);
- it->name = STRDUP(ifa->ifa_name);
- it->bip = temp;
- }
- }
- freeifaddrs(ifaddr);
- return bil->used;
- }
- ///////////////////////////////////////////////////////////////////////////////
- const BinIPList_t * GetInterfaceAddressList ( bool update )
- {
- static BinIPList_t *list = 0;
- if ( !list || update )
- {
- bool init = !list;
- if (init)
- list = MALLOC(sizeof(*list));
- ScanInterfaceAddresses(list,init);
- }
- return list;
- }
- ///////////////////////////////////////////////////////////////////////////////
- bool IsLocalBIL ( BinIP_t *addr, uint use_mask )
- {
- const BinIPList_t *ial = GetInterfaceAddressList(false);
- BinIPIterate_t iter = FindAddressBIL(ial,addr,use_mask);
- return iter.valid;
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// struct ManageIP_t ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- void ResetMIP ( ManageIP_t *mip )
- {
- if (mip)
- {
- FreeString(mip->name);
- FreeString(mip->decoded_name);
- memset(mip,0,sizeof(*mip));
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- void ClearNameMIP ( ManageIP_t *mip )
- {
- if (mip)
- {
- FreeString(mip->name);
- FreeString(mip->decoded_name);
- mip->name = mip->decoded_name = 0;
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- ManageIP_t GetCopyMIP ( const ManageIP_t *mip )
- {
- ManageIP_t res;
- if (mip)
- {
- memcpy(&res,mip,sizeof(res));
- if (res.name)
- res.name = STRDUP(res.name);
- if (res.decoded_name)
- res.decoded_name = STRDUP(res.decoded_name);
- }
- else
- memset(&res,0,sizeof(res));
- return res;
- }
- ///////////////////////////////////////////////////////////////////////////////
- bool AssignMIP ( ManageIP_t *dest, const ManageIP_t *src )
- {
- if (dest)
- {
- ClearNameMIP(dest);
- *dest = GetCopyMIP(src);
- return dest->bin.ipvers != 0;
- }
- return false;
- }
- ///////////////////////////////////////////////////////////////////////////////
- bool AssignBinMIP ( ManageIP_t *mip, cvp bin, int bits )
- {
- DASSERT(mip);
- ResetMIP(mip);
- if (!bin)
- return false;
- const BinIP_t *bip = bin;
- if ( bip->ipvers == 4 )
- mip->relevant_bits = 32;
- else if ( bip->ipvers == 6 )
- mip->relevant_bits = 128;
- else
- return false;
- memcpy(&mip->bin,bin,sizeof(mip->bin));
- if ( bits >= 0 )
- {
- mip->have_bits = true;
- mip->bin.bits = bits < mip->relevant_bits ? bits : mip->relevant_bits;
- }
- if ( mip->bin.bits < mip->relevant_bits )
- mip->have_bits = true;
- else
- mip->bin.bits = mip->relevant_bits;
- return true;
- }
- ///////////////////////////////////////////////////////////////////////////////
- bool AssignSockaddrMIP ( ManageIP_t *mip, cvp sockaddr, u16 port, int bits )
- {
- DASSERT(mip);
- ResetMIP(mip);
- if (!sockaddr)
- return false;
- const sockaddr_in46_t *sa = sockaddr;
- if ( sa->family == AF_INET )
- {
- mip->bin.ipvers = 4;
- mip->bin.bits = 32;
- mip->bin.ip4 = sa->in4.sin_addr.s_addr;
- mip->port = ntohs(sa->in4.sin_port);
- }
- else if ( sa->family == AF_INET6 )
- {
- mip->bin.ipvers = 6;
- mip->bin.bits = 128;
- memcpy(mip->bin.ip6_8,sa->in6.sin6_addr.s6_addr,sizeof(mip->bin.ip6_8));
- mip->port = ntohs(sa->in6.sin6_port);
- }
- mip->relevant_bits = mip->bin.bits;
- if ( bits >= 0 )
- {
- mip->have_bits = true;
- if ( mip->bin.bits > bits )
- mip->bin.bits = bits;
- }
- if ( !mip->port )
- mip->port = port;
- return true;
- }
- ///////////////////////////////////////////////////////////////////////////////
- bool ScanMIP ( ManageIP_t *mip, ccp addr )
- {
- DASSERT(mip);
- ResetMIP(mip);
- SplitIP_t sip;
- if (!SplitIP(&sip,addr))
- return false;
- if (strchr(sip.name,':'))
- {
- if ( inet_pton(AF_INET6,sip.name,mip->bin.ip6_32) != 1 )
- return false;
- mip->bin.ipvers = 6;
- mip->relevant_bits = 128;
- }
- else
- {
- struct in_addr inp;
- if (!dclib_aton(sip.name,&inp))
- return false;
- mip->bin.ipvers = 4;
- mip->bin.ip4 = inp.s_addr;
- mip->relevant_bits = 32;
- }
- mip->bin.bits = mip->relevant_bits;
- if ( sip.bits >= 0 )
- {
- mip->have_bits = true;
- if ( sip.bits < mip->relevant_bits )
- mip->bin.bits = sip.bits;
- }
- mip->port = sip.port;
- return true;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ManageIP_t GetSockNameMIP ( int sock )
- {
- ManageIP_t mip = {{0}};
- sockaddr_in46_t sa;
- socklen_t sa_len = sizeof(sa);
- if (!getsockname(sock,(sockaddr_t*)&sa,&sa_len))
- AssignSockaddrMIP(&mip,&sa,0,-1);
- return mip;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ManageIP_t GetPeerNameMIP ( int sock )
- {
- ManageIP_t mip = {{0}};
- sockaddr_in46_t sa;
- socklen_t sa_len = sizeof(sa);
- if (!getpeername(sock,(sockaddr_t*)&sa,&sa_len))
- AssignSockaddrMIP(&mip,&sa,0,-1);
- return mip;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ManageIP_t GetAddrInfoMIP ( ccp addr, int protocol, IpMode_t ipm )
- {
- ManageIP_t mip = {{0}};
- SplitIP_t sip;
- if (SplitIP(&sip,addr))
- {
- struct addrinfo hints
- = { .ai_family = AF_UNSPEC,
- .ai_protocol = protocol < 0 ? IPPROTO_TCP : protocol };
- struct addrinfo *result;
- if (!getaddrinfo(sip.name,0,&hints,&result))
- {
- struct addrinfo *ip4 = 0, *ip6 = 0;
- for ( struct addrinfo *rp = result; rp; rp = rp->ai_next)
- {
- if ( !ip4 && rp->ai_family == AF_INET )
- ip4 = rp;
- else if ( !ip6 && rp->ai_family == AF_INET6 )
- ip6 = rp;
- }
- switch (ipm)
- {
- case IPV4_ONLY: break; // nothing to do
- case IPV6_ONLY: ip4 = ip6; break;
- case IPV4_FIRST: if (!ip4) ip4 = ip6; break;
- case IPV6_FIRST: if (ip6) ip4 = ip6; break;
- }
- if (ip4)
- AssignSockaddrMIP(&mip,ip4->ai_addr,sip.port,sip.bits);
- freeaddrinfo(result);
- }
- }
- return mip;
- }
- ///////////////////////////////////////////////////////////////////////////////
- sockaddr_in46_t GetSockaddrMIP ( const ManageIP_t *mip )
- {
- DASSERT(mip);
- sockaddr_in46_t sa = { .family = 0 };
- if ( mip->bin.ipvers == 4 )
- {
- sa.in4.sin_family = AF_INET;
- sa.in4.sin_addr.s_addr = mip->bin.ip4;
- sa.in4.sin_port = htons(mip->port);
- }
- else if ( mip->bin.ipvers == 6 )
- {
- sa.in6.sin6_family = AF_INET6;
- sa.in6.sin6_port = htons(mip->port);
- memcpy(sa.in6.sin6_addr.s6_addr,mip->bin.ip6_8,sizeof(sa.in6.sin6_addr));
- }
- return sa;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ccp GetNameInfoMIP ( ManageIP_t *mip )
- {
- DASSERT(mip);
- if ( !mip->name && mip->bin.ipvers )
- {
- char host1[NI_MAXHOST+20], host2[NI_MAXHOST+20];
- sockaddr_in46_t sa = GetSockaddrMIP(mip);
- if (!getnameinfo( (sockaddr_t*)&sa,sizeof(sa), host1,sizeof(host1), 0,0, 0 ))
- {
- mip->name = STRDUP(host1);
- FreeString(mip->decoded_name);
- const uint stat = Domain2UTF8(host2,sizeof(host2),host1,-1);
- mip->decoded_name = stat && *host2 && strcmp(host1,host2) ? STRDUP(host2) : 0;
- }
- }
- return mip->name;
- }
- ///////////////////////////////////////////////////////////////////////////////
- void ApplyMaskMIP ( ManageIP_t *mip, int bits )
- {
- DASSERT(mip);
- if ( bits >= 0 && bits < mip->bin.bits )
- mip->bin.bits = bits;
- ApplyIPMask(&mip->bin);
- }
- ///////////////////////////////////////////////////////////////////////////////
- void MaskPrefixMIP ( ManageIP_t *mip )
- {
- DASSERT(mip);
- if ( mip->bin.ipvers == 4 || mip->bin.ip6_64[0] != 0ull )
- ApplyMaskMIP(mip,64);
- }
- ///////////////////////////////////////////////////////////////////////////////
- ccp PrintAddrMIP ( const ManageIP_t *mip, PrintModeIP_t pmode )
- {
- DASSERT(mip);
- ccp res;
- char buf[INET6_ADDRSTRLEN+1];
- switch (mip->bin.ipvers)
- {
- case 4:
- res = buf;
- if ( pmode & PMIP_0DOTS )
- snprintf(buf,sizeof(buf),"%u",ntohl(mip->bin.ip4));
- else if ( pmode & PMIP_1DOT )
- snprintf(buf,sizeof(buf), "%u.%u",
- mip->bin.ip4x.v8[0], ntohl(mip->bin.ip4)&0xffffff );
- else if ( pmode & PMIP_2DOTS )
- snprintf(buf,sizeof(buf), "%u.%u.%u",
- mip->bin.ip4x.v8[0], mip->bin.ip4x.v8[1], ntohs(mip->bin.ip4x.v16[1]) );
- else
- snprintf(buf,sizeof(buf), "%u.%u.%u.%u",
- mip->bin.ip4x.v8[0], mip->bin.ip4x.v8[1],
- mip->bin.ip4x.v8[2], mip->bin.ip4x.v8[3] );
- break;
- case 6:
- if ( pmode & PMIP_FULL_IPV6 )
- {
- snprintf(buf,sizeof(buf), "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
- ntohs(mip->bin.ip6.v16[0]),
- ntohs(mip->bin.ip6.v16[1]),
- ntohs(mip->bin.ip6.v16[2]),
- ntohs(mip->bin.ip6.v16[3]),
- ntohs(mip->bin.ip6.v16[4]),
- ntohs(mip->bin.ip6.v16[5]),
- ntohs(mip->bin.ip6.v16[6]),
- ntohs(mip->bin.ip6.v16[7]) );
- res = buf;
- }
- else
- res = inet_ntop(AF_INET6,mip->bin.ip6_32,buf,sizeof(buf));
- break;
- default:
- res = 0;
- }
- if (!res)
- return 0;
- char port[100];
- *port = 0;
- if ( mip->port && pmode & (PMIP_SERVICE|PMIP_PORT) )
- {
- if ( pmode & PMIP_SERVICE )
- {
- struct servent result_buf;
- struct servent *result;
- char buf[1000];
- const int stat = getservbyport_r(htons(mip->port),0,&result_buf,buf,sizeof(buf),&result);
- if ( !stat && result )
- snprintf(port,sizeof(port),":%s",result_buf.s_name);
- }
- if (!*port)
- snprintf(port,sizeof(port),":%u",mip->port);
- pmode |= PMIP_BRACKETS;
- }
- char bits[20];
- if (PrintBitsMIP(mip,pmode))
- {
- if ( mip->bin.ipvers == 4 && pmode & PMIP_MASK )
- {
- ipv4x_t mask;
- mask.ip4 = GetIP4Mask(mip->bin.bits);
- snprintf(bits,sizeof(bits),"/%d.%d.%d.%d",
- mask.v8[0], mask.v8[1], mask.v8[2], mask.v8[3] );
- }
- else
- snprintf(bits,sizeof(bits),"/%u",mip->bin.bits);
- }
- else
- *bits = 0;
- return pmode & PMIP_BRACKETS && mip->bin.ipvers == 6
- ? PrintCircBuf("[%s]%s%s",res,port,bits)
- : PrintCircBuf("%s%s%s",res,port,bits);
- }
- ///////////////////////////////////////////////////////////////////////////////
- ccp PrintVersAddrMIP ( const ManageIP_t *mip, PrintModeIP_t pmode )
- {
- DASSERT(mip);
- ccp res = PrintAddrMIP(mip,pmode);
- return res ? PrintCircBuf("IPv%u %s",mip->bin.ipvers,res) : 0;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- ccp GetSqlSetAddrMIP ( const ManageIP_t *mip, const NamesIP_t *names )
- {
- if (!mip)
- return 0;
- NamesIP_t nip;
- SetupNamesIP(&nip,names);
- if ( mip->bin.ipvers == 4 )
- {
- const ipv4_t mask = GetIP4Mask(mip->bin.bits);
- return PrintCircBuf("%s=4,%s=0,%s=0x%08x",
- nip.ipvers, nip.addr1,
- nip.addr2, ntohl( mip->bin.ip4 & mask ));
- }
- else if ( mip->bin.ipvers == 6 )
- {
- const ipv6_t mask = GetIP6Mask(mip->bin.bits);
- return PrintCircBuf("%s=6,%s=0x%llx,%s=0x%llx",
- nip.ipvers,
- nip.addr1, ntoh64( mip->bin.ip6_64[0] & mask.v64[0] ),
- nip.addr2, ntoh64( mip->bin.ip6_64[1] & mask.v64[1] ));
- }
- return 0;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ccp GetSqlSetMaskMIP ( const ManageIP_t *mip, const NamesIP_t *names )
- {
- if (!mip)
- return 0;
- NamesIP_t nip;
- SetupNamesIP(&nip,names);
- if ( mip->bin.ipvers == 4 )
- {
- const ipv4_t mask = GetIP4Mask(mip->bin.bits);
- return PrintCircBuf("%s=4,%s=0,%s=0x%08x,%s=0,%s=0x%08x",
- nip.ipvers, nip.addr1,
- nip.addr2, ntohl( mip->bin.ip4 & mask ),
- nip.mask1, nip.mask2, ntohl(mask));
- }
- else if ( mip->bin.ipvers == 6 )
- {
- const ipv6_t mask = GetIP6Mask(mip->bin.bits);
- return PrintCircBuf("%s=6,%s=0x%llx,%s=0x%llx,%s=0x%llx,%s=0x%llx",
- nip.ipvers,
- nip.addr1, ntoh64( mip->bin.ip6_64[0] & mask.v64[0] ),
- nip.addr2, ntoh64( mip->bin.ip6_64[1] & mask.v64[1] ),
- nip.mask1, ntoh64(mask.v64[0]),
- nip.mask2, ntoh64(mask.v64[1]) );
- }
- return 0;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ccp GetSqlSetBinMIP ( const ManageIP_t *mip, const NamesIP_t *names )
- {
- if (!mip)
- return 0;
- NamesIP_t nip;
- SetupNamesIP(&nip,names);
- return PrintCircBuf("%s=unhex('%02x%02x%016llx%016llx')",
- nip.binaddr, mip->bin.ipvers, mip->bin.bits,
- ntoh64(mip->bin.ip6_64[0]), ntoh64(mip->bin.ip6_64[0]) );
- }
- ///////////////////////////////////////////////////////////////////////////////
- ccp GetSqlCondAddrMIP ( const ManageIP_t *mip, const NamesIP_t *names )
- {
- if (!mip)
- return 0;
- NamesIP_t nip;
- SetupNamesIP(&nip,names);
- if ( mip->bin.ipvers == 4 )
- return PrintCircBuf("%s=4 && %s=0x%08x",
- nip.ipvers, nip.addr2, ntohl(mip->bin.ip4) );
- else if ( mip->bin.ipvers == 6 )
- return PrintCircBuf("%s=6 && %s=0x%llx && %s=0x%llx",
- nip.ipvers,
- nip.addr1, ntoh64(mip->bin.ip6_64[0]),
- nip.addr2, ntoh64(mip->bin.ip6_64[1]) );
- return 0;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ccp GetSqlCondMaskMIP ( const ManageIP_t *mip, const NamesIP_t *names )
- {
- if (!mip)
- return 0;
- NamesIP_t nip;
- SetupNamesIP(&nip,names);
- if ( mip->bin.ipvers == 4 )
- return PrintCircBuf("%s=4 && %s=(%s&0x%08x)",
- nip.ipvers,
- nip.addr2, nip.mask2, ntohl(mip->bin.ip4) );
- else if ( mip->bin.ipvers == 6 )
- return PrintCircBuf("%s=6 && %s=(%s&0x%llx) && %s=(%s&0x%llx)",
- nip.ipvers,
- nip.addr1, nip.mask1, ntoh64(mip->bin.ip6_64[0]),
- nip.addr2, nip.mask2, ntoh64(mip->bin.ip6_64[1]) );
- return 0;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ccp GetSqlCondBinMaskMIP ( const ManageIP_t *mip, const NamesIP_t *names )
- {
- if (!mip)
- return 0;
- NamesIP_t nip;
- SetupNamesIP(&nip,names);
- if ( mip->bin.ipvers == 4 )
- return PrintCircBuf("compare_binaddr(%s,4,0,0x%08x,%s,%s)",
- nip.binaddr, ntohl(mip->bin.ip4),
- nip.mask1, nip.mask2 );
- else if ( mip->bin.ipvers == 6 )
- return PrintCircBuf("compare_binaddr(%s,6,0x%llx,0x%llx,%s,%s)",
- nip.binaddr,
- ntoh64(mip->bin.ip6_64[0]), ntoh64(mip->bin.ip6_64[1]),
- nip.mask1, nip.mask2 );
- return 0;
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// struct ResolveIP_t ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- void ResetRIP ( ResolveIP_t *rip )
- {
- if (rip)
- {
- ResetMIP(&rip->mip4);
- ResetMIP(&rip->mip6);
- memset(rip,0,sizeof(*rip));
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- void ClearNamesRIP ( ResolveIP_t *rip )
- {
- if (rip)
- {
- ClearNameMIP(&rip->mip4);
- ClearNameMIP(&rip->mip6);
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- int SetupListRIP ( ResolveIP_t *rip )
- {
- DASSERT(rip);
- memset(rip->mip_list,0,sizeof(rip->mip_list));
- ManageIP_t **mp = rip->mip_list;
- switch (rip->ip_mode)
- {
- case IPV6_FIRST:
- if (rip->mip6.bin.ipvers)
- *mp++ = &rip->mip6;
- // fall though
- case IPV4_ONLY:
- if (rip->mip4.bin.ipvers)
- *mp++ = &rip->mip4;
- break;
- case IPV4_FIRST:
- if (rip->mip4.bin.ipvers)
- *mp++ = &rip->mip4;
- // fall though
- case IPV6_ONLY:
- if (rip->mip6.bin.ipvers)
- *mp++ = &rip->mip6;
- break;
- }
- return mp - rip->mip_list;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ResolveIP_t GetCopyRIP ( const ResolveIP_t *rip )
- {
- ResolveIP_t res;
- if (rip)
- {
- res.ip_mode = rip->ip_mode;
- res.mip4 = GetCopyMIP(&rip->mip4);
- res.mip6 = GetCopyMIP(&rip->mip6);
- SetupListRIP(&res);
- }
- else
- memset(&res,0,sizeof(res));
- return res;
- }
- ///////////////////////////////////////////////////////////////////////////////
- void AssignRIP ( ResolveIP_t *dest, const ResolveIP_t *src )
- {
- if (dest)
- {
- ClearNamesRIP(dest);
- *dest = GetCopyRIP(src);
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- int ScanRIP
- (
- // return 0..2 = number of records
- ResolveIP_t *rip, // valid data, ResetRIP()
- ccp addr, // address to scan
- int protocol, // protocol to use: 0=all, -1=default (IPPROTO_TCP at the moment)
- IpMode_t ip_mode, // IPv4 and/or IPV6, order of 'mip_list'
- bool get_names // true: call GetNameInfoMIP()
- )
- {
- DASSERT(rip);
- ResetRIP(rip);
- SplitIP_t sip;
- if (!SplitIP(&sip,addr))
- return 0;
- NormalizeNameSIP(&sip);
- rip->ip_mode = ip_mode;
- struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM };
- struct addrinfo *result;
- char aname[300];
- Domain2ASCII(aname,sizeof(aname),sip.name,-1);
- if (!getaddrinfo(aname,0,&hints,&result))
- {
- struct addrinfo *ip4 = 0, *ip6 = 0;
- for ( struct addrinfo *rp = result; rp; rp = rp->ai_next)
- {
- if ( !ip4 && rp->ai_family == AF_INET )
- ip4 = rp;
- else if ( !ip6 && rp->ai_family == AF_INET6 )
- ip6 = rp;
- }
- if (ip4)
- AssignSockaddrMIP(&rip->mip4,ip4->ai_addr,sip.port,sip.bits);
- if (ip6)
- AssignSockaddrMIP(&rip->mip6,ip6->ai_addr,sip.port,sip.bits);
- if (get_names)
- {
- GetNameInfoMIP(&rip->mip4);
- GetNameInfoMIP(&rip->mip6);
- }
- freeaddrinfo(result);
- }
- return SetupListRIP(rip);
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- #if 0
- void DumpRIP ( FILE *f, int indent, const ResolveIP_t *rip )
- {
- if ( !f || !rip )
- return;
- indent = NormalizeIndent(indent);
- }
- #endif
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// struct AllowIP4_t ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- const KeywordTab_t AllowIP4KeyTable[] =
- {
- { 0, "0", 0, 1 },
- { ALLOW_MODE_DENY, "DENY", 0, 1 },
- { ALLOW_MODE_ALLOW, "ALLOW", 0, 0 },
- { ALLOW_MODE_AKEY, "AKEY", "JACC", 0 },
- { ALLOW_MODE_LOCAL, "LOCAL", 0, 0 },
- { ALLOW_MODE_LAN, "LAN", 0, 0 },
- { ALLOW_MODE_EXTERN, "EXTERN", 0, 0 },
- { ALLOW_MODE_PUBLIC, "PUBLIC", 0, 0 },
- { ALLOW_MODE_USER, "USER", 0, 0 },
- { ALLOW_MODE_MOD, "MOD", "MODERATOR", 0 },
- { ALLOW_MODE_ADMIN, "ADMIN", "ADMINISTRATOR",0 },
- { ALLOW_MODE_DEVELOP, "DEVELOP", "DEVELOPER", 0 },
- { ALLOW_MODE_LOG, "LOG", 0, 0 },
- { ALLOW_MODE_VERBOSE, "VERBOSE", 0, 0 },
- { ALLOW_RELEASE, "RELEASE", 0, 0 },
- { ALLOW_DEBUG, "DEBUG", 0, 0 },
- { ALLOW_MODE_NOT, "NOT", 0, 0 },
- { ALLOW_MODE_SET, "SET", 0, ALLOW_MODE__OP },
- { ALLOW_MODE_AND, "AND", 0, ALLOW_MODE__OP },
- { 0, "OR", 0, ALLOW_MODE__OP },
- { ALLOW_MODE_CONTINUE, "CONTINUE", 0, 0 },
- {0,0,0,0}
- };
- ///////////////////////////////////////////////////////////////////////////////
- void InitializeAllowIP4 ( AllowIP4_t *ai )
- {
- DASSERT(ai);
- memset(ai,0,sizeof(*ai));
- ai->ref_counter = 1;
- ai->fallback_mode = ALLOW_MODE_DENY;
- ai->allow_mode = ALLOW_MODE_ALLOW|ALLOW_MODE_AKEY;
- }
- ///////////////////////////////////////////////////////////////////////////////
- void ResetAllowIP4 ( AllowIP4_t *ai )
- {
- if (ai)
- {
- FREE(ai->list);
- ai->list = 0;
- ai->used = ai->size = 0;
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- void ClearAllowIP4 ( AllowIP4_t *ai )
- {
- if (ai)
- {
- FREE(ai->list);
- InitializeAllowIP4(ai);
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- AllowIP4_t * NewReferenceAllowIP4 ( AllowIP4_t *ai )
- {
- if (ai)
- ai->ref_counter++;
- else
- {
- ai = MALLOC(sizeof(*ai));
- DASSERT(ai);
- InitializeAllowIP4(ai);
- }
- return ai;
- }
- ///////////////////////////////////////////////////////////////////////////////
- AllowIP4_t * DeleteReferenceAllowIP4 ( AllowIP4_t *ai )
- {
- if ( ai && !--ai->ref_counter )
- {
- ResetAllowIP4(ai);
- FREE(ai);
- }
- return 0;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- enumError ScanLineAllowIP4
- (
- AllowIP4_t *ai, // valid structure; new elements are appended
- mem_t line, // single line to analyse
- const KeywordTab_t *tab // NULL or keyword table.
- // If NULL, a local table with keywords 0 DENY
- // ALLOW SET REMOVE AND OR and CONTINUE is used.
- )
- {
- if ( !line.ptr || !line.len )
- return ERR_OK;
- ccp ptr = line.ptr;
- ccp end = ptr + line.len;
- //--- find first character
- while ( ptr < end && *(uchar*)ptr <= ' ' )
- ptr++;
- if ( ptr == end || *ptr == '#' )
- return ERR_OK;
- NetworkHost_t host;
- ResolveHostMem(&host,true,BehindMem(line,ptr),0,false,false);
- if (!host.ip4_valid)
- return ERR_ERROR;
- line = host.not_scanned;
- u32 mask = M1(mask);
- if ( line.len && *line.ptr == '/' )
- line = ScanNetworkMaskMem(&mask,line);
- //--- scan options
- if (!tab)
- tab = AllowIP4KeyTable;
- char arg[1000];
- StringCopySMem(arg,sizeof(arg),line); // to be NULL terminated
- s64 res = ScanKeywordList(arg,tab,0,true,0,0,"AllowIP4",ERR_SYNTAX);
- if ( res == M1(res) )
- return ERR_SYNTAX;
- if ( res & ALLOW_MODE_NOT )
- res = res ^ ALLOW_MODE__MASK;
- #if defined(DEBUG) && DEBUG > 0 || defined(IS_DEVELOP) && IS_DEVELOP > 0
- if ( res & ALLOW_RELEASE )
- return ERR_OK;
- #else
- if ( res & ALLOW_DEBUG )
- return ERR_OK;
- #endif
- //--- add item
- if ( ai->used == ai->size )
- {
- ai->size = 11*ai->size/10 + 10;
- ai->list = REALLOC(ai->list,ai->size*sizeof(*ai->list));
- }
- DASSERT( ai->used < ai->size );
- DASSERT( ai->list );
- AllowIP4Item_t *it = ai->list + ai->used++;
- //memset(it,0,sizeof(*it));
- it->addr = host.ip4 & mask;
- it->mask = mask;
- it->mode = res;
- it->count = 0;
- return ERR_OK;
- }
- ///////////////////////////////////////////////////////////////////////////////
- enumError ScanFileAllowIP4
- (
- AllowIP4_t *ai, // valid structure; new elements are appended
- ccp fname, // ffilename of the source
- FileMode_t fmode, // flags for OpenFile()
- const KeywordTab_t *tab // NULL or keyword table -> see ScanLineAllowIP4()
- )
- {
- File_t F;
- enumError err = OpenFile(&F,true,fname,fmode,0,0);
- if (err)
- return err;
- char iobuf[10000];
- while (fgets(iobuf,sizeof(iobuf)-1,F.f))
- {
- err = ScanLineAllowIP4(ai,MemByString(iobuf),tab);
- if (err)
- break;
- }
- CloseFile(&F,0);
- return err;
- }
- ///////////////////////////////////////////////////////////////////////////////
- void ResetCountersAllowIP4
- (
- AllowIP4_t *ai // NULL or dest for addition
- )
- {
- if (ai)
- {
- uint i;
- AllowIP4Item_t *p = ai->list;
- for ( i = 0; i < ai->used; i++, p++ )
- p->count = 0;
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- void AddCountersAllowIP4
- (
- AllowIP4_t *dest, // NULL or dest for addition
- const AllowIP4_t *src // NULL or source for addition
- )
- {
- if ( dest && dest->used && src && src->used )
- {
- uint is;
- const AllowIP4Item_t *ps = src->list;
- for ( is = 0; is < src->used; is++, ps++ )
- {
- uint id;
- AllowIP4Item_t *pd = dest->list;
- for ( id = 0; id < dest->used; id++, pd++ )
- if ( pd->addr == ps->addr
- && pd->mask == ps->mask
- && pd->mode == ps->mode
- )
- {
- pd->count += ps->count;
- break;
- }
- }
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- static uint print_mode_helper
- ( char *buf, uint bufsize, const KeywordTab_t *keytab, u64 mode )
- {
- ASSERT(buf);
- ASSERT(bufsize>1);
- char *dest = buf, *end = buf + bufsize-1;
- if (keytab)
- {
- mode &= ~(ALLOW_MODE_SET|ALLOW_MODE_AND);
- for ( ; mode && keytab->name1; keytab++ )
- {
- if ( keytab->id & mode )
- {
- dest = StringCat2E(dest,end,keytab->name1," ");
- mode &= ~keytab->id;
- }
- }
- }
- *dest = 0;
- return dest-buf;
- }
- //-----------------------------------------------------------------------------
- void DumpAllowIP4
- (
- FILE *f, // NULL or output file
- int indent, // indention
- const AllowIP4_t *ai, // NULL or source
- const KeywordTab_t *keytab, // NULL or key table for output
- ccp title, // not NULL: Add title
- bool print_tab_head // true: add table headings and separators
- )
- {
- if ( !f || !ai )
- return;
- char buf[200];
- uint i, fw_mode = 5, fw_settings = 8;
- for ( i = 0; i < ai->used; i++ )
- {
- const AllowIP4Item_t *it = ai->list + i;
- uint len = snprintf(buf,sizeof(buf),"%llx",it->mode);
- if ( fw_mode < len )
- fw_mode = len;
- len = print_mode_helper(buf,sizeof(buf),keytab,it->mode);
- if ( fw_settings < len )
- fw_settings = len;
- }
- indent = NormalizeIndent(indent);
- fprintf(f, "%*sAllowIP4[%s]: %u reference%s, %u/%u elements,"
- " fallback:%llx, allow:%llx\n",
- indent,"", title ? title : "",
- ai->ref_counter, ai->ref_counter == 1 ? "" : "s",
- ai->used, ai->size,
- ai->fallback_mode, ai->allow_mode );
- const uint seplen = 52 + fw_mode + fw_settings;
- if (print_tab_head)
- fprintf(f,"\n"
- "%*s counter ipv4 address ipv4/netmask > %-*s"
- " settings\n%*s%.*s\n",
- indent,"", fw_mode+4, "operation",
- indent,"", seplen, Minus300 );
- for ( i = 0; i < ai->used; i++ )
- {
- const AllowIP4Item_t *it = ai->list + i;
- print_mode_helper(buf,sizeof(buf),keytab,it->mode);
- fprintf(f, "%*s%8s %-15s %08x/%08x > %s %*llx %s\n",
- indent, "",
- PrintNumberU7(0,0,it->count,DC_SFORM_ALIGN|DC_SFORM_DASH),
- PrintIP4(0,0,it->addr,-1),
- it->addr, it->mask,
- it->mode & ALLOW_MODE_SET ? "SET"
- : it->mode & ALLOW_MODE_AND ? "AND" : "OR ",
- fw_mode, it->mode, *buf ? buf : "-" );
- }
- if (print_tab_head)
- fprintf(f,"%*s%.*s\n", indent,"", seplen, Minus300 );
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- u64 GetAllowIP4ByAddr ( const AllowIP4_t *ai, u32 addr, u64 if_not_found )
- {
- DASSERT(ai);
- bool found = false;
- uint i;
- u64 res = 0;
- AllowIP4Item_t *it = (AllowIP4Item_t*)ai->list;
- for ( i = 0; i < ai->used; i++, it++ )
- {
- if ( ( addr & it->mask ) == it->addr )
- {
- it->count++;
- found = true;
- if ( it->mode & ALLOW_MODE_SET )
- res = it->mode;
- else if ( it->mode & ALLOW_MODE_AND )
- res &= it->mode;
- else
- res |= it->mode;
- if ( !(it->mode & ALLOW_MODE_CONTINUE) )
- break;
- }
- }
- return found ? res & ALLOW_MODE__MASK : if_not_found;
- }
- ///////////////////////////////////////////////////////////////////////////////
- u64 GetAllowIP4ByName ( const AllowIP4_t *ai, mem_t name, u64 if_not_found )
- {
- DASSERT(ai);
- NetworkHost_t host;
- ResolveHostMem(&host,true,name,0,false,false);
- return host.ip4_valid
- ? GetAllowIP4ByAddr(ai,host.ip4,if_not_found)
- : if_not_found;
- }
- ///////////////////////////////////////////////////////////////////////////////
- u64 GetAutoAllowIP4ByAddr ( const AllowIP4_t *ai, u32 addr )
- {
- if (!ai)
- return ALLOW_MODE_ALLOW;
- const u64 res = GetAllowIP4ByAddr(ai,addr,M1(res));
- return IS_M1(res) ? ai->fallback_mode : res & ALLOW_MODE__MASK;
- }
- ///////////////////////////////////////////////////////////////////////////////
- u64 GetAutoAllowIP4ByName ( const AllowIP4_t *ai, mem_t name )
- {
- if (!ai)
- return ALLOW_MODE_ALLOW;
- NetworkHost_t host;
- ResolveHostMem(&host,true,name,0,false,false);
- return host.ip4_valid
- ? GetAllowIP4ByAddr(ai,host.ip4,ai->fallback_mode)
- : ai->fallback_mode;
- }
- ///////////////////////////////////////////////////////////////////////////////
- u64 GetAutoAllowIP4BySock ( const AllowIP4_t *ai, int sock )
- {
- if (!ai)
- return ALLOW_MODE_ALLOW;
- struct sockaddr_in sa;
- socklen_t sa_len = sizeof(sa);
- if ( getpeername(sock,(struct sockaddr*)&sa,&sa_len) || sa.sin_family != AF_INET )
- return ai->fallback_mode;
- return GetAutoAllowIP4ByAddr(ai,ntohl(sa.sin_addr.s_addr));
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- void SaveCurrentStateAllowIP4
- (
- FILE *f, // output file
- ccp section, // not NULL and not empty: create own section
- ccp name_prefix, // NULL or prefix of name
- uint tab_pos, // tab pos of '='
- const AllowIP4_t *ai // valid struct
- )
- {
- DASSERT(f);
- DASSERT(ai);
- if ( section && *section )
- fprintf(f,"\n#%.50s\n[%s]\n\n",Minus300,section);
- if (!name_prefix)
- name_prefix = EmptyString;
- const int base = 8*tab_pos + 7 - strlen(name_prefix);
- fprintf(f,
- "%s" "fallback%.*s= %#llx\n"
- "%s" "allow%.*s= %#llx\n"
- "%s" "n-rules%.*s= %u\n"
- ,name_prefix, (base-8)/8, Tabs20, ai->fallback_mode
- ,name_prefix, (base-5)/8, Tabs20, ai->allow_mode
- ,name_prefix, (base-7)/8, Tabs20, ai->used
- );
- uint i;
- char name[30];
- for ( i = 0; i < ai->used; i++ )
- {
- const AllowIP4Item_t *it = ai->list + i;
- const uint len = snprintf(name,sizeof(name),"rule-%u",i);
- fprintf(f, "%s%s%.*s= 0x%08x,0x%08x,%#llx,%llu\n",
- name_prefix, name, (base-len)/8, Tabs20,
- it->addr, it->mask, it->mode, it->count );
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- bool ScanAllowIP4Item
- (
- // return true on success; counter is optional
- AllowIP4Item_t *it, // store data here, cleared first
- ccp line // NULL or line to scan
- )
- {
- DASSERT(it);
- memset(it,0,sizeof(*it));
- if (line)
- {
- char *end;
- it->addr = str2ul(line,&end,10);
- if ( end > line )
- {
- line = SkipControls1(end,',');
- it->mask = str2ul(line,&end,10);
- if ( end > line )
- {
- line = SkipControls1(end,',');
- it->mode = str2ull(line,&end,10);
- if ( end > line )
- {
- line = SkipControls1(end,',');
- it->count = str2ull(line,0,10); // optional -> no error check
- return true;
- }
- }
- }
- }
- return false;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- void RestoreStateAllowIP4
- (
- RestoreState_t *rs, // info data, can be modified (cleaned after call)
- cvp user_table // pointer provided by RestoreStateTab_t[]
- )
- {
- DASSERT(rs);
- if (user_table)
- RestoreStateAllowIP4Ex(rs,(AllowIP4_t*)user_table,0);
- }
- ///////////////////////////////////////////////////////////////////////////////
- void RestoreStateAllowIP4Ex
- (
- RestoreState_t *rs, // info data, modified
- AllowIP4_t *ai, // valid struct
- ccp name_prefix // NULL or prefix of name
- )
- {
- DASSERT(ai);
- DASSERT(rs);
- ClearAllowIP4(ai);
- if (!name_prefix)
- name_prefix = EmptyString;
- char name[200]; // name buf
- snprintf(name,sizeof(name),"%sfallback",name_prefix);
- ai->fallback_mode = GetParamFieldU64(rs,name,ai->fallback_mode);
- snprintf(name,sizeof(name),"%sallow",name_prefix);
- ai->allow_mode = GetParamFieldU64(rs,name,ai->allow_mode);
- snprintf(name,sizeof(name),"%sn-rules",name_prefix);
- const uint n_rules = GetParamFieldUINT(rs,name,0);
- uint i;
- for ( i = 0; i < n_rules; i++ )
- {
- snprintf(name,sizeof(name),"%srule-%u",name_prefix,i);
- ParamFieldItem_t *pfi = GetParamField(rs,name);
- AllowIP4Item_t ait;
- if ( pfi && ScanAllowIP4Item(&ait,(ccp)pfi->data) )
- {
- if ( ai->used == ai->size )
- {
- ai->size = 11*ai->size/10 + 10;
- ai->list = REALLOC(ai->list,ai->size*sizeof(*ai->list));
- }
- DASSERT( ai->used < ai->size );
- DASSERT( ai->list );
- ai->list[ai->used++] = ait;
- }
- }
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// TCP + UDP connections ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- int ConnectByHost
- (
- NetworkHost_t *host, // valid pointer to NetworkHost_t
- int type, // AF_INET type, e.g. SOCK_STREAM, SOCK_DGRAM
- int protocol, // AF_INET protocol, e.g. IPPROTO_TCP, IPPROTO_UDP
- bool silent // true: suppress error messages
- )
- {
- DASSERT(host);
- int sock = socket(AF_INET,type,protocol);
- if ( sock == -1 )
- {
- if (!silent)
- ERROR1(ERR_CANT_CONNECT,
- "Can't create socket: %s\n",
- GetHostName(host));
- return -1;
- }
- if (connect(sock,(struct sockaddr *)&host->sa,sizeof(host->sa)))
- {
- if (!silent)
- ERROR1(ERR_CANT_CONNECT,
- "Can't connect to %s:%d\n",
- GetHostName(host), host->port );
- close(sock);
- return -1;
- }
- return sock;
- }
- ///////////////////////////////////////////////////////////////////////////////
- int ConnectByHostTCP
- (
- NetworkHost_t *host, // valid pointer to NetworkHost_t
- bool silent // true: suppress error messages
- )
- {
- DASSERT(host);
- return ConnectByHost(host,SOCK_STREAM,IPPROTO_TCP,silent);
- }
- ///////////////////////////////////////////////////////////////////////////////
- int ConnectTCP
- (
- ccp addr, // optional service + server + optional host
- // e.g.: "service://host:port/....."
- int default_port, // default port
- bool silent // true: suppress error messages
- )
- {
- Setup_ConnectTCP_Hook(false);
- ccp unix_path = CheckUnixSocketPath(addr,0);
- if (unix_path)
- return ConnectUnixTCP(unix_path,silent);
- if (!strncasecmp(addr,"tcp:",4))
- addr += 4;
- NetworkHost_t host;
- int sock = -1;
- if (ResolveHost(&host,true,addr,default_port,false,true))
- sock = ConnectByHost(&host,SOCK_STREAM,IPPROTO_TCP,silent);
- ResetHost(&host);
- return sock;
- }
- ///////////////////////////////////////////////////////////////////////////////
- void Setup_ConnectTCP_Hook ( bool force )
- {
- if ( force || !ConnectTCP_Hook )
- ConnectTCP_Hook = ConnectTCP;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- int ConnectByHostUDP
- (
- NetworkHost_t *host, // valid pointer to NetworkHost_t
- bool silent // true: suppress error messages
- )
- {
- DASSERT(host);
- return ConnectByHost(host,SOCK_DGRAM,IPPROTO_UDP,silent);
- }
- ///////////////////////////////////////////////////////////////////////////////
- int ConnectUDP
- (
- ccp name, // optional service + server + optional host
- // e.g.: "service://host:port/....."
- int default_host, // default host
- bool silent // true: suppress error messages
- )
- {
- NetworkHost_t host;
- int sock = -1;
- if (ResolveHost(&host,true,name,default_host,false,true))
- sock = ConnectByHost(&host,SOCK_DGRAM,IPPROTO_UDP,silent);
- ResetHost(&host);
- return sock;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- int WillReceiveNotBlock
- (
- // returns: -1:error, 0:may block, 1:will not block
- int fd, // file handle of source
- uint msec // timeout: 0:no timeout, >0: milliseconds
- )
- {
- fd_set read_set;
- FD_ZERO(&read_set);
- FD_SET(fd,&read_set);
- struct timeval timeout;
- timeout.tv_sec = msec/1000;
- timeout.tv_usec = (msec%1000) * 1000;
- errno = 0;
- const int stat = select(fd+1,&read_set,0,0,&timeout);
- return stat < 0 ? stat : stat > 0 && FD_ISSET(fd,&read_set);
- }
- ///////////////////////////////////////////////////////////////////////////////
- ssize_t ReceiveTimeout
- (
- // returns: <0: on error, 0:timeout, >0: bytes read
- int fd, // file handle of source
- void *buf, // valid pointer to buffer
- uint size, // size to receive
- int flags, // flags for recv()
- int msec // timeout: -1:unlimited, 0:no timeout, >0: milliseconds
- )
- {
- if ( fd == -1 )
- return -1;
- if ( !buf || !size )
- return 0;
- if ( msec >= 0 )
- {
- fd_set read_set;
- FD_ZERO(&read_set);
- FD_SET(fd,&read_set);
- struct timeval timeout;
- timeout.tv_sec = msec/1000;
- timeout.tv_usec = (msec%1000) * 1000;
- errno = 0;
- const int stat = select(fd+1,&read_set,0,0,&timeout);
- if ( stat <= 0 )
- return stat;
- }
- return recv(fd,buf,size,flags);
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- int WillSendNotBlock
- (
- // returns: -1:error, 0:may block, 1:will not block
- int fd, // file handle of source
- uint msec // timeout: 0:no timeout, >0: milliseconds
- )
- {
- fd_set write_set;
- FD_ZERO(&write_set);
- FD_SET(fd,&write_set);
- struct timeval timeout; // kein Warten
- timeout.tv_sec = msec/1000;
- timeout.tv_usec = (msec%1000) * 1000;
- errno = 0;
- const int stat = select(fd+1,0,&write_set,0,&timeout);
- return stat < 0 ? stat : stat > 0 && FD_ISSET(fd,&write_set);
- }
- ///////////////////////////////////////////////////////////////////////////////
- ssize_t SendTimeout
- (
- // returns: <0: on error, 0:timeout, >0: bytes written
- int fd, // file hande of destination
- const void *data, // valid pointer to data
- uint size, // size to receive
- int flags, // flags for send()
- int msec, // total timeout: -1:unlimited, 0:no timeout, >0: milliseconds
- bool all // true: send all data until done, total timeout or error
- )
- {
- if ( fd == -1 )
- return -1;
- if ( !data || !size )
- return 0;
- //--- send loop for complete sending
- if (all)
- {
- uint max_time = msec < 0 ? 0 : GetTimerMSec() + msec;
- ssize_t total = 0;
- while (size)
- {
- ssize_t stat = SendTimeout(fd,data,size,flags,msec,false);
- if ( stat < 0 )
- return stat;
- data = (u8*)data + stat;
- size -= stat;
- total += stat;
- if ( msec >= 0 )
- {
- msec = max_time - GetTimerMSec();
- if ( msec < 0 )
- break;
- }
- }
- return total;
- }
- //--- send, single try
- if ( msec >= 0 )
- {
- fd_set write_set;
- FD_ZERO(&write_set);
- FD_SET(fd,&write_set);
- struct timeval timeout;
- timeout.tv_sec = msec/1000;
- timeout.tv_usec = (msec%1000) * 1000;
- errno = 0;
- const int stat = select(fd+1,0,&write_set,0,&timeout);
- if ( stat <= 0 )
- return stat;
- }
- return send(fd,data,size,flags);
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// IP interface: check sums ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- u16 CalcChecksumIP4
- (
- const void *data, // ip4 header
- // make sure, that the checksum member is NULL
- uint size // size of ip4 header
- )
- {
- // http://en.wikipedia.org/wiki/IPv4_header_checksum
- DASSERT(data);
- const u16 *ptr = (u16*)data;
- u32 csum = 0;
- while ( size > 1 )
- {
- csum += ntohs(*ptr++);
- size -= 2;
- }
- if (size)
- csum += *(u8*)ptr << 8;
- return ~( ( csum >> 16 ) + ( csum & 0xffff ));
- }
- ///////////////////////////////////////////////////////////////////////////////
- u16 CalcChecksumUDP
- (
- const ip4_head_t *ip4, // IP4 header
- const udp_head_t *udp, // UDP header
- const void *data // UDP data, size is 'udp->data_len'
- )
- {
- DASSERT(ip4);
- DASSERT(udp);
- DASSERT( data || !udp->data_len );
- int dlen = ntohs(udp->data_len);
- u32 csum = ntohs(((u16*)&ip4->ip_src)[0])
- + ntohs(((u16*)&ip4->ip_src)[1])
- + ntohs(((u16*)&ip4->ip_dest)[0])
- + ntohs(((u16*)&ip4->ip_dest)[1])
- + ip4->protocol
- + ntohs(udp->port_src)
- + ntohs(udp->port_dest)
- + 2*dlen;
- dlen -= 8;
- const u16 *ptr = (u16*)data;
- while ( dlen > 1 )
- {
- csum += ntohs(*ptr++);
- dlen -= 2;
- }
- if ( dlen > 0 )
- csum += *(u8*)ptr << 8;
- while ( csum >= 0x10000 )
- csum = (u32)((u16*)&csum)[0] + (u32)((u16*)&csum)[1];
- return csum == 0xffff ? 0xffff : htons(~csum);
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// UNIX sockets ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- enumError SendUnixUDP
- (
- ccp path1, // NULL or part #1 of path
- ccp path2, // NULL or part #2 of path
- bool silent, // suppress all error messages
- cvp data, // data to send
- uint size // size of 'data'
- )
- {
- if ( !data || !size )
- return ERR_NOTHING_TO_DO;
- char pathbuf[PATH_MAX];
- ccp path = PathCatPP(pathbuf,sizeof(pathbuf),path1,path2);
- PRINT("SendUnixUDP(%s)\n",path);
- static int sock = -1;
- if ( sock == -1 )
- {
- sock = socket(AF_UNIX,SOCK_STREAM|SOCK_CLOEXEC,0);
- if ( sock == -1 )
- {
- if (!silent)
- ERROR1(ERR_CANT_CREATE,
- "Can't create UNIX stream socket: %s\n",path);
- return ERR_CANT_CREATE;
- }
- }
- struct sockaddr_un sa;
- memset(&sa,0,sizeof(sa));
- sa.sun_family = AF_UNIX;
- StringCopyS(sa.sun_path,sizeof(sa.sun_path),path);
- if ( sendto(sock,data,size,0,(struct sockaddr*)&sa,sizeof(sa)) < 0 )
- {
- if (!silent)
- ERROR1(ERR_WRITE_FAILED,
- "Can't send %u bytes to UNIX stream socket: %s\n",
- size, path );
- return ERR_WRITE_FAILED;
- }
- return ERR_OK;
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// Transfer Statistics ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- TransferStats_t * Add2TransferStats
- (
- // return dest
- // calculate: dest += src
- TransferStats_t *dest, // NULL or destination and first source
- const TransferStats_t *src // NULL or second source
- )
- {
- if ( dest && src )
- {
- dest->conn_count += src->conn_count;
- dest->recv_count += src->recv_count;
- dest->recv_size += src->recv_size;
- dest->send_count += src->send_count;
- dest->send_size += src->send_size;
- }
- return dest;
- }
- ///////////////////////////////////////////////////////////////////////////////
- TransferStats_t * Sub2TransferStats
- (
- // return dest
- // calculate: dest -= src
- TransferStats_t *dest, // NULL or destination and first source
- const TransferStats_t *src // NULL or second source
- )
- {
- if ( dest && src )
- {
- dest->conn_count -= src->conn_count;
- dest->recv_count -= src->recv_count;
- dest->recv_size -= src->recv_size;
- dest->send_count -= src->send_count;
- dest->send_size -= src->send_size;
- }
- return dest;
- }
- ///////////////////////////////////////////////////////////////////////////////
- TransferStats_t * Add3TransferStats
- (
- // return dest
- // calculate: dest = src1 + src2
- TransferStats_t *dest, // NULL or destination (maybe same as source)
- const TransferStats_t *src1, // NULL or first source
- const TransferStats_t *src2 // NULL or second source
- )
- {
- if (dest)
- {
- if (!src1)
- {
- if (src2)
- memcpy(dest,src2,sizeof(*dest));
- else
- memset(dest,0,sizeof(*dest));
- }
- else if (!src2)
- {
- DASSERT(src1);
- memcpy(dest,src1,sizeof(*dest));
- }
- else
- {
- DASSERT(src1);
- DASSERT(src2);
- dest->conn_count = src1->conn_count + src2->conn_count;
- dest->recv_count = src1->recv_count + src2->recv_count;
- dest->recv_size = src1->recv_size + src2->recv_size;
- dest->send_count = src1->send_count + src2->send_count;
- dest->send_size = src1->send_size + src2->send_size;
- }
- }
- return dest;
- }
- ///////////////////////////////////////////////////////////////////////////////
- TransferStats_t * Sub3TransferStats
- (
- // return dest
- // calculate: dest = src1 - src2
- TransferStats_t *dest, // NULL or destination (maybe same as source)
- const TransferStats_t *src1, // NULL or first source
- const TransferStats_t *src2 // NULL or second source
- )
- {
- if (dest)
- {
- if (!src1)
- {
- if (src2)
- {
- TransferStats_t temp;
- memset(&temp,0,sizeof(temp));
- Sub3TransferStats(dest,&temp,src2);
- }
- else
- memset(dest,0,sizeof(*dest));
- }
- else if (!src2)
- {
- DASSERT(src1);
- memcpy(dest,src1,sizeof(*dest));
- }
- else
- {
- DASSERT(src1);
- DASSERT(src2);
- dest->conn_count = src1->conn_count - src2->conn_count;
- dest->recv_count = src1->recv_count - src2->recv_count;
- dest->recv_size = src1->recv_size - src2->recv_size;
- dest->send_count = src1->send_count - src2->send_count;
- dest->send_size = src1->send_size - src2->send_size;
- }
- }
- return dest;
- }
- ///////////////////////////////////////////////////////////////////////////////
- TransferStats_t * SumTransferStats
- (
- // return dest
- // calculate: dest = sum(all_sources)
- TransferStats_t *dest, // NULL or destination (maybe same as source)
- const TransferStats_t * const *src, // NULL or source list, elements may be NULL
- int n_src // number of element; if -1: term at first NULL
- )
- {
- if (dest)
- {
- TransferStats_t temp;
- memset(&temp,0,sizeof(temp));
- if (src)
- {
- if ( n_src < 0 )
- while ( *src )
- Add2TransferStats(&temp,*src++);
- else
- for ( ; *src; src++ )
- if (*src)
- Add2TransferStats(&temp,*src);
- }
- memcpy(dest,&temp,sizeof(*dest));
- }
- return dest;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ccp PrintTransferStatsSQL
- (
- // print statistic as SQL assigning list.
- // arguments are speparated by a comma.
- char *buf, // result buffer
- // NULL: use a local circulary static buffer
- size_t buf_size, // size of 'buf', ignored if buf==NULL
- const TransferStats_t *ts, // valid source
- ccp prefix // not NULL: prefix member names
- )
- {
- DASSERT(ts);
- const bool alloced = !buf;
- if (alloced)
- buf = GetCircBuf( buf_size = CIRC_BUF_MAX_ALLOC );
- if (!prefix)
- prefix = "";
- const uint len
- = snprintf( buf, buf_size,
- "%sconn=%u, %srecv_n=%u, %srecv=%llu, %ssend_n=%u, %ssend=%llu",
- prefix, ts->conn_count,
- prefix, ts->recv_count,
- prefix, ts->recv_size,
- prefix, ts->send_count,
- prefix, ts->send_size );
- if ( alloced && len < buf_size )
- ReleaseCircBuf(buf+buf_size,buf_size-len-1);
- return buf;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- static inline u32 calc_rate ( u64 count, u64 duration )
- { return ( count * USEC_PER_SEC + duration/2 ) / duration; }
- static inline double calc_drate ( u64 count, u64 duration )
- { return (double)( count * USEC_PER_SEC ) / duration; }
- ///////////////////////////////////////////////////////////////////////////////
- void PrintTranferStatistics
- (
- FILE *f, // output file, never NULL
- ccp prefix, // NULL or prefix for each line
- ccp name, // statistics name, up to 5 chars including colon
- const TransferStats_t *stat,// statistics record
- TransferStats_t *prev, // NULL statistics record with previous data
- u64 duration, // delta duration in usec
- ccp duration_info, // text representation of 'duration'
- const ColorSet_t *colset // NULL (no colors) or color set to use
- )
- {
- DASSERT(f);
- DASSERT(name);
- DASSERT(stat);
- if (!prefix)
- prefix = "";
- if (!colset)
- colset = GetColorSet0();
- ccp color1 = colset->status;
- ccp color0 = colset->reset;
- if (stat->conn_count)
- {
- fprintf(f,
- "%s%s#STAT-%-5s %u connect%s,"
- " %u packet%s (%s) received, %u packet%s (%s) send.%s\n",
- prefix, color1, name,
- stat->conn_count, stat->conn_count == 1 ? "" : "s",
- stat->recv_count, stat->recv_count == 1 ? "" : "s",
- PrintSize1024(0,0,stat->recv_size,0),
- stat->send_count, stat->send_count == 1 ? "" : "s",
- PrintSize1024(0,0,stat->send_size,0),
- color0 );
- }
- else if ( stat->recv_count || stat->send_count )
- {
- fprintf(f,
- "%s%s#STAT-%-5s %u packet%s (%s) received, %u packet%s (%s) send.%s\n",
- prefix, color1, name,
- stat->recv_count, stat->recv_count == 1 ? "" : "s",
- PrintSize1024(0,0,stat->recv_size,0),
- stat->send_count, stat->send_count == 1 ? "" : "s",
- PrintSize1024(0,0,stat->send_size,0),
- color0 );
- }
- else
- return;
- if ( duration > 0 && prev )
- {
- TransferStats_t delta;
- Sub3TransferStats(&delta,stat,prev);
- char duration_buf[10];
- if (!duration_info)
- {
- PrintTimerUSec6(duration_buf,sizeof(duration_buf),duration,false);
- duration_info = duration_buf;
- }
- if ( delta.recv_count )
- {
- const double crate = calc_drate( delta.recv_count, duration );
- const u32 srate = calc_rate( delta.recv_size, duration );
- fprintf(f,
- "%s%s#STAT-%-5s >Last "
- "%s: %u (%4.2f/s) packet%s with %s (%s/s) received.%s\n",
- prefix, color1, name,
- duration_info,
- delta.recv_count, crate,
- delta.recv_count == 1 ? "" : "s",
- PrintSize1024(0,0,delta.recv_size,0),
- PrintSize1024(0,0,srate,0),
- color0 );
- }
- if ( delta.send_count )
- {
- const double crate = calc_drate( delta.send_count, duration );
- const u32 srate = calc_rate( delta.send_size, duration );
- fprintf(f,
- "%s%s#STAT-%-5s >Last "
- "%s: %u (%4.2f/s) packet%s with %s (%s/s) send.%s\n",
- prefix, color1, name,
- duration_info,
- delta.send_count, crate,
- delta.send_count == 1 ? "" : "s",
- PrintSize1024(0,0,delta.send_size,0),
- PrintSize1024(0,0,srate,0),
- color0 );
- }
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- void SaveCurrentStateTransferStats
- (
- FILE *f, // output file
- const TransferStats_t *stat // valid stat object
- )
- {
- DASSERT(f);
- DASSERT(stat);
- fprintf(f,
- "conn-count = %u\n"
- "recv-count = %u\n"
- "recv-size = %llu\n"
- "send-count = %u\n"
- "send-size = %llu\n"
- ,stat->conn_count
- ,stat->recv_count
- ,stat->recv_size
- ,stat->send_count
- ,stat->send_size
- );
- }
- ///////////////////////////////////////////////////////////////////////////////
- void SaveCurrentStateTransferStats1
- (
- // print as single line
- FILE *f, // output file
- ccp name, // var name; use "tfer-stat" if NULL or EMPTY
- const TransferStats_t *stat // valid stat object
- )
- {
- DASSERT(f);
- DASSERT(stat);
- if ( !name || !*name )
- name = "tfer-stat";
- const int tab_size = ( 23 - strlen(name) ) / 8;
- fprintf(f,
- "%s%.*s= %u,%u,%llu,%u,%llu\n"
- ,name
- ,tab_size > 0 ? tab_size : 0
- ,"\t\t"
- ,stat->conn_count
- ,stat->recv_count
- ,stat->recv_size
- ,stat->send_count
- ,stat->send_size
- );
- }
- ///////////////////////////////////////////////////////////////////////////////
- void SaveCurrentStateTransferStatsN
- (
- // print multiple stats each as single line
- FILE *f, // output file
- ccp name, // var name; use "tfer-stat-" if NULL or EMPTY
- const TransferStats_t *stat, // list of valid stat objects
- uint n_stat // number of elements in 'stat'
- )
- {
- DASSERT(f);
- DASSERT(stat||!n_stat);
- if ( !name || !*name )
- name = "tfer-stat-";
- const int tab_size = ( 23 - strlen(name) ) / 8;
- fprintf(f,"%sn%.*s= %u\n",
- name, tab_size > 0 ? tab_size : 0, "\t\t", n_stat );
- uint i;
- char buf[100];
- for ( i = 0; i < n_stat; i++ )
- {
- snprintf(buf,sizeof(buf),"%s%u",name,i);
- SaveCurrentStateTransferStats1(f,buf,stat++);
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- void RestoreStateTransferStats
- (
- RestoreState_t *rs, // info data, can be modified (cleaned after call)
- cvp user_table // pointer provided by RestoreStateTab_t[]
- )
- {
- DASSERT(rs);
- TransferStats_t *stat = (TransferStats_t*)user_table;
- if (!stat)
- return;
- stat->conn_count = GetParamFieldUINT( rs, "conn-count", stat->conn_count );
- stat->recv_count = GetParamFieldUINT( rs, "recv-count", stat->recv_count );
- stat->send_count = GetParamFieldUINT( rs, "send-count", stat->send_count );
- stat->recv_size = GetParamFieldU64 ( rs, "recv-size", stat->recv_size );
- stat->send_size = GetParamFieldU64 ( rs, "send-size", stat->send_size );
- }
- ///////////////////////////////////////////////////////////////////////////////
- void RestoreStateTransferStats1
- (
- // scan single line
- RestoreState_t *rs, // info data, can be modified (cleaned after call)
- ccp name, // var name; use "tfer-stat" if NULL or EMPTY
- TransferStats_t *stat, // valid stat object
- bool fall_back // true: fall back to RestoreStateTransferStats()
- )
- {
- DASSERT(rs);
- DASSERT(stat);
- if ( !name || !*name )
- name = "tfer-stat";
- char buf[100];
- int res = GetParamFieldBUF( buf, sizeof(buf), rs, name, ENCODE_OFF, 0 );
- if ( res > 0 )
- {
- memset(stat,0,sizeof(*stat));
- char *ptr;
- stat->conn_count = strtoul (buf,&ptr,10); if (*ptr == ',' ) ptr++;
- stat->recv_count = strtoul (ptr,&ptr,10); if (*ptr == ',' ) ptr++;
- stat->recv_size = strtoull(ptr,&ptr,10); if (*ptr == ',' ) ptr++;
- stat->send_count = strtoul (ptr,&ptr,10); if (*ptr == ',' ) ptr++;
- stat->send_size = strtoull(ptr,&ptr,10);
- return;
- }
- if (fall_back)
- RestoreStateTransferStats(rs,stat);
- }
- ///////////////////////////////////////////////////////////////////////////////
- uint RestoreStateTransferStatsN
- (
- // print multiple stats each as single line
- // returns the number of read elements; all others are set to NULL
- RestoreState_t *rs, // info data, can be modified (cleaned after call)
- ccp name, // var name; use "tfer-stat-" if NULL or EMPTY
- TransferStats_t *stat, // list of valid stat objects
- uint n_stat // number of elements in 'stat'
- )
- {
- DASSERT(rs);
- DASSERT(stat||!n_stat);
- if ( !name || !*name )
- name = "tfer-stat-";
- memset(stat,0,n_stat*sizeof(*stat));
- char buf[100];
- snprintf(buf,sizeof(buf),"%sn",name);
- uint n_read = GetParamFieldUINT(rs,buf,0);
- if ( n_read > n_stat )
- n_read = n_stat;
- uint i;
- for ( i = 0; i < n_read; i++ )
- {
- snprintf(buf,sizeof(buf),"%s%u",name,i);
- RestoreStateTransferStats1(rs,buf,stat++,false);
- }
- return n_read;
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// TCP HANDLER ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- #define LOG_TCP HAVE_PRINT0
- #undef INC_TCP_INDENT
- #undef DEC_TCP_INDENT
- #undef LOG_TCP_BUFFER
- #if LOG_TCP
- static int tcp_indent = 5;
- #define INC_TCP_INDENT tcp_indent += 2
- #define DEC_TCP_INDENT tcp_indent -= 2
- #define LOG_TCP_BUFFER(tb,f,...) LogGrowBuffer(stderr,tcp_indent,tb,f,__VA_ARGS__)
- #define LOG_TCP_STREAM(ts,r,f,...) LogTCPStream(stderr,tcp_indent,ts,r,f,__VA_ARGS__)
- #define LOG_TCP_HANDLER(th,r,f,...) LogTCPHandler(stderr,tcp_indent,th,r,f,__VA_ARGS__)
- #else
- #define INC_TCP_INDENT
- #define DEC_TCP_INDENT
- #define LOG_TCP_BUFFER(tb,f,...)
- #define LOG_TCP_STREAM(ts,r,f,...)
- #define LOG_TCP_HANDLER(th,r,f,...)
- #endif
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// TCPStream_t ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- void InitializeTCPStream ( TCPStream_t *ts, int sock )
- {
- DASSERT(ts);
- memset(ts,0,sizeof(*ts));
- ts->unique_id = CreateUniqueId();
- ts->sock = sock;
- ts->poll_index = M1(ts->poll_index);
- LOG_TCP_STREAM(ts,0,"%s","INIT()");
- INC_TCP_INDENT;
- InitializeGrowBuffer(&ts->ibuf,0x4000);
- InitializeGrowBuffer(&ts->obuf,0x4000);
- DEC_TCP_INDENT;
- }
- ///////////////////////////////////////////////////////////////////////////////
- void ResetTCPStream
- (
- TCPStream_t *ts // valid TCP handler
- )
- {
- DASSERT(ts);
- LogTCPStreamActivity(ts,"ResetTCPStream");
- TCPHandler_t *th = ts->handler;
- if (th)
- {
- if (th->OnDestroyStream)
- th->OnDestroyStream(ts);
- th->used_streams--;
- }
- if ( ts->sock != -1 )
- {
- shutdown(ts->sock,SHUT_RDWR);
- close(ts->sock);
- ts->sock = -1;
- }
- INC_TCP_INDENT;
- ResetGrowBuffer(&ts->ibuf);
- ResetGrowBuffer(&ts->obuf);
- DEC_TCP_INDENT;
- if (th)
- {
- // chain is only valid if part of TCP-handler
- if (ts->prev)
- ts->prev->next = ts->next;
- if (ts->next)
- ts->next->prev = ts->prev;
- if ( th->first == ts )
- th->first = ts->next;
- }
- memset(ts,0,sizeof(*ts));
- }
- ///////////////////////////////////////////////////////////////////////////////
- void DestroyTCPStream
- (
- TCPStream_t *ts // valid TCP handler
- )
- {
- DASSERT(ts);
- LogTCPStreamActivity(ts,"DestroyTCPStream");
- ResetTCPStream(ts);
- FREE(ts);
- }
- ///////////////////////////////////////////////////////////////////////////////
- ssize_t UpdateRecvStatTCPStream
- (
- // returns 'send_stat'
- TCPStream_t *ts, // valid TCP handler
- ssize_t recv_stat, // result of recv(), update stats on >0
- u64 now_usec // NULL or current time
- )
- {
- DASSERT(ts);
- if ( recv_stat > 0 )
- {
- ts->receive_usec = now_usec ? now_usec : GetTimeUSec(false);
- ts->stat.recv_count++;
- ts->stat.recv_size += recv_stat;
- if (ts->xstat)
- {
- ts->xstat->recv_count++;
- ts->xstat->recv_size += recv_stat;
- }
- if (ts->handler)
- {
- ts->handler->stat.recv_count++;
- ts->handler->stat.recv_size += recv_stat;
- }
- }
- return recv_stat;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ssize_t UpdateSendStatTCPStream
- (
- // returns 'send_stat'
- TCPStream_t *ts, // valid TCP handler
- ssize_t send_stat, // result of send(), update stats on >0
- u64 now_usec // NULL or current time
- )
- {
- DASSERT(ts);
- if ( send_stat > 0 )
- {
- ts->send_usec = now_usec ? now_usec : GetTimeUSec(false);
- ts->stat.send_count++;
- ts->stat.send_size += send_stat;
- if (ts->xstat)
- {
- ts->xstat->send_count++;
- ts->xstat->send_size += send_stat;
- }
- if (ts->handler)
- {
- ts->handler->stat.send_count++;
- ts->handler->stat.send_size += send_stat;
- }
- }
- return send_stat;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- int WriteDirectGrowBuffer
- (
- // write() data direct without blocking and without calling any notifier.
- // If output buf is not empty or send failed, append the data to 'gb'.
- // Returns the number of bytes added to the grow buffer or -1 on error.
- // The data is send+stored completely (returns 'size') or not at all
- // (returns '0'). -1 is returned if the socket is invalid.
- GrowBuffer_t *gb, // grow buffer to cache data
- int fd, // destination file
- bool flush_output, // true: try to flush 'gb' before
- cvp data, // data to send
- uint size, // size of 'data', If NULL && flush: flush only
- uint *send_count // not NULL: add num of sent bytes
- )
- {
- DASSERT(gb);
- DASSERT(data||!size);
- const u8 *d = data;
- if ( fd != -1 )
- {
- int final_stat = 0;
- if ( gb->disabled <= 0 )
- {
- if ( flush_output && gb->used )
- {
- ssize_t stat = write(fd,gb->ptr,gb->used);
- if ( stat > 0 )
- {
- if (send_count)
- *send_count += stat;
- DropGrowBuffer(gb,stat);
- }
- }
- if ( !gb->used && size )
- {
- ssize_t stat = write(fd,d,size);
- if ( stat > 0 )
- {
- if (send_count)
- *send_count += stat;
- size -= stat;
- if (!size) // likely
- return stat;
- d += stat;
- final_stat = stat;
- // for this case: force growing buffer (because of 'all or none')
- PrepareGrowBuffer(gb,size,true);
- }
- }
- }
- if ( size && size <= GetSpaceGrowBuffer(gb) )
- final_stat += InsertGrowBuffer(gb,d,size);
- return final_stat;
- }
- return -1;
- }
- ///////////////////////////////////////////////////////////////////////////////
- int SendDirectGrowBuffer
- (
- // send() data direct without blocking and without calling any notifier.
- // If output buf is not empty or send failed, append the data to 'gb'.
- // Returns the number of bytes added to the grow buffer or -1 on error.
- // The data is send+stored completely (returns 'size') or not at all
- // (returns '0'). -1 is returned if the socket is invalid.
- GrowBuffer_t *gb, // grow buffer to cache data
- int sock, // destination socket
- bool flush_output, // true: try to flush 'gb' before
- cvp data, // data to send
- uint size, // size of 'data', If NULL && flush: flush only
- uint *send_count // not NULL: add num of sent bytes
- )
- {
- DASSERT(gb);
- DASSERT(data||!size);
- const u8 *d = data;
- if ( sock != -1 )
- {
- int final_stat = 0;
- if ( gb->disabled <= 0 )
- {
- if ( flush_output && gb->used )
- {
- ssize_t stat = send(sock,gb->ptr,gb->used,MSG_DONTWAIT);
- if ( stat > 0 )
- {
- if (send_count)
- *send_count += stat;
- DropGrowBuffer(gb,stat);
- }
- }
- if ( !gb->used && size )
- {
- ssize_t stat = send(sock,d,size,MSG_DONTWAIT);
- if ( stat > 0 )
- {
- if (send_count)
- *send_count += stat;
- size -= stat;
- if (!size) // likely
- return stat;
- d += stat;
- final_stat = stat;
- // for this case: force growing buffer (because of 'all or none')
- PrepareGrowBuffer(gb,size,true);
- }
- }
- }
- if ( size && size <= GetSpaceGrowBuffer(gb) )
- final_stat += InsertGrowBuffer(gb,d,size);
- return final_stat;
- }
- return -1;
- }
- ///////////////////////////////////////////////////////////////////////////////
- int SendDirectTCPStream
- (
- // Send data direct without blocking and without calling any notifier.
- // If output buf is not empty or send failed, append the data to output buf.
- // Returns the number of bytes added to the output buffer or -1 on error.
- // The data is send+stored completely (returns 'size') or not at all
- // (returns '0'). -1 is returned if the socket is invalid.
- TCPStream_t *ts, // valid TCP handler
- bool flush_output, // true: try to flush out-buf before
- cvp data, // data to send
- uint size // size of 'data', If NULL && flush: flush only
- )
- {
- DASSERT(ts);
- DASSERT(data||!size);
- uint count = 0;
- const int stat
- = SendDirectGrowBuffer(&ts->obuf,ts->sock,flush_output,data,size,&count);
- if ( count > 0 )
- UpdateSendStatTCPStream(ts,count,0);
- return stat;
- }
- ///////////////////////////////////////////////////////////////////////////////
- int PrintArgDirectTCPStream
- (
- // Printing interface for SendDirectTCPStream()
- TCPStream_t *ts, // valid TCP handler
- bool flush_output, // true: try to flush out-buf before
- ccp format, // format string for vsnprintf()
- va_list arg // parameters for 'vfprintf(...,format,...)'
- )
- {
- DASSERT(ts);
- if (!format)
- return SendDirectTCPStream(ts,flush_output,0,0);
- char buf[10000];
- va_list arg2;
- va_copy(arg2,arg);
- int stat = vsnprintf(buf,sizeof(buf),format,arg2);
- va_end(arg2);
- if ( stat < sizeof(buf) )
- return SendDirectTCPStream(ts,flush_output,buf,stat);
- //--- buffer too small, use dynamic memory
- noPRINT("PrintArgGrowBuffer() -> MALLOC(%u)\n",stat+1);
- char *temp = MALLOC(stat+1);
- stat = vsnprintf(temp,stat+1,format,arg);
- stat = SendDirectTCPStream(ts,flush_output,temp,stat);
- FREE(temp);
- return stat;
- }
- ///////////////////////////////////////////////////////////////////////////////
- int PrintDirectTCPStream
- (
- // Printing interface for SendDirectTCPStream()
- TCPStream_t *ts, // valid TCP handler
- bool flush_output, // true: try to flush out-buf before
- ccp format, // format string for vfprintf()
- ... // arguments for 'vfprintf(...,format,...)'
- )
- {
- DASSERT(ts);
- if (format)
- {
- va_list arg;
- va_start(arg,format);
- const int stat = PrintArgDirectTCPStream(ts,flush_output,format,arg);
- va_end(arg);
- return stat;
- }
- return SendDirectTCPStream(ts,flush_output,0,0);
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- int PrintBinary1TCPStream
- (
- TCPStream_t *ts, // NULL or destination
- ccp cmd, // command name
- cvp bin_data, // pointer to binary data
- uint bin_size, // size of binary data
- ccp format, // NULL or format string with final ';'
- ... // parameters for 'format'
- )
- {
- DASSERT(cmd);
- DASSERT(bin_data||!bin_size);
- if (!ts)
- return -1;
- char buf[10000], *end_buf = buf + sizeof(buf) - 4;
- #if 0 // gcc-12: throws error: 'buf' may be used uninitialized
- char *dest = StringCopyE(buf,end_buf,cmd);
- #else
- char *dest = StringCopyS(buf,sizeof(buf)-4,cmd);
- #endif
- if ( dest + 6 + bin_size >= end_buf )
- return -1;
- *dest++ = ' ';
- *dest++ = 1;
- write_be16(dest,bin_size);
- dest += 2;
- memcpy(dest,bin_data,bin_size);
- dest += bin_size;
- *dest++ = ' ';
- *dest++ = '=';
- int len;
- if (format)
- {
- va_list arg;
- va_start(arg,format);
- len = vsnprintf(dest,end_buf-dest,format,arg);
- va_end(arg);
- if ( len < 0 )
- return -1;
- len += dest - buf;
- if ( len >= sizeof(buf) )
- return -1;
- }
- else
- {
- *dest++ = ';';
- len = dest - buf;
- }
- return SendDirectTCPStream(ts,false,buf,len);
- }
- ///////////////////////////////////////////////////////////////////////////////
- int PrintBinary2TCPStream
- (
- TCPStream_t *ts, // NULL or destination
- ccp cmd, // command name
- cvp bin1_data, // pointer to binary data
- uint bin1_size, // size of binary data
- cvp bin2_data, // pointer to binary data
- uint bin2_size, // size of binary data
- ccp format, // NULL or format string with final ';'
- ... // parameters for 'format'
- )
- {
- DASSERT(cmd);
- DASSERT(bin1_data||!bin1_size);
- DASSERT(bin2_data||!bin2_size);
- if (!ts)
- return -1;
- char buf[10000], *end_buf = buf + sizeof(buf) - 4;
- #if 0 // gcc-12: throws error: 'buf' may be used uninitialized
- char *dest = StringCopyE(buf,end_buf,cmd);
- #else
- char *dest = StringCopyS(buf,sizeof(buf)-4,cmd);
- #endif
- if ( dest + 9 + bin1_size + bin2_size >= end_buf )
- return -1;
- *dest++ = ' ';
- *dest++ = 1;
- write_be16(dest,bin1_size);
- dest += 2;
- memcpy(dest,bin1_data,bin1_size);
- dest += bin1_size;
- *dest++ = 1;
- write_be16(dest,bin2_size);
- dest += 2;
- memcpy(dest,bin2_data,bin2_size);
- dest += bin2_size;
- *dest++ = ' ';
- *dest++ = '=';
- int len;
- if (format)
- {
- va_list arg;
- va_start(arg,format);
- len = vsnprintf(dest,end_buf-dest,format,arg);
- va_end(arg);
- if ( len < 0 )
- return -1;
- len += dest - buf;
- if ( len >= sizeof(buf) )
- return -1;
- }
- else
- {
- *dest++ = ';';
- len = dest - buf;
- }
- return SendDirectTCPStream(ts,false,buf,len);
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- void LogTCPStream
- (
- FILE *f, // output file
- int indent, // indention
- const TCPStream_t *ts, // valid TCP handler
- int recurse, // >0: print stream list, >1: print buffer status
- ccp format, // format string for vfprintf()
- ... // arguments for 'vfprintf(format,...)'
- )
- {
- DASSERT(f);
- DASSERT(ts);
- indent = NormalizeIndent(indent);
- fprintf(f,"%*sTS: id:%x, sock=%d, %u packets received (%s), %u packets send (%s)",
- indent,"",
- ts->unique_id, ts->sock,
- ts->stat.recv_count, PrintSize1024(0,0,ts->stat.recv_size,0),
- ts->stat.send_count, PrintSize1024(0,0,ts->stat.send_size,0) );
- if (format)
- {
- fputs(" : ",f);
- va_list arg;
- va_start(arg,format);
- vfprintf(f,format,arg);
- va_end(arg);
- }
- fputc('\n',f);
- if (recurse>0)
- {
- LogGrowBuffer(f,indent+2,&ts->ibuf,"in buf");
- LogGrowBuffer(f,indent+2,&ts->obuf,"out buf");
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- void LogTCPStreamActivity
- (
- const TCPStream_t *ts, // valid TCP handler
- ccp activity
- )
- {
- if (!ts->tracelog)
- return;
- char hbuf[200];
- if (ts->handler)
- {
- const TCPHandler_t *th = ts->handler;
- const Socket_t *so = th->listen;
- DASSERT( TCP_HANDLER_MAX_LISTEN >= 3 );
- snprintf(hbuf,sizeof(hbuf),
- " | TH#%u: %u/%u/%u, sock=%d,%d,%d",
- th->unique_id,
- th->used_streams, th->max_used_streams, th->total_streams,
- so[0].sock, so[1].sock, so[2].sock );
- }
- else
- *hbuf = 0;
- TraceLogPrint(ts->tracelog,
- "%p %-20s sock=%d%s\n", ts, activity, ts->sock, hbuf );
- }
- ///////////////////////////////////////////////////////////////////////////////
- char * BufInfoHeadTCPStream
- (
- // returns a pointer to the head line
- uint line // 0|1
- )
- {
- switch (line)
- {
- case 0:
- return "connect in buf out buf"
- " received data send data";
- case 1:
- return " time sock status use/ max use/ max"
- " time pkt size time pkt size stream info";
- }
- return 0;
- }
- ///////////////////////////////////////////////////////////////////////////////
- char * BufInfoTCPStream
- (
- // returns a pointer to the buffer
- char * buf, // result (BUF_INFO_TCP_STREAM_SIZE bytes are good)
- // If NULL, a local circulary static buffer is used
- size_t buf_size, // size of 'buf', ignored if buf==NULL
- const TCPStream_t *ts, // valid TCP handler
- u64 now_usec // NULL or current time, GetTimeUSec(false)
- )
- {
- DASSERT(ts);
- if (!now_usec)
- now_usec = GetTimeUSec(false);
- char connect_usec[7];
- if ( ts->connect_usec )
- PrintTimerUSec6(connect_usec,sizeof(connect_usec),
- now_usec - ts->connect_usec, true );
- else
- connect_usec[0] = '-', connect_usec[1] = 0;
- char receive_usec[7];
- if ( ts->receive_usec )
- PrintTimerUSec6(receive_usec,sizeof(receive_usec),
- now_usec - ts->receive_usec, true );
- else
- receive_usec[0] = '-', receive_usec[1] = 0;
- char send_usec[7];
- if ( ts->send_usec )
- PrintTimerUSec6(send_usec,sizeof(send_usec),
- now_usec - ts->send_usec, true );
- else
- send_usec[0] = '-', send_usec[1] = 0;
- if (!buf)
- buf = GetCircBuf( buf_size = BUF_INFO_TCP_STREAM_SIZE );
- snprintf(buf,buf_size,
- "%6.6s%5d %c%c%c%c%c%c%c %s/%s %s/%s %6s %s %s %6s %s %s %s"
- ,connect_usec
- ,ts->sock
- ,ts->protect > 0 ? 'P' : '-'
- ,ts->auto_close > 0 ? 'A' : '-'
- ,ts->rescan > 0 ? 'S' : '-'
- ,ts->eof > 0 ? 'X' : '-'
- ,ts->error > 0 ? 'E' : '-'
- ,ts->ibuf.disabled ? 'D' : 'i'
- ,ts->obuf.disabled ? 'D' : 'o'
- ,PrintNumberU4(0,0,ts->ibuf.used,true)
- ,PrintNumberU4(0,0,ts->ibuf.max_used,true)
- ,PrintNumberU4(0,0,ts->obuf.used,true)
- ,PrintNumberU4(0,0,ts->obuf.max_used,true)
- ,receive_usec
- ,PrintNumberU5(0,0,ts->stat.recv_count,true)
- ,PrintSize1024(0,0,ts->stat.recv_size,DC_SFORM_TINY|DC_SFORM_ALIGN)
- ,send_usec
- ,PrintNumberU5(0,0,ts->stat.send_count,true)
- ,PrintSize1024(0,0,ts->stat.send_size,DC_SFORM_TINY|DC_SFORM_ALIGN)
- ,ts->info
- );
- return buf;
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// TCPHandler_t ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- void AddSocketTCPStream
- (
- TCPStream_t *ts, // valid TCP handler
- FDList_t *fdl // valid file descriptor list
- )
- {
- DASSERT(ts);
- DASSERT(fdl);
- if ( ts->OnFDList && ts->OnFDList(ts,fdl,TCP_FM_ADD_SOCK,false) < 0 || ts->sock == -1 )
- return;
- uint events = POLLERR|POLLRDHUP;
- if ( !ts->eof && !ts->ibuf.disabled && GetSpaceGrowBuffer(&ts->ibuf) )
- events |= POLLIN;
- if ( !ts->obuf.disabled && ts->obuf.used )
- events |= POLLOUT;
- ts->poll_index = AddFDList(fdl,ts->sock,events);
- if ( ts->OnTimeout && ts->trigger_usec && fdl->timeout_usec > ts->trigger_usec )
- fdl->timeout_usec = ts->trigger_usec;
- }
- ///////////////////////////////////////////////////////////////////////////////
- void CheckSocketTCPStream
- (
- TCPStream_t *ts, // valid TCP handler
- FDList_t *fdl, // valid socket list
- bool check_timeout // true: enable timeout checks
- )
- {
- DASSERT(ts);
- DASSERT(fdl);
- if ( ts->OnFDList && ts->OnFDList(ts,fdl,TCP_FM_CHECK_SOCK,check_timeout) < 0
- || ts->sock == -1 )
- {
- return;
- }
- const u64 now_usec = GetTimeUSec(false);
- typeof(ts->rescan) rescan = ts->rescan;
- ts->rescan = 0;
- const uint revents = GetEventFDList(fdl,ts->sock,ts->poll_index);
- if ( !ts->ibuf.disabled && revents & POLLIN )
- {
- noPRINT("RECV: %d\n",ts->sock);
- OnReceivedStream(ts,now_usec);
- rescan = 0;
- }
- if ( !ts->obuf.disabled && ts->obuf.used && revents & POLLOUT )
- OnWriteStream(ts,now_usec);
- if ( revents & (POLLERR|POLLHUP|POLLRDHUP|POLLNVAL) )
- {
- ts->error |= 1;
- OnCloseStream(ts,now_usec);
- }
- if ( rescan && ts->OnReceived )
- {
- uchar ch = 0;
- ts->OnReceived(ts,&ch,0);
- }
- if (check_timeout)
- CheckTimeoutTCPStream(ts);
- if (ts->rescan)
- ts->trigger_usec = ts->accept_usec = now_usec;
- }
- ///////////////////////////////////////////////////////////////////////////////
- #undef PRINT_TIMEOUT
- #define PRINT_TIMEOUT(ts,now,info) \
- noPRINT("%s[%d]: now=%lld, trig=%lld, accept=%lld, OnTimeout=%d\n", \
- info, ts->sock, now, ts->trigger_usec ? ts->trigger_usec - now : 0, \
- ts->accept_usec ? ts->accept_usec - now : 0, ts->OnTimeout != 0 )
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- void CheckTimeoutTCPStream ( TCPStream_t *ts )
- {
- DASSERT(ts);
- if ( ts->OnFDList && ts->OnFDList(ts,0,TCP_FM_TIMEOUT,true) < 0 || ts->sock == -1 )
- return;
- const u64 now_usec = GetTimeUSec(false);
- PRINT_TIMEOUT(ts,now_usec,"TIMEOUT");
- if ( ts->trigger_usec && ts->trigger_usec <= now_usec
- || ts->accept_usec && ts->accept_usec <= now_usec
- )
- {
- ts->trigger_usec = ts->accept_usec = 0;
- if (ts->OnTimeout)
- ts->OnTimeout(ts,now_usec);
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- u64 GetLastActivityTCPStream ( TCPStream_t *ts )
- {
- DASSERT(ts);
- const u64 ref = ts->connect_usec > ts->receive_usec
- ? ts->connect_usec : ts->receive_usec;
- return ref > ts->send_usec ? ref : ts->send_usec;
- }
- ///////////////////////////////////////////////////////////////////////////////
- u64 GetTimeoutTCPStream ( TCPStream_t *ts )
- {
- DASSERT(ts);
- return ts->timeout_usec
- ? GetLastActivityTCPStream(ts) + ts->timeout_usec
- : 0;
- }
- ///////////////////////////////////////////////////////////////////////////////
- int OnTimeoutTCPStream ( TCPStream_t *ts, u64 now_usec )
- {
- DASSERT(ts);
- if ( ts->sock != -1 && ts->timeout_usec )
- {
- if (!now_usec)
- now_usec = GetTimeUSec(false);
- if ( now_usec >= GetLastActivityTCPStream(ts) + ts->timeout_usec )
- OnCloseStream(ts,now_usec);
- else
- SetupTriggerTCPStream(ts,now_usec);
- }
- return 0;
- }
- ///////////////////////////////////////////////////////////////////////////////
- void SetupTriggerTCPStream ( TCPStream_t *ts, u64 now_usec )
- {
- DASSERT(ts);
- const u64 next = GetTimeoutTCPStream(ts);
- if (next)
- {
- if (!now_usec)
- now_usec = GetTimeUSec(false);
- if ( ts->accept_usec <= now_usec || ts->accept_usec > next )
- ts->accept_usec = next;
- ts->trigger_usec = ts->accept_usec + ts->delay_usec;
- noPRINT("next=%lld [%lld], accept=%lld [%lld]\n",
- next, next-now_usec, ts->accept_usec, ts->accept_usec-now_usec );
- }
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// TCPHandler_t ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- void InitializeTCPHandler
- (
- TCPHandler_t *th, // not NULL
- uint data_size // size of 'TCPStream_t::data'
- )
- {
- DASSERT(th);
- memset(th,0,sizeof(*th));
- th->unique_id = CreateUniqueId();
- th->data_size = data_size;
- th->OnAllowStream = IsStreamAllowed;
- uint i;
- for ( i = 0; i < TCP_HANDLER_MAX_LISTEN; i++ )
- th->listen[i].sock = -1;
- LOG_TCP_HANDLER(th,0,"INIT(%u)",data_size);
- }
- ///////////////////////////////////////////////////////////////////////////////
- void ResetTCPHandler
- (
- TCPHandler_t *th // valid TCP handler
- )
- {
- DASSERT(th);
- th->allow_ip4 = DeleteReferenceAllowIP4(th->allow_ip4);
- UnlistenAllTCP(th);
- while (th->first)
- DestroyTCPStream(th->first);
- usleep(1);
- InitializeTCPHandler(th,th->data_size);
- }
- ///////////////////////////////////////////////////////////////////////////////
- uint CloseTCPHandler
- (
- // returns the number of waiting clients (obuf not empty and !disabled)
- TCPHandler_t *th // valid TCP handler
- )
- {
- DASSERT(th);
- UnlistenAllTCP(th);
- uint count = 0;
- u64 now = GetTimeUSec(false);
- TCPStream_t *ts;
- for ( ts = th->first; ts; ts = ts->next )
- {
- OnCloseStream(ts,now);
- if ( ts->obuf.used && !ts->obuf.disabled )
- count++;
- }
- return count;
- }
- ///////////////////////////////////////////////////////////////////////////////
- TCPStream_t * AddTCPStream
- (
- TCPHandler_t *th, // valid TCP handler
- TCPStream_t *ts // the new stream
- )
- {
- DASSERT(th);
- DASSERT(ts);
- ts->handler = th;
- ts->prev = 0;
- ts->next = th->first;
- if (th->first)
- th->first->prev = ts;
- th->first = ts;
- if ( th->max_used_streams < ++th->used_streams )
- th->max_used_streams = th->used_streams;
- th->total_streams++;
- th->stat.conn_count++;
- ts->connect_usec = GetTimeUSec(false);
- LogTCPStreamActivity(ts,"AddTCPStream");
- return ts;
- }
- ///////////////////////////////////////////////////////////////////////////////
- TCPStream_t * CreateTCPStream
- (
- TCPHandler_t *th, // valid TCP handler
- int sock, // -1 or valid socket
- u64 allow_mode, // stored in 'allow_mode'
- const Socket_t *listen // NULL or related listen object
- )
- {
- DASSERT(th);
- TCPStream_t *ts = listen && listen->OnCreateStream
- ? listen->OnCreateStream(th,sock) : 0;
- if (!ts)
- {
- if (th->OnCreateStream)
- ts = th->OnCreateStream(th,sock);
- if (!ts)
- {
- ts = CALLOC(sizeof(*ts)+th->data_size,1);
- InitializeTCPStream(ts,sock);
- }
- }
- if ( th->tracelog.level >= 0 )
- {
- ts->tracelog = &th->tracelog;
- LogTCPStreamActivity(ts,"CreateTCPStream");
- }
- ts->allow_mode = allow_mode;
- AddTCPStream(th,ts);
- if ( listen && listen->OnAddedStream )
- listen->OnAddedStream(ts);
- else if (th->OnAddedStream)
- th->OnAddedStream(ts);
- return ts;
- }
- ///////////////////////////////////////////////////////////////////////////////
- TCPStream_t * ConnectUnixTCPStream
- (
- TCPHandler_t *th, // valid TCP handler
- ccp path, // NULL or path part 1 to socket file
- bool silent // suppress error messages
- )
- {
- DASSERT(th);
- DASSERT(path);
- int sock = socket(AF_UNIX,SOCK_STREAM,0);
- if ( sock == -1 )
- {
- if (!silent)
- ERROR1(ERR_CANT_CREATE,"Can't create UNIX stream socket: %s\n",path);
- return 0;
- }
- struct sockaddr_un sa;
- memset(&sa,0,sizeof(sa));
- sa.sun_family = AF_UNIX;
- StringCopyS(sa.sun_path,sizeof(sa.sun_path),path);
- int stat = connect(sock,(struct sockaddr*)&sa,sizeof(sa));
- if (stat)
- {
- if (!silent)
- ERROR1(ERR_CANT_OPEN,"Can't connect UNIX stream socket: %s\n",path);
- shutdown(sock,SHUT_RDWR);
- close(sock);
- return 0;
- }
- return CreateTCPStream(th,sock,ALLOW_MODE_ALLOW,0);
- }
- ///////////////////////////////////////////////////////////////////////////////
- TCPStream_t * ConnectTCPStream
- (
- TCPHandler_t *th, // valid TCP handler
- ccp addr, // address -> NetworkHost_t
- u16 default_port, // default port
- bool silent // suppress error messages
- )
- {
- DASSERT(th);
- DASSERT(addr);
- ccp unix_path = CheckUnixSocketPath(addr,0);
- if (unix_path)
- return ConnectUnixTCPStream(th,unix_path,silent);
- if (!strncasecmp(addr,"tcp:",4))
- addr += 4;
- NetworkHost_t nh;
- ResolveHost(&nh,true,addr,default_port,false,false);
- PRINT("SINGLE/CONNECT/TCP: %s -> %s\n",
- addr, PrintIP4(0,0,nh.ip4,nh.port) );
- int sock = socket(AF_INET,SOCK_STREAM|SOCK_NONBLOCK,0);
- if ( sock == -1 )
- {
- if (!silent)
- ERROR1(ERR_CANT_CREATE,"Can't create TCP socket: %s\n",
- PrintIP4(0,0,nh.ip4,nh.port));
- return 0;
- }
- struct sockaddr_in sa;
- memset(&sa,0,sizeof(sa));
- sa.sin_family = AF_INET;
- sa.sin_addr.s_addr = htonl(nh.ip4);
- sa.sin_port = htons(nh.port);
- int stat = connect(sock,(struct sockaddr*)&sa,sizeof(sa));
- if ( stat && errno != EINPROGRESS )
- {
- if (!silent)
- ERROR1(ERR_CANT_OPEN,"Can't connect TCP socket: %s\n",
- PrintIP4(0,0,nh.ip4,nh.port));
- shutdown(sock,SHUT_RDWR);
- close(sock);
- ResetHost(&nh);
- return 0;
- }
- return CreateTCPStream(th,sock,ALLOW_MODE_ALLOW,0);
- }
- ///////////////////////////////////////////////////////////////////////////////
- TCPStream_t * FindTCPStreamByUniqueID
- (
- TCPHandler_t *th, // valid TCP handler
- uint unique_id // id to search
- )
- {
- TCPStream_t *ts;
- for ( ts = th->first; ts; ts = ts->next )
- if ( ts->unique_id == unique_id )
- return ts;
- return 0;
- }
- ///////////////////////////////////////////////////////////////////////////////
- uint NumOfSocketsTCP ( const TCPHandler_t *th )
- {
- uint i, count = 0;
- for ( i = 0; i < TCP_HANDLER_MAX_LISTEN; i++ )
- if ( th->listen[i].sock != -1 )
- count++;
- const TCPStream_t *ts;
- for ( ts = th->first; ts; ts = ts->next )
- if ( ts->sock != -1
- && ( !ts->eof && !ts->ibuf.disabled
- || !ts->obuf.disabled && ts->obuf.used ))
- {
- count++;
- }
- return count;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- Socket_t * GetUnusedListenSocketTCP ( TCPHandler_t *th, bool silent )
- {
- DASSERT(th);
- uint i;
- for ( i = 0; i < TCP_HANDLER_MAX_LISTEN; i++ )
- if ( th->listen[i].sock == -1 )
- return th->listen+i;
- if (!silent)
- ERROR0(ERR_CANT_CREATE,"No socket available.\n");
- return 0;
- }
- ///////////////////////////////////////////////////////////////////////////////
- enumError ListenUnixTCP
- (
- TCPHandler_t *th, // valid TCP handler
- ccp path // path to unix file
- )
- {
- DASSERT(th);
- DASSERT(path);
- PRINT("LISTEN/UNIX: %s\n",path);
- Socket_t *lsock = GetUnusedListenSocketTCP(th,false);
- if (!lsock)
- return ERR_CANT_CREATE;
- unlink(path);
- int sock = socket(AF_UNIX,SOCK_STREAM,0);
- if ( sock == -1 )
- return ERROR1(ERR_CANT_CREATE,"Can't create UNIX socket: %s\n",path);
- struct sockaddr_un sa;
- memset(&sa,0,sizeof(sa));
- sa.sun_family = AF_UNIX;
- StringCopyS(sa.sun_path,sizeof(sa.sun_path),path);
- int stat = bind(sock,(struct sockaddr*)&sa,sizeof(sa));
- if ( stat == -1 )
- {
- close(sock);
- return ERROR1(ERR_CANT_CREATE,"Can't bind UNIX socket: %s\n",path);
- }
- stat = listen(sock,50);
- if ( stat == -1 )
- {
- close(sock);
- return ERROR1(ERR_CANT_CREATE,"Can't listen UNIX socket: %s\n",path);
- }
- //SetSocketBlocking(cmdi_sock,false);
- DASSERT(lsock);
- lsock->sock = sock;
- lsock->is_unix = true;
- snprintf(lsock->info,sizeof(lsock->info),"UNIX socket %d",sock);
- PRINT("LISTEN: %s [idx=%zu]\n",lsock->info,lsock-th->listen);
- LOG_TCP_HANDLER(th,0,"LISTEN/UNIX[%u] %s",listen_idx,path);
- return ERR_OK;
- }
- ///////////////////////////////////////////////////////////////////////////////
- enumError ListenTCP
- (
- TCPHandler_t *th, // valid TCP handler
- ccp addr, // IPv4 address with optional port -> NetworkHost_t
- // fall back to ListenUnixTCP() if addr begins with
- // 'unix:' or '/' or './ or '../'
- u16 default_port // default port
- )
- {
- DASSERT(th);
- DASSERT(addr);
- Socket_t *lsock = GetUnusedListenSocketTCP(th,false);
- if (!lsock)
- return ERR_CANT_CREATE;
- const bool allow_unix = memcmp(addr,"tcp:",4) != 0;
- if (!allow_unix)
- {
- addr += 4;
- while ( *addr == '/' )
- addr++;
- }
- NetworkHost_t nh;
- if ( !ResolveHost(&nh,true,addr,default_port,allow_unix,true) && nh.filename )
- {
- ccp unix_path = nh.filename;
- ResetHost(&nh);
- return ListenUnixTCP(th,unix_path);
- }
- ccp path = GetHostName(&nh);
- PRINT("LISTEN/TCP: %s:%u -> %s\n",nh.name,default_port,PrintIP4(0,0,nh.ip4,nh.port));
- int sock = socket(AF_INET,SOCK_STREAM|SOCK_NONBLOCK,0);
- if ( sock == -1 )
- {
- ERROR1(ERR_CANT_CREATE,"Can't create TCP socket: %s\n",path);
- ResetHost(&nh);
- return ERR_CANT_CREATE;
- }
- int on = 1;
- setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, (ccp)&on, sizeof(on) );
- struct sockaddr_in sa;
- memset(&sa,0,sizeof(sa));
- sa.sin_family = AF_INET;
- sa.sin_addr.s_addr = htonl(nh.ip4);
- sa.sin_port = htons(nh.port);
- int stat = bind(sock,(struct sockaddr*)&sa,sizeof(sa));
- if ( stat == -1 )
- {
- ERROR1(ERR_CANT_CREATE,"Can't bind TCP socket: %s\n",
- PrintIP4(0,0,nh.ip4,nh.port));
- close(sock);
- ResetHost(&nh);
- return ERR_CANT_CREATE;
- }
- stat = listen(sock,50);
- if ( stat == -1 )
- {
- ERROR1(ERR_CANT_CREATE,"Can't listen TCP socket: %s\n",
- PrintIP4(0,0,nh.ip4,nh.port));
- close(sock);
- ResetHost(&nh);
- return ERR_CANT_CREATE;
- }
- //SetSocketBlocking(cmdi_sock,false);
- DASSERT(lsock);
- lsock->sock = sock;
- lsock->is_unix = false;
- snprintf(lsock->info,sizeof(lsock->info),"TCP socket %d",sock);
- PRINT("LISTEN: %s [idx=%zu]\n",lsock->info,lsock-th->listen);
- ResetHost(&nh);
- return ERR_OK;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- int UnlistenTCP
- (
- // returns the index of the closed socket, or if not found
- TCPHandler_t *th, // valid TCP handler
- int sock // socket to close
- )
- {
- uint i;
- for ( i = 0; i < TCP_HANDLER_MAX_LISTEN; i++ )
- if ( th->listen[i].sock == sock )
- {
- close(sock);
- th->listen[i].sock = -1;
- return i;
- }
- return -1;
- }
- ///////////////////////////////////////////////////////////////////////////////
- uint UnlistenAllTCP
- (
- // returns the number of closed sockets
- TCPHandler_t *th // valid TCP handler
- )
- {
- uint i, count = 0;
- for ( i = 0; i < TCP_HANDLER_MAX_LISTEN; i++ )
- if ( th->listen[i].sock != -1 )
- {
- socket_info_t si;
- GetSocketInfoBySocket(&si,th->listen[i].sock,true);
- if ( si.is_valid && si.protocol == AF_UNIX
- && si.address && *si.address )
- {
- PRINT("unlink(%s)\n",si.address);
- unlink(si.address);
- }
- ResetSocketInfo(&si);
- close(th->listen[i].sock);
- th->listen[i].sock = -1;
- count++;
- }
- return count;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- void AddSocketsTCP
- (
- TCPHandler_t *th, // valid TCP handler
- FDList_t *fdl // valid file descriptor list
- )
- {
- DASSERT(th);
- DASSERT(fdl);
- AnnounceFDList(fdl,TCP_HANDLER_MAX_LISTEN+th->used_streams+1);
- if ( !th->max_conn || th->used_streams < th->max_conn )
- {
- uint i;
- for ( i = 0; i < TCP_HANDLER_MAX_LISTEN; i++ )
- {
- Socket_t *lsock = th->listen + i;
- lsock->poll_index = AddFDList(fdl,lsock->sock,POLLIN);
- }
- }
- TCPStream_t *ts;
- for ( ts = th->first; ts; ts = ts->next )
- AddSocketTCPStream(ts,fdl);
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- bool IsStreamAllowed
- (
- // returns true if access is allowed
- struct TCPHandler_t *th, // valid TCP handler
- const Socket_t *lsock, // valid listen-socket
- int sock, // valid socket to verify
- u64 *allow // not NULL: store allow code here
- )
- {
- DASSERT(th);
- if ( !th->allow_ip4 || lsock && lsock->is_unix )
- {
- // no checks for unix sockets
- if (allow)
- *allow = ALLOW_MODE_ALLOW;
- return true;
- }
- const u64 res = GetAutoAllowIP4BySock(th->allow_ip4,sock);
- if (allow)
- *allow = res;
- return ( res & th->allow_ip4->allow_mode ) != 0;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- TCPStream_t * OnAcceptStream
- (
- TCPHandler_t *th, // valid TCP handler
- const Socket_t *lsock, // listen-socket
- u64 now_usec // time for timestamps, GetTimeUSec(false)
- )
- {
- DASSERT(th);
- DASSERT(lsock);
- DASSERT( lsock >= th->listen );
- DASSERT( lsock < th->listen + TCP_HANDLER_MAX_LISTEN );
- DASSERT( lsock->sock != -1 );
- PRINT("OnAcceptStream() lsock=%d,%s\n",lsock->sock,lsock->info);
- TCPStream_t *ts = NULL;
- int new_sock = accept(lsock->sock,0,0);
- if ( new_sock != -1 )
- {
- RegisterFileId(new_sock);
- u64 allow_code = 0;
- const u64 is_allowed = th->OnAllowStream
- ? th->OnAllowStream(th,lsock,new_sock,&allow_code)
- : ALLOW_MODE_ALLOW;
- if ( !is_allowed || th->OnAcceptStream && th->OnAcceptStream(th,lsock,new_sock) )
- {
- PRINT("NOT ACCEPTED: %d -> %d\n",lsock->sock,new_sock);
- shutdown(new_sock,SHUT_RDWR);
- close(new_sock);
- }
- else
- {
- PRINT("ACCEPTED: %d -> %d [alloe=%llx]\n",lsock->sock,new_sock,allow_code);
- ts = CreateTCPStream(th,new_sock,allow_code,lsock);
- if (ts)
- {
- if (!ts->info[0])
- {
- if (lsock->info[0])
- snprintf(ts->info,sizeof(ts->info),
- "by %s [%x]",
- lsock->info, ts->unique_id );
- else
- snprintf(ts->info,sizeof(ts->info),
- "by socket %d [%x]",
- lsock->sock, ts->unique_id );
- }
- }
- else
- {
- shutdown(new_sock,SHUT_RDWR);
- close(new_sock);
- }
- }
- }
- return ts;
- }
- ///////////////////////////////////////////////////////////////////////////////
- void OnCloseStream
- (
- TCPStream_t *ts, // valid TCP stream
- u64 now_usec // time for timestamps, GetTimeUSec(false)
- )
- {
- DASSERT(ts);
- if ( ts->sock != -1 )
- {
- PRINT("CLOSE: %d\n",ts->sock);
- if (ts->OnClose)
- ts->OnClose(ts,now_usec);
- if ( ts->sock != -1 )
- {
- // if not closed by OnClose()
- shutdown(ts->sock,SHUT_RDWR);
- close(ts->sock);
- ts->sock = -1;
- }
- if ( !ts->protect && ts->handler )
- ts->handler->need_maintenance |= 1;
- ts->OnReceived = 0;
- ts->OnSend = 0;
- ts->OnTimeout = 0;
- ts->OnClose = 0;
- ts->OnFDList = 0;
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- void SetNotSocketStream
- (
- TCPStream_t *ts // valid TCP stream
- )
- {
- DASSERT(ts);
- if ( ts->sock != -1 )
- {
- ts->not_socket = true;
- int flags = fcntl(ts->sock,F_GETFL,0);
- if ( flags != -1 )
- {
- flags |= O_NONBLOCK;
- fcntl(ts->sock,F_SETFL,flags);
- }
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- void OnReceivedStream
- (
- TCPStream_t *ts, // valid TCP stream
- u64 now_usec // time for timestamps, GetTimeUSec(false)
- )
- {
- DASSERT(ts);
- uint max_read = GetSpaceGrowBuffer(&ts->ibuf);
- if (max_read)
- {
- u8 buf[0x4000];
- if ( max_read > sizeof(buf) )
- max_read = sizeof(buf);
- ssize_t stat;
- retry:
- if (ts->not_socket)
- stat = read(ts->sock,buf,max_read);
- else
- stat = recv(ts->sock,buf,max_read,MSG_DONTWAIT);
- if ( stat < 0 && !ts->not_socket && errno == ENOTSOCK )
- {
- SetNotSocketStream(ts);
- goto retry;
- }
- #if HAVE_PRINT
- noPRINT("RECV[%d] %lld/%u, err=%d\n",ts->sock,(s64)stat,max_read,errno);
- if ( stat < 0 )
- PRINT("!! %s(), ERRNO=%d: %s\n",__FUNCTION__,errno,strerror(errno));
- #endif
- if ( stat >= 0 )
- {
- if ( stat > 0 )
- UpdateRecvStatTCPStream(ts,stat,now_usec);
- else
- ts->eof |= 1;
- if (ts->OnReceived)
- stat = ts->OnReceived(ts,buf,stat);
- if ( stat > 0 )
- InsertGrowBuffer(&ts->ibuf,buf,stat);
- //X if ( ts->eof && !ts->ibuf.used && !ts->obuf.used )
- //X OnCloseStream(ts,now_usec);
- }
- else if ( errno != EWOULDBLOCK )
- OnCloseStream(ts,now_usec);
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- void OnWriteStream
- (
- TCPStream_t *ts, // valid TCP stream
- u64 now_usec // time for timestamps, GetTimeUSec(false)
- )
- {
- DASSERT(ts);
- restart:;
- ssize_t stat;
- if (ts->not_socket)
- stat = write(ts->sock,ts->obuf.ptr,ts->obuf.used);
- else
- stat = send(ts->sock,ts->obuf.ptr,ts->obuf.used,MSG_DONTWAIT);
- noPRINT("SEND[%d] %lld/%u, err=%d\n",ts->sock,(s64)stat,ts->obuf.used,errno);
- if ( stat < 0 )
- {
- if ( !ts->not_socket && errno == ENOTSOCK )
- {
- SetNotSocketStream(ts);
- goto restart;
- }
- PRINT("!! %s(), ERRNO=%d: %s\n",__FUNCTION__,errno,strerror(errno));
- OnCloseStream(ts,now_usec);
- }
- else if (!stat)
- ts->obuf.disabled |= 1;
- else
- {
- UpdateSendStatTCPStream(ts,stat,now_usec);
- if (ts->OnSend)
- stat = ts->OnSend(ts,ts->obuf.ptr,stat);
- if ( stat > 0 )
- DropGrowBuffer(&ts->obuf,stat);
- if ( ts->auto_close && !ts->obuf.used )
- OnCloseStream(ts,now_usec);
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- void CheckSocketsTCP
- (
- TCPHandler_t *th, // valid TCP handler
- FDList_t *fdl, // valid socket list
- bool check_timeout // true: enable timeout checks
- )
- {
- DASSERT(th);
- DASSERT(fdl);
- const u64 now_usec = GetTimeUSec(false);
- uint i;
- for ( i = 0; i < TCP_HANDLER_MAX_LISTEN; i++ )
- {
- Socket_t *lsock = th->listen + i;
- if ( lsock->sock != -1 )
- {
- const uint revents = GetEventFDList(fdl,lsock->sock,lsock->poll_index);
- if ( revents & POLLIN )
- OnAcceptStream(th,lsock,now_usec);
- }
- }
- TCPStream_t *next = th->first;
- while (next)
- {
- // Do it in this way, because 'ts' may become invalid
- TCPStream_t *ts = next;
- next = ts->next;
- CheckSocketTCPStream(ts,fdl,check_timeout);
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- void CheckTimeoutTCP ( TCPHandler_t *th )
- {
- DASSERT(th);
- TCPStream_t *next = th->first;
- while (next)
- {
- // Do it in this way, because 'ts' may becomes invalid
- TCPStream_t *ts = next;
- next = ts->next;
- CheckTimeoutTCPStream(ts);
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- bool MaintainTCP ( TCPHandler_t *th )
- {
- DASSERT(th);
- th->need_maintenance = 0;
- const u64 now_usec = GetTimeUSec(false);
- TCPStream_t *next = th->first;
- while (next)
- {
- // Do it in this way, because 'ts' may becomes invalid
- TCPStream_t *ts = next;
- next = ts->next;
- if ( ts->sock == -1 && ts->protect <= 0 )
- DestroyTCPStream(ts);
- else if (ts->OnMaintenance)
- ts->OnMaintenance(ts,now_usec);
- }
- return true;
- }
- ///////////////////////////////////////////////////////////////////////////////
- void ManageSocketsTCP
- (
- // call CheckSocketsTCP(), CheckTimeoutTCP(), MaintainTCP()
- TCPHandler_t *th, // valid TCP handler
- FDList_t *fdl, // valid socket list
- int stat // result of a WAIT function
- )
- {
- if ( stat > 0 )
- CheckSocketsTCP(th,fdl,true);
- else
- CheckTimeoutTCP(th);
- if (th->need_maintenance)
- MaintainTCP(th);
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- void LogTCPHandler
- (
- FILE *f, // output file
- int indent, // indention
- const TCPHandler_t *th, // valid TCP handler
- int recurse, // >0: print stream list, >1: print buffer status
- ccp format, // format string for vfprintf()
- ... // arguments for 'vfprintf(format,...)'
- )
- {
- DASSERT(f);
- DASSERT(th);
- indent = NormalizeIndent(indent);
- fprintf(f,"%*sTH: id:%x, n=%u/%u/%u, listen=",
- indent,"", th->unique_id,
- th->used_streams, th->max_used_streams, th->total_streams );
- uint i;
- for ( i = 0; i < TCP_HANDLER_MAX_LISTEN; i++ )
- fprintf(f,"%d,",th->listen[i].sock);
- fprintf(f," max=%u, dsize=%u, ready=%u",
- th->max_conn, th->data_size, NumOfSocketsTCP(th) );
- if (format)
- {
- fputs(" : ",f);
- va_list arg;
- va_start(arg,format);
- vfprintf(f,format,arg);
- va_end(arg);
- }
- fprintf(f,"\n%*s %u connects, %u packets received (%s), %u packets send (%s)\n",
- indent,"",
- th->stat.conn_count,
- th->stat.recv_count, PrintSize1024(0,0,th->stat.recv_size,0),
- th->stat.send_count, PrintSize1024(0,0,th->stat.send_size,0) );
- if (recurse>0)
- {
- recurse--;
- uint idx = 0;
- const TCPStream_t *ts;
- for ( ts = th->first; ts; ts = ts->next )
- LogTCPStream(f,indent+2,ts,recurse,"Stream #%u",idx++);
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- void PrintStreamTableTCPHandler
- (
- FILE *f, // output file
- const ColorSet_t *colset, // NULL (no colors) or valid color set
- int indent, // indention
- const TCPHandler_t *th // valid TCP handler
- )
- {
- DASSERT(f);
- DASSERT(th);
- indent = NormalizeIndent(indent);
- if (!colset)
- colset = GetColorSet0();
- const u64 now_usec = GetTimeUSec(false);
- const TCPStream_t *ts;
- ccp line1 = BufInfoHeadTCPStream(0);
- ccp line2 = BufInfoHeadTCPStream(1);
- const uint sep_len = strlen(line2)+sizeof(ts->info)-13;
- fprintf(f,"%s%*s%.*s\n%s%*s%s\n%s%*s%s\n%s%*s%.*s%s\n",
- colset->heading, indent,"", sep_len, Minus300,
- colset->heading, indent,"", line1,
- colset->heading, indent,"", line2,
- colset->heading, indent,"", sep_len, Minus300,
- colset->reset );
- char buf[BUF_INFO_TCP_STREAM_SIZE];
- for ( ts = th->first; ts; ts = ts->next )
- {
- BufInfoTCPStream(buf,BUF_INFO_TCP_STREAM_SIZE,ts,now_usec);
- fprintf(f,"%*s%s\n",indent,"",buf);
- }
- if (th->used_streams)
- fprintf(f,
- "%s%*s%.*s%s\n",
- colset->heading, indent,"", sep_len, Minus300,
- colset->reset );
- if ( th->total_streams > 1 || th->total_streams > th->used_streams )
- {
- snprintf(buf,sizeof(buf),"TOTAL: %u current client%s, %u max",
- th->used_streams, th->used_streams == 1 ? "" : "s",
- th->max_used_streams );
- fprintf(f,
- "%s%*s%-45s%s %s%13s %s Summary of %u stream%s\n%s%*s%.*s%s\n",
- colset->status, indent,"", buf,
- PrintNumberU7(0,0,th->stat.recv_count,true),
- PrintSize1024(0,0,th->stat.recv_size,DC_SFORM_TINY|DC_SFORM_ALIGN),
- PrintNumberU7(0,0,th->stat.send_count,true),
- PrintSize1024(0,0,th->stat.send_size,DC_SFORM_TINY|DC_SFORM_ALIGN),
- th->total_streams, th->total_streams == 1 ? "" : "s",
- colset->heading, indent,"", sep_len,Minus300,
- colset->reset );
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- bool GetSocketInfoBySocket
- (
- // returns TRUE, if infos retrived
- socket_info_t *si, // result, not NULL, will be initialized
- int sock, // socket id, maybe -1
- bool get_name // true: alloc 'address' and copy name
- // -> call ResetSocketInfo() to free mem
- )
- {
- DASSERT(si);
- InitializeSocketInfo(si);
- if ( sock == -1 )
- return false;
- si->sock = sock;
- DASSERT( sizeof(struct sockaddr_un) >= sizeof(struct sockaddr_in) );
- DASSERT( sizeof(struct sockaddr_un) >= sizeof(struct sockaddr_in6) );
- struct sockaddr_un sa;
- memset(&sa,0,sizeof(sa));
- socklen_t sa_len = sizeof(sa);
- if (getsockname(sock,(struct sockaddr*)&sa,&sa_len))
- return false;
- char buf[INET6_ADDRSTRLEN+10];
- switch (sa.sun_family)
- {
- case AF_UNIX:
- si->protocol = AF_UNIX;
- if ( get_name && sa.sun_path[0] )
- {
- si->address = STRDUP(sa.sun_path);
- si->alloced = true;
- }
- break;
- case AF_INET:
- si->protocol = AF_INET;
- if (get_name)
- {
- const struct sockaddr_in *sin = (struct sockaddr_in*)&sa;
- PrintIP4sa(buf,sizeof(buf),sin);
- si->address = STRDUP(buf);
- si->alloced = true;
- }
- break;
- case AF_INET6:
- si->protocol = AF_INET6;
- if (get_name)
- {
- const struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&sa;
- if (inet_ntop(AF_INET6,&sin6->sin6_addr,buf+1,sizeof(buf)-1))
- {
- *buf = '[';
- char *dest = buf + strlen(buf);
- snprintf(dest,buf+sizeof(buf)-dest,"]:%u",ntohs(sin6->sin6_port));
- si->address = STRDUP(buf);
- si->alloced = true;
- }
- }
- break;
- default:
- return false;
- }
- int socktype = -1;
- socklen_t psize = sizeof(socktype);
- if (!getsockopt(sock,SOL_SOCKET,SO_TYPE,&socktype,&psize))
- si->type = socktype;
- return si->is_valid = true;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- uint GetSocketNameBySA
- (
- char *buf, // dest buffer
- uint bufsize, // size of 'dest'
- const struct sockaddr *sa, // socket address
- socklen_t sa_len // length of 'sa'
- )
- {
- DASSERT(buf);
- DASSERT(bufsize>0);
- DASSERT(sa);
- DASSERT(sa_len>0);
- if ( sa_len >= sizeof(struct sockaddr_un) )
- {
- const struct sockaddr_un *sun = (struct sockaddr_un*)sa;
- if ( sun->sun_family == AF_UNIX && sun->sun_path[0] )
- return snprintfS(buf,bufsize,"unix:%s",sun->sun_path);
- }
- if ( sa_len >= sizeof(struct sockaddr_in) )
- {
- const struct sockaddr_in *sin = (struct sockaddr_in*)sa;
- if ( sin->sin_family == AF_INET && bufsize > 5 )
- {
- strcpy(buf,"tcp:");
- return PrintIP4sa(buf+4,bufsize-4,sin) - buf;
- }
- }
- if ( sa_len >= sizeof(struct sockaddr_in6) )
- {
- const struct sockaddr_in6 *sin = (struct sockaddr_in6*)sa;
- if ( sin->sin6_family == AF_INET6 && bufsize >= 5 + INET6_ADDRSTRLEN )
- {
- // [[2do]] ??? "[addr]:port"
- strcpy(buf,"tcp6:");
- if (inet_ntop(AF_INET6,&sin->sin6_addr,buf+5,bufsize-5))
- return strlen(buf);
- }
- }
- *buf = 0;
- return 0;
- }
- ///////////////////////////////////////////////////////////////////////////////
- uint GetSocketName ( char *buf, uint bufsize, int sock )
- {
- DASSERT(buf);
- DASSERT(bufsize>0);
- if ( sock != -1 )
- {
- DASSERT( sizeof(struct sockaddr_un) >= sizeof(struct sockaddr_in) );
- DASSERT( sizeof(struct sockaddr_un) >= sizeof(struct sockaddr_in6) );
- struct sockaddr_un sun;
- memset(&sun,0,sizeof(sun));
- socklen_t sun_len = sizeof(sun);
- if (!getsockname(sock,(struct sockaddr*)&sun,&sun_len))
- return GetSocketNameBySA(buf,bufsize,(struct sockaddr*)&sun,sun_len);
- }
- *buf = 0;
- return 0;
- }
- ///////////////////////////////////////////////////////////////////////////////
- uint GetPeerName ( char *buf, uint bufsize, int sock )
- {
- DASSERT(buf);
- DASSERT(bufsize>0);
- if ( sock != -1 )
- {
- DASSERT( sizeof(struct sockaddr_un) >= sizeof(struct sockaddr_in) );
- struct sockaddr_un sun;
- memset(&sun,0,sizeof(sun));
- socklen_t sun_len = sizeof(sun);
- if (!getpeername(sock,(struct sockaddr*)&sun,&sun_len))
- return GetSocketNameBySA(buf,bufsize,(struct sockaddr*)&sun,sun_len);
- }
- *buf = 0;
- return 0;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- bool DeleteSocketFile ( int sock )
- {
- if ( sock != -1 )
- {
- DASSERT( sizeof(struct sockaddr_un) >= sizeof(struct sockaddr_in) );
- struct sockaddr_un sun;
- memset(&sun,0,sizeof(sun));
- socklen_t sun_len = sizeof(sun);
- if (!getsockname(sock,(struct sockaddr*)&sun,&sun_len))
- {
- if ( sun.sun_family == AF_UNIX )
- {
- unlink(sun.sun_path);
- return true;
- }
- }
- }
- return false;
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// TCP: send single strings ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- static int OnTimeoutSingleTCP ( struct TCPStream_t * ts, u64 now_usec )
- {
- PRINT("OnTimeoutSingleTCP(%p,%llu) sock=%d, to=%lld,%lld d=%lld,%lld\n",
- ts, now_usec, ts->sock,
- ts->trigger_usec, ts->trigger_usec - now_usec,
- ts->accept_usec, ts->accept_usec - now_usec );
- DASSERT(ts);
- OnCloseStream(ts,now_usec);
- return 0;
- }
- ///////////////////////////////////////////////////////////////////////////////
- static int OnReceivedSingleTCP ( struct TCPStream_t * ts, u8 *buf, uint size )
- {
- PRINT("OnReceivedSingleTCP(%p,%p,%u) to=%lld\n",ts,buf,size,*(u64*)ts->data);
- DASSERT(ts);
- ts->accept_usec = GetTimeUSec(false) + *(u64*)ts->data;
- ts->trigger_usec = ts->accept_usec + 100000;
- return 0;
- }
- ///////////////////////////////////////////////////////////////////////////////
- static int OnSendSingleTCP ( struct TCPStream_t * ts, u8 *buf, uint size )
- {
- PRINT("OnSendSingleTCP(%p,%p,%u) to=%lld\n",ts,buf,size,*(u64*)ts->data);
- DASSERT(ts);
- ts->accept_usec = GetTimeUSec(false) + *(u64*)ts->data;
- ts->trigger_usec = ts->accept_usec + 100000;
- return size;
- }
- ///////////////////////////////////////////////////////////////////////////////
- static TCPStream_t * SendSingleTCPHelper
- (
- TCPHandler_t *th, // valid handle
- int sock, // valid socket
- const void *data, // data to send
- uint size, // size of 'data'
- u64 timeout_usec, // timeout before closing the connection
- TransferStats_t *xstat, // NULL or pointer to summary statistics
- bool silent // suppress error messages
- )
- {
- DASSERT(th);
- DASSERT(sock!=-1);
- DASSERT(data||!size);
- PRINT("SendSingleStringTCPHelper(%p,%d,%lld,%d)\n",th,sock,timeout_usec,silent);
- th->stat.conn_count++;
- TCPStream_t *ts = CALLOC(sizeof(*ts)+sizeof(u64),1);
- InitializeTCPStream(ts,sock);
- AddTCPStream(th,ts);
- ts->xstat = xstat;
- ts->OnTimeout = OnTimeoutSingleTCP;
- ts->OnReceived = OnReceivedSingleTCP;
- ts->OnSend = OnSendSingleTCP;
- ts->accept_usec = GetTimeUSec(false) + timeout_usec;
- ts->trigger_usec = ts->accept_usec + 100000;
- *(u64*)ts->data = timeout_usec;
- snprintf(ts->info,sizeof(ts->info),"send single, %u bytes",size);
- #if 1
- ts->obuf.max_size = size > 10240 ? size : 10240;
- SendDirectTCPStream(ts,false,data,size);
- #else
- ts->obuf.max_size = size;
- InsertGrowBuffer(&ts->obuf,data,size);
- #endif
- return ts;
- }
- ///////////////////////////////////////////////////////////////////////////////
- TCPStream_t * SendSingleUnixTCP
- (
- TCPHandler_t *th, // valid handle
- ccp path, // path to socket file
- const void *data, // data to send
- uint size, // size of 'data'
- u64 timeout_usec, // timeout before closing the connection
- TransferStats_t *xstat, // NULL or pointer to summary statistics
- bool silent // suppress error messages
- )
- {
- DASSERT(th);
- DASSERT(path);
- DASSERT(data||!size);
- PRINT("SINGLE/CONNECT/UNIX: %s\n",path);
- int sock = socket(AF_UNIX,SOCK_STREAM,0);
- if ( sock == -1 )
- {
- if (!silent)
- ERROR1(ERR_CANT_CREATE,"Can't create UNIX socket: %s\n",path);
- return 0;
- }
- struct sockaddr_un sa;
- memset(&sa,0,sizeof(sa));
- sa.sun_family = AF_UNIX;
- StringCopyS(sa.sun_path,sizeof(sa.sun_path),path);
- int stat = connect(sock,(struct sockaddr*)&sa,sizeof(sa));
- if (stat)
- {
- if (!silent)
- ERROR1(ERR_CANT_OPEN,"Can't connect UNIX socket: %s\n",path);
- shutdown(sock,SHUT_RDWR);
- close(sock);
- return 0;
- }
- return SendSingleTCPHelper(th,sock,data,size,timeout_usec,xstat,silent);
- }
- ///////////////////////////////////////////////////////////////////////////////
- TCPStream_t * SendSingleTCP
- (
- TCPHandler_t *th, // valid handle
- ccp addr, // address -> NetworkHost_t
- u16 default_port, // default port
- const void *data, // data to send
- uint size, // size of 'data'
- u64 timeout_usec, // timeout before closing the connection
- TransferStats_t *xstat, // NULL or pointer to summary statistics
- bool silent // suppress error messages
- )
- {
- DASSERT(th);
- DASSERT(addr);
- DASSERT(data||!size);
- ccp unix_path = CheckUnixSocketPath(addr,0);
- if (unix_path)
- return SendSingleUnixTCP(th,unix_path,data,size,timeout_usec,xstat,silent);
- if (!strncasecmp(addr,"tcp:",4))
- addr += 4;
- NetworkHost_t nh;
- ResolveHost(&nh,true,addr,default_port,false,false);
- PRINT("SINGLE/CONNECT/TCP: %s -> %s\n",
- addr, PrintIP4(0,0,nh.ip4,nh.port) );
- int sock = socket(AF_INET,SOCK_STREAM|SOCK_NONBLOCK,0);
- if ( sock == -1 )
- {
- if (!silent)
- ERROR1(ERR_CANT_CREATE,"Can't create TCP socket: %s\n",
- PrintIP4(0,0,nh.ip4,nh.port));
- return 0;
- }
- struct sockaddr_in sa;
- memset(&sa,0,sizeof(sa));
- sa.sin_family = AF_INET;
- sa.sin_addr.s_addr = htonl(nh.ip4);
- sa.sin_port = htons(nh.port);
- int stat = connect(sock,(struct sockaddr*)&sa,sizeof(sa));
- if ( stat && errno != EINPROGRESS )
- {
- if (!silent)
- ERROR1(ERR_CANT_OPEN,"Can't connect TCP socket: %s\n",
- PrintIP4(0,0,nh.ip4,nh.port));
- shutdown(sock,SHUT_RDWR);
- close(sock);
- ResetHost(&nh);
- return 0;
- }
- TCPStream_t *ts = SendSingleTCPHelper(th,sock,data,size,timeout_usec,xstat,silent);
- ResetHost(&nh);
- return ts;
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// TCP: CommandTCP ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- void SetTimeoutCommandTCP
- (
- TCPStream_t *ts, // valid stream
- u64 now_usec // NULL or current time in usec
- )
- {
- DASSERT(ts);
- const CommandTCPInfo_t *ci = (CommandTCPInfo_t*)ts->data;
- if (!ci->timeout_usec)
- ts->accept_usec = ts->trigger_usec = 0;
- else
- {
- if (!now_usec)
- now_usec = GetTimeUSec(false);
- ts->accept_usec = now_usec + ci->timeout_usec;
- ts->trigger_usec = ts->accept_usec + 100000;
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- static char * ScanLineCommandTCP
- (
- // return first non scanned character, or NULL on error
- struct TCPStream_t *ts,
- char *line,
- char *line_end,
- u64 now_usec
- )
- {
- DASSERT(ts);
- DASSERT(line);
- DASSERT(line_end);
- DASSERT( line <= line_end );
- *line_end = 0;
- const CommandTCPInfo_t *ci = (CommandTCPInfo_t*)ts->data;
- if (ci->OnScanArg)
- {
- SplitArg_t sa;
- ScanSplitArg(&sa,true,line,line_end,line);
- sa.argv[0] = ts->info;
- const int stat = ci->OnScanArg(ts,sa.argc,sa.argv,now_usec);
- ResetSplitArg(&sa);
- return stat > ERR_WARNING ? line : line_end;
- }
- if (ci->OnScanLine)
- return ci->OnScanLine(ts,line,line_end,now_usec);
- //--- fall back: mirror
- InsertGrowBuffer(&ts->obuf,line,line_end-line);
- InsertCharGrowBuffer(&ts->obuf,'\n');
- return line_end;
- }
- ///////////////////////////////////////////////////////////////////////////////
- static void ScanBufferCommandTCP ( struct TCPStream_t * ts, bool finish )
- {
- DASSERT(ts);
- //--- setup
- const u64 now_usec = GetTimeUSec(false);
- const CommandTCPInfo_t *ci = (CommandTCPInfo_t*)ts->data;
- const u8 comma = ci->comma_is_eol ? ',' : ';';
- //--- skip uneeded data
- u8 *beg = ts->ibuf.ptr, *end = beg + ts->ibuf.used;
- while ( beg < end )
- {
- const u8 ch = *beg;
- if ( ch > ' ' && ch != ';' && ch != comma )
- break;
- beg++;
- }
- DropGrowBuffer(&ts->ibuf,beg-ts->ibuf.ptr);
- //--- find end of command
- u8 *ptr;
- for ( ptr = beg; ptr < end; ptr++ )
- {
- const u8 ch = *ptr;
- if ( !ch || ch == '\n' || ch == '\r' || ch == ';' || ch == comma )
- {
- DropGrowBuffer(&ts->ibuf,ptr+1-beg);
- ScanLineCommandTCP(ts,(char*)beg,(char*)ptr,now_usec);
- return;
- }
- }
- if ( ptr > beg && ( finish || ts->eof ) )
- {
- DropGrowBuffer(&ts->ibuf,ptr-beg);
- ScanLineCommandTCP(ts,(char*)beg,(char*)ptr,now_usec);
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- static int OnCommandTCP ( struct TCPStream_t * ts )
- {
- DASSERT(ts);
- SetTimeoutCommandTCP(ts,0);
- while ( ts->sock != -1 && !ts->obuf.used )
- {
- const uint watermark = ts->ibuf.used;
- ScanBufferCommandTCP(ts,false);
- if ( watermark == ts->ibuf.used )
- break;
- }
- if ( ts->eof && !ts->obuf.used && !ts->ibuf.used )
- OnCloseStream(ts,0);
- return 0;
- }
- ///////////////////////////////////////////////////////////////////////////////
- static int OnReceivedCommandTCP ( struct TCPStream_t * ts, u8 *buf, uint size )
- {
- DASSERT(ts);
- noPRINT("---------- OnReceivedCommandTCP(%p,%p,%u), used=%d,%d\n",
- ts, buf, size, ts->ibuf.used, ts->obuf.used );
- InsertGrowBuffer(&ts->ibuf,buf,size);
- return OnCommandTCP(ts);
- }
- ///////////////////////////////////////////////////////////////////////////////
- static int OnSendCommandTCP ( struct TCPStream_t * ts, u8 *buf, uint size )
- {
- DASSERT(ts);
- noPRINT("---------- OnSendCommandTCP(%p,%p,%u), used=%d,%d\n",
- ts, buf, size, ts->ibuf.used, ts->obuf.used );
- DropGrowBuffer(&ts->obuf,size);
- return OnCommandTCP(ts);
- }
- ///////////////////////////////////////////////////////////////////////////////
- static int OnTimeoutCommandTCP ( struct TCPStream_t * ts, u64 now_usec )
- {
- DASSERT(ts);
- noPRINT("---------- OnTimeoutCommandTCP(%p,%llu)\n",ts,now_usec);
- if ( ts->sock != -1 )
- {
- if (!ts->obuf.used)
- {
- ScanBufferCommandTCP(ts,true);
- if (ts->obuf.used)
- {
- SetTimeoutCommandTCP(ts,now_usec);
- return 0;
- }
- }
- OnCloseStream(ts,now_usec);
- }
- return 0;
- }
- ///////////////////////////////////////////////////////////////////////////////
- int OnCreateCommandTCP ( TCPStream_t *ts )
- {
- noPRINT("---------- OnCreateCommandTCP(%p)\n",ts);
- DASSERT(ts);
- ts->OnReceived = OnReceivedCommandTCP;
- ts->OnSend = OnSendCommandTCP;
- ts->OnTimeout = OnTimeoutCommandTCP;
- CommandTCPInfo_t *ci = (CommandTCPInfo_t*)ts->data;
- ci->OnScanLine = 0;
- ci->timeout_usec = 10*USEC_PER_SEC;
- ci->comma_is_eol = false;
- SetTimeoutCommandTCP(ts,0);
- return 0;
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// SaveCurrentState*() ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- void SaveCurrentStateSocket
- (
- FILE *f, // output file
- const Socket_t *sock // valid socket object
- )
- {
- DASSERT(f);
- DASSERT(sock);
- char info[3*sizeof(sock->info)];
- PrintEscapedString(info,sizeof(info),sock->info,-1,CHMD__ALL,0,0);
- fprintf(f,
- "sock = %d\n"
- "is-unix = %d\n"
- "info = %s\n"
- ,sock->sock
- ,sock->is_unix
- ,info
- );
- }
- ///////////////////////////////////////////////////////////////////////////////
- void SaveCurrentStateTCPStream
- (
- FILE *f, // output file
- const TCPStream_t *ts, // valid TCP stream
- TCPStreamSaveFunc func // NULL or function for 'TCPStream_t.data' extend
- )
- {
- DASSERT(f);
- DASSERT(ts);
- char info[1000];
- PrintEscapedString(info,sizeof(info),ts->info,-1,CHMD__ALL,0,0);
- fprintf(f,
- "sock = %d\n"
- "rescan = %u\n"
- "eof = %u\n"
- "protect = %u\n"
- "auto-close = %u\n"
- "accept-usec = %llu\n"
- "trigger-usec = %llu\n"
- "delay-usec = %llu\n"
- "timeout-usec = %llu\n"
- "connect-usec = %llu\n"
- "receive-usec = %llu\n"
- "send-usec = %llu\n"
- "info = %s\n"
- ,ts->sock
- ,ts->rescan
- ,ts->eof
- ,ts->protect
- ,ts->auto_close
- ,ts->accept_usec
- ,ts->trigger_usec
- ,ts->delay_usec
- ,ts->timeout_usec
- ,ts->connect_usec
- ,ts->receive_usec
- ,ts->send_usec
- ,info
- );
- if (func)
- func(f,ts);
- SaveCurrentStateTransferStats1(f,"tfer-stat",&ts->stat);
- SaveCurrentStateGrowBuffer(f,"ibuf-",2,&ts->ibuf);
- SaveCurrentStateGrowBuffer(f,"obuf-",2,&ts->obuf);
- }
- ///////////////////////////////////////////////////////////////////////////////
- void SaveCurrentStateCommandTCP
- (
- FILE *f, // output file
- const TCPStream_t *ts // valid TCP stream
- )
- {
- DASSERT(f);
- DASSERT(ts);
- const CommandTCPInfo_t *ci = (CommandTCPInfo_t*)ts->data;
- fprintf(f,
- "cmd-comma = %d\n"
- "cmd-timeout = %llu\n"
- ,ci->comma_is_eol
- ,ci->timeout_usec
- );
- }
- ///////////////////////////////////////////////////////////////////////////////
- void SaveCurrentStateTCPHandler
- (
- FILE *f, // output file
- ccp sect_name, // section base name
- const TCPHandler_t *th, // valid TCP handler
- TCPStreamSaveFunc func // NULL or function for 'TCPStream_t.data' extend
- )
- {
- DASSERT(f);
- DASSERT(sect_name);
- DASSERT(th);
- fprintf(f,
- "\n#%.50s\n"
- "[%s]\n"
- "\n"
- "data-size = %u\n"
- "max-conn = %u\n"
- "maintenance = %u\n"
- "used-streams = %u\n"
- "max-used = %u\n"
- "total-streams = %u\n"
- ,Minus300
- ,sect_name
- ,th->data_size
- ,th->max_conn
- ,th->need_maintenance
- ,th->used_streams
- ,th->max_used_streams
- ,th->total_streams
- );
- SaveCurrentStateTransferStats1(f,"tfer-stat",&th->stat);
- uint i;
- for ( i = 0; i < TCP_HANDLER_MAX_LISTEN; i++ )
- {
- if ( th->listen[i].sock != -1 )
- {
- fprintf(f,"\n[%s/socket:%u]\n\n",sect_name,i);
- SaveCurrentStateSocket(f,th->listen+i);
- }
- }
- const TCPStream_t *ts;
- for ( ts = th->first, i = 0; ts; ts = ts->next, i++ )
- {
- fprintf(f,"\n[%s/stream:%u]\n\n",sect_name,i);
- SaveCurrentStateTCPStream(f,ts,func);
- }
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// RestoreState*() ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- void RestoreStateSocket
- (
- RestoreState_t *rs, // info data, can be modified (cleaned after call)
- cvp user_table // pointer provided by RestoreStateTab_t[]
- )
- {
- DASSERT(rs);
- Socket_t *sock = (Socket_t*)user_table;
- if (!sock)
- return;
- int fd = GetParamFieldINT(rs,"sock",-1);
- if ( fd != -1 && fcntl(fd,F_GETFD) != -1 )
- {
- sock->sock = fd;
- sock->is_unix = GetParamFieldINT(rs,"is-unix",0);
- GetParamFieldBUF(sock->info,sizeof(sock->info),rs,"info",ENCODE_STRING,"?");
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- TCPStream_t * RestoreStateTCPStream
- (
- // return 'ts' or the new TCPStream_t
- RestoreState_t *rs, // info data, can be modified (cleaned after call)
- TCPStream_t *ts, // if NULL: create it
- uint extra_size // if 'ts' alloced: alloc some byte more
- )
- {
- DASSERT(rs);
- TRACE("RestoreStateTCPStream()\n");
- int fd = ts ? ts->sock : -1;
- if ( fd == -1 )
- {
- fd = GetParamFieldINT(rs,"sock",-1);
- if ( fd != -1 && fcntl(fd,F_GETFD) == -1 )
- fd = -1;
- }
- if (!ts)
- {
- ts = CALLOC(sizeof(*ts)+extra_size,1);
- InitializeTCPStream(ts,fd);
- }
- else
- ts->sock = fd;
- DASSERT(ts);
- ts->protect = GetParamFieldUINT(rs, "protect", ts->protect);
- ts->auto_close = GetParamFieldUINT(rs, "auto-close", ts->auto_close);
- ts->rescan = GetParamFieldUINT(rs, "rescan", ts->rescan );
- ts->eof = GetParamFieldUINT(rs, "eof", ts->eof );
- ts->accept_usec = GetParamFieldU64 (rs, "accept-usec", ts->accept_usec );
- ts->trigger_usec = GetParamFieldU64 (rs, "trigger-usec", ts->trigger_usec );
- ts->delay_usec = GetParamFieldU64 (rs, "delay-usec", ts->delay_usec );
- ts->timeout_usec = GetParamFieldU64 (rs, "timeout-usec", ts->timeout_usec );
- ts->connect_usec = GetParamFieldU64 (rs, "connect-usec", ts->connect_usec );
- ts->receive_usec = GetParamFieldU64 (rs, "receive-usec", ts->receive_usec );
- ts->send_usec = GetParamFieldU64 (rs, "send-usec", ts->send_usec );
- GetParamFieldBUF(ts->info,sizeof(ts->info),rs,"info",ENCODE_STRING,"?");
- RestoreStateTransferStats1(rs,"tfer-stat",&ts->stat,true);
- RestoreStateGrowBuffer(&ts->ibuf,"ibuf-",rs);
- RestoreStateGrowBuffer(&ts->obuf,"obuf-",rs);
- return ts;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- void RestoreStateTCPHandler_base
- (
- TCPHandler_t *th, // valid TCPHandler_t
- RestoreState_t *rs // info data, can be modified (cleaned after call)
- )
- {
- DASSERT(th);
- DASSERT(rs);
- TRACE("RestoreStateTCPHandler_base()\n");
- //ResetTCPHandler(th); // don't call, because call back functions are cleared
- struct uint_parm_t
- {
- ccp name;
- uint *param;
- };
- const struct uint_parm_t uint_parm_tab[] =
- {
- { "max-conn", &th->max_conn },
- { "maintenance", &th->need_maintenance },
- { "max-used", &th->max_used_streams },
- { "total-streams", &th->total_streams },
- {0,0}
- };
- const struct uint_parm_t *up;
- for ( up = uint_parm_tab; up->name; up++ )
- *up->param = GetParamFieldUINT(rs,up->name,*up->param);
- RestoreStateTransferStats1(rs,"tfer-stat",&th->stat,true);
- if ( rs->log_mode & RSL_UNUSED_NAMES )
- {
- // known as 'unused'
- GetParamField(rs,"data-size");
- GetParamField(rs,"used-streams");
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- Socket_t * RestoreStateTCPHandler_socket
- (
- TCPHandler_t *th, // valid TCPHandler_t
- RestoreState_t *rs // info data, can be modified (cleaned after call)
- )
- {
- DASSERT(th);
- DASSERT(rs);
- TRACE("RestoreStateTCPHandler_socket()\n");
- Socket_t *sock = GetUnusedListenSocketTCP(th,false);
- if (sock)
- RestoreStateSocket(rs,sock);
- return sock;
- }
- ///////////////////////////////////////////////////////////////////////////////
- TCPStream_t * RestoreStateTCPHandler_stream
- (
- TCPHandler_t *th, // valid TCPHandler_t
- RestoreState_t *rs // info data, can be modified (cleaned after call)
- )
- {
- DASSERT(th);
- DASSERT(rs);
- TRACE("RestoreStateTCPHandler_stream()\n");
- int fd = GetParamFieldINT(rs,"sock",-1);
- bool protect = GetParamFieldUINT(rs,"protect",0);
- #ifdef TEST
- if ( !protect && fd == -1 )
- return 0;
- #else
- if ( !protect && ( fd == -1 || fcntl(fd,F_GETFD) == -1 ))
- return 0;
- #endif
- TCPStream_t *ts = CreateTCPStream(th,fd,ALLOW_MODE_ALLOW,0);
- RestoreStateTCPStream(rs,ts,th->data_size);
- return ts;
- }
- ///////////////////////////////////////////////////////////////////////////////
- void RestoreStateTCPHandler
- (
- RestoreState_t *rs, // info data, can be modified (cleaned after call)
- cvp user_table // pointer provided by RestoreStateTab_t[]
- )
- {
- DASSERT(rs);
- TRACE("Scan TCP Handler (%s/%s,%d)\n",rs->sect,rs->path,rs->index);
- TCPHandler_t *th = (TCPHandler_t*)user_table;
- if (!th)
- return;
- if (!*rs->path)
- RestoreStateTCPHandler_base(th,rs);
- else if (!strcmp(rs->path,"socket"))
- RestoreStateTCPHandler_socket(th,rs);
- else if (!strcmp(rs->path,"stream"))
- RestoreStateTCPHandler_stream(th,rs);
- }
- ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////
- void RestoreStateCommandTCP
- (
- RestoreState_t *rs, // info data, can be modified (cleaned after call)
- cvp user_table // pointer provided by RestoreStateTab_t[]
- )
- {
- DASSERT(rs);
- TCPHandler_t *th = (TCPHandler_t*)user_table;
- if (!th)
- return;
- if (!strcmp(rs->path,"stream"))
- {
- TCPStream_t *ts = RestoreStateTCPHandler_stream(th,rs);
- if (ts)
- {
- CommandTCPInfo_t *ci = (CommandTCPInfo_t*)ts->data;
- ci->comma_is_eol = GetParamFieldINT( rs, "cmd-comma", ci->comma_is_eol ) > 0;
- ci->timeout_usec = GetParamFieldU64( rs, "cmd-timeout", ci->timeout_usec );
- }
- }
- else
- RestoreStateTCPHandler(rs,user_table);
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// Misc ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- bool fix_ether_head_vlan ( ether_head_vlan_t *head )
- {
- DASSERT(head);
- const u16 vlan_tag_type = ntohs(head->vlan_tag_type);
- if ( vlan_tag_type == 0x8100 )
- {
- head->have_vlan = true;
- head->head_size = 18;
- return true;
- }
- head->ether_type = head->vlan_tag_type;
- head->have_vlan = false;
- head->head_size = 14;
- return false;
- }
- ///////////////////////////////////////////////////////////////////////////////
- void ntoh_ether_head_vlan ( ether_head_vlan_t *dest, const void * src )
- {
- if (dest)
- {
- if (src)
- memcpy(dest,src,sizeof(*dest));
- fix_ether_head_vlan(dest);
- dest->vlan_tag_type = ntohs(dest->vlan_tag_type);
- dest->vlan_param = ntohs(dest->vlan_param);
- dest->ether_type = ntohs(dest->ether_type);
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- void ntoh_ether_head ( ether_head_t *dest, const void * src )
- {
- if (dest)
- {
- if (src)
- memcpy(dest,src,sizeof(*dest));
- dest->ether_type = ntohs(dest->ether_type);
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- void ntoh_ip4_head ( ip4_head_t *dest, const void * src )
- {
- if (dest)
- {
- if (src)
- memcpy(dest,src,sizeof(*dest));
- dest->total_len = ntohs(dest->total_len);
- dest->id = ntohs(dest->id);
- dest->frag_off = ntohs(dest->frag_off);
- dest->checksum = ntohs(dest->checksum);
- dest->ip_src = ntohl(dest->ip_src);
- dest->ip_dest = ntohl(dest->ip_dest);
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- void ntoh_udp_head ( udp_head_t *dest, const void * src )
- {
- if (dest)
- {
- const udp_head_t *usrc = src ? src : dest;
- dest->port_src = ntohs(usrc->port_src);
- dest->port_dest = ntohs(usrc->port_dest);
- dest->data_len = ntohs(usrc->data_len);
- dest->checksum = ntohs(usrc->checksum);
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- void ntoh_tcp_head ( tcp_head_t *dest, const void * src )
- {
- if (dest)
- {
- const tcp_head_t *usrc = src ? src : dest;
- dest->port_src = ntohs(usrc->port_src);
- dest->port_dest = ntohs(usrc->port_dest);
- dest->seq_num = ntohl(usrc->seq_num);
- dest->acc_num = ntohl(usrc->acc_num);
- dest->data_off = usrc->data_off;
- dest->flags = usrc->flags;
- dest->window = ntohs(usrc->window);
- dest->checksum = ntohs(usrc->checksum);
- dest->urgent = ntohs(usrc->urgent);
- }
- }
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// Linux support ///////////////
- ///////////////////////////////////////////////////////////////////////////////
- #if defined(SYSTEM_LINUX) || defined(__CYGWIN__)
- #include "dclib-network-linux.c"
- #endif // SYSTEM_LINUX
- //
- ///////////////////////////////////////////////////////////////////////////////
- /////////////// END ///////////////
- ///////////////////////////////////////////////////////////////////////////////
|